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.
BookingHeChuan/Myshipping.Application/Service/TaskManagePlat/TaskManageRollingNomination...

1816 lines
81 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 Furion;
using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using Mapster;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Myshipping.Application.ConfigOption;
using Myshipping.Application.Entity;
using Myshipping.Application.Enum;
using Myshipping.Application.Helper;
using Myshipping.Application.Service.TaskManagePlat;
using Myshipping.Core;
using Myshipping.Core.Entity;
using Myshipping.Core.Service;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json;
using NPOI.XWPF.UserModel;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Myshipping.Application
{
/// <summary>
/// 预甩货通知
/// </summary>
[ApiDescriptionSettings("Application", Name = "TaskManageRollingNomination", Order = 10)]
public class TaskManageRollingNominationService : ITaskManageRollingNominationService, IDynamicApiController, ITransient
{
private readonly ISysCacheService _cache;
private readonly ILogger<TaskManageRollingNominationService> _logger;
private readonly SqlSugarRepository<TaskBaseInfo> _taskBaseRepository;
private readonly SqlSugarRepository<TaskRollingNominationInfo> _taskRollingNominationInfoRepository;
private readonly SqlSugarRepository<TaskRollingNominationShipInfo> _taskRollingNominationShipInfoRepository;
private readonly SqlSugarRepository<TaskRollingNominationDetailInfo> _taskRollingNominationDetailInfoRepository;
private readonly SqlSugarRepository<TaskRollingNominationDispatchInfo> _taskRollingNominationDispatchInfoRepository;
private readonly SqlSugarRepository<TaskShareLinkInfo> _taskShareLinkInfoRepository;
private readonly SqlSugarRepository<BookingOrder> _bookingOrderRepository;
private readonly SqlSugarRepository<BookingCtn> _bookingCtnRepository;
private readonly SqlSugarRepository<BookingPrintTemplate> _repPrintTemplate;
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
private readonly SqlSugarRepository<DjyUserMailAccount> _djyUserMailAccount;
private readonly SqlSugarRepository<BookingOrderContact> _bookingOrderContactRepository;
private readonly IDjyTenantParamService _djyTenantParamService;
private readonly INamedServiceProvider<ITaskManageShareLinkService> _namedServiceProvider;
public TaskManageRollingNominationService(SqlSugarRepository<TaskBaseInfo> taskBaseRepository,
SqlSugarRepository<TaskRollingNominationInfo> taskRollingNominationInfoRepository,
SqlSugarRepository<TaskRollingNominationDetailInfo> taskRollingNominationDetailInfoRepository,
SqlSugarRepository<TaskRollingNominationDispatchInfo> taskRollingNominationDispatchInfoRepository,
SqlSugarRepository<TaskRollingNominationShipInfo> taskRollingNominationShipInfoRepository,
SqlSugarRepository<TaskShareLinkInfo> taskShareLinkInfoRepository,
SqlSugarRepository<BookingOrder> bookingOrderRepository,
SqlSugarRepository<BookingPrintTemplate> repPrintTemplate,
SqlSugarRepository<SysUser> sysUserRepository,
SqlSugarRepository<DjyUserMailAccount> djyUserMailAccount,
SqlSugarRepository<BookingOrderContact> bookingOrderContactRepository,
INamedServiceProvider<ITaskManageShareLinkService> namedServiceProvider,
SqlSugarRepository<BookingCtn> bookingCtnRepository, ISysCacheService cache, ILogger<TaskManageRollingNominationService> logger,
IDjyTenantParamService djyTenantParamService)
{
_taskBaseRepository = taskBaseRepository;
_taskRollingNominationInfoRepository = taskRollingNominationInfoRepository;
_taskRollingNominationDetailInfoRepository = taskRollingNominationDetailInfoRepository;
_taskRollingNominationDispatchInfoRepository = taskRollingNominationDispatchInfoRepository;
_taskRollingNominationShipInfoRepository = taskRollingNominationShipInfoRepository;
_taskShareLinkInfoRepository = taskShareLinkInfoRepository;
_bookingOrderRepository = bookingOrderRepository;
_bookingCtnRepository = bookingCtnRepository;
_repPrintTemplate = repPrintTemplate;
_sysUserRepository = sysUserRepository;
_djyUserMailAccount = djyUserMailAccount;
_bookingOrderContactRepository = bookingOrderContactRepository;
_namedServiceProvider = namedServiceProvider;
_djyTenantParamService = djyTenantParamService;
_cache = cache;
_logger = logger;
}
#region 获取预甩详情
/// <summary>
/// 获取预甩详情
/// </summary>
/// <param name="pkId">预甩主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageRollingNomination/GetInfo")]
public async Task<TaskRollingNominationShowDto> GetInfo(string pkId)
{
TaskRollingNominationShowDto model = null;
try
{
var rollModel = _taskRollingNominationInfoRepository.AsQueryable()
.First(a => a.PK_ID == pkId && !a.IsDeleted);
if (rollModel == null)
throw Oops.Oh($"预甩货主键{pkId}无法获取业务信息");
model = await InnerGetInfo(rollModel);
}
catch (Exception ex)
{
_logger.LogError($"获取预甩详情异常,原因:{ex.Message}");
throw ex;
}
return model;
}
#endregion
#region 通过任务主键获取预甩详情
/// <summary>
/// 通过任务主键获取预甩详情
/// </summary>
/// <param name="taskPkId">预甩任务主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageRollingNomination/GetInfoByTaskId")]
public async Task<TaskRollingNominationShowDto> GetInfoByTaskId(string taskPkId)
{
TaskRollingNominationShowDto model = null;
try
{
var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId && !a.IsDeleted);
if (taskBase == null)
throw Oops.Oh($"预甩货任务主键{taskPkId}无法获取任务信息");
var rollModel = _taskRollingNominationInfoRepository.AsQueryable()
.First(a => a.TASK_ID == taskBase.PK_ID && !a.IsDeleted);
if (rollModel == null)
throw Oops.Oh($"预甩货任务主键{taskBase.PK_ID}无法获取业务信息");
model = await InnerGetInfo(rollModel);
}
catch(Exception ex)
{
_logger.LogError($"获取预甩详情异常,原因:{ex.Message}");
throw ex;
}
return model;
}
#endregion
#region 获取预甩详情
/// <summary>
/// 获取预甩详情
/// </summary>
/// <param name="rollModel">预甩货详情实体类</param>
/// <returns>返回详情</returns>
private async Task<TaskRollingNominationShowDto> InnerGetInfo(TaskRollingNominationInfo rollModel)
{
TaskRollingNominationShowDto model = null;
try
{
List<string> rollingPlanList = new List<string>();
if (!string.IsNullOrWhiteSpace(rollModel.PLAN_TXT))
{
rollingPlanList = rollModel.PLAN_TXT.Split("\\n").ToList();
}
model = new TaskRollingNominationShowDto
{
PlanType = rollModel.PLAN_TYPE,
CarrierId = rollModel.CARRIERID,
Carrier = rollModel.CARRIER,
ConfirmDeadLine = rollModel.CONFIRM_DEAD_LINE,
CreateTime = rollModel.READ_CREATE_TIME,
RollingTouchDoubleRollRemark = rollModel.ROLL_DOUBLE_REMARK,
LoadDetailList = new List<TaskRollingNominationShipDetailShowDto>(),
RollingPlanList = rollingPlanList,
PreBillList = new List<TaskRollingNominationShipPreBillShowDto>(),
NominationId = rollModel.PK_ID
};
var shipList = _taskRollingNominationShipInfoRepository.AsQueryable()
.Where(a => a.NOM_ID == rollModel.PK_ID && a.IsDeleted == false).ToList();
var fromEntity = shipList.Where(a =>
a.SHIP_TYPE.Equals("From", StringComparison.OrdinalIgnoreCase)).ToList();
if (fromEntity.Count > 0)
model.From = fromEntity.Select(p=>p.Adapt<TaskRollingNominationShipDto>()).ToList();
var toEntity = shipList.Where(a => Regex.IsMatch(a.SHIP_TYPE,"To(\\s+[0-9]+)?"
, RegexOptions.IgnoreCase)).ToList();
if (toEntity.Count > 0)
model.To = toEntity.Select(p => p.Adapt<TaskRollingNominationShipDto>()).ToList();
//优先PORT关联FROM和TO也有PORT为空的情况这种就需要用Terminal来关联
if (model.From.Any(t => string.IsNullOrWhiteSpace(t.Port)))
{
//这里为了前端原船和换船做了根据Terminal对应
model.FromToList = model.From.GroupJoin(model.To, l => l.Terminal?.Trim(), r => r.Terminal?.Trim(), (l, r) =>
{
TaskRollingNominationShipFromToDto dto = new TaskRollingNominationShipFromToDto();
dto.FromShip = l;
var currArg = r.ToList();
if (currArg.Count > 0)
{
dto.ToShipList = currArg.Select((p, idx) =>
{
if (Regex.IsMatch(p.ShipType, "[0-9]+"))
return new { SortNo = int.Parse(Regex.Match(p.ShipType, "[0-9]+").Value), Obj = p };
return new { SortNo = idx + 1, Obj = p };
}).OrderBy(p => p.SortNo).Select(p => p.Obj).ToList();
}
return dto;
}).ToList();
}
else
{
//这里为了前端原船和换船做了根据PORT对应
model.FromToList = model.From.GroupJoin(model.To, l => l.Port?.Trim(), r => r.Port?.Trim(), (l, r) =>
{
TaskRollingNominationShipFromToDto dto = new TaskRollingNominationShipFromToDto();
dto.FromShip = l;
var currArg = r.ToList();
if (currArg.Count > 0)
{
dto.ToShipList = currArg.Select((p, idx) =>
{
if (Regex.IsMatch(p.ShipType, "[0-9]+"))
return new { SortNo = int.Parse(Regex.Match(p.ShipType, "[0-9]+").Value), Obj = p };
return new { SortNo = idx + 1, Obj = p };
}).OrderBy(p => p.SortNo).Select(p => p.Obj).ToList();
}
return dto;
}).ToList();
}
List<Tuple<string, int>> tuples = new List<Tuple<string, int>>();
var withDispatchList = _taskRollingNominationDetailInfoRepository.AsQueryable().Filter(null, true)
.LeftJoin<TaskRollingNominationDispatchInfo>((detail, dispatch) => detail.PK_ID == dispatch.DETAIL_ID)
.Where((detail, dispatch) => detail.NOM_ID == rollModel.PK_ID && detail.IsDeleted == false
&& (string.IsNullOrWhiteSpace(dispatch.PK_ID) || (!string.IsNullOrWhiteSpace(dispatch.PK_ID) && dispatch.IsDeleted == false)))
.Select((detail, dispatch) => new { Detail = detail, Dispatch = dispatch }).ToList();
if (withDispatchList.Count > 0)
{
model.PreBillList = withDispatchList.Where(a => !a.Detail.NOM_STATUS_NOTE.Equals("Load",StringComparison.OrdinalIgnoreCase))
.Select((a, idx) => {
TaskRollingNominationShipPreBillShowDto preBillInfo = new TaskRollingNominationShipPreBillShowDto
{
Bookedby = a.Detail.BOOKED_BY,
ConfirmDate = a.Dispatch?.CONFIRM_DATE,
ConfirmDeadLine = a.Dispatch?.CONFIRM_DEAD_LINE,
CtnStat = $"{a.Detail.CTNALL}*{a.Detail.CTNNUM}",
CustomerId = a.Detail.CUSTOMERID,
CustomerName = a.Detail.CUSTOMERNAME,
ContractualName = a.Detail.CONTRACTUAL_NAME,
CreateShareLinkDate = a.Dispatch?.CREATE_SHARE_LINK_DATE,
DischargePortName = a.Detail.DISCHARGEPORT_NAME,
IsSend = a.Dispatch != null ? a.Dispatch.IS_SEND : false,
IsUserManual = a.Dispatch != null ? a.Dispatch.IS_USER_MANUAL : false,
LoadPortName = a.Detail.LOADPORT_NAME,
PlaceOfDelivery = a.Detail.PLACEOF_DELIVERY,
PlaceOfReceipt = a.Detail.PLACEOF_RECEIPT,
Shipment = a.Detail.SHIPMENT,
Status = a.Dispatch?.STATUS,
ShareLinkKey = a.Dispatch?.SHARE_LINK_KEY,
UserOpinion = a.Dispatch?.USER_OPINION,
UserOpinionTxt = a.Dispatch?.USER_OPINION_TXT,
BatchId = a.Dispatch?.BATCH_ID,
BookingId = a.Detail.BOOKING_ID,
GroupName = a.Detail.CUSTOMERID.HasValue ? $"CUST_{idx + 1}" : "",
CtnNote = !string.IsNullOrWhiteSpace(a.Detail.CTNNOTE) ? a.Detail.CTNNOTE : ""
};
return preBillInfo;
}).ToList();
tuples = withDispatchList.Where(a => !a.Detail.NOM_STATUS_NOTE.Equals("Load", StringComparison.OrdinalIgnoreCase))
.GroupBy(t => t.Detail.CTNALL)
.Select(t => new
{
Key = t.Key,
Num = t.ToList().Sum(x => x.Detail.CTNNUM)
}).Select(x => new Tuple<string, int>(x.Key, x.Num)).ToList();
}
if (withDispatchList.Any(a =>
a.Detail.NOM_STATUS_NOTE.Equals("Load", StringComparison.OrdinalIgnoreCase)))
{
model.LoadDetailList.AddRange(withDispatchList.Where(a =>
a.Detail.NOM_STATUS_NOTE.Equals("Load", StringComparison.OrdinalIgnoreCase))
.Select((a, idx) =>
{
return a.Detail.Adapt<TaskRollingNominationShipDetailShowDto>();
}).ToList());
}
model.TotalPreBillCtnStat = string.Join(",", tuples.GroupBy(x => x.Item1)
.Select(x =>
$"{x.Key}*{x.Sum(t => t.Item2)}").ToArray());
if (model.LoadDetailList.Count > 0)
{
model.TotalLoadCtnStat = string.Join(",", model.LoadDetailList.GroupBy(x => x.CtnAll)
.Select(x =>
$"{x.Key}*{x.Sum(t => t.CtnNum)}").ToArray());
}
}
catch (Exception ex)
{
_logger.LogError($"获取预甩详情异常,原因:{ex.Message}");
throw ex;
}
return model;
}
#endregion
#region 推送预甩货客户访问链接
/// <summary>
/// 推送预甩货客户访问链接
/// </summary>
/// <param name="nominationDispatchId">预甩货任务主键组</param>
/// <returns>返回回执</returns>
[HttpPost("/TaskManageRollingNomination/PushShareLink")]
public async Task<TaskManageOrderResultDto> PushShareLink([FromBody] string[] nominationDispatchId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"推送预甩货客户访问链接异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 生成预甩货调度
/// <summary>
/// 生成预甩货调度
/// </summary>
/// <param name="model">生成预甩货调度请求</param>
/// <returns>返回回执</returns>
[HttpPost("/TaskManageRollingNomination/DispatchRollingNomination")]
public async Task<TaskManageOrderResultDto> DispatchRollingNomination([FromBody] RollingNominationDispatchRequestDto model)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
/*
1、如果调度ID不为空标识选择新的明细替换原有的调度。
1首先匹配所选的箱型箱量是否一致装货港、卸货港必需一致不满足不能进行生成调度。
2删除原调度生成新调度。
2、如果调度ID为空标识是新增调度。
3、没有订舱ID或委托单位ID的数据不能生成调度。
*/
DateTime nowDate = DateTime.Now;
if (!model.isAdd)
{
if(string.IsNullOrWhiteSpace(model.nominationBatchId))
{
throw Oops.Oh($"改配调度需要提供预甩货调度批次ID");
}
if (model.loadDetailIds == null || model.loadDetailIds.Length == 0)
{
throw Oops.Oh($"预甩货可Load明细信息不能为空");
}
var detailList = _taskRollingNominationDetailInfoRepository.AsQueryable()
.Where(a => model.loadDetailIds.Contains(a.PK_ID) && a.IsDeleted == false).ToList();
if (detailList.Count != model.loadDetailIds.Length)
{
throw Oops.Oh($"预甩货明细部分获取失败,请重新获取预甩货明细");
}
if (detailList.Any(a => !a.BOOKING_ID.HasValue || !a.CUSTOMERID.HasValue))
{
throw Oops.Oh($"预甩货明细存在未对应订舱的记录,不能生成调度");
}
var nomId = detailList.FirstOrDefault().NOM_ID;
var nomModel = _taskRollingNominationInfoRepository.AsQueryable()
.First(a => a.PK_ID == nomId);
var shipmentList = detailList.Select(a => a.SHIPMENT).Distinct().ToList();
Dictionary<string, string> batchDict = shipmentList.Select(a => new { Key = a, BatchId = IDGen.NextID().ToString() })
.ToDictionary(a => a.Key, b => b.BatchId);
List<TaskRollingNominationDispatchInfo> dispatchList = new List<TaskRollingNominationDispatchInfo>();
List<TaskRollingNominationDetailInfo> withDispatchDetailList = new List<TaskRollingNominationDetailInfo>();
var withDispatchList = _taskRollingNominationDetailInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskRollingNominationDispatchInfo>((detail, dispatch) => detail.PK_ID == dispatch.DETAIL_ID)
.Where((detail, dispatch) => detail.PK_ID == dispatch.DETAIL_ID && detail.IsDeleted == false
&& dispatch.IsDeleted == false && dispatch.BATCH_ID == model.nominationBatchId)
.Select((detail, dispatch) => new { Detail = detail, Dispatch = dispatch }).ToList();
if (withDispatchList.Count > 0)
{
withDispatchDetailList = withDispatchList.Select(a => a.Detail)
.ToList();
}
if (dispatchList.Count == 0)
{
throw Oops.Oh($"预甩货调度获取失败,无法改配");
}
//如果原调度对应的明细含有本次提交的明细,不允许改配调度
if (withDispatchDetailList.Any(a =>
model.loadDetailIds.Any(b => b == a.PK_ID)))
{
throw Oops.Oh($"预甩货调度获取失败,提交明细已生成调度,无法改配");
}
//需要匹配箱型箱量
var origCtnStat = string.Join(",", withDispatchDetailList
.GroupBy(a => a.CTNALL).OrderBy(a => a.Key)
.Select(a => $"{a.Key}*{a.Sum(b => b.CTNNUM)}").ToArray());
detailList = _taskRollingNominationDetailInfoRepository.AsQueryable()
.Where(a => shipmentList.Contains(a.SHIPMENT) && a.IsDeleted == false && a.NOM_ID == nomId).ToList();
var targetCtnStat = string.Join(",", detailList
.GroupBy(a => a.CTNALL).OrderBy(a => a.Key)
.Select(a => $"{a.Key}*{a.Sum(b => b.CTNNUM)}").ToArray());
//如果箱型箱量不一致不能改配
if (!origCtnStat.Equals(targetCtnStat))
{
throw Oops.Oh($"预甩货调度获取失败,提交明细箱型箱量于被改配调度不一致,无法改配");
}
var origShip = withDispatchDetailList.FirstOrDefault();
var targetShip = detailList.FirstOrDefault();
var origKey = $"{origShip.PLACEOF_RECEIPT}_{origShip.LOADPORT_NAME}_{origShip.DISCHARGEPORT_NAME}_{origShip.PLACEOF_DELIVERY}";
var targeKey = $"{targetShip.PLACEOF_RECEIPT}_{targetShip.LOADPORT_NAME}_{targetShip.DISCHARGEPORT_NAME}_{targetShip.PLACEOF_DELIVERY}";
//收货地、装货港、卸货港、交货地必需一致
if (!origKey.Equals(targeKey))
{
throw Oops.Oh($"预甩货调度获取失败,提交明细收货地、装货港、卸货港、交货地被改配调度不一致,无法改配");
}
//删除原调度
withDispatchList.ForEach(async a =>
{
a.Dispatch.IsDeleted = true;
a.Dispatch.UpdatedTime = nowDate;
a.Dispatch.UpdatedUserId = UserManager.UserId;
a.Dispatch.UpdatedUserName = UserManager.Name;
await _taskRollingNominationDispatchInfoRepository.AsUpdateable(a.Dispatch)
.UpdateColumns(it => new
{
it.IsDeleted,
it.UpdatedTime,
it.UpdatedUserId,
it.UpdatedUserName
}).ExecuteCommandAsync();
});
//写入新调度
detailList.ForEach(a =>
{
TaskRollingNominationDispatchInfo dispatchInfo = new TaskRollingNominationDispatchInfo
{
PK_ID = IDGen.NextID().ToString(),
CreatedTime = nowDate,
UpdatedTime = nowDate,
CreatedUserId = UserManager.UserId,
CreatedUserName = UserManager.Name,
DETAIL_ID = a.PK_ID,
NOM_ID = a.NOM_ID,
NOM_SHIP_ID = a.NOM_SHIP_ID,
IsDeleted = false,
STATUS = "WAIT",
TASK_ID = nomModel.TASK_ID,
TenantId = UserManager.TENANT_ID,
TenantName = UserManager.TENANT_NAME,
BATCH_ID = batchDict[a.SHIPMENT],
};
_taskRollingNominationDispatchInfoRepository.Insert(dispatchInfo);
});
}
else
{
var withDispatchList =
_taskRollingNominationInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskRollingNominationDetailInfo>((nom, detail) => nom.PK_ID == detail.NOM_ID)
.LeftJoin<TaskRollingNominationDispatchInfo>((nom, detail, dispatch) =>
detail.PK_ID == dispatch.DETAIL_ID && dispatch.IsDeleted == false)
.Where((nom, detail, dispatch) =>
detail.IsDeleted == false
&& detail.NOM_ID == model.nominationId)
.Select((nom, detail, dispatch) =>
new { Nom = nom, Detail = detail, Dispatch = dispatch }).ToList();
if (withDispatchList.Any(p => p.Dispatch != null
&& !string.IsNullOrWhiteSpace(p.Dispatch.PK_ID)))
{
throw Oops.Oh($"预甩货明细已生成调度不能重复");
}
var nomiInfo = withDispatchList.FirstOrDefault().Nom;
var shipmentList = withDispatchList
.Select(a => a.Detail.SHIPMENT)
.Distinct().ToList();
Dictionary<string, string> batchDict = shipmentList.Select(a => new { Key = a, BatchId = IDGen.NextID().ToString() })
.ToDictionary(a => a.Key, b => b.BatchId);
DateTime deadLine = nomiInfo.CONFIRM_DEAD_LINE.Value.AddHours(2);
//开始写入调度
withDispatchList.ForEach(info =>
{
var a = info.Detail;
if (!a.NOM_STATUS_NOTE.Equals("Load", StringComparison.OrdinalIgnoreCase))
{
TaskRollingNominationDispatchInfo dispatchInfo = new TaskRollingNominationDispatchInfo
{
PK_ID = IDGen.NextID().ToString(),
CreatedTime = nowDate,
UpdatedTime = nowDate,
CreatedUserId = UserManager.UserId,
CreatedUserName = UserManager.Name,
DETAIL_ID = a.PK_ID,
NOM_ID = a.NOM_ID,
NOM_SHIP_ID = a.NOM_SHIP_ID,
IsDeleted = false,
STATUS = RollingNominationDispatchStatusEnum.WAIT.ToString(),
TASK_ID = nomiInfo.TASK_ID,
TenantId = UserManager.TENANT_ID,
TenantName = UserManager.TENANT_NAME,
BATCH_ID = batchDict[a.SHIPMENT],
CONFIRM_DEAD_LINE = deadLine
};
_taskRollingNominationDispatchInfoRepository.Insert(dispatchInfo);
}
});
}
result.succ = true;
result.msg = "成功";
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"生成预甩货调度异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 刷新预甩货对应订舱
/// <summary>
/// 刷新预甩货对应订舱
/// </summary>
/// <param name="taskPkId">预甩货主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageRollingNomination/RefreshBookingOrder")]
public async Task<TaskManageOrderResultDto> RefreshBookingOrder(string taskPkId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
/*
获取所有当票预甩的所有没有BOOKING_ID的明细记录并用SHIPMENT(提单号),检索订舱数据,能匹配的更新
*/
var list = _taskRollingNominationInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskRollingNominationDetailInfo>((nom, detail) => nom.PK_ID == detail.NOM_ID)
.Where((nom, detail) => nom.TASK_ID == taskPkId
&& detail.IsDeleted == false && !detail.BOOKING_ID.HasValue)
.Select((nom, detail) => detail).ToList();
if (list.Count > 0)
{
var mblNoArg = list.Select(a => a.SHIPMENT?.Trim()).Distinct().ToList();
var orderList = _bookingOrderRepository.AsQueryable()
.Where(a => mblNoArg.Contains(a.MBLNO) && (a.ParentId == null || a.ParentId == 0) && a.IsDeleted == false).ToList();
DateTime nowDate = DateTime.Now;
if (orderList.Count > 0)
{
orderList.ForEach(ord =>
{
var dlist = list.Where(b => b.SHIPMENT.Equals(ord.MBLNO)).ToList();
if (dlist.Count > 0)
{
dlist.ForEach(dt =>
{
dt.BOOKING_ID = ord.Id;
dt.UpdatedTime = nowDate;
dt.UpdatedUserId = UserManager.UserId;
dt.UpdatedUserName = UserManager.Name;
_taskRollingNominationDetailInfoRepository.AsUpdateable(dt)
.UpdateColumns(it => new
{
it.BOOKING_ID,
it.UpdatedTime,
it.UpdatedUserId,
it.UpdatedUserName
}).ExecuteCommand();
});
}
});
}
}
result.succ = true;
result.msg = "对应订舱完成";
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"刷新预甩货对应订舱异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 查看分享链接
/// <summary>
/// 查看分享链接
/// </summary>
/// <param name="dispatchBatchId">预甩调度批次号</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageRollingNomination/GetUrl")]
public async Task<TaskManageOrderResultDto> GetUrl(string dispatchBatchId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
/*
用预甩调度的dispatchBatchId关联分享表的BUSI_ID获取分享KEY
*/
if (string.IsNullOrWhiteSpace(dispatchBatchId))
throw Oops.Oh($"预甩调度批次号不能为空");
var dispatchInfo = _taskRollingNominationDispatchInfoRepository.AsQueryable()
.First(a => a.BATCH_ID == dispatchBatchId);
if (dispatchInfo == null)
{
throw Oops.Oh($"获取预甩调度信息失败,不存在或已作废");
}
if(string.IsNullOrWhiteSpace(dispatchInfo.SHARE_LINK_KEY))
throw Oops.Oh($"链接访问KEY不存在请生成分享链接");
string[] statusArg = new string[] { RollingNominationDispatchStatusEnum.CANCEL.ToString(),
RollingNominationDispatchStatusEnum.EXPIRE.ToString() };
if (statusArg.Any(a => a.Equals(dispatchInfo.STATUS, StringComparison.OrdinalIgnoreCase)))
throw Oops.Oh($"链接访问KEY状态不可用");
result.succ = true;
result.ext = dispatchInfo.SHARE_LINK_KEY;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"推送预甩货客户访问链接异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 获取Status是load的可配载的列表
/// <summary>
/// 获取Status是load的可配载的列表
/// </summary>
/// <param name="taskPkId">预甩货任务主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageRollingNomination/GetLoadStatusDetailList")]
public async Task<TaskManageOrderResultDto> GetLoadStatusDetailList(string taskPkId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var withDispatchList =
_taskRollingNominationInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskRollingNominationDetailInfo>((nom,detail)=> nom.PK_ID == detail.NOM_ID)
.LeftJoin<TaskRollingNominationDispatchInfo>((nom,detail, dispatch) =>
detail.PK_ID == dispatch.DETAIL_ID && dispatch.IsDeleted == false)
.Where((nom,detail, dispatch) =>
nom.TASK_ID == taskPkId && detail.IsDeleted == false && string.IsNullOrWhiteSpace(dispatch.TASK_ID))
.Select((nom, detail, dispatch) => new { Detail = detail}).ToList();
if (withDispatchList.Count > 0)
{
result.ext = withDispatchList.Select(a => a.Detail.Adapt<TaskRollingNominationShipDetailShowDto>()).ToList();
}
result.succ = true;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"推送预甩货客户访问链接异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 获取提单号下预甩货的单票明细
/// <summary>
/// 获取提单号下预甩货的单票明细
/// </summary>
/// <param name="nominationId">预甩货主键</param>
/// <param name="shipmentNo">提单号</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageRollingNomination/GetPreBillDetailList")]
public async Task<TaskManageOrderResultDto> GetPreBillDetailList([FromQuery] string nominationId, [FromQuery] string shipmentNo)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var withDispatchList =
_taskRollingNominationInfoRepository.AsQueryable()
.InnerJoin<TaskRollingNominationDetailInfo>((nom, detail) => nom.PK_ID == detail.NOM_ID)
.Where((nom, detail) =>
nom.PK_ID == nominationId && detail.IsDeleted == false && detail.SHIPMENT == shipmentNo)
.Select((nom, detail) => new { Detail = detail }).ToList();
if (withDispatchList.Count > 0)
{
result.ext = withDispatchList.Select(a => a.Detail.Adapt<TaskRollingNominationShipDetailShowDto>()).ToList();
}
result.succ = true;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"获取提单号下预甩货的单票明细异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 保存预甩货明细箱型信息
/// <summary>
/// 保存预甩货明细箱型信息(处理没有给箱型高度或者未能翻译的箱型,进行人工修正)
/// </summary>
/// <param name="model">保存预甩货明细箱型请求</param>
/// <returns>返回回执</returns>
[HttpPost("/TaskManageRollingNomination/SaveDetailContainer")]
public async Task<TaskManageOrderResultDto> SaveDetailContainer(SaveDetailContainerDto model)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
if (string.IsNullOrWhiteSpace(model.ctnCode))
{
throw Oops.Oh($"请求的箱型代码不能为空");
}
var detailInfo = _taskRollingNominationDetailInfoRepository.AsQueryable()
.First(a => a.PK_ID == model.detailPKId && a.IsDeleted == false);
if (detailInfo == null)
throw Oops.Oh($"预甩货明细主键{model.detailPKId}无法获取业务信息");
var ctnCodeList = _cache.GetAllCodeCtn().GetAwaiter().GetResult().ToList();
var ctnCodeModel = ctnCodeList.FirstOrDefault(a => !string.IsNullOrWhiteSpace(a.Name) &&
a.Code.Equals(model.ctnCode, StringComparison.OrdinalIgnoreCase));
if (ctnCodeModel == null)
throw Oops.Oh($"请求的箱型代码基础数据不存在,请修改");
detailInfo.CTNCODE = ctnCodeModel.Code;
detailInfo.CTNALL = ctnCodeModel.Name;
detailInfo.UpdatedTime = DateTime.Now;
detailInfo.UpdatedUserId = UserManager.UserId;
detailInfo.UpdatedUserName = UserManager.Name;
await _taskRollingNominationDetailInfoRepository.AsUpdateable(detailInfo).UpdateColumns(it => new
{
it.CTNCODE,
it.CTNALL,
it.UpdatedTime,
it.UpdatedUserId,
it.UpdatedUserName
}).ExecuteCommandAsync();
result.succ = true;
result.msg = "成功";
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"保存预甩货明细箱型信息异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 生成访问链接
/// <summary>
/// 生成访问链接
/// </summary>
/// <param name="model">创建分享链接请求</param>
/// <returns>返回回执</returns>
[HttpPost("/TaskManageRollingNomination/GenShareLink")]
public async Task<TaskManageOrderResultDto> GenShareLink(RollingNominationGenShareLinkDto model)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
if (string.IsNullOrWhiteSpace(model.dispatchBatchId))
{
throw Oops.Oh($"预甩调度批次ID不能为空");
}
var list = _taskRollingNominationDispatchInfoRepository.AsQueryable()
.Where(a => a.BATCH_ID == model.dispatchBatchId).ToList();
if(list.Count == 0)
throw Oops.Oh($"预甩调度批次ID无法获取业务信息");
var taskInfo = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == list.FirstOrDefault().TASK_ID);
ShareLinkRequestDto reqDto = new ShareLinkRequestDto {
businessId = model.dispatchBatchId,
businessType = "NOMI_DISPATCH",
expireDate = list.FirstOrDefault().CONFIRM_DEAD_LINE.Value.ToString("yyyy-MM-dd HH:mm:ss"),
isUserFeedBack = true,
taskType = taskInfo.TASK_BASE_TYPE,
isRenew = model.isRenew
};
var service = _namedServiceProvider.GetService(nameof(TaskManageShareLinkService));
result = await service.CreateShareLink(reqDto);
if(result.succ)
{
DateTime nowDate = DateTime.Now;
string shareKey = result.ext.ToString();
list.ForEach(p => {
p.SHARE_LINK_KEY = shareKey;
p.CREATE_SHARE_LINK_DATE = nowDate;
p.UpdatedTime = nowDate;
p.UpdatedUserId = UserManager.UserId;
p.UpdatedUserName = UserManager.Name;
_taskRollingNominationDispatchInfoRepository.AsUpdateable(p)
.UpdateColumns(it => new
{
it.SHARE_LINK_KEY,
it.CREATE_SHARE_LINK_DATE,
it.UpdatedTime,
it.UpdatedUserId,
it.UpdatedUserName
}).ExecuteCommandAsync();
});
}
}
catch(Exception ex)
{
result.succ = false;
result.msg = $"生成访问链接异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 取消访问链接
/// <summary>
/// 取消访问链接
/// </summary>
/// <param name="dispatchBatchId">预甩调度批次ID</param>
/// <returns>返回回执</returns>
[HttpPost("/TaskManageRollingNomination/CancelShareLink")]
public async Task<TaskManageOrderResultDto> CancelShareLink(string dispatchBatchId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
if (string.IsNullOrWhiteSpace(dispatchBatchId))
{
throw Oops.Oh($"预甩调度批次ID不能为空");
}
var list = _taskRollingNominationDispatchInfoRepository.AsQueryable()
.Where(a => a.BATCH_ID == dispatchBatchId).ToList();
if (list.Count == 0)
throw Oops.Oh($"预甩调度批次ID无法获取业务信息");
var service = _namedServiceProvider.GetService(nameof(TaskManageShareLinkService));
result = await service.CancelShareLink(dispatchBatchId);
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"取消访问链接异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 获取用户反馈信息
/// <summary>
/// 获取用户反馈信息
/// </summary>
/// <param name="dispatchBatchId">预甩调度批次ID</param>
/// <returns>返回回执</returns>
[HttpPost("/TaskManageRollingNomination/GetUserFeedBack")]
public async Task<TaskManageOrderResultDto> GetUserFeedBack(string dispatchBatchId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
if (string.IsNullOrWhiteSpace(dispatchBatchId))
{
throw Oops.Oh($"预甩调度批次ID不能为空");
}
var list = _taskRollingNominationDispatchInfoRepository.AsQueryable()
.Where(a => a.BATCH_ID == dispatchBatchId).ToList();
if (list.Count == 0)
throw Oops.Oh($"预甩调度批次ID无法获取业务信息");
result.succ = true;
result.ext = new
{
userOpinion = list.FirstOrDefault().USER_OPINION,
userOpinionTxt = list.FirstOrDefault().USER_OPINION_TXT
};
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"获取用户反馈信息异常,原因:{ex.Message}";
}
return result;
}
#endregion
/// <summary>
/// 发送预甩的通知
/// </summary>
/// <param name="model">请求详情</param>
/// <returns></returns>
[HttpPost("/TaskManageRollingNomination/SendRollingNominationNotice")]
public async Task<TaskManageOrderResultDto> SendRollingNominationNotice(RollingNominationNoticeDto model)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
if (string.IsNullOrWhiteSpace(model.taskId))
{
throw Oops.Oh($"预甩任务ID不能为空");
}
var printTemplate = await _repPrintTemplate.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == model.templateId && x.TenantId == UserManager.TENANT_ID);
if (printTemplate == null)
{
throw Oops.Bah(BookingErrorCode.BOOK115);
}
if (string.IsNullOrWhiteSpace(printTemplate.CateCode) || !printTemplate.CateCode.Contains("rolling_nomination_notice_template"))
{
throw Oops.Bah("模板类型分类错误,当前只支持预甩邮件通知");
}
string html = string.Empty;
var list = _taskRollingNominationDetailInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskRollingNominationInfo>((detail, norm) => detail.NOM_ID == norm.PK_ID)
.Where((detail, norm) => norm.TASK_ID == model.taskId && detail.IsDeleted == false && norm.IsDeleted == false)
.Select((detail, norm) => detail).ToList();
var shipList = _taskRollingNominationShipInfoRepository.AsQueryable().Filter(null, true).Where(p => (p.PK_ID.Equals(model.fromShipPKId) || p.PK_ID.Equals(model.toShipPKId))
&& p.IsDeleted == false).ToList();
var fromShipInfo = shipList.FirstOrDefault(p => p.PK_ID == model.fromShipPKId);
if (fromShipInfo == null)
throw Oops.Bah("当前预甩原船信息获取失败");
var toShipInfo = shipList.FirstOrDefault(p => p.PK_ID == model.toShipPKId);
if (fromShipInfo == null)
throw Oops.Bah("当前预甩换船信息获取失败");
BookingOrder bookingOrderEntity = null;
if (list.Any(p => p.BOOKING_ID.HasValue))
{
var bookingId = list.FirstOrDefault().BOOKING_ID.Value;
//读取订舱数据
bookingOrderEntity = _bookingOrderRepository.AsQueryable().Filter(null, true)
.First(a => a.Id == bookingId);
}
if (bookingOrderEntity == null)
throw Oops.Bah("当前预甩没有对应的订舱信息,请先生成订舱订单才能转发邮件");
SysUser opUserInfo = null;
if (!string.IsNullOrWhiteSpace(bookingOrderEntity.OPID) && Regex.IsMatch(bookingOrderEntity.OPID, "[0-9]+"))
{
opUserInfo = _sysUserRepository.AsQueryable().Filter(null, true).First(u => u.Id == long.Parse(bookingOrderEntity.OPID));
}
if (opUserInfo == null)
throw Oops.Bah("当前预甩对应的订舱信息未指定操作OP不能转发邮件");
html = GenerateTemplateHtml(printTemplate.FilePath, fromShipInfo, toShipInfo, opUserInfo, UserManager.TENANT_NAME);
if(string.IsNullOrWhiteSpace(html))
throw Oops.Bah("生成预甩邮件通知正文失败,未生成有效信息");
//TO 邮件接收人
string toEmail = string.Empty;
//订舱OP的邮箱
string opEmail = string.Empty;
var bookingContactList = _bookingOrderContactRepository.AsQueryable().Filter(null, true)
.Where(a => a.BookingId == bookingOrderEntity.Id && a.IsDeleted == false).ToList();
if (bookingContactList == null || bookingContactList.Count == 0)
{
_logger.LogInformation($"当前订舱未指定的联系人toEmail={toEmail}");
}
toEmail = string.Join(";", bookingContactList.Select(x => x.Email.Trim()).Distinct().ToArray());
//获取操作OP的邮箱
if (!string.IsNullOrWhiteSpace(bookingOrderEntity.OPID))
{
var opId = long.Parse(bookingOrderEntity.OPID);
var opUser = _sysUserRepository.AsQueryable().Filter(null, true).First(a => a.Id == opId);
if (opUser != null && !string.IsNullOrWhiteSpace(opUser.Email))
{
opEmail = opUser.Email.Trim();
_logger.LogInformation($"获取操作OP的邮箱opEmail={opEmail} id={opId} name={opUser.Name}");
}
}
//推送邮件
var opt = App.GetOptions<BookingAttachOptions>();
var dirAbs = opt.basePath;
if (string.IsNullOrEmpty(dirAbs))
{
dirAbs = App.WebHostEnvironment.WebRootPath;
}
string emailTitle = $"【预甩通知】{list.FirstOrDefault().SHIPMENT} 原船名/航次 {fromShipInfo.VESSEL}/{fromShipInfo.VOYNO}";
var sendRlt = await SendEmail(emailTitle, html, toEmail, opEmail, list.FirstOrDefault().SHIPMENT);
if (sendRlt.succ)
{
result.succ = true;
result.msg = "成功";
}
else
{
result.succ = false;
result.msg = sendRlt.msg;
new EmailNoticeHelper().SendEmailNotice($"MBLNO={list.FirstOrDefault().SHIPMENT} 发送预甩的通知失败", $"MBLNO={list.FirstOrDefault().SHIPMENT} 发送预甩的通知失败,原因:{sendRlt.msg}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
}
result.succ = true;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"发送预甩的通知失败,原因:{ex.Message}";
}
return result;
}
#region 获取预甩的通知预览
/// <summary>
/// 获取预甩的通知预览
/// </summary>
/// <param name="model">请求详情</param>
/// <returns></returns>
[HttpPost("/TaskManageRollingNomination/GetRollingNominationNoticeReview")]
public async Task<TaskManageOrderResultDto> GetRollingNominationNoticeReview(RollingNominationNoticeDto model)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
if (string.IsNullOrWhiteSpace(model.taskId))
{
throw Oops.Oh($"预甩任务ID不能为空");
}
var printTemplate = await _repPrintTemplate.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == model.templateId && x.TenantId == UserManager.TENANT_ID);
if (printTemplate == null)
{
throw Oops.Bah(BookingErrorCode.BOOK115);
}
if (string.IsNullOrWhiteSpace(printTemplate.CateCode) || !printTemplate.CateCode.Contains("rolling_nomination_notice_template"))
{
throw Oops.Bah("模板类型分类错误,当前只支持预甩邮件通知");
}
string html = string.Empty;
var list = _taskRollingNominationDetailInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskRollingNominationInfo>((detail, norm) => detail.NOM_ID == norm.PK_ID)
.Where((detail, norm) => norm.TASK_ID == model.taskId && detail.IsDeleted == false && norm.IsDeleted == false)
.Select((detail, norm) => detail).ToList();
var shipList = _taskRollingNominationShipInfoRepository.AsQueryable().Filter(null, true).Where(p => (p.PK_ID.Equals(model.fromShipPKId) || p.PK_ID.Equals(model.toShipPKId))
&& p.IsDeleted == false).ToList();
var fromShipInfo = shipList.FirstOrDefault(p => p.PK_ID == model.fromShipPKId);
if (fromShipInfo == null)
throw Oops.Bah("当前预甩原船信息获取失败");
var toShipInfo = shipList.FirstOrDefault(p => p.PK_ID == model.toShipPKId);
if (fromShipInfo == null)
throw Oops.Bah("当前预甩换船信息获取失败");
BookingOrder bookingOrderEntity = null;
if (list.Any(p => p.BOOKING_ID.HasValue))
{
var bookingId = list.FirstOrDefault().BOOKING_ID.Value;
//读取订舱数据
bookingOrderEntity = _bookingOrderRepository.AsQueryable().Filter(null, true)
.First(a => a.Id == bookingId);
}
if (bookingOrderEntity == null)
throw Oops.Bah("当前预甩没有对应的订舱信息,请先生成订舱订单才能转发邮件");
SysUser opUserInfo = null;
if (!string.IsNullOrWhiteSpace(bookingOrderEntity.OPID) && Regex.IsMatch(bookingOrderEntity.OPID, "[0-9]+"))
{
opUserInfo = _sysUserRepository.AsQueryable().Filter(null, true).First(u => u.Id == long.Parse(bookingOrderEntity.OPID));
}
if (opUserInfo == null)
throw Oops.Bah("当前预甩对应的订舱信息未指定操作OP不能转发邮件");
html = GenerateTemplateHtml(printTemplate.FilePath, fromShipInfo, toShipInfo, opUserInfo, UserManager.TENANT_NAME);
result.succ = true;
result.ext = html;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"取消获取预甩的通知预览异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 获取换船选择列表
/// <summary>
/// 获取换船选择列表
/// </summary>
/// <param name="taskPkId">任务ID</param>
/// <returns></returns>
[HttpGet("/TaskManageRollingNomination/GetToShipSelect")]
public async Task<TaskManageOrderResultDto> GetToShipSelect(string taskPkId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
List<TaskRollingNominationShipFromToDto> fromToList = new List<TaskRollingNominationShipFromToDto>();
try
{
var list = _taskRollingNominationDetailInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskRollingNominationInfo>((detail, norm) => detail.NOM_ID == norm.PK_ID)
.Where((detail, norm) => norm.TASK_ID == taskPkId && detail.IsDeleted == false && norm.IsDeleted == false)
.Select((detail, norm) => detail).ToList();
if (list.Count == 0)
throw Oops.Oh($"预甩货任务主键{taskPkId}无法获取业务信息");
TaskRollingNominationShowDto model = new TaskRollingNominationShowDto();
var shipList = _taskRollingNominationShipInfoRepository.AsQueryable()
.Where(a => a.NOM_ID == list.FirstOrDefault().NOM_ID && a.IsDeleted == false).ToList();
var fromEntity = shipList.Where(a =>
a.SHIP_TYPE.Equals("From", StringComparison.OrdinalIgnoreCase)).ToList();
if (fromEntity.Count > 0)
model.From = fromEntity.Select(p => p.Adapt<TaskRollingNominationShipDto>()).ToList();
model.LoadDetailList = list.Select(a => a.Adapt<TaskRollingNominationShipDetailShowDto>()).ToList();
if (model.From != null && model.From.Count > 1)
{
var firstLoadDetail = model.LoadDetailList.FirstOrDefault();
if (model.From.Any(t => string.IsNullOrWhiteSpace(t.Port)))
{
model.From = model.From.Where(a => a.Terminal.Contains(firstLoadDetail.LoadPortName?.Trim())).ToList();
}
else
{
model.From = model.From.Where(a => a.Port.Equals(firstLoadDetail.LoadPortName?.Trim(),StringComparison.OrdinalIgnoreCase)).ToList();
}
}
var toEntity = shipList.Where(a => Regex.IsMatch(a.SHIP_TYPE, "To(\\s+[0-9]+)?"
, RegexOptions.IgnoreCase)).ToList();
if (toEntity.Count > 0)
model.To = toEntity.Select(p => p.Adapt<TaskRollingNominationShipDto>()).ToList();
//优先PORT关联FROM和TO也有PORT为空的情况这种就需要用Terminal来关联
if (model.From.Any(t => string.IsNullOrWhiteSpace(t.Port)))
{
//这里为了前端原船和换船做了根据Terminal对应
fromToList = model.From.GroupJoin(model.To, l => l.Terminal?.Trim(), r => r.Terminal?.Trim(), (l, r) =>
{
TaskRollingNominationShipFromToDto dto = new TaskRollingNominationShipFromToDto();
dto.FromShip = l;
var currArg = r.ToList();
if (currArg.Count > 0)
{
dto.ToShipList = currArg.Select((p, idx) =>
{
if (Regex.IsMatch(p.ShipType, "[0-9]+"))
return new { SortNo = int.Parse(Regex.Match(p.ShipType, "[0-9]+").Value), Obj = p };
return new { SortNo = idx + 1, Obj = p };
}).OrderBy(p => p.SortNo).Select(p => p.Obj).ToList();
}
return dto;
}).ToList();
}
else
{
//这里为了前端原船和换船做了根据PORT对应
fromToList = model.From.GroupJoin(model.To, l => l.Port?.Trim(), r => r.Port?.Trim(), (l, r) =>
{
TaskRollingNominationShipFromToDto dto = new TaskRollingNominationShipFromToDto();
dto.FromShip = l;
var currArg = r.ToList();
if (currArg.Count > 0)
{
dto.ToShipList = currArg.Select((p, idx) =>
{
if (Regex.IsMatch(p.ShipType, "[0-9]+"))
return new { SortNo = int.Parse(Regex.Match(p.ShipType, "[0-9]+").Value), Obj = p };
return new { SortNo = idx + 1, Obj = p };
}).OrderBy(p => p.SortNo).Select(p => p.Obj).ToList();
}
return dto;
}).ToList();
}
List<Tuple<string, int>> tuples = new List<Tuple<string, int>>();
model.FromToList = new List<TaskRollingNominationShipFromToDto>();
if (model.LoadDetailList.Count > 0)
{
model.TotalLoadCtnStat = string.Join(",", model.LoadDetailList.GroupBy(x => x.CtnAll)
.Select(x =>
$"{x.Key}*{x.Sum(t => t.CtnNum)}").ToArray());
string rollRegex = "Roll\\s+to\\s+\\w+\\s+\\w{3,}\\/\\w+,\\s?if\\s+cannot\\s+catch\\s?,\\s+roll\\s+to\\s+\\w{3,}\\s+next\\s+sailing";
string rollontoRegex = "Roll\\s+onto\\s+\\w{3,}\\s+\\w+,\\s+[0-9]+\\s+days\\s+delay\\.";
bool isSelectRoll = false;
bool isRoll = false;
bool isRollOnto = false;
model.LoadDetailList.ForEach(p =>
{
string vslCode = string.Empty;
string voyNo = string.Empty;
string strCode = string.Empty;
string strCode2 = string.Empty;
if (Regex.IsMatch(p.Status, rollRegex, RegexOptions.IgnoreCase))
{
string currS = Regex.Match(p.Status, "(?<=Roll\\sto\\s\\w+\\s)\\w{3,}\\/\\w+(?=,)").Value;
vslCode = Regex.Split(currS, "\\/")[0]?.Trim();
voyNo = Regex.Split(currS, "\\/")[1]?.Trim();
strCode = Regex.Match(p.Status, "(?<=if\\scannot\\scatch\\s?,\\sroll\\sto\\s)\\w{3,}(?=\\s+next\\s+sailing)").Value?.Trim();
isSelectRoll = true;
}
else if (p.Status.Trim().Equals("roll", StringComparison.OrdinalIgnoreCase))
{
isRoll = true;
}
else if (Regex.IsMatch(p.Status, rollontoRegex, RegexOptions.IgnoreCase))
{
vslCode = Regex.Match(p.Status, "(?<=Roll\\sonto\\s)\\w{3,}(?=\\s+\\w+,)").Value?.Trim();
isRollOnto = true;
}
for (int i = 0; i < fromToList.Count; i++)
{
if (!string.IsNullOrWhiteSpace(fromToList[i].FromShip.Port))
{
if (fromToList[i].FromShip.Port.Equals(p.PlaceOfReceipt, StringComparison.OrdinalIgnoreCase))
{
var fromInfo = fromToList[i].FromShip.Adapt<TaskRollingNominationShipDto>();
List<TaskRollingNominationShipDto> toShipList = new List<TaskRollingNominationShipDto>();
if (isSelectRoll)
{
for (int j = 0; j < fromToList[i].ToShipList.Count; j++)
{
if (fromToList[i].ToShipList[j].VslCode.Equals(vslCode, StringComparison.OrdinalIgnoreCase))
{
toShipList.Add(fromToList[i].ToShipList[j].Adapt<TaskRollingNominationShipDto>());
}
else if (fromToList[i].ToShipList[j].ShipString.Equals(strCode, StringComparison.OrdinalIgnoreCase))
{
toShipList.Add(fromToList[i].ToShipList[j].Adapt<TaskRollingNominationShipDto>());
}
}
}
else if (isRoll)
{
for (int j = 0; j < fromToList[i].ToShipList.Count; j++)
{
if (fromToList[i].ToShipList[j].Port.Equals(p.PlaceOfDelivery?.Trim(), StringComparison.OrdinalIgnoreCase))
{
toShipList.Add(fromToList[i].ToShipList[j].Adapt<TaskRollingNominationShipDto>());
}
}
}
if (toShipList.Count == 0)
{
if (fromToList[i].ToShipList.Count == 1)
{
toShipList.Add(fromToList[i].ToShipList.FirstOrDefault().Adapt<TaskRollingNominationShipDto>());
}
}
model.FromToList.Add(new TaskRollingNominationShipFromToDto
{
FromShip = fromInfo,
ToShipList = toShipList
});
}
}
else
{
if (fromToList[i].FromShip.Terminal.Contains(p.PlaceOfReceipt, StringComparison.OrdinalIgnoreCase))
{
var fromInfo = fromToList[i].FromShip.Adapt<TaskRollingNominationShipDto>();
List<TaskRollingNominationShipDto> toShipList = new List<TaskRollingNominationShipDto>();
if (isRollOnto)
{
for (int j = 0; j < fromToList[i].ToShipList.Count; j++)
{
if (fromToList[i].ToShipList[j].VslCode.Equals(vslCode, StringComparison.OrdinalIgnoreCase))
{
toShipList.Add(fromToList[i].ToShipList[j].Adapt<TaskRollingNominationShipDto>());
}
}
}
model.FromToList.Add(new TaskRollingNominationShipFromToDto
{
FromShip = fromInfo,
ToShipList = toShipList
});
}
}
}
});
}
result.succ = true;
result.ext = fromToList;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"获取换船选择列表异常,原因:{ex.Message}";
}
return result;
}
#endregion
#region 通过邮件模板生成预甩邮件通知内容
/// <summary>
/// 通过邮件模板生成预甩邮件通知内容
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="fromShipInfo">原船详情</param>
/// <param name="toShipInfo">换船详情</param>
/// <param name="opUserInfo">操作OP详情</param>
/// <param name="tenantName">租户名称</param>
/// <returns>返回生成后邮件正文</returns>
private string GenerateTemplateHtml(string filePath, TaskRollingNominationShipInfo fromShipInfo, TaskRollingNominationShipInfo toShipInfo,
SysUser opUserInfo, string tenantName)
{
string result = string.Empty;
string baseHtml = string.Empty;
try
{
var opt = App.GetOptions<PrintTemplateOptions>();
var dirAbs = opt.basePath;
if (string.IsNullOrEmpty(dirAbs))
{
dirAbs = App.WebHostEnvironment.WebRootPath;
}
var fileAbsPath = Path.Combine(dirAbs, filePath);
_logger.LogInformation($"查找模板文件:{fileAbsPath}");
if (!File.Exists(fileAbsPath))
{
throw Oops.Bah(BookingErrorCode.BOOK115);
}
baseHtml = File.ReadAllText(fileAbsPath);
if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Name))
{
baseHtml = baseHtml.Replace("#opname#", opUserInfo.Name);
}
else
{
baseHtml = baseHtml.Replace("#opname#", "操作");
}
if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Email))
{
baseHtml = baseHtml.Replace("#opemail#", opUserInfo.Email);
}
else
{
baseHtml = baseHtml.Replace("#opemail#", "");
}
if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Phone))
{
baseHtml = baseHtml.Replace("#optel#", opUserInfo.Phone);
}
else if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Tel))
{
baseHtml = baseHtml.Replace("#optel#", opUserInfo.Tel);
}
else
{
baseHtml = baseHtml.Replace("#optel#", "");
}
//原船
if (fromShipInfo.ETD.HasValue && fromShipInfo.ETD.Value != DateTime.MinValue)
{
baseHtml = baseHtml.Replace("#ETD#", fromShipInfo.ETD.Value.ToString("yyyy-MM-dd"));
}
else
{
baseHtml = baseHtml.Replace("#ETD#", "");
}
//原船
if (!string.IsNullOrWhiteSpace(fromShipInfo.VESSEL) && !string.IsNullOrWhiteSpace(fromShipInfo.VOYNO))
{
baseHtml = baseHtml.Replace("#VesselVoyno#", $"{fromShipInfo.VESSEL}/{fromShipInfo.VOYNO}");
}
else
{
baseHtml = baseHtml.Replace("#VesselVoyno#", "");
}
//换船
if (toShipInfo.ETD.HasValue && toShipInfo.ETD.Value != DateTime.MinValue)
{
baseHtml = baseHtml.Replace("#newETD#", toShipInfo.ETD.Value.ToString("yyyy-MM-dd"));
}
else
{
baseHtml = baseHtml.Replace("#newETD#", "");
}
//换船
if (!string.IsNullOrWhiteSpace(toShipInfo.VESSEL) && !string.IsNullOrWhiteSpace(toShipInfo.VOYNO))
{
baseHtml = baseHtml.Replace("#newVesselVoyno#", $"{toShipInfo.VESSEL}/{toShipInfo.VOYNO}");
}
else
{
baseHtml = baseHtml.Replace("#newVesselVoyno#", "");
}
//换船
if (toShipInfo.SI_CUT_DATE.HasValue && toShipInfo.SI_CUT_DATE.Value != DateTime.MinValue)
{
baseHtml = baseHtml.Replace("#CutSingleTime#", toShipInfo.SI_CUT_DATE.Value.ToString("yyyy-MM-dd"));
}
else
{
baseHtml = baseHtml.Replace("#CutSingleTime#", "");
}
if (!string.IsNullOrWhiteSpace(tenantName))
{
baseHtml = baseHtml.Replace("#TenantCompanyName#", tenantName);
}
else
{
baseHtml = baseHtml.Replace("#TenantCompanyName#", "");
}
}
catch (Exception ex)
{
_logger.LogInformation($"生成预甩通知邮件正文失败,原因:{ex.Message}");
throw Oops.Bah($"生成预甩通知邮件正文失败,原因:{ex.Message}");
}
result = baseHtml;
return result;
}
#endregion
#region 发送邮件
/// <summary>
/// 发送邮件
/// </summary>
/// <param name="emailTitle">邮件标题</param>
/// <param name="emailHtml">邮件正文</param>
/// <param name="toEmail">邮件接收人</param>
/// <param name="opEmail">邮件抄送人</param>
/// <param name="mblNo">提单号</param>
/// <param name="usePersonalEmailSend">是否使用个人邮箱</param>
/// <returns>返回发送回执</returns>
private async Task<TaskManageOrderResultDto> SendEmail(string emailTitle,string emailHtml,string toEmail,string opEmail,string mblNo,bool usePersonalEmailSend = false)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
//提取当前公共邮箱的配置
DjyUserMailAccount publicMailAccount = null;
if (usePersonalEmailSend)
{
publicMailAccount = _djyUserMailAccount.AsQueryable().Filter(null, true).First(x => x.CreatedUserId == UserManager.UserId
&& x.SmtpPort > 0 && x.SmtpServer != null && x.SmtpServer != "");
}
else
{
//这个是公共邮箱配置
publicMailAccount = _djyUserMailAccount.AsQueryable().Filter(null, true).First(x => x.TenantId == UserManager.TENANT_ID && x.ShowName == "PublicSend"
&& x.SmtpPort > 0 && x.SmtpServer != null && x.SmtpServer != "");
}
if (publicMailAccount == null)
{
throw Oops.Oh($"提取公共邮箱配置失败请在用户邮箱账号管理增加配置显示名为PublicSend或者配置个人邮箱");
}
_logger.LogInformation($"提取当前公共邮箱的配置完成id={publicMailAccount.Id}");
EmailApiUserDefinedDto emailApiUserDefinedDto = new EmailApiUserDefinedDto
{
SendTo = toEmail,
//CCTo = opEmail,
Title = emailTitle,
Body = emailHtml,
Account = publicMailAccount.MailAccount?.Trim(),
Password = publicMailAccount.Password?.Trim(),
Server = publicMailAccount.SmtpServer?.Trim(),
Port = publicMailAccount.SmtpPort.HasValue ? publicMailAccount.SmtpPort.Value : 465,
UseSSL = publicMailAccount.SmtpSSL.HasValue ? publicMailAccount.SmtpSSL.Value : true,
Attaches = new List<AttachesInfo>()
};
//如果配置了租户参数AUTO_TRANS_EMAIL_OP_CCTO-自动转发是否默认抄送操作=ENABLE发送邮件时自动抄送操作
DjyTenantParamValueOutput paramConfig = _djyTenantParamService.GetParaCodeWithValue(new[] { "AUTO_TRANS_EMAIL_OP_CCTO" }).GetAwaiter().GetResult().FirstOrDefault();
if (paramConfig != null && paramConfig.ParaValue.Equals("ENABLE", StringComparison.OrdinalIgnoreCase))
{
emailApiUserDefinedDto.CCTo = opEmail;
}
_logger.LogInformation($"生成请求邮件参数,结果:{JSON.Serialize(emailApiUserDefinedDto)}");
string filePath = string.Empty;
//推送邮件
var emailRlt = await PushEmail(emailApiUserDefinedDto, filePath);
_logger.LogInformation($"推送邮件完成,结果:{JSON.Serialize(emailRlt)}");
if (emailRlt.succ)
{
result.succ = true;
result.msg = "成功";
}
else
{
result.succ = false;
result.msg = emailRlt.msg;
new EmailNoticeHelper().SendEmailNotice($"MBLNO={mblNo} 转发预甩通知邮件失败", $"MBLNO={mblNo} 转发预甩通知邮件失败,原因:{emailRlt.msg}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
}
}
catch(Exception ex)
{
result.succ = false;
result.msg = $"推送邮件失败,原因:{ex.Message}";
}
return result;
}
#endregion
#region 推送邮件
/// <summary>
/// 推送邮件
/// </summary>
/// <param name="emailApiUserDefinedDto">自定义邮件详情</param>
/// <param name="filePath">文件路径</param>
/// <returns>返回回执</returns>
private async Task<CommonWebApiResult> PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto, string filePath)
{
CommonWebApiResult result = new CommonWebApiResult { succ = true };
List<EmailApiUserDefinedDto> emailList = new List<EmailApiUserDefinedDto>();
var emailUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == "email_api_url")?.Value;
if (emailUrl == null)
throw Oops.Bah("字典未配置 url_set->email_api_url 请联系管理员");
if (!string.IsNullOrWhiteSpace(filePath))
{
System.IO.FileStream file = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read);
int SplitSize = 5242880;//5M分片长度
int index = 1; //序号 第几片
long StartPosition = 5242880 * (index - 1);
long lastLens = file.Length - StartPosition;//真不知道怎么起命了,就这样吧
if (lastLens < 5242880)
{
SplitSize = (int)lastLens;
}
byte[] heByte = new byte[SplitSize];
file.Seek(StartPosition, SeekOrigin.Begin);
//第一个参数是 起始位置
file.Read(heByte, 0, SplitSize);
//第三个参数是 读取长度(剩余长度)
file.Close();
string base64Str = Convert.ToBase64String(heByte);
emailApiUserDefinedDto.Attaches.Add(new AttachesInfo
{
AttachName = Path.GetFileName(filePath).Replace("_MODIFY", ""),
AttachContent = base64Str
});
}
emailList.Add(emailApiUserDefinedDto);
//string strJoin = System.IO.File.ReadAllText(filePath);
DateTime bDate = DateTime.Now;
HttpResponseMessage res = null;
try
{
res = await emailUrl.SetBody(emailList, "application/json").PostAsync();
}
catch (Exception ex)
{
_logger.LogInformation($"发送邮件异常:{ex.Message}");
}
DateTime eDate = DateTime.Now;
TimeSpan ts = eDate.Subtract(bDate);
var timeDiff = ts.TotalMilliseconds;
//_logger.LogInformation($"邮件上传完成 上传文件大小:{heByte.Length} 用时:{timeDiff}ms.,");
_logger.LogInformation($"发送邮件返回:{JSON.Serialize(res)}");
if (res != null && res.StatusCode == System.Net.HttpStatusCode.OK)
{
var userResult = await res.Content.ReadAsStringAsync();
var respObj = JsonConvert.DeserializeAnonymousType(userResult, new
{
Success = false,
Message = string.Empty,
Code = -9999,
});
result.succ = respObj.Success;
result.msg = respObj.Message;
}
return result;
}
#endregion
}
}