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.

665 lines
30 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Amazon.Runtime.Internal.Util;
using DS.Module.Core;
using DS.Module.Core.Log;
using DS.Module.SqlSugar;
using DS.Module.UserModule;
using DS.WMS.Core.Op.Dtos;
using DS.WMS.Core.Op.Entity;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using DS.WMS.Core.Op.Interface;
using SqlSugar.IOC;
using Newtonsoft.Json;
using NLog;
using DS.WMS.Core.Sys.Interface;
namespace DS.WMS.Core.Op.Method
{
public class BookingSlotService //: IBookingSlotService
{
private readonly IServiceProvider _serviceProvider;
private readonly ISqlSugarClient db;
private readonly IUser user;
private readonly ISaasDbService saasService;
private readonly ISeaExportService _seaExportService;
private readonly IBookingLabelService _bookingLabelService;
private readonly ILogAuditService _logAuditService;
private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger();
public BookingSlotService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
db = _serviceProvider.GetRequiredService<ISqlSugarClient>();
user = _serviceProvider.GetRequiredService<IUser>();
saasService = _serviceProvider.GetRequiredService<ISaasDbService>();
_seaExportService = _serviceProvider.GetRequiredService<ISeaExportService>();
_bookingLabelService = _serviceProvider.GetRequiredService<IBookingLabelService>();
_logAuditService = _serviceProvider.GetRequiredService<ILogAuditService>();
}
#region 保存舱位
/// <summary>
/// 保存舱位
/// </summary>
/// <param name="input">舱位详情</param>
/// <returns>返回输出</returns>
public async Task<DataResult<BookingSlotBaseSaveOutput>> Save(BookingSlotBaseSaveInput input)
{
BookingSlotBase model = null;
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
if (input.Id > 0) //修改
{
var c = tenantDb.Queryable<BookingSlotBase>().Where(x => x.SlotBookingNo == input.SlotBookingNo
&& input.Id != input.Id).Count();
if (c > 0)
{
//订舱提单号已存在
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotSlotBookingNoExists)));
}
model = tenantDb.Queryable<BookingSlotBase>().First(x => x.Id == input.Id);
var oldObj = model.Adapt<BookingSlotBaseSaveInput>();
input.Adapt(model);
// 1.判断新的舱位信息的7个库存统计维度是否发生变化
// 2.如果有变化,则需要更新旧的库存信息
bool isNeedUpdateOldStock = false;
if (oldObj.Vessel != model.Vessel
|| oldObj.Voyno != model.Voyno
|| oldObj.BookingSlotType != model.BookingSlotType
|| oldObj.CarrierCode != model.CarrierCode
|| oldObj.PortLoadId != model.PortLoadId
|| oldObj.PortDischargeId != model.PortDischargeId)
{
isNeedUpdateOldStock = true;
}
await tenantDb.Updateable<BookingSlotBase>(model).ExecuteCommandAsync();
if (isNeedUpdateOldStock)
{
//更新库存
//await _publisher.PublishAsync(new ChannelEventSource("BookingSlotStock:Update", new BookingSlotStockUpdateModel
//{
// BOOKING_SLOT_TYPE = oldObj.BOOKING_SLOT_TYPE,
// CARRIERID = oldObj.CARRIERID,
// CONTRACT_NO = oldObj.CONTRACT_NO,
// VESSEL = oldObj.VESSEL,
// VOYNO = oldObj.VOYNO,
// PORTLOADID = oldObj.PORTLOADID,
// PORTDISCHARGEID = oldObj.PORTDISCHARGEID,
// TenantId = model.TenantId
//}));
}
var delCtnList = tenantDb.Queryable<BookingSlotCtn>().Where(x => x.SlotId == model.Id).ToList();
if(delCtnList.Count > 0)
await tenantDb.Deleteable<BookingSlotCtn>(delCtnList).ExecuteCommandAsync();
if (input.CtnList != null)
{
foreach (var ctn in input.CtnList)
{
var newCtn = ctn.Adapt<BookingSlotCtn>();
newCtn.SlotId = model.Id;
await tenantDb.Insertable<BookingSlotCtn>(newCtn).ExecuteCommandAsync();
}
}
#region 关联订舱信息修改
if (input.BookingSlotSaleInfoList != null)
{
foreach (var item in input.BookingSlotSaleInfoList)
{
if (!item.UpdateFlag)
{
continue;
}
var allocation = await tenantDb.Queryable<BookingSlotAllocation>().FirstAsync(x => x.Id == item.Id);
if (allocation == null)
{
//保存失败原因更新关联订舱时未查询到订舱关联表Id{item.Id}
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotSaveFailAllocRecordNull)), item.Id));
}
// 更新关联表
item.Adapt(allocation);
await tenantDb.Ado.BeginTranAsync();
try
{
await tenantDb.Updateable<BookingSlotAllocation>(allocation).UpdateColumns(x => new
{
x.CustomerId,
x.CustomerName,
x.CustServiceId,
x.CustService,
x.Sale,
x.SaleId,
x.Op,
x.OpId,
x.Doc,
x.DocId,
x.BusinessId,
x.Business,
x.Shipper,
x.SaleTime,
x.GoodsName,
x.SellingPrice,
x.UpdateBy,
//x.UpdatedUserName,
x.UpdateTime,
}).ExecuteCommandAsync();
// 更新订舱表
//var bookingOrder = await _repBookingOrder.FirstOrDefaultAsync(x => x.Id == allocation.BOOKING_ID);
var bookingOrder = _seaExportService.GetSeaExportInfo(allocation.BookingId.ToString()).Data;
/*
var oldBookingOrder = bookingOrder.Adapt<BookingOrder>();
if (bookingOrder != null)
{
bookingOrder.CUSTOMERID = allocation.CUSTOMERID;
bookingOrder.CUSTOMERNAME = allocation.CUSTOMERNAME;
bookingOrder.CUSTSERVICE = allocation.CUSTSERVICE;
bookingOrder.CUSTSERVICEID = allocation.CUSTSERVICEID;
bookingOrder.SALE = allocation.SALE;
bookingOrder.SALEID = allocation.SALEID;
bookingOrder.OP = allocation.OP;
bookingOrder.OPID = allocation.OPID;
bookingOrder.DOC = allocation.DOC;
bookingOrder.DOCID = allocation.DOCID;
bookingOrder.BUSINESS = allocation.BUSINESS;
bookingOrder.BUSINESSID = allocation.BUSINESSID;
await _repBookingOrder.AsUpdateable(bookingOrder).UpdateColumns(x => new
{
x.CUSTOMERID,
x.CUSTOMERNAME,
x.CUSTSERVICE,
x.CUSTSERVICEID,
x.SALE,
x.SALEID,
x.OP,
x.OPID,
x.DOC,
x.DOCID,
x.UpdatedUserId,
x.UpdatedUserName,
x.UpdatedTime,
}).ExecuteCommandAsync();
Parallel.For(0, 1, (n) =>
{
//bookingOrderService.SaveLog(bookingOrder, oldBookingOrder, "舱位关联更新");
// 推送东胜
//bookingOrderService.SendBookingOrder(new long[] { allocation.BOOKING_ID });
});
}
*/
await tenantDb.Ado.CommitTranAsync();
}
catch (Exception)
{
await tenantDb.Ado.RollbackTranAsync();
//await ex.LogAsync(Db);
//return DataResult.Failed(MultiLanguageConst.Operation_Failed);
//_repAllocation.CurrentRollbackTran();
throw;
}
}
}
#endregion
//Parallel.For(0, 1, (n) =>
//{
// _ = InsLog("Update", model.Id, typeof(BookingSlotBaseSaveInput), oldObj, input,
// nameof(BookingSlotBaseApiSaveDto.CtnList),
// nameof(BookingSlotBaseApiSaveDto.BookingSlotSaleInfoList));
//});
}
else
{
var c = tenantDb.Queryable<BookingSlotBase>().Where(x => x.SlotBookingNo == input.SlotBookingNo).Count();
if (c > 0)
{
//订舱提单号已存在
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotSlotBookingNoExists)));
}
model = input.Adapt<BookingSlotBase>();
await tenantDb.Insertable<BookingSlotBase>(model).ExecuteReturnEntityAsync();
foreach (var ctn in input.CtnList)
{
var newCtn = ctn.Adapt<BookingSlotCtn>();
newCtn.SlotId = model.Id;
await tenantDb.Insertable<BookingSlotCtn>(newCtn).ExecuteCommandAsync();
}
//await InsLog("Add", model.Id, "新增舱位");
}
//更新库存
//await _publisher.PublishAsync(new ChannelEventSource("BookingSlotStock:Update", new BookingSlotStockUpdateModel
//{
// BOOKING_SLOT_TYPE = model.BOOKING_SLOT_TYPE,
// CARRIERID = model.CARRIERID,
// CONTRACT_NO = model.CONTRACT_NO,
// VESSEL = model.VESSEL,
// VOYNO = model.VOYNO,
// PORTLOADID = model.PORTLOADID,
// PORTDISCHARGEID = model.PORTDISCHARGEID,
// TenantId = model.TenantId
//}));
var inputDto = new BookingSlotBaseApiDto
{
DataObj = new BookingSlotBaseApiSaveDto
{
PortDischargeId = model.PortDischargeId,
PortDischarge = model.PortDischarge,
PortLoadId = model.PortLoadId,
PortLoad = model.PortLoad,
PlaceDelivery = model.PlaceDelivery,
PlaceDeliveryId = model.PlaceDeliveryId,
PlaceReceipt = model.PlaceReceipt,
PlaceReceiptId = model.PlaceReceiptId,
}
};
//这里自动匹配标签
await GenerateSlotLabel(inputDto, model.Id);
return await Detail(model.Id);
}
#endregion
#region 自动生成舱位标签
/// <summary>
/// 自动生成舱位标签
/// </summary>
/// <param name="dto">舱位详情</param>
/// <param name="id">舱位ID</param>
/// <returns></returns>
private async Task<DataResult<string>> GenerateSlotLabel(BookingSlotBaseApiDto dto, long id)
{
try
{
/*
1、获取所有的可用标签
2、只执行REGEX_PATTERN_TXT有值的标签记录。
3、根据提取的标签JSON执行验证符合条件的自动标记本标签
*/
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var labelList = _bookingLabelService.List(1).GetAwaiter().GetResult().Data;
List<BookingLabelBaseDto> ruleList = new List<BookingLabelBaseDto>();
if (labelList.Count > 0)
{
for (int i = 0; i < labelList.Count; i++)
{
if (!string.IsNullOrWhiteSpace(labelList[i].RegexPatternTxt))
{
try
{
var regList = JsonConvert.DeserializeObject<List<BookingLabelRegexDto>>(labelList[i].RegexPatternTxt);
if (regList != null && regList.Count > 0)
{
bool isSucc = true;
for (int j = 0; j < regList.Count; j++)
{
var operEnum = (LabelRegexOperEnum)System.Enum.Parse(typeof(LabelRegexOperEnum), regList[j].oper);
if (regList[j].name.Equals("PORTLOADID", StringComparison.OrdinalIgnoreCase))
{
isSucc = CheckLabel("PORTLOADID", dto.DataObj.PortLoadId, regList[j].val, regList[j].master, operEnum);
if (isSucc)
{
ruleList.Add(labelList[i]);
break;
}
else
{
if (regList[j].master)
break;
continue;
}
}
else if (regList[j].name.Equals("PLACERECEIPT", StringComparison.OrdinalIgnoreCase))
{
isSucc = CheckLabel("PLACERECEIPT", dto.DataObj.PlaceReceipt, regList[j].val, regList[j].master, operEnum);
if (isSucc)
{
ruleList.Add(labelList[i]);
break;
}
else
{
if (regList[j].master)
break;
continue;
}
}
else if (regList[j].name.Equals("PORTLOAD", StringComparison.OrdinalIgnoreCase))
{
isSucc = CheckLabel("PORTLOAD", dto.DataObj.PortLoad, regList[j].val, regList[j].master, operEnum);
if (isSucc)
{
ruleList.Add(labelList[i]);
break;
}
else
{
if (regList[j].master)
break;
continue;
}
}
else if (regList[j].name.Equals("PORTDISCHARGEID", StringComparison.OrdinalIgnoreCase))
{
isSucc = CheckLabel("PORTDISCHARGEID", dto.DataObj.PortDischargeId, regList[j].val, regList[j].master, operEnum);
if (isSucc)
{
ruleList.Add(labelList[i]);
break;
}
else
{
if (regList[j].master)
break;
continue;
}
}
else if (regList[j].name.Equals("PORTDISCHARGE", StringComparison.OrdinalIgnoreCase))
{
isSucc = CheckLabel("PORTDISCHARGE", dto.DataObj.PortDischarge, regList[j].val, regList[j].master, operEnum);
if (isSucc)
{
ruleList.Add(labelList[i]);
break;
}
else
{
if (regList[j].master)
break;
continue;
}
}
else if (regList[j].name.Equals("PLACEDELIVERY", StringComparison.OrdinalIgnoreCase))
{
isSucc = CheckLabel("PLACEDELIVERY", dto.DataObj.PlaceDelivery, regList[j].val, regList[j].master, operEnum);
if (isSucc)
{
ruleList.Add(labelList[i]);
break;
}
else
{
if (regList[j].master)
break;
continue;
}
}
}
if (isSucc)
{
Logger.Log(NLog.LogLevel.Info, $"标签对应到有效规则,{labelList[i].Name}");
}
}
}
catch (Exception innEx)
{
Logger.Log(NLog.LogLevel.Info, $"标签对应失败,{labelList[i].Name},原因:{innEx.Message}");
}
}
else
{
continue;
}
}
if (ruleList.Count > 0)
{
var bindModel = new BindLabelDto
{
BusinessIdArray = new[] { id },
LabelIdArray = ruleList.Select(a => a.Id.Value).ToArray()
};
Logger.Log(NLog.LogLevel.Info, $"标签绑定请求,{JsonConvert.SerializeObject(bindModel)}");
await _bookingLabelService.SetLabel(bindModel);
Logger.Log(NLog.LogLevel.Info, $"标签绑定请求完成");
}
}
}
catch (Exception e)
{
Logger.Log(NLog.LogLevel.Error, $"自动生成舱位标签失败,原因:{e.Message}");
return DataResult<string>.Failed(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotSlotBookingNoExists)),e.Message));
}
return DataResult<string>.Success(string.Empty);
}
#endregion
#region 判断标签识别
/// <summary>
/// 判断标签识别
/// </summary>
/// <param name="name">字段名称</param>
/// <param name="val">字段值</param>
/// <param name="checkVal">判断值</param>
/// <param name="isMaster">是否必校验</param>
/// <param name="operEnum">操作符枚举</param>
/// <returns>true-满足识别 false-不满足识别</returns>
private bool CheckLabel(string name, string val, string checkVal, bool isMaster, LabelRegexOperEnum operEnum)
{
if (operEnum == LabelRegexOperEnum.equal)
{
if (!string.IsNullOrWhiteSpace(val) && val.Equals(checkVal, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
else if (operEnum == LabelRegexOperEnum.startwith)
{
if (!string.IsNullOrWhiteSpace(val) && val.StartsWith(checkVal, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
else if (operEnum == LabelRegexOperEnum.like)
{
if (!string.IsNullOrWhiteSpace(val) && val.Contains(checkVal, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
else if (operEnum == LabelRegexOperEnum.notequal)
{
if (!string.IsNullOrWhiteSpace(val))
{
if (!val.Equals(checkVal, StringComparison.OrdinalIgnoreCase))
{
return true;
}
else
{
if (isMaster)
return false;
}
}
}
else if (operEnum == LabelRegexOperEnum.notexists)
{
if (!string.IsNullOrWhiteSpace(val))
{
if (!val.Contains(checkVal, StringComparison.OrdinalIgnoreCase))
{
return true;
}
else
{
if (isMaster)
return false;
}
}
}
else if (operEnum == LabelRegexOperEnum.notstartwith)
{
if (!string.IsNullOrWhiteSpace(val))
{
if (!val.StartsWith(checkVal, StringComparison.OrdinalIgnoreCase))
{
return true;
}
else
{
if (isMaster)
return false;
}
}
}
return false;
}
#endregion
#region 获取舱位详情
/// <summary>
/// 获取舱位详情
/// </summary>
/// <param name="id">舱位主键</param>
/// <returns>返回舱位详情</returns>
public async Task<DataResult<BookingSlotBaseSaveOutput>> Detail(long id)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var slotBase = await tenantDb.Queryable<BookingSlotBase>().FirstAsync(u => u.Id == id);
if (slotBase == null)
{
//未查询到此舱位信息,已删除或不存在
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotBaseInfoNull)));
}
var ctns = await tenantDb.Queryable<BookingSlotCtn>().Where(x => x.SlotId == id).ToListAsync();
var rtn = slotBase.Adapt<BookingSlotBaseSaveOutput>();
rtn.CtnList = ctns.Adapt<List<BookingSlotCtnSaveInput>>();
rtn.LogList = _logAuditService.GetAuditLogBookingList(slotBase.Id).GetAwaiter().GetResult()?.Data;
// 赋值关联的订舱列表
// 查询舱位绑定的销售信息,赋值到舱位对象中
List<BookingSlotSaleInfoDto> saleInfoList = await tenantDb.Queryable<BookingSlotAllocation>()
.Where(x => x.BookingSlotId == id)
.Select(x => new BookingSlotSaleInfoDto
{
Id = x.Id,
BookingId = x.BookingId,
BookingSlotId = x.BookingSlotId,
CustomerId = x.CustomerId,
CustomerName = x.CustomerName,
CustServiceId = x.CustServiceId,
CustService = x.CustService,
SaleId = x.SaleId,
Sale = x.Sale,
OpId = x.OpId,
Op = x.Op,
DocId = x.DocId,
Doc = x.Doc,
BusinessId = x.BusinessId,
Business = x.Business,
SaleTime = x.SaleTime,
Shipper = x.Shipper,
GoodsName = x.GoodsName,
SellingPrice = x.SellingPrice,
CreatedUserId = x.CreateBy
}).ToListAsync();
/*
if (saleInfoList.Any())
{
// 判断是否启用了委托单位查看控制权限
var tenantParamList = await _cache.GetAllTenantParam();
var isEnableCustomerAuthority = tenantParamList.FirstOrDefault(x => x.TenantId == UserManager.TENANT_ID
&& x.ParaCode == TenantParamCode.IS_ENABLE_CUSTOMER_AUTHORITY)?.ItemCode == "YES";
List<long> userList = null;
List<string> userListStr = null;
if (isEnableCustomerAuthority)
{
userList = await _sysDataUserMenuService.GetDataScopeList(MenuConst.MenuDjyCustomer);
if (userList != null && userList.Count > 0)
{
userListStr = userList.Select(x => x.ToString()).ToList();
// 遍历销售信息,如果销售信息中的“销售、操作、单证、客服、创建人”中不在当前登陆人的权限范围,则隐藏客户信息
foreach (BookingSlotSaleInfoDto saleInfoItem in saleInfoList)
{
if (!userList.Contains(saleInfoItem.CreatedUserId ?? 0)
&& !userListStr.Contains(saleInfoItem.OPID)
&& !userListStr.Contains(saleInfoItem.DOCID)
&& !userListStr.Contains(saleInfoItem.SALEID)
&& !userListStr.Contains(saleInfoItem.CUSTSERVICEID))
{
saleInfoItem.CUSTOMERID = 0;
saleInfoItem.CUSTOMERNAME = "--";
saleInfoItem.OPID = "";
saleInfoItem.OP = "--";
saleInfoItem.DOCID = "";
saleInfoItem.DOC = "--";
saleInfoItem.SALEID = "";
saleInfoItem.SALE = "--";
saleInfoItem.SHIPPER = "--";
saleInfoItem.GOODSNAME = "--";
saleInfoItem.CUSTSERVICEID = "";
saleInfoItem.CUSTSERVICE = "--";
}
}
}
}
}
*/
rtn.BookingSlotSaleInfoList = saleInfoList;
return DataResult<BookingSlotBaseSaveOutput>.Success(rtn);
}
#endregion
}
}