You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

597 lines
25 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Helpers;
using DS.Module.MQ;
using DS.Module.SqlSugar;
using DS.Module.UserModule;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.HangfireJob.Interface;
using DS.WMS.Core.Info.Entity;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
using DS.WMS.FeeBillRecvService.Dtos;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPOI.OpenXmlFormats.Wordprocessing;
using Org.BouncyCastle.Ocsp;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using SqlSugar;
namespace DS.WMS.FeeBillRecvService
{
public class RecvFeeBillWorker : BackgroundService
{
private readonly ILogger<RecvFeeBillWorker> _logger;
private IConnection mqConn;
private IModel model;
private readonly IServiceProvider _serviceProvider;
private readonly ISqlSugarClient db;
private readonly IUser user;
private readonly ISaasDbService saasService;
public RecvFeeBillWorker(IServiceProvider serviceProvider,
ILogger<RecvFeeBillWorker> logger)
{
_logger = logger;
_serviceProvider = serviceProvider;
db = _serviceProvider.GetRequiredService<ISqlSugarClient>();
user = _serviceProvider.GetRequiredService<IUser>();
saasService = _serviceProvider.GetRequiredService<ISaasDbService>();
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("启动账单 ExecuteAsync");
return Task.Run(() =>
{
_logger.LogInformation("BookingAutoService ExecuteAsync RunTask");
//绑定队列
BindMQ();
});
}
private void BindMQ()
{
//string ExchangeName = "billcenter.output.ds7new.444c19c1-0bf5-4709-a08b-c9859ca775e6";
//string QueueName = $"billcenter.output.ds7new.444c19c1-0bf5-4709-a08b-c9859ca775e6";
string ExchangeName = AppSetting.app(new string[] { "FeeSettings", "ExchangeName" });
string QueueName = AppSetting.app(new string[] { "FeeSettings", "QueueName" });
var mqUrl = AppSetting.app(new string[] { "FeeSettings", "MQUrl" });
ConnectionFactory factory = new ConnectionFactory();
//var repoSysCfg = _serviceScope.ServiceProvider.GetService<SqlSugarRepository<SysConfig>>();
//var mqUrl = "amqp://dongsheng8bill:dongsheng8bill@47.104.207.5:12567/billcenter";
//var mqUrl = repoSysCfg.FirstOrDefault(x => x.Code == "DjyBookingAutoMQUrl")?.Value;
if (string.IsNullOrEmpty(mqUrl))
{
_logger.LogError($"接收订舱自动化消息推送所需MQUrl未配置");
}
else
{
_logger.LogInformation($"准备连接订舱自动化消息队列:{mqUrl}");
factory.Uri = new Uri(mqUrl);
mqConn = factory.CreateConnection("东胜8接收账单邮件解析");
model = mqConn.CreateModel();
model.ExchangeDeclare(ExchangeName, ExchangeType.Topic);
model.QueueDeclare(QueueName, false, false, false, null);
model.QueueBind(QueueName, ExchangeName, "*", null);
var consumer = new EventingBasicConsumer(model);
consumer.Received += (obj, arg) =>
{
var body = arg.Body;
var strBody = Encoding.UTF8.GetString(body.ToArray());
_logger.LogInformation($"收到订舱自动化消息队列:{strBody}");
DoWork(strBody);
};
model.BasicConsume(QueueName, true, consumer);
}
}
public override void Dispose()
{
base.Dispose();
//_serviceScope.Dispose();
if (mqConn != null && mqConn.IsOpen)
mqConn.Close();
_logger.LogInformation("BookingAutoService Dispose");
}
private void DoWork(string json)
{
/*
1
2
3
*/
string msg = string.Empty;
string gid = string.Empty;
try
{
var model = GetInfo(json, out msg);
_logger.LogInformation($"报文转换完成 GID={model.GID} BookingBill={model.BookingBill} 共【{model.DetailList.Count}】条");
//var tenantDb = saasService.GetBizJobDbScopeById(new JobDbInitConfig
//{
// UserId = 1819549542463442944,
// UserName = "东胜8测试",
// TenantId = 1819549542425694208,
// OrgId = 1819557001806614528
//});
var tenantDb = saasService.GetBizJobDbScopeExtById(new JobDbInitConfig
{
//UserId = long.Parse(AppSetting.app(new string[] { "FeeSettings", "UserId" })),
//UserName = AppSetting.app(new string[] { "FeeSettings", "UserName" }),
TenantId = long.Parse(AppSetting.app(new string[] { "FeeSettings", "TenantId" })),
//OrgId = long.Parse(AppSetting.app(new string[] { "FeeSettings", "OrgId" })),
});
_logger.LogInformation($"提取对应租户数据访问完成 GID={model.GID} BookingBill={model.BookingBill}");
string blno = model.BookingBill?.Trim();
gid = model.GID?.Trim();
_logger.LogInformation($"提取订单信息 GID={model.GID} BookingBill={model.BookingBill}");
var booking = tenantDb.Queryable<SeaExport>().ClearFilter(typeof(IOrgId)).First(a => a.MBLNO == blno && a.Deleted == false && (a.IsRefund == null || a.IsRefund.Value == false)
&& (a.IsChangeETD == null || a.IsChangeETD.Value == false));
_logger.LogInformation($"提取订单完成 GID={model.GID} BookingBill={model.BookingBill} Order={JsonConvert.SerializeObject(booking)}");
if (booking != null && booking.IsFeeLocking.HasValue && booking.IsFeeLocking.Value)
{
SendCallBack(new SingleBillReceiveResult
{
ReceiveId = model.GID,
Success = false,
Reason = "订单费用已锁定"
});
_logger.LogInformation($"提取订单完成 GID={model.GID} BookingBill={model.BookingBill} id={booking.Id}");
return;
}
if (booking != null)
{
var ctnList = tenantDb.Queryable<OpCtn>().ClearFilter(typeof(IOrgId)).Where(a => a.BSNO == booking.Id.ToString() && a.Deleted == false).ToList();
DateTime etd = DateTime.MinValue;
if (booking.ETD.HasValue)
etd = booking.ETD.Value;
DateTime nowDate = DateTime.Now;
var custTypeDict = DS.Module.Core.EnumUtil.GetEnumDictionaryWithKey(typeof(CustomerTypeEnum));
var feeUnitDict = DS.Module.Core.EnumUtil.GetEnumDictionaryWithKey(typeof(FeeUnitEnum));
var codeCurrency = tenantDb.Queryable<FeeCurrency>().ToList();
long tenantId = long.Parse(AppSetting.app(new string[] { "FeeSettings", "TenantId" }));
var userInfo = db.Queryable<SysUser>().ClearFilter(typeof(ITenantId)).First(x => x.Id == booking.OperatorId && x.TenantId == tenantId);
List<string> errorMsgList = new List<string>();
int start = 1;
//需要先全部费用跟库匹配,存在不匹配的,终止整个入库
Dictionary<string, Tuple<string, bool>> doResultDict = new Dictionary<string, Tuple<string, bool>>();
var checkFeeArg = model.DetailList.Select(f=>f.CustSysName).Distinct().ToList();
string reason = string.Empty;
bool isStop = false;
bool isNoNotice = false;
if (checkFeeArg.Any(x => string.IsNullOrWhiteSpace(x)))
{
isStop = true;
reason = "费用名称不能为空";
//new EmailNoticeHelper().SendEmailNotice("")
isNoNotice = true;
}
var queryFeeList = tenantDb.Queryable<FeeCode>().Where(x => checkFeeArg.Contains(x.Name) && x.IsSea == true).ToList();
if(queryFeeList.Count == 0)
{
isStop = true;
reason = $"费用名称不存在,{(string.Join(",", checkFeeArg))}";
isNoNotice = true;
}
else
{
var checkRlt = checkFeeArg.GroupJoin(queryFeeList, l => l, r => r.Name, (l, r) =>
{
var currFee = r.FirstOrDefault();
if (currFee == null)
return new { Succ = false, Obj = l };
return new { Succ = true, Obj = l };
}).ToList();
if (checkRlt.Any(b => !b.Succ))
{
isStop = true;
reason = "费用名称不存在," + string.Join(",", checkRlt.Where(b => !b.Succ).Select(b => b.Obj).ToArray());
isNoNotice = true;
}
}
if (!isStop)
{
foreach (var fee in model.DetailList)
{
string qFee = fee.CustSysName?.Trim();
try
{
var feecode = tenantDb.Queryable<FeeCode>().First(x => x.Name == qFee && x.IsSea == true);
if (feecode == null)
{
}
var newfee = new FeeRecord();
newfee.BusinessId = booking.Id;
newfee.FeeId = feecode.Id;
newfee.FeeName = feecode.Name;
newfee.FeeCode = feecode.Code;
newfee.TaxRate = feecode.TaxRate == null ? 0 : (decimal)feecode.TaxRate;
newfee.BusinessType = BusinessType.OceanShippingExport;
string custShortName = string.Empty;
string custType = string.Empty;
if (fee.CustSettleFor.IndexOf("#") >= 0)
{
var currArg = fee.CustSettleFor.Split(new char[] { '#' });
custShortName = currArg[0]?.Trim();
if (currArg.Length == 2)
{
custType = currArg.LastOrDefault().Trim();
}
}
else
{
custShortName = fee.CustSettleFor?.Trim();
}
var customerInfo = tenantDb.Queryable<InfoClient>().ClearFilter(typeof(ISharedOrgId)).First(x => x.ShortName == custShortName);
newfee.CustomerId = customerInfo.Id;
newfee.CustomerName = customerInfo.Description;
if (!string.IsNullOrWhiteSpace(custType))
{
var custTypeKey = custTypeDict.FirstOrDefault(x => x.Value == custType);
newfee.CustomerType = custTypeKey.Key;
newfee.CustomerTypeText = custTypeKey.Value;
}
newfee.FeeType = FeeType.Payable; //租箱月结明细.FeeType;
var feeUnitKey = feeUnitDict.FirstOrDefault(x => x.Value == fee.CustFeeStandard?.Trim());
newfee.Unit = feeUnitKey.Key;
newfee.UnitText = feeUnitKey.Value;
var currCurrCode = codeCurrency.First(a => a.CodeName == fee.CustCurrency);
newfee.Currency = currCurrCode.CodeName;
decimal qty = 0;
if (fee.CustFeeStandard.Equals("箱"))
{
var ctnSumList = ctnList.GroupBy(a => a.Ctn)
.Select(a => new { Key = a.Key, Code = a.ToList().FirstOrDefault().CtnCode, Num = a.Sum(b => b.CtnNum.HasValue ? b.CtnNum.Value : 1) }).ToList();
if (ctnSumList.Count == 1)
{
newfee.Unit = ctnSumList.FirstOrDefault().Code;
newfee.UnitText = ctnSumList.FirstOrDefault().Key;
}
if (!fee.Quantity.HasValue)
{
qty = ctnSumList.Sum(x => x.Num);
}
else
{
qty = fee.Quantity.Value;
}
}
else if (fee.CustFeeStandard.Equals("票"))
{
qty = 1;
}
if (!fee.UnitPrice.HasValue)
{
if (fee.Amount.HasValue)
{
var price = fee.Amount.Value / qty;
newfee.TaxUnitPrice = price;
}
else
{
newfee.TaxUnitPrice = 0;
}
}
else
{
newfee.TaxUnitPrice = fee.UnitPrice.Value;
}
if (newfee.Currency.Equals("RMB", StringComparison.OrdinalIgnoreCase) || newfee.Currency.Equals("CNY", StringComparison.OrdinalIgnoreCase))
{
newfee.ExchangeRate = 1;
}
else
{
if (etd != DateTime.MinValue)
{
var exchangeInfo = tenantDb.Queryable<FeeCurrencyExchange>().ClearFilter(typeof(IOrgId))
.First(x => x.CurrencyCode == newfee.Currency && x.OrgId == booking.OrgId
&& x.StartDate.Value <= etd && x.EndDate.Value >= etd && x.LocalCurrency == "RMB");
if (exchangeInfo == null)
{
exchangeInfo = tenantDb.Queryable<FeeCurrencyExchange>().ClearFilter(typeof(IOrgId))
.First(x => x.CurrencyCode == newfee.Currency && x.StartDate.Value <= etd && x.EndDate.Value >= etd && x.LocalCurrency == "RMB");
}
if (exchangeInfo != null)
{
newfee.ExchangeRate = exchangeInfo.CRValue;
}
}
}
newfee.Quantity = qty;
newfee.Amount = fee.Amount.HasValue ? fee.Amount.Value : 0;
newfee.CreateTime = nowDate;
newfee.CreateBy = userInfo.Id;
newfee.CreateUserName = userInfo.UserName;
newfee.UpdateTime = nowDate;
//2024-11-08 按照董怡含要求,先不要默认审批通过,暂时关闭
//newfee.FeeStatus = FeeStatus.AuditPassed;
newfee.Note = "大简云账单解析";
_logger.LogInformation($"写入账单开始 第【{start}】条 GID={model.GID} BookingBill={model.BookingBill} Order={JsonConvert.SerializeObject(newfee)}");
tenantDb.Insertable<FeeRecord>(newfee).ExecuteCommand();
_logger.LogInformation($"写入账单完成 第【{start}】条 GID={model.GID} BookingBill={model.BookingBill} Order={JsonConvert.SerializeObject(newfee)}");
//入库成功
doResultDict.Add(fee.GID, new Tuple<string, bool>(qFee, true));
}
catch (Exception ex)
{
doResultDict.Add(fee.GID, new Tuple<string, bool>(qFee, false));
_logger.LogInformation($"明细写入产生异常qFee={qFee} 原因:{ex.Message}");
}
//callbackList.Add()
start++;
}
//如果存在失败情况,回执失败
if (doResultDict.Count(b => !b.Value.Item2) > 0)
{
reason = "入库失败," + string.Join(",", doResultDict.Where(b => !b.Value.Item2).ToArray());
SendCallBack(new SingleBillReceiveResult
{
ReceiveId = model.GID,
Success = false,
Reason = reason
});
}
else
{
//全部成功,推送成功回执
SendCallBack(new SingleBillReceiveResult
{
ReceiveId = model.GID,
Success = true,
Reason = string.Empty
});
}
}
else
{
if (!isNoNotice)
{
SendCallBack(new SingleBillReceiveResult
{
ReceiveId = model.GID,
Success = false,
Reason = reason
});
}
}
}
else
{
SendCallBack(new SingleBillReceiveResult
{
ReceiveId = model.GID,
Success = false,
Reason = "当前订单不存在"
});
}
}
catch (Exception ex)
{
_logger.LogInformation($"产生异常,原因:{ex.Message}");
if (!string.IsNullOrWhiteSpace(gid))
{
//SendCallBack(new SingleBillReceiveResult
//{
// ReceiveId = gid,
// Success = false,
// Reason = "当前订单不存在"
//});
}
}
}
private void SendCallBack(SingleBillReceiveResult dto)
{
_logger.LogInformation($"开始准备发送回执MQ json={JsonConvert.SerializeObject(dto)}");
var mqRlt = PublishMessage(new MQPublishMessageReqDto
{
BusinessId = dto.ReceiveId,
IsZip = false,
json = JsonConvert.SerializeObject(dto),
mqUri = AppSetting.app(new string[] { "FeeCallBacSettings", "MQUrl" }),
mqExchangeName = AppSetting.app(new string[] { "FeeCallBacSettings", "ExchangeName" }),
mqQueueName = AppSetting.app(new string[] { "FeeCallBacSettings", "QueueName" })
}).GetAwaiter().GetResult();
_logger.LogInformation($"发送回执MQ完成结果 json={JsonConvert.SerializeObject(mqRlt)}");
}
#region 发送MQ报文
/// <summary>
/// 发送MQ报文
/// </summary>
/// <param name="request">请求参数</param>
/// <returns>true-发送成功 false-发送失败</returns>
public async Task<string> PublishMessage(MQPublishMessageReqDto request)
{
bool isException = false;
string msg = string.Empty;
try
{
ConnectionFactory factory = new ConnectionFactory();
factory.Uri = new Uri(request.mqUri);
using (IConnection conn = factory.CreateConnection())
{
try
{
IModel mqModel = conn.CreateModel();
mqModel.ExchangeDeclare(request.mqExchangeName, ExchangeType.Direct);
//var queueName = $"{MqActionQueueName}.{(item.SubTenantId.HasValue && item.SubTenantId > 0 ? item.SubTenantId.Value : item.TenantId)}";
mqModel.QueueDeclare(request.mqQueueName, false, false, false, null);
mqModel.QueueBind(request.mqQueueName, request.mqExchangeName, request.mqQueueName, null);
byte[] messageBodyBytes = Encoding.UTF8.GetBytes(request.json);
IBasicProperties props = mqModel.CreateBasicProperties();
props.DeliveryMode = 2;
mqModel.BasicPublish(request.mqExchangeName, request.mqQueueName, props, messageBodyBytes);
_logger.LogInformation($"Id:{request.BusinessId},订舱数据回推,已发送数据到消息队列【{request.mqUri}】,队列名称:【{request.mqQueueName}】");
}
catch (Exception inne)
{
_logger.LogInformation($"Id:{request.BusinessId}推送MQ时发生异常原因:{inne.Message}");
msg = $"Id:{request.BusinessId}推送MQ时发生异常原因:{inne.Message}";
isException = true;
}
finally
{
conn.Close();
}
}
}
catch (Exception ex)
{
_logger.LogInformation($"Id:{request.BusinessId},启动推送MQ时发生异常原因:{ex.Message}");
msg = $"Id:{request.BusinessId},启动推送MQ时发生异常原因:{ex.Message}";
isException = true;
}
if (isException)
return msg;
return string.Empty;
}
#endregion
private FeeBillReadDto GetInfo(string json,out string msg)
{
FeeBillReadDto model = null;
msg = string.Empty;
try
{
model = JsonConvert.DeserializeObject<FeeBillReadDto>(json);
}
catch(Exception ex)
{
msg = $"转换报文异常,原因:{ex.Message}";
}
return model;
}
}
}