using Furion; using Furion.DynamicApiController; using Furion.FriendlyException; using Mapster; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.ConfigOption; using Myshipping.Application.Entity; using Myshipping.Application.Enum; using Myshipping.Core; using Myshipping.Core.Entity; using Myshipping.Core.Service; using NPOI.SS.Formula.Functions; using SqlSugar; using StackExchange.Profiling.Internal; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; namespace Myshipping.Application { /// /// BC任务 /// [ApiDescriptionSettings("Application", Name = "TaskManageBC", Order = 10)] public class TaskManageBCService: ITaskManageBCService, IDynamicApiController { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _taskBCInfoRepository; private readonly SqlSugarRepository _taskBCCTNInfoRepository; private readonly SqlSugarRepository _taskBaseRepository; private readonly SqlSugarRepository _taskFileRepository; private readonly SqlSugarRepository _bookingOrderRepository; private readonly SqlSugarRepository _bookingCtnRepository; private readonly SqlSugarRepository _sysUserRepository; private readonly IServiceWorkFlowBaseService _serviceWorkFlowBaseService; public TaskManageBCService(SqlSugarRepository taskBCInfoRepository, SqlSugarRepository taskBaseRepository, SqlSugarRepository taskBCCTNInfoRepository, SqlSugarRepository taskFileRepository, SqlSugarRepository bookingOrderRepository, SqlSugarRepository bookingCtnRepository, SqlSugarRepository sysUserRepository, IServiceWorkFlowBaseService serviceWorkFlowBaseService) { _taskBaseRepository = taskBaseRepository; _taskBCInfoRepository = taskBCInfoRepository; _taskBCCTNInfoRepository = taskBCCTNInfoRepository; _taskFileRepository = taskFileRepository; _bookingOrderRepository = bookingOrderRepository; _bookingCtnRepository = bookingCtnRepository; _sysUserRepository = sysUserRepository; _serviceWorkFlowBaseService = serviceWorkFlowBaseService; } #region 获取BC详情 /// /// 获取BC详情 /// /// BC主键 /// 返回回执 [HttpGet("/TaskManageBC/GetInfo")] public async Task GetInfo(string pkId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var bcOrder = _taskBCInfoRepository.AsQueryable().First(a => a.PK_ID == pkId); if (bcOrder == null) throw Oops.Oh($"BC主键{pkId}无法获取业务信息"); var BCCtnList = _taskBCCTNInfoRepository.AsQueryable().Where(a => a.P_ID == pkId).ToList(); TaskBCShowBaseDto model = bcOrder.Adapt(); if (BCCtnList.Count > 0) model.CtnList = BCCtnList.Adapt>(); var fileList = _taskFileRepository.AsQueryable().Where(a => a.TASK_PKID == bcOrder.TASK_ID).ToList(); if (fileList.Count > 0) model.FileList = fileList.Adapt>(); result.succ = true; result.ext = model; //如果当前BC有对应记录,则读取订舱详情 if (bcOrder.BOOKING_ORDER_ID.HasValue) { var bkOrder = await _bookingOrderRepository.AsQueryable(). FirstAsync(a => a.Id == bcOrder.BOOKING_ORDER_ID.Value); if (bkOrder != null) { var showBKOrder = bkOrder.Adapt(); var ctnList = await _bookingCtnRepository.AsQueryable(). Where(a => a.BILLID == bkOrder.Id).ToListAsync(); if (ctnList.Count > 0) showBKOrder.ctnInputs = ctnList.Adapt>(); result.ext2 = showBKOrder; } } } catch (Exception ex) { result.succ = false; result.msg = $"获取BC详情异常,原因:{ex.Message}"; } return result; } #endregion #region 通过任务主键获取BC详情 /// /// 通过任务主键获取BC详情 /// /// BC任务主键 /// 返回回执 [HttpGet("/TaskManageBC/GetInfoByTaskId")] public async Task GetInfoByTaskId(string taskPkId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息"); var bcOrder = _taskBCInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID); if (bcOrder == null) throw Oops.Oh($"任务主键{taskPkId}无法获取BC业务信息"); var bcCtnList = _taskBCCTNInfoRepository.AsQueryable().Where(a => a.P_ID == bcOrder.PK_ID).ToList(); TaskBCShowBaseDto model = bcOrder.Adapt(); if (bcCtnList.Count > 0) model.CtnList = bcCtnList.Adapt>(); var fileList = _taskFileRepository.AsQueryable().Where(a => a.TASK_PKID == bcOrder.TASK_ID).ToList(); if (fileList.Count > 0) model.FileList = fileList.Adapt>(); model.taskStatus = taskBase.STATUS; //生成关键信息 #region 生成关键信息 model.Keywords = new List(); if(bcOrder.CARRIAGE_TYPE == "DIRECT_SHIP") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"承运方式:{bcOrder.CARRIAGE_TYPE_NAME}", Background = "#FFFF80",Icon= "icon-yunshu1" }); } else if (bcOrder.CARRIAGE_TYPE == "TRANSFER_SHIP") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"承运方式:{bcOrder.CARRIAGE_TYPE_NAME}", Background = "#CAF982", Icon = "icon-shuaxin" }); } if (bcOrder.BOOKING_SLOT_TYPE == "CONTRACT_ORDER") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"订舱方式:{bcOrder.BOOKING_SLOT_TYPE_NAME}", Background = "#81D3F8", Icon = "icon-touzijilu" }); } else if (bcOrder.BOOKING_SLOT_TYPE == "SPOT_ORDER") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"订舱方式:{bcOrder.BOOKING_SLOT_TYPE_NAME}", Background = "#FACD91", Icon = "icon-beizhu1" }); } #endregion result.succ = true; result.ext = model; //如果当前BC有对应记录,则读取订舱详情 if (bcOrder.BOOKING_ORDER_ID.HasValue) { var bkOrder = await _bookingOrderRepository.AsQueryable(). FirstAsync(a => a.Id == bcOrder.BOOKING_ORDER_ID.Value); if(bkOrder != null) { var showBKOrder = bkOrder.Adapt(); var ctnList = await _bookingCtnRepository.AsQueryable(). Where(a => a.BILLID == bkOrder.Id).ToListAsync(); if (ctnList.Count > 0) showBKOrder.ctnInputs = ctnList.Adapt>(); result.ext2 = showBKOrder; } } } catch (Exception ex) { result.succ = false; result.msg = $"获取BC详情异常,原因:{ex.Message}"; } return result; } #endregion #region 获取待处理的BC任务 /// /// 获取待处理的BC任务(来自邮件解析需要对应订舱,系统会根据用户的订舱台账预配) /// /// 返回回执 [HttpGet("/TaskManageBC/GetToDoBCList")] public async Task GetToDoBCList() { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); /* 1、优先匹配提单号一致的 2、判断船名航次一致的 */ try { Dictionary> toDoListDict = new Dictionary>(); //获取所有待处理的BC任务 var taskList = await _taskBCInfoRepository.AsQueryable().InnerJoin((a,b)=>a.TASK_ID == b.PK_ID) .Where((a, b)=> !a.BOOKING_ORDER_ID.HasValue && b.STATUS == TaskStatusEnum.Create.ToString()) .Select((a,b)=>new { BC = a,TSK = b }).ToListAsync(); if (taskList.Count > 0) { taskList.ForEach(async tsk => { var curList = await _bookingOrderRepository.AsQueryable() .Where(a => a.VESSEL.Contains(tsk.BC.VESSEL) && a.VOYNO.Contains(tsk.BC.VOYNO) || a.MBLNO.Contains(tsk.BC.MBL_NO) ).ToListAsync(); if (curList.Count > 0) { toDoListDict.Add(tsk.BC.PK_ID, curList); } else { toDoListDict.Add(tsk.BC.PK_ID, new List()); } }); } //这里最后清洗一下对应的订舱数据,只保留一条符合的数据 if (toDoListDict.Count > 0) { List> tupList = new List>(); int num = 1; int odNum = 1; foreach (var kvp in toDoListDict) { var bcInfo = taskList.FirstOrDefault(a => a.BC.PK_ID == kvp.Key).BC.Adapt(); bcInfo.Indx = num; if (kvp.Value.Count > 0) { var bookingOrder = kvp.Value.Select(a => { if (a.MBLNO.Equals(bcInfo.MBLNo, StringComparison.OrdinalIgnoreCase)) { return new { Sort = 90, OBJ = a }; } else if (a.VESSEL.Equals(bcInfo.Vessel, StringComparison.OrdinalIgnoreCase) && a.VOYNO.Equals(bcInfo.VoyNo, StringComparison.OrdinalIgnoreCase)) { return new { Sort = 80, OBJ = a }; } return new { Sort = 1, OBJ = a }; }).OrderByDescending(a => a.Sort).FirstOrDefault().OBJ.Adapt(); bookingOrder.Indx = odNum; bookingOrder.BCIndx = num; bcInfo.BKOrderIndx = odNum; odNum++; tupList.Add(new Tuple( bcInfo, bookingOrder )); } else { tupList.Add(new Tuple( bcInfo, null )); } num++; } result.ext = tupList.Select(a=>a.Item1).ToList(); result.ext2 = tupList.Select(a => a.Item2).ToList(); } result.succ = true; } catch (Exception ex) { result.succ = false; result.msg = $"获取派车详情异常,原因:{ex.Message}"; } return result; } #endregion #region 任务ID下载附件 /// /// 任务ID下载附件 /// /// BC任务主键 /// 附件分类代码 /// 返回数据流 [HttpGet("/TaskManageBC/DownloadFile")] public async Task DownloadFile([FromQuery] string taskPKId, [FromQuery] string fileCategory = "BC") { var bcTaskInfo = await _taskBaseRepository.AsQueryable().FirstAsync(u => u.PK_ID == taskPKId); if (bcTaskInfo == null) { throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); } TaskFileCategoryEnum fileCategoryEnum = TaskFileCategoryEnum.NONE; System.Enum.TryParse(fileCategory, out fileCategoryEnum); if (fileCategoryEnum == TaskFileCategoryEnum.NONE) { throw Oops.Oh($"附件分类代码错误,请提供正确的分类代码"); } string name = fileCategoryEnum.ToString(); var fileInfo = await _taskFileRepository.AsQueryable().FirstAsync(u => u.TASK_PKID == taskPKId && u.FILE_CATEGORY == name); if (fileInfo == null) { throw Oops.Oh($"任务主键{taskPKId}没有可下载的附件"); } var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } var fileFullPath = Path.Combine(dirAbs, fileInfo.FILE_PATH); if (!File.Exists(fileFullPath)) { throw Oops.Oh($"任务主键{taskPKId} 附件下载请求失败,请确认文件是否存在"); } var fileName = HttpUtility.UrlEncode(fileInfo.FILE_NAME, Encoding.GetEncoding("UTF-8")); var result = new FileStreamResult(new FileStream(fileFullPath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName }; return result; } #endregion #region 检索订舱信息 /// /// 检索订舱信息 /// /// 检索条件 /// 返回回执 [HttpPost("/TaskManageBC/QueryBookingOrderList")] public async Task QueryBookingOrderList([FromBody] BookingOrderBCQuery query) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { bool isAvailable = false; var queryWhere = _bookingOrderRepository.AsQueryable(); #region 查询条件 if (query.beginETD.HasValue || query.endETD.HasValue) { /* 起始结束时间间隔不能超过7天 */ DateTime beginDate = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd")); DateTime endDate = beginDate; if (query.beginETD.HasValue) beginDate = query.beginETD.Value; if (query.endETD.HasValue) endDate = query.endETD.Value; if (endDate > beginDate.AddDays(7)) throw Oops.Oh($"船期的日期范围不能超过7天"); endDate = endDate.AddDays(1); queryWhere = queryWhere.Where(a => a.ETD >= beginDate && a.ETD < endDate); isAvailable = true; } if (query.beginCreated.HasValue || query.endCreated.HasValue) { /* 起始结束时间间隔不能超过7天 */ DateTime beginDate = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd")); DateTime endDate = beginDate; if (query.beginCreated.HasValue) beginDate = query.beginCreated.Value; if (query.endCreated.HasValue) endDate = query.endCreated.Value; if (endDate > beginDate.AddDays(7)) throw Oops.Oh($"制单的日期范围不能超过7天"); endDate = endDate.AddDays(1); queryWhere = queryWhere.Where(a => a.CreatedTime >= beginDate && a.CreatedTime < endDate); isAvailable = true; } if (!string.IsNullOrWhiteSpace(query.mblNo)) { queryWhere = queryWhere.Where(a => a.MBLNO.Contains(query.mblNo)); isAvailable = true; } if (!string.IsNullOrWhiteSpace(query.custNo)) { queryWhere = queryWhere.Where(a => a.CUSTNO.Contains(query.custNo)); isAvailable = true; } if (!string.IsNullOrWhiteSpace(query.vessel)) { queryWhere = queryWhere.Where(a => a.VESSEL.Contains(query.vessel)); isAvailable = true; } if (!string.IsNullOrWhiteSpace(query.voyno)) { queryWhere = queryWhere.Where(a => a.VOYNO.Contains(query.voyno)); isAvailable = true; } #endregion if (!isAvailable) throw Oops.Oh($"查询条件不能为空"); var list = await queryWhere.OrderBy(a => a.CreatedTime) .Take(query.topNum).ToListAsync(); var bkList = list.Adapt>(); result.succ = true; result.ext = bkList; } catch (Exception ex) { result.succ = false; result.msg = $"查询失败,原因:{ex.Message}"; } return result; } #endregion #region 转移任务(将任务指定给其他人) /// /// 转移任务(将任务指定给其他人) /// /// BC任务主键 /// 用户ID /// 返回回执 [HttpGet("/TaskManageBC/TransferTask")] public async Task TransferTask([FromQuery] string taskPKId, [FromQuery] long userId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { /* 1、如果当前任务是公共任务,则更新为相关人后,变更任务为个人。 */ var bcTaskInfo = await _taskBaseRepository.AsQueryable().FirstAsync(u => u.PK_ID == taskPKId); if (bcTaskInfo == null) { throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); } if(userId < 0) throw Oops.Oh($"指定用户ID不能为空"); var targetUserId = _sysUserRepository.AsQueryable().First(u => u.Id == userId); if (targetUserId == null) throw Oops.Oh($"指定用户不存在"); if (bcTaskInfo.IS_PUBLIC == 1) { bcTaskInfo.IS_PUBLIC = 0; bcTaskInfo.CreatedUserId = targetUserId.Id; bcTaskInfo.CreatedUserName = targetUserId.Name; bcTaskInfo.UpdatedTime = DateTime.Now; bcTaskInfo.UpdatedUserId = targetUserId.Id; bcTaskInfo.UpdatedUserName = targetUserId.Name; await _taskBaseRepository.AsUpdateable(bcTaskInfo).IgnoreColumns(it => new { it.TenantId, it.CreatedTime, it.IsDeleted, it.TASK_NO, it.TASK_TYPE, it.TASK_SOURCE }).ExecuteCommandAsync(); } else { bcTaskInfo.CreatedUserId = targetUserId.Id; bcTaskInfo.CreatedUserName = targetUserId.Name; bcTaskInfo.UpdatedTime = DateTime.Now; bcTaskInfo.UpdatedUserId = targetUserId.Id; bcTaskInfo.UpdatedUserName = targetUserId.Name; await _taskBaseRepository.AsUpdateable(bcTaskInfo).IgnoreColumns(it => new { it.TenantId, it.CreatedTime, it.IsDeleted, it.TASK_NO, it.TASK_TYPE, it.TASK_SOURCE }).ExecuteCommandAsync(); } result.succ = true; result.msg = "成功"; } catch (Exception ex) { result.succ = false; result.msg = $"转移任务失败,原因:{ex.Message}"; } return result; } #endregion #region 生成订舱或舱位 /// /// 生成订舱或舱位 /// /// 生成订舱或者舱位请求 /// 返回回执 [HttpPost("/TaskManageBC/CreateBookingAndSlot")] public async Task CreateBookingAndSlot([FromBody] BookingOrSlotGenerateDto model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { /* 1、推送舱位生成方法。 2、推送舱位暂存方法。 3、推送舱位分配方法。 4、更新任务状态位完成。 */ if(string.IsNullOrWhiteSpace(model.BCTaskId)) throw Oops.Oh($"BC任务主键不能为空"); //生成方式(GEN_BOOKING_SLOT-生成舱位和订舱;GEN_BOOKING-只生成订舱;GEN_SLOT-只生成舱位;GEN_EXIST_BOOKING-匹配指定的订舱) if (string.IsNullOrWhiteSpace(model.GenerateMethod)) throw Oops.Oh($"生成方式不能为空,需要指定一种生成方式"); var bcTaskInfo = await _taskBaseRepository.AsQueryable().FirstAsync(u => u.PK_ID == model.BCTaskId); if (bcTaskInfo == null) { throw Oops.Oh($"任务主键{model.BCTaskId}无法获取业务信息"); } var bcOrder = _taskBCInfoRepository.AsQueryable().First(a => a.TASK_ID == bcTaskInfo.PK_ID); if (bcOrder == null) throw Oops.Oh($"任务主键{model.BCTaskId}无法获取BC业务信息"); var bcCtnList = _taskBCCTNInfoRepository.AsQueryable().Where(a => a.P_ID == bcOrder.PK_ID).ToList(); if ((bcOrder.BOOKING_ORDER_ID.HasValue && bcOrder.BOOKING_ORDER_ID.Value>0) || (bcOrder.BOOKING_SLOT_ID.HasValue && bcOrder.BOOKING_SLOT_ID.Value > 0)) { throw Oops.Oh($"当前BC任务已生成订舱或舱位,不能重复生成"); } result.succ = true; result.msg = "成功"; } catch (Exception ex) { result.succ = false; result.msg = $"生成订舱或舱位失败,原因:{ex.Message}"; } return result; } #endregion #region 取消任务 /// /// 取消任务 /// /// BC任务主键 /// 返回回执 [HttpGet("/TaskManageBC/CancelTask")] public async Task CancelTask([FromQuery] string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var bcTaskInfo = await _taskBaseRepository.AsQueryable().FirstAsync(u => u.PK_ID == taskPKId); if (bcTaskInfo == null) { throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); } bcTaskInfo.IsDeleted = true; bcTaskInfo.UpdatedTime = DateTime.Now; bcTaskInfo.UpdatedUserId = UserManager.UserId; bcTaskInfo.UpdatedUserName = UserManager.Name; await _taskBaseRepository.AsUpdateable(bcTaskInfo).IgnoreColumns(it => new { it.TenantId, it.CreatedTime, it.CreatedUserId, it.CreatedUserName, it.IsDeleted, it.TASK_NO, it.TASK_TYPE, it.TASK_SOURCE }).ExecuteCommandAsync(); result.succ = true; result.msg = "成功"; } catch (Exception ex) { result.succ = false; result.msg = $"取消任务失败,原因:{ex.Message}"; } return result; } #endregion #region 获取服务项目列表 /// /// 获取服务项目列表 /// /// 返回回执 [HttpGet("/TaskManageBC/GetProjectList")] public async Task> GetProjectList() { List list = new List(); return await _serviceWorkFlowBaseService.GetEnableProjectList(UserManager.TENANT_ID.ToString()); } #endregion } }