using Furion; using Furion.DependencyInjection; using Furion.DistributedIDGenerator; using Furion.DynamicApiController; using Furion.FriendlyException; using Furion.JsonSerialization; using Mapster; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.Entity; using Myshipping.Application.Enum; using Myshipping.Application.Helper; using Myshipping.Core; using Myshipping.Core.Entity; using Myshipping.Core.Service; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Crypto; 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 { /// /// 派车任务 /// [ApiDescriptionSettings("Application", Name = "TaskManageTruck", Order = 10)] public class TaskManageTruckService : ITaskManageTruckService, IDynamicApiController { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _taskTruckRepository; private readonly SqlSugarRepository _taskTruckContaRepository; private readonly SqlSugarRepository _taskBaseRepository; private readonly SqlSugarRepository _bookingPrintTemplateRepository; private readonly SqlSugarRepository _djyUserConfigConfig; private readonly SqlSugarRepository _bookingExcelTemplateRepository; private readonly SqlSugarRepository _bookingOrderRepository; private readonly SqlSugarRepository _sysUserRepository; private readonly INamedServiceProvider _namedServiceProvider; const string PRINT_LIST_TYPE_KEY = "booking_truck_print_list"; const string PRINT_DATASOURCE_KEY = "booking_order"; public TaskManageTruckService(SqlSugarRepository taskTruckRepository, SqlSugarRepository taskTruckContaRepository, SqlSugarRepository taskBaseRepository, SqlSugarRepository bookingPrintTemplateTemplate, SqlSugarRepository djyUserConfigConfig, SqlSugarRepository bookingExcelTemplateRepository, SqlSugarRepository bookingOrderRepository, SqlSugarRepository sysUserRepository, INamedServiceProvider namedServiceProvider, ISysCacheService cache, ILogger logger) { _cache = cache; _logger = logger; _taskTruckRepository = taskTruckRepository; _taskTruckContaRepository = taskTruckContaRepository; _taskBaseRepository = taskBaseRepository; _bookingPrintTemplateRepository = bookingPrintTemplateTemplate; _djyUserConfigConfig = djyUserConfigConfig; _bookingExcelTemplateRepository = bookingExcelTemplateRepository; _bookingOrderRepository = bookingOrderRepository; _sysUserRepository = sysUserRepository; _namedServiceProvider = namedServiceProvider; } /// /// 保存派车 /// /// 派车信息 /// 返回回执 [HttpPost("/TaskManageTruck/Save")] public async Task Save(TaskTruckDto info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var id = await InnerSave(info); result.succ = true; result.msg = "保存成功"; result.ext = id; } catch (Exception ex) { result.succ = false; result.msg = $"{ex.Message}"; } return result; } /// /// 保存内部方法 /// /// 派车信息 /// 返回派车Id [SqlSugarUnitOfWork] private async Task InnerSave(TaskTruckDto info) { TaskTruckInfo entity = info.Adapt(); if (entity == null) throw Oops.Oh($"派车信息不能为空"); if(!entity.KGS.HasValue) throw Oops.Oh($"吨数不能为空"); List entityCtnList = info.ContaList.Adapt>(); if (entityCtnList != null && entityCtnList.Count > 0) { //保存时默认统计箱型箱量 entity.CntrTotal = string.Join(";", entityCtnList.GroupBy(a => a.CTNALL) .Select(a => { return $"{a.Key}*{a.ToList().Sum(b => b.CTNNUM.HasValue ? b.CTNNUM.Value : 1)}"; }).ToArray()); } if (entity.DispatcherId.HasValue && entity.DispatcherId.Value > 0) { var dispatchUser = _sysUserRepository.AsQueryable().First(a => a.Id == entity.DispatcherId.Value); if (dispatchUser != null) entity.DispatcherName = dispatchUser.Name; } if (string.IsNullOrWhiteSpace(entity.PK_ID)) { entity.Status = BookingTruckStatus.TEMP.ToString(); entity.PK_ID = IDGen.NextID().ToString(); _taskTruckRepository.Insert(entity); if (entityCtnList != null && entityCtnList.Count > 0) { entityCtnList.ForEach(async ctn => { ctn.P_ID = entity.PK_ID; ctn.PK_ID = IDGen.NextID().ToString(); await _taskTruckContaRepository.InsertAsync(ctn); }); } } else { var model = _taskTruckRepository.AsQueryable().First(a => a.PK_ID == entity.PK_ID); if (model == null) throw Oops.Oh($"派车信息获取失败,派车信息不存在或已作废"); //校验 ValidateTruck(OperateTypeEnum.Save, new TaskTruckInfo[] { model }); entity.UpdatedTime = DateTime.Now; entity.UpdatedUserId = UserManager.UserId; entity.UpdatedUserName = UserManager.Name; await _taskTruckRepository.AsUpdateable(entity).IgnoreColumns(it => new { it.TenantId, it.TenantName, it.CreatedTime, it.CreatedUserId, it.CreatedUserName, it.IsDeleted, it.BookingId, it.Status, it.TruckFlowNo, it.TaskNo, it.TASK_ID, it.BookingTruckId, it.DispatcherId, it.DispatcherName }).ExecuteCommandAsync(); await _taskTruckContaRepository.DeleteAsync(x => x.P_ID == model.PK_ID); if (entityCtnList != null && entityCtnList.Count > 0) { entityCtnList.ForEach(async ctn => { ctn.P_ID = entity.PK_ID; ctn.PK_ID = IDGen.NextID().ToString(); //await _bookingTruckContaRepository.AsUpdateable(ctn).IgnoreColumns(it => new //{ // it.TenantId, // it.CreatedTime, // it.CreatedUserId, // it.CreatedUserName, // it.IsDeleted, //}).ExecuteCommandAsync(); await _taskTruckContaRepository.InsertAsync(ctn); }); } var taskInfo = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == model.TASK_ID); if(taskInfo != null) { taskInfo.TRUCK_NAME = entity.TruckName; taskInfo.NeedArriveTime = entity.NeedArriveTime; taskInfo.UpdatedTime = entity.UpdatedTime; taskInfo.UpdatedUserId = UserManager.UserId; taskInfo.UpdatedUserName = UserManager.Name; await _taskBaseRepository.AsUpdateable(taskInfo).UpdateColumns(it => new { it.TRUCK_NAME, it.NeedArriveTime, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); } } return entity.PK_ID; } /// /// 获取派车详情 /// /// 派车主键 /// 返回回执 [HttpGet("/TaskManageTruck/GetInfo")] public async Task GetInfo(string pkId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var truckOrder = _taskTruckRepository.AsQueryable().First(a => a.PK_ID == pkId); if (truckOrder == null) throw Oops.Oh($"派车主键{pkId}无法获取业务信息"); var truckCtnList = _taskTruckContaRepository.AsQueryable().Where(a => a.P_ID == pkId).ToList(); TaskTruckShowDto model = truckOrder.Adapt(); if (truckCtnList.Count > 0) model.ContaList = truckCtnList.Adapt>(); result.succ = true; result.ext = model; } catch (Exception ex) { result.succ = false; result.msg = $"获取派车详情异常,原因:{ex.Message}"; } return result; } /// /// 通过任务主键获取派车详情 /// /// 派车主键 /// 返回回执 [HttpGet("/TaskManageTruck/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 truckOrder = _taskTruckRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID); if (truckOrder == null) throw Oops.Oh($"任务主键{taskPkId}无法获取派车业务信息"); var truckCtnList = _taskTruckContaRepository.AsQueryable().Where(a => a.P_ID == truckOrder.PK_ID).ToList(); TaskTruckShowDto model = truckOrder.Adapt(); if (truckCtnList.Count > 0) model.ContaList = truckCtnList.Adapt>(); result.succ = true; result.ext = model; } catch (Exception ex) { result.succ = false; result.msg = $"获取派车详情异常,原因:{ex.Message}"; } return result; } /// /// 打印派车 /// /// 派车主键 /// 打印模板ID /// 分类代码(使用字典【booking_template_category】中的代码) /// 类型,1:pdf、2:xlsx、3:docx /// 打印类型,10:FastReport、20:Excel模板 /// 返回回执 [HttpGet("/TaskManageTruck/Print")] public async Task Print([FromQuery] string taskPKId, [FromQuery] long templateId, [FromQuery] string cateCode, [FromQuery] PrintFileTypeEnum printFileType = PrintFileTypeEnum.PDF, [FromQuery] BookingPrintTemplateType printType = BookingPrintTemplateType.FastReport) { var printTemplate = await _bookingPrintTemplateRepository.AsQueryable().Filter(null, true) .FirstAsync(x => x.Id == templateId); if (printTemplate == null) { throw Oops.Bah(BookingErrorCode.BOOK115); } var truckOrder = _taskTruckRepository.AsQueryable().First(x => x.PK_ID == taskPKId); if (!truckOrder.NeedArriveTime.HasValue) { throw Oops.Oh("要求送达日期不能为空"); } //var order = await _bookingTruckRepository.FirstOrDefaultAsync(x => x.Id == bookingId); //var edi = await _bookingEDIExt.FirstOrDefaultAsync(x => x.BookingId == bookingId); //if (order == null) //{ // throw Oops.Bah(BookingErrorCode.BOOK001); //} var fileName = string.Empty; //var dicCate = (await _cache.GetAllDictData()).FirstOrDefault(x => x.Code == cateCode && x.TypeCode == "booking_template_category"); //if (dicCate == null) //{ // throw Oops.Bah("分类代码参数不正确"); //} if (printType == BookingPrintTemplateType.FastReport) { #region FastReport打印 var bs = await GenPrintFile(taskPKId, printTemplate, printFileType); var fileType = ""; if (printFileType == PrintFileTypeEnum.PDF) { fileType = ".pdf"; } else if (printFileType == PrintFileTypeEnum.XLSX) { fileType = ".xlsx"; } else if (printFileType == PrintFileTypeEnum.DOCX) { fileType = ".docx"; } else { throw Oops.Bah("类型参数不正确"); } fileName = $"{DateTime.Now.Ticks}{fileType}";//名称 ////2023-4-3,根据河川操作要求,文件名只带提单号 //if (!string.IsNullOrEmpty(order.MBLNO)) //{ // fileName = $"{order.MBLNO}{fileType}";//名称 //} //else //{ // fileName = $"{order.Id}_{DateTime.Now.Ticks}{fileType}";//名称 //} var opt = App.GetOptions().Path; var serverpath = Path.Combine(App.WebHostEnvironment.WebRootPath, opt);//服务器路径 if (!Directory.Exists(serverpath)) { Directory.CreateDirectory(serverpath); } var fullPath = Path.Combine(serverpath, fileName); await File.WriteAllBytesAsync(fullPath, bs); #endregion } /* else if (printType == BookingPrintTemplateType.ExcelTemplate) { #region Excel模板打印 var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } var fileAbsPath = Path.Combine(dirAbs, printTemplate.FilePath); _logger.LogInformation($"准备调用EXCEL生成:id:{id},文件:{printTemplate.FileName}"); var result = new FileStream(fileAbsPath, FileMode.Open); var excelwork = new HSSFWorkbook(result); var sheet = excelwork.GetSheetAt(0); var entity = await _bookingExcelTemplateRepository.AsQueryable() .Where(x => x.PId == templateId).OrderBy(x => x.Row).ToListAsync(); if (entity == null) { throw Oops.Bah("当前模板未设置"); } for (int _row = 1; _row <= entity.Max(x => x.Row); _row++) { if (entity.Where(x => x.Row == _row).Count() > 0) { ////获取行 var row = sheet.GetRow(_row - 1); if (row != null) { for (int _cellNum = 1; _cellNum <= entity.Max(x => x.Column); _cellNum++) { if (entity.Where(x => x.Row == _row && x.Column == _cellNum).Count() > 0) { var name = entity.Where(x => x.Row == _row && x.Column == _cellNum).Select(x => x.Field).FirstOrDefault(); if (name.Split('.')[0].ToLower() == "order") { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(order)) { var _name = descriptor.Name.ToLower(); if (name.Split('.')[0].ToLower() == "order" && name.Split('.')[1].ToLower() == _name) { var value = descriptor.GetValue(order) != null ? descriptor.GetValue(order).ToString() : ""; ICell cell = row.GetCell(_cellNum - 1); if (descriptor.PropertyType.FullName.Contains("DateTime")) { value = value != "" ? Convert.ToDateTime(value).ToString("yyyy-MM-dd") : ""; } if (cell != null) { row.Cells[_cellNum - 1].SetCellValue(value); } else { row.CreateCell(_cellNum - 1).SetCellValue(value); } } } } if (name.Split('.')[0].ToLower() == "edi") { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(edi)) { var _name = descriptor.Name.ToLower(); if (name.Split('.')[0].ToLower() == "edi" && name.Split('.')[1].ToLower() == _name) { var value = descriptor.GetValue(edi) != null ? descriptor.GetValue(edi).ToString() : ""; ICell cell = row.GetCell(_cellNum - 1); if (descriptor.PropertyType.FullName.Contains("DateTime")) { value = value != "" ? Convert.ToDateTime(value).ToString("yyyy-MM-dd") : ""; } if (cell != null) { row.Cells[_cellNum - 1].SetCellValue(value); } else { row.CreateCell(_cellNum - 1).SetCellValue(value); } } } } if (name.Split('.')[0].ToLower() == "userinfo") { ICell cell = row.GetCell(_cellNum - 1); var value = string.Empty; if (name.Split('.')[1].ToLower() == "username") { value = UserManager.Name; } if (name.Split('.')[1].ToLower() == "usertel") { value = UserManager.TEl; } if (name.Split('.')[1].ToLower() == "usermobile") { value = UserManager.Phone; } if (name.Split('.')[1].ToLower() == "useremail") { value = UserManager.Email; } if (name.Split('.')[1].ToLower() == "usertenant") { value = UserManager.TENANT_NAME; } if (cell != null) { row.Cells[_cellNum - 1].SetCellValue(value); } else { row.CreateCell(_cellNum - 1).SetCellValue(value); } } } } } else { ////创建行 var srow = NpoiExcelExportHelper._.CreateRow(sheet, _row - 1); for (int _cellNum = 1; _cellNum <= entity.Max(x => x.Column); _cellNum++) { if (entity.Where(x => x.Row == _row && x.Column == _cellNum).Count() > 0) { var name = entity.Where(x => x.Row == _row && x.Column == _cellNum).Select(x => x.Field).FirstOrDefault(); if (name.Split('.')[0].ToLower() == "order") { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(order)) { var _name = descriptor.Name.ToLower(); if (name.Split('.')[1].ToLower() == _name && name.Split('.')[0].ToLower() == "order") { var value = descriptor.GetValue(order) != null ? descriptor.GetValue(order).ToString() : ""; if (descriptor.PropertyType.FullName.Contains("DateTime")) { value = value != "" ? Convert.ToDateTime(value).ToString("yyyy-MM-dd") : ""; } srow.CreateCell(_cellNum - 1).SetCellValue(value); } } } if (name.Split('.')[0].ToLower() == "edi") { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(edi)) { var _name = descriptor.Name.ToLower(); if (name.Split('.')[1].ToLower() == _name && name.Split('.')[0].ToLower() == "edi") { var value = descriptor.GetValue(edi) != null ? descriptor.GetValue(edi).ToString() : ""; if (descriptor.PropertyType.FullName.Contains("DateTime")) { value = value != "" ? Convert.ToDateTime(value).ToString("yyyy-MM-dd") : ""; } srow.CreateCell(_cellNum - 1).SetCellValue(value); } } } if (name.Split('.')[0].ToLower() == "userinfo") { var value = string.Empty; if (name.Split('.')[1].ToLower() == "username") { value = UserManager.Name; } if (name.Split('.')[1].ToLower() == "usertel") { value = UserManager.TEl; } if (name.Split('.')[1].ToLower() == "usermobile") { value = UserManager.Phone; } if (name.Split('.')[1].ToLower() == "useremail") { value = UserManager.Email; } if (name.Split('.')[1].ToLower() == "usertenant") { value = UserManager.TENANT_NAME; } srow.CreateCell(_cellNum - 1).SetCellValue(value); } } } } } } var fileFullPath = Path.Combine(App.WebHostEnvironment.WebRootPath, App.GetOptions().Path);//服务器路径 if (!Directory.Exists(fileFullPath)) { Directory.CreateDirectory(fileFullPath); } fileName = $"{DateTime.Now.Ticks}.xls";//名称 ////2023-4-3,根据河川操作要求,文件名只带提单号 //if (!string.IsNullOrEmpty(order.MBLNO)) //{ // fileName = $"{order.MBLNO}.xls";//名称 //} //else //{ // fileName = $"{order.Id}_{DateTime.Now.Ticks}.xls";//名称 //} _logger.LogInformation("导出excel:" + Path.Combine(fileFullPath, fileName)); var filestream = new FileStream(Path.Combine(fileFullPath, fileName), FileMode.OpenOrCreate, FileAccess.ReadWrite); excelwork.Write(filestream); #endregion } */ //记录打印次数和时间,用于前端动态展示常用的打印类型 var printRecentListKey = $"{PRINT_LIST_TYPE_KEY}_{cateCode}_{printType}"; var usrCfg = _djyUserConfigConfig.AsQueryable().First(x => x.CreatedUserId == UserManager.UserId && x.Type == printRecentListKey); if (usrCfg == null) { usrCfg = new DjyUserConfig(); usrCfg.Type = printRecentListKey; usrCfg.ConfigJson = (new long[] { templateId }).ToJson(); await _djyUserConfigConfig.InsertAsync(usrCfg); } else { var arr = JArray.Parse(usrCfg.ConfigJson).Select(x => Convert.ToInt64(x)).Where(x => x != templateId).ToList(); arr.Insert(0, templateId); usrCfg.ConfigJson = arr.ToArray().ToJson(); await _djyUserConfigConfig.UpdateAsync(usrCfg); } return HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8")); } /// /// 生成打印报表文件 /// /// 派车ID /// 打印模板 /// 文档类型,1:pdf、2:xlsx、3:docx /// 返回文件流 [NonAction] private async Task GenPrintFile(string taskTruckId, BookingPrintTemplate printTemplate, PrintFileTypeEnum printFileType = PrintFileTypeEnum.PDF) { //打印报表服务地址 var reportUrl = _cache.GetAllDictData().Result.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == "url_report_generate").Value; if (!reportUrl.EndsWith("/")) { reportUrl += "/"; } var truckOrder = _taskTruckRepository.AsQueryable().First(a => a.PK_ID == taskTruckId); if (truckOrder == null) throw Oops.Oh($"派车主键{taskTruckId}无法获取业务信息"); var truckCtnList = _taskTruckContaRepository.AsQueryable().Where(a => a.P_ID == taskTruckId).ToList(); BookingOrder bookingOrder = null; if (truckOrder.BookingId.HasValue && truckOrder.BookingId.Value > 0) { bookingOrder = _bookingOrderRepository.AsQueryable().First(a => a.Id == truckOrder.BookingId.Value); } TaskTruckPrintDto model = truckOrder.Adapt(); model.IsGuaJi = truckOrder.IsGuaJi ? "需要挂机" : "无"; if (bookingOrder != null) { model.Vessel = bookingOrder.VESSEL; if (!string.IsNullOrWhiteSpace(bookingOrder.VOYNO)) { model.VoyNo = bookingOrder.VOYNO; } else { model.VoyNo = bookingOrder.VOYNOINNER; } model.MBLNo = bookingOrder.MBLNO; model.CarrierID = bookingOrder.CARRIERID; model.Carrier = bookingOrder.CARRIER; model.DestinationID = bookingOrder.DESTINATIONID; model.Destination = bookingOrder.DESTINATION; model.ETD = bookingOrder.ETD; } if (truckCtnList.Count > 0) model.ContaList = truckCtnList.Adapt>(); _logger.LogInformation($"taskTruckId={taskTruckId} 请求打印 JSON={JSON.Serialize(model)}"); return await PrintHelper.GeneratePrintFile(JSON.Serialize(model), reportUrl, PRINT_DATASOURCE_KEY, printFileType, printTemplate); } /// /// 派车 /// /// 派车详情 /// 返回回执 [HttpPost("/TaskManageTruck/SendDispatch")] public async Task SendDispatch([FromBody] TaskTruckDto info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { //先保存再触发派车 var id = await InnerSave(info); var model = _taskTruckRepository.AsQueryable() .First(a => a.PK_ID == info.PK_ID); if (model == null) throw Oops.Oh($"派车主键{info.PK_ID}无法获取业务信息"); result = await InnerSendDispatch(model); } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage(); } return result; } /// /// 批量派车 /// /// 派车主键组 /// 返回回执 [HttpPost("/TaskManageTruck/SendDispatchBatch")] public async Task SendDispatchBatch([FromBody] string[] pkIds) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no}获取派车请求 {ids}", batchNo, pkIds); try { var list = _taskTruckRepository.AsQueryable() .Where(a => pkIds.Contains(a.PK_ID)).ToList(); if (list.Count != pkIds.Length) throw Oops.Oh($"部分派车信息获取失败,不能提交,派车信息不存在或已作废"); //校验 ValidateTruck(OperateTypeEnum.SendDispatch, list.ToArray()); List> taskList = new List>(); list.ForEach(async tk => { taskList.Add(InnerSendDispatch(tk)); }); //等待所有结果 Task.WaitAll(taskList.ToArray(), 20000); result.succ = true; result.msg = "派车成功"; List msgList = new List(); taskList.ForEach(async a => { var rlt = a.Result; if (!rlt.succ) { result.succ = false; var curInfo = list.FirstOrDefault(a => a.BookingTruckId.Value == (long)rlt.ext2); msgList.Add($"{curInfo.TaskNo} 派车失败 {rlt.msg}"); } }); if (msgList.Count > 0) { result.succ = false; result.msg = String.Join(";", msgList.ToArray()); } result.ext = msgList; } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage("批量派车"); } return result; } /// /// 批量派车通过任务ID /// /// Task任务主键组 /// 返回回执 [HttpPost("/TaskManageTruck/SendDispatchBatchByTask")] public async Task SendDispatchBatchByTask([FromBody] string[] taskPkIds) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no}获取派车请求 {ids}", batchNo, taskPkIds); try { var list = _taskTruckRepository.AsQueryable() .Where(a => taskPkIds.Contains(a.TASK_ID)).ToList(); if (list.Count != taskPkIds.Length) throw Oops.Oh($"部分派车信息获取失败,不能提交,派车信息不存在或已作废"); //校验 ValidateTruck(OperateTypeEnum.SendDispatch, list.ToArray()); List> taskList = new List>(); list.ForEach(async tk => { taskList.Add(InnerSendDispatch(tk)); }); //等待所有结果 Task.WaitAll(taskList.ToArray(), 20000); result.succ = true; result.msg = "派车成功"; List msgList = new List(); taskList.ForEach(a => { var rlt = a.Result; if (!rlt.succ) { result.succ = false; var curInfo = list.FirstOrDefault(a => a.BookingTruckId.Value == (long)rlt.ext2); msgList.Add($"{curInfo.TaskNo} 派车失败 {rlt.msg}"); } }); if (msgList.Count > 0) { result.succ = false; result.msg = String.Join(";", msgList.ToArray()); } result.ext = msgList; } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage("批量派车"); } return result; } /// /// 派车(内部方法) /// /// 派车详情 /// 返回回执 private async Task InnerSendDispatch(TaskTruckInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { ValidateTruck(OperateTypeEnum.SendDispatch, new TaskTruckInfo[] { info }); if (!info.KGS.HasValue) throw Oops.Oh($"吨数不能为空"); if(string.IsNullOrWhiteSpace(info.TruckCode) || string.IsNullOrWhiteSpace(info.TruckName)) throw Oops.Oh($"车队不能为空"); info.UpdatedTime = DateTime.Now; info.UpdatedUserId = UserManager.UserId; info.UpdatedUserName = UserManager.Name; info.Status = BookingTruckStatus.SEND_DISPATCH.ToString(); await _taskTruckRepository.AsUpdateable(info).IgnoreColumns(it => new { it.TenantId, it.TenantName, it.CreatedTime, it.CreatedUserId, it.CreatedUserName, it.IsDeleted, it.BookingId, it.TruckId, it.TruckName, it.TruckCode, it.TruckFlowNo, it.TaskNo, it.TASK_ID, it.BookingTruckId, it.DispatcherId, it.DispatcherName }).ExecuteCommandAsync(); var taskInfo = _taskBaseRepository.AsQueryable() .First(a => a.PK_ID == info.TASK_ID); if (taskInfo != null) { taskInfo.TRUCK_NAME = info.TruckName; taskInfo.NeedArriveTime = info.NeedArriveTime; taskInfo.UpdatedTime = info.UpdatedTime; taskInfo.UpdatedUserId = UserManager.UserId; taskInfo.UpdatedUserName = UserManager.Name; await _taskBaseRepository.AsUpdateable(taskInfo).UpdateColumns(it => new { it.TRUCK_NAME, it.NeedArriveTime, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); } var truckCtnList = _taskTruckContaRepository.AsQueryable().Where(a => a.P_ID == info.PK_ID).ToList(); BookingTruckDto model = info.Adapt(); model.CallBackStatus = info.Status; if (truckCtnList.Count > 0) model.ContaList = truckCtnList.Adapt>(); if (info.BookingTruckId.HasValue) model.Id = info.BookingTruckId.Value; //更新完回写订舱的派车信息 var service = _namedServiceProvider.GetService(nameof(BookingTruckService)); var rlt = await service.TruckDispatchCompleteCallBack(model); if(!rlt.succ) { throw Oops.Oh(rlt.msg); } result.succ = true; result.msg = "派车成功"; result.ext = rlt; } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage("发送派车失败"); } return result; } /// /// 取消派车 /// /// 派车主键 /// 返回回执 [HttpGet("/TaskManageTruck/CancelDispatch")] public async Task CancelDispatch(string pkId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var model = _taskTruckRepository.AsQueryable().First(a => a.PK_ID == pkId); if (model == null) throw Oops.Oh($"派车主键{pkId}无法获取业务信息"); result = await InnerCancelDispatch(model); } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage(); } return result; } /// /// 取消派车(内部方法) /// /// 派车详情 /// 返回回执 private async Task InnerCancelDispatch(TaskTruckInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { ValidateTruck(OperateTypeEnum.CancelDispatch, new TaskTruckInfo[] { info }); info.UpdatedTime = DateTime.Now; info.UpdatedUserId = UserManager.UserId; info.UpdatedUserName = UserManager.Name; info.Status = BookingTruckStatus.CANCEL_DISPATCH.ToString(); await _taskTruckRepository.AsUpdateable(info).IgnoreColumns(it => new { it.TenantId, it.CreatedTime, it.CreatedUserId, it.CreatedUserName, it.IsDeleted, it.BookingId, it.TruckId, it.TruckName, it.TruckCode, }).ExecuteCommandAsync(); var truckCtnList = _taskTruckContaRepository.AsQueryable().Where(a => a.P_ID == info.PK_ID).ToList(); BookingTruckDto model = info.Adapt(); model.CallBackStatus = info.Status; if (truckCtnList.Count > 0) model.ContaList = truckCtnList.Adapt>(); if (info.BookingTruckId.HasValue) model.Id = info.BookingTruckId.Value; //更新完回写订舱的派车信息 var service = _namedServiceProvider.GetService(nameof(BookingTruckService)); var rlt = await service.TruckDispatchCompleteCallBack(model); result.succ = true; result.msg = "取消成功"; result.ext = rlt; } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage("取消派车失败"); } return result; } /// /// 批量取消派车 /// /// 派车主键组 /// 返回回执 [HttpPost("/TaskManageTruck/CancelDispatchBatch")] public async Task CancelDispatchBatch([FromBody] string[] pkIds) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no}获取派车请求 {ids}", batchNo, pkIds); try { var list = _taskTruckRepository.AsQueryable() .Where(a => pkIds.Contains(a.PK_ID)).ToList(); if (list.Count != pkIds.Length) throw Oops.Oh($"部分派车信息获取失败,不能提交,派车信息不存在或已作废"); //校验 ValidateTruck(OperateTypeEnum.CancelDispatch, list.ToArray()); List> taskList = new List>(); list.ForEach(async tk => { taskList.Add(InnerCancelDispatch(tk)); }); //等待所有结果 Task.WaitAll(taskList.ToArray(), 20000); result.succ = true; result.msg = "取消派车成功"; List msgList = new List(); taskList.ForEach(async a => { var rlt = a.Result; if (!rlt.succ) { result.succ = false; var curInfo = list.FirstOrDefault(a => a.BookingTruckId.Value == (long)rlt.ext2); msgList.Add($"{curInfo.TaskNo} 取消派车失败 {rlt.msg}"); } }); if (msgList.Count > 0) { result.succ = false; result.msg = String.Join(";", msgList.ToArray()); } result.ext = msgList; } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage("批量取消派车失败"); } return result; } /// /// 批量取消派车通过任务ID /// /// Task任务主键组 /// 返回回执 [HttpPost("/TaskManageTruck/CancelDispatchBatchByTask")] public async Task CancelDispatchBatchByTask([FromBody] string[] taskPkIds) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no}获取派车请求 {ids}", batchNo, taskPkIds); try { var list = _taskTruckRepository.AsQueryable() .Where(a => taskPkIds.Contains(a.TASK_ID)).ToList(); if (list.Count != taskPkIds.Length) throw Oops.Oh($"部分派车信息获取失败,不能提交,派车信息不存在或已作废"); //校验 ValidateTruck(OperateTypeEnum.CancelDispatch, list.ToArray()); List> taskList = new List>(); list.ForEach(async tk => { taskList.Add(InnerCancelDispatch(tk)); }); //等待所有结果 Task.WaitAll(taskList.ToArray(), 20000); result.succ = true; result.msg = "取消派车成功"; List msgList = new List(); taskList.ForEach(a => { var rlt = a.Result; if (!rlt.succ) { result.succ = false; var curInfo = list.FirstOrDefault(a => a.BookingTruckId.Value == (long)rlt.ext2); msgList.Add($"{curInfo.TaskNo} 取消派车失败 {rlt.msg}"); } }); if (msgList.Count > 0) { result.succ = false; result.msg = String.Join(";", msgList.ToArray()); } result.ext = msgList; } catch (Exception ex) { result.succ = false; result.msg = ex.GetMessage("批量取消派车失败"); } return result; } #region 校验派车 /// /// 校验派车 /// /// 操作类型 /// 派车信息列表 private void ValidateTruck(OperateTypeEnum operateType, TaskTruckInfo[] entityArg) { if (operateType == OperateTypeEnum.Save) { if (entityArg.Any(a => a.Status != BookingTruckStatus.TEMP.ToString() && a.Status != BookingTruckStatus.CANCEL_DISPATCH.ToString())) { throw Oops.Oh($"派车状态只有暂存才能保存"); } } else if (operateType == OperateTypeEnum.Submit) { if (entityArg.Any(a => a.Status != BookingTruckStatus.TEMP.ToString() && a.Status != BookingTruckStatus.CANCELED.ToString())) { throw Oops.Oh($"派车状态只有暂存、已撤销才能提交"); } } else if (operateType == OperateTypeEnum.Cancel) { if (entityArg.Any(a => a.Status != BookingTruckStatus.SUBMITED.ToString())) { throw Oops.Oh($"派车状态只有已提交才能撤销派车"); } } else if (operateType == OperateTypeEnum.Delete) { if (entityArg.Any(a => a.Status != BookingTruckStatus.TEMP.ToString() && a.Status != BookingTruckStatus.CANCELED.ToString())) { throw Oops.Oh($"派车状态只有暂存、已撤销才能作废"); } } else if (operateType == OperateTypeEnum.SendDispatch) { if (entityArg.Any(a => a.Status != BookingTruckStatus.TEMP.ToString() && a.Status != BookingTruckStatus.SUBMITED.ToString() && a.Status != BookingTruckStatus.CANCEL_DISPATCH.ToString())) { throw Oops.Oh($"派车状态只有暂存、已撤销、已提交、已撤销派车才能发送派车"); } } else if (operateType == OperateTypeEnum.CancelDispatch) { if (entityArg.Any(a => a.Status != BookingTruckStatus.SEND_DISPATCH.ToString())) { throw Oops.Oh($"派车状态只有已派车才能取消派车"); } } } #endregion /// /// 获取订舱打印模板列表(带有当前用户打印历史排序) /// /// 分类代码(使用字典【booking_template_category】中的代码) /// 打印分类,10:FastReport、20:Excel模板 /// [HttpGet("/TaskManageTruck/PrintTemplateWithHistoryList")] public async Task PrintTemplateWithHistoryList(string cateCode, BookingPrintTemplateType printType) { var typeCode = printType.ToString(); //当前公司所有已配置的模板 var allList = await _bookingPrintTemplateRepository.AsQueryable() .Filter(null, true).InnerJoin((d, t) => d.Id == t.PrintTemplateId && t.SysUserId == UserManager.UserId) .Where(d => d.TenantId == UserManager.TENANT_ID && d.CateCode.Contains(cateCode) && d.Type == typeCode) .Select(d => new { d.Id, d.CateCode, d.CateName, d.DisplayName }) .ToListAsync(); var listReult = new List(); //当前用户打印历史数据 var printRecentListKey = $"{PRINT_LIST_TYPE_KEY}_{cateCode}_{printType}"; var usrCfg = await _djyUserConfigConfig.AsQueryable().FirstAsync(x => x.CreatedUserId == UserManager.UserId && x.Type == printRecentListKey); if (usrCfg != null) { var arr = JArray.Parse(usrCfg.ConfigJson).Select(x => Convert.ToInt64(x)).ToList(); //按顺序加入到结果 arr.ForEach(x => { var find = allList.FirstOrDefault(y => y.Id == x); if (find != null) { listReult.Add(find); } }); var listOut = allList.Where(x => !arr.Contains(x.Id)).ToList(); listReult.AddRange(listOut); return listReult; } else { return allList; } } /// /// 获取场站数据 /// /// 派车任务主键 /// /// 返回场站详情 [HttpGet("/TaskManageTruck/GetYardData")] public async Task GetYardData(string pkId, bool isWeb = false) { //订舱派车数据 var entity = _taskTruckRepository.AsQueryable().First(x => x.PK_ID == pkId); if (entity == null) throw Oops.Oh($"派车信息不能为空", typeof(InvalidOperationException)); BookingOrder bookingOrder = null; if (entity.BookingId.HasValue) { bookingOrder = _bookingOrderRepository.AsQueryable().First(x => x.Id == entity.BookingId); } string yardId = string.Empty; string mblNo = string.Empty; if (bookingOrder != null) { yardId = bookingOrder.YARDID; mblNo = bookingOrder.MBLNO; } if (string.IsNullOrWhiteSpace(yardId)) yardId = entity.YARDID; if (string.IsNullOrWhiteSpace(mblNo)) mblNo = entity.MBLNo; if (string.IsNullOrEmpty(yardId)) { throw Oops.Bah("场站信息不能为空"); } if (string.IsNullOrEmpty(mblNo)) { throw Oops.Bah("提单号不能为空"); } var rtn = await YardDataHelper.GetYardDataWithTranslateAsync(UserManager.UserId, bookingOrder.TenantId.Value, bookingOrder.TenantName, mblNo, yardId, isWeb); return rtn; } /// /// 派车任务台账保存 /// /// 请求详情 /// 返回回执 [HttpPost("/TaskManageTruck/SaveTruckByPage")] public async Task SaveTruckByPage([FromBody] TruckPageDto model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var entity = _taskTruckRepository.AsQueryable().First(a => a.TASK_ID == model.TaskPKId); if (model == null) throw Oops.Oh($"派车信息获取失败,派车信息不存在或已作废"); //校验 ValidateTruck(OperateTypeEnum.Save, new TaskTruckInfo[] { entity }); entity.TruckId = model.TruckId; entity.TruckCode = model.TruckCode; entity.TruckName = model.TruckName; entity.UpdatedTime = DateTime.Now; entity.UpdatedUserId = UserManager.UserId; entity.UpdatedUserName = UserManager.Name; //更新 await _taskTruckRepository.AsUpdateable(entity).UpdateColumns(it => new { it.TruckId, it.TruckCode, it.TruckName, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); var taskInfo = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == entity.TASK_ID); if (taskInfo != null) { taskInfo.TRUCK_NAME = entity.TruckName; taskInfo.UpdatedTime = entity.UpdatedTime; taskInfo.UpdatedUserId = UserManager.UserId; taskInfo.UpdatedUserName = UserManager.Name; await _taskBaseRepository.AsUpdateable(taskInfo).UpdateColumns(it => new { it.TRUCK_NAME, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); } if(model.IsSendDispatch) { var sendDispatchRlt = await InnerSendDispatch(entity); if(!sendDispatchRlt.succ) { result.succ = false; result.msg = sendDispatchRlt.msg; } else { result.succ = true; result.msg = "保存成功,发派车成功"; } } else { result.succ = true; result.msg = "保存成功"; } } catch (Exception ex) { result.succ = false; result.msg = $"{ex.Message}"; } return result; } /// /// 发送完派车后手工同步东胜 /// /// 派车详情 /// 返回回执 [HttpPost("/TaskManageTruck/SendTruckAfterDispatch")] public async Task SendTruckAfterDispatch([FromBody] TaskTruckDto info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { /* 1、校验必需是已经派车状态的任务。 2、只更新集装箱信息。 3、还是回调派车服务的方法。 */ var entity = _taskTruckRepository.AsQueryable().First(a => a.PK_ID == info.PK_ID); if (entity == null) throw Oops.Oh($"派车信息获取失败,派车信息不存在或已作废"); if(entity.Status != BookingTruckStatus.SEND_DISPATCH.ToString()) throw Oops.Oh($"同步东胜只能用于已派车的任务"); //保存集装箱列表信息 var saveRlt = InnerSaveAfterDispatch(info).GetAwaiter().GetResult(); var truckModel = _taskTruckRepository.AsQueryable().First(a => a.PK_ID == info.PK_ID); var truckCtnList = _taskTruckContaRepository.AsQueryable().Where(a => a.P_ID == info.PK_ID).ToList(); BookingTruckDto model = truckModel.Adapt(); model.CallBackStatus = truckModel.Status; if (truckCtnList.Count > 0) model.ContaList = truckCtnList.Adapt>(); if (truckModel.BookingTruckId.HasValue) model.Id = truckModel.BookingTruckId.Value; //回调同步东胜 var service = _namedServiceProvider.GetService(nameof(BookingTruckService)); var rlt = await service.TruckDispatchCompleteCallBack(model); if (!rlt.succ) { throw Oops.Oh(rlt.msg); } result.succ = true; result.msg = "同步成功"; result.ext = rlt; } catch(Exception ex) { result.succ = false; result.msg = $"{ex.Message}"; } return result; } /// /// 保存内部方法 /// /// 派车信息 /// 返回派车Id [SqlSugarUnitOfWork] private async Task InnerSaveAfterDispatch(TaskTruckDto info) { TaskTruckInfo entity = info.Adapt(); if (entity == null) throw Oops.Oh($"派车信息不能为空"); if (!entity.KGS.HasValue) throw Oops.Oh($"吨数不能为空"); List entityCtnList = info.ContaList.Adapt>(); if (entityCtnList != null && entityCtnList.Count > 0) { //保存时默认统计箱型箱量 entity.CntrTotal = string.Join(";", entityCtnList.GroupBy(a => a.CTNALL) .Select(a => { return $"{a.Key}*{a.ToList().Sum(b => b.CTNNUM.HasValue ? b.CTNNUM.Value : 1)}"; }).ToArray()); } var model = _taskTruckRepository.AsQueryable().First(a => a.PK_ID == entity.PK_ID); if (model == null) throw Oops.Oh($"派车信息获取失败,派车信息不存在或已作废"); model.UpdatedTime = DateTime.Now; model.UpdatedUserId = UserManager.UserId; model.UpdatedUserName = UserManager.Name; model.CntrTotal = entity.CntrTotal; await _taskTruckRepository.AsUpdateable(model).UpdateColumns(it => new { it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName, it.CntrTotal }).ExecuteCommandAsync(); await _taskTruckContaRepository.DeleteAsync(x => x.P_ID == model.PK_ID); if (entityCtnList != null && entityCtnList.Count > 0) { entityCtnList.ForEach(async ctn => { ctn.P_ID = entity.PK_ID; ctn.PK_ID = IDGen.NextID().ToString(); await _taskTruckContaRepository.InsertAsync(ctn); }); } return entity.PK_ID; } } }