using Furion; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; using Furion.RemoteRequest.Extensions; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.ConfigOption; using Myshipping.Application.Entity; using Myshipping.Core; using Myshipping.Core.Service; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; using Yitter.IdGenerator; namespace Myshipping.Application { /// /// 客户订舱 /// [ApiDescriptionSettings("Application", Name = "BookingCustomerOrder", Order = 1)] public class BookingCustomerOrderService : IDynamicApiController, ITransient { private const string StaLogCateAudit = "cust_audit"; private readonly SqlSugarRepository _rep; private readonly SqlSugarRepository _repCtn; private readonly ILogger _logger; private readonly ISysCacheService _cache; private readonly SqlSugarRepository _repFile; private readonly SqlSugarRepository _repStatuslog; private readonly SqlSugarRepository _repStatuslogDetail; private readonly SqlSugarRepository _repServiceItem; private readonly SqlSugarRepository _repOrder; public BookingCustomerOrderService(SqlSugarRepository rep, SqlSugarRepository repCtn, ILogger logger, ISysCacheService cache, SqlSugarRepository repFile, SqlSugarRepository statuslog, SqlSugarRepository repServiceItem, SqlSugarRepository repOrder, SqlSugarRepository repStatuslogDetail) { this._logger = logger; this._rep = rep; this._repCtn = repCtn; this._cache = cache; this._repFile = repFile; this._repStatuslog = statuslog; this._repServiceItem = repServiceItem; this._repOrder = repOrder; this._repStatuslogDetail = repStatuslogDetail; } #region 订舱草稿及附件 /// /// 订舱草稿台账 /// /// /// [HttpPost("/BookingCustomerOrder/PageData")] public async Task> PageData(BookingCustomerOrderQueryInput input) { var query = _rep.AsQueryable().Filter(null, true).Where(x => x.TenantId == UserManager.TENANT_ID) .Where(x => !x.IsDeleted) .WhereIF(!string.IsNullOrEmpty(input.BOOKINGNO), x => x.BOOKINGNO.Contains(input.BOOKINGNO)) .WhereIF(!string.IsNullOrEmpty(input.VESSEL), x => x.VESSEL.Contains(input.VESSEL)) .WhereIF(!string.IsNullOrEmpty(input.VOYNO), x => x.VOYNO.Contains(input.VOYNO)) .WhereIF(!string.IsNullOrEmpty(input.YARDID), x => x.YARDID == input.YARDID) .WhereIF(!string.IsNullOrEmpty(input.YARD), x => x.YARD.Contains(input.YARD)) .WhereIF(!string.IsNullOrEmpty(input.PORTDISCHARGEID), x => x.PORTDISCHARGEID == input.PORTDISCHARGEID) .WhereIF(!string.IsNullOrEmpty(input.PORTDISCHARGE), x => x.PORTDISCHARGE.Contains(input.PORTDISCHARGE)) .WhereIF(!string.IsNullOrEmpty(input.CARRIERID), x => x.CARRIERID == input.CARRIERID) .WhereIF(!string.IsNullOrEmpty(input.CARRIER), x => x.CARRIER.Contains(input.CARRIER)) .WhereIF(!string.IsNullOrEmpty(input.BookingTenantName), x => x.BookingTenantName.Contains(input.BookingTenantName)) .WhereIF(input.ETDStart.HasValue, x => x.ETD >= input.ETDStart) .WhereIF(input.ETDEnd.HasValue, x => x.ETD < input.ETDEnd.Value.Date.AddDays(1)) .WhereIF(input.CreatedTimeStart.HasValue, x => x.CreatedTime >= input.CreatedTimeStart) .WhereIF(input.CreatedTimeEnd.HasValue, x => x.CreatedTime < input.CreatedTimeEnd.Value.Date.AddDays(1)) .WhereIF(input.UpdateTimeStart.HasValue, x => x.UpdatedTime >= input.UpdateTimeStart) .WhereIF(input.UpdateTimeEnd.HasValue, x => x.UpdatedTime < input.UpdateTimeEnd.Value.Date.AddDays(1)) .WhereIF(input.BSStatusList != null && input.BSStatusList.Count > 0, x => input.BSStatusList.Contains(x.BSSTATUS)) ; if (!string.IsNullOrEmpty(input.SortField) || input.MultiSort == null || input.MultiSort.Count == 0) { query = query.OrderBy(PageInputOrder.OrderBuilder(input.SortField, input.DescSort)); } else { query = query.OrderBy(PageInputOrder.MultiOrderBuilder(input.MultiSort)); } var entities = await query.ToPagedListAsync(input.PageNo, input.PageSize); var list = entities.Adapt>(); //动态日志 var bkIdList = list.Items.Select(x => x.Id).ToList(); var staLogList = _repStatuslog.Where(x => bkIdList.Contains(x.BookingId.Value) && x.Category == StaLogCateAudit).ToList(); foreach (var item in list.Items) { item.LogList = staLogList.Where(x => x.BookingId == item.Id).OrderByDescending(x => x.OpTime).Adapt>(); } return list; } /// /// 保存草稿数据 /// /// /// [HttpPost("/BookingCustomerOrder/Save")] public async Task Save(BookingCustomerOrderSaveInput input) { if (input == null) { throw Oops.Bah("请传入正常数据!"); } var ms = JsonUtil.TrimFields(input); if (!string.IsNullOrEmpty(ms)) { throw Oops.Bah(ms); } BookingCustomerOrder entity = null; List ctnList = new List(); if (input.Id == 0) { entity = input.Adapt(); if (string.IsNullOrEmpty(entity.VOYNO)) { entity.VOYNO = entity.VOYNOINNER; } entity.BSSTATUS = "已录入"; entity.BOOKINGNO = $"BK{YitIdHelper.NextId()}"; await _rep.InsertAsync(entity); } else { entity = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == input.Id); if (entity.BSSTATUS != "已录入" && entity.BSSTATUS != "已驳回") { throw Oops.Bah("当前状态不允许修改"); } if (string.IsNullOrEmpty(entity.VOYNO)) { entity.VOYNO = entity.VOYNOINNER; } entity = input.Adapt(entity); await _rep.UpdateAsync(entity); await _repCtn.DeleteAsync(x => x.BILLID == input.Id); } //箱信息保存 if (input.CtnList != null) { foreach (var item in input.CtnList) { var ctnentity = item.Adapt(); ctnentity.BILLID = entity.Id; await _repCtn.InsertAsync(ctnentity); ctnList.Add(ctnentity); } var groupList = input.CtnList.Where(x => x.CTNNUM > 0).GroupBy(c => c.CTNALL).Select(g => $"{g.Key}*{g.Sum(gg => gg.CTNNUM)}"); entity.CNTRTOTAL = string.Join(" / ", groupList); } else { entity.CNTRTOTAL = ""; } await _rep.UpdateAsync(entity); //服务项目 _repServiceItem.Delete(x => x.BookingId == entity.Id); foreach (var item in input.ServiceItemList) { var bsi = item.Adapt(); bsi.Id = YitIdHelper.NextId(); bsi.BookingId = entity.Id; await _repServiceItem.InsertAsync(bsi); } //文件 var dbFiles = _repFile.AsQueryable().Where(x => x.BookingId == entity.Id).ToList(); var opt = App.GetOptions(); var dirAbs = string.Empty; if (string.IsNullOrEmpty(opt.basePath)) { dirAbs = Path.Combine(App.WebHostEnvironment.WebRootPath, opt.relativePath); } else { dirAbs = Path.Combine(opt.basePath, opt.relativePath); } if (!Directory.Exists(dirAbs)) Directory.CreateDirectory(dirAbs); //清除前端已删除的文件 if (input.Files != null && input.Files.Count() > 0) { var delIds = dbFiles.Where(x => !input.Files.Contains(x.Id)).Select(x => x.Id); await _repFile.DeleteAsync(x => delIds.Contains(x.Id)); } else { await _repFile.DeleteAsync(x => x.BookingId == entity.Id); } //临时文件转为正式文件 if (input.TempFileNames != null && input.TempFileNames.Count() > 0) { var optTempFile = App.GetOptions().Path; foreach (var tmpFile in input.TempFileNames) { var tempPath = Path.Combine(optTempFile, tmpFile); if (File.Exists(tempPath)) { var saveFileName = $"{DateTime.Now.Ticks}{Path.GetExtension(tmpFile)}"; var fileRelaPath = Path.Combine(opt.relativePath, saveFileName).ToLower(); var fileAbsPath = Path.Combine(dirAbs, saveFileName).ToLower(); File.Copy(tempPath, fileAbsPath, true); var newFile = new BookingFile { Id = YitIdHelper.NextId(), FileName = Path.GetFileName(tmpFile), FilePath = fileRelaPath, TypeCode = "tuodan", TypeName = "托单文件", BookingId = entity.Id, }; await _repFile.InsertAsync(newFile); } } } //日志动态 SaveAuditLog(input.Id == 0 ? "已录入" : "已修改", entity.Id); //返回给前端数据 var outModel = entity.Adapt(); outModel.CtnList = ctnList.Adapt>(); var dicFile = new Dictionary(); _repFile.AsQueryable().Where(x => x.BookingId == entity.Id).ForEach(x => dicFile.Add(x.Id, x.FileName)); outModel.Files = dicFile; outModel.LogList = _repStatuslog.AsQueryable().Where(x => x.BookingId == entity.Id && x.Category == StaLogCateAudit).OrderByDescending(x => x.OpTime).ToList().Adapt>(); outModel.ServiceItemList = _repServiceItem.AsQueryable().Where(x => x.BookingId == entity.Id).ToList().Adapt>(); return outModel; } /// /// 获取详情 /// /// /// [HttpPost("/BookingCustomerOrder/Get")] public async Task Get(long id) { var entity = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == id); var outModel = entity.Adapt(); outModel.CtnList = _repCtn.Where(x => x.BILLID == id).ToList().Adapt>(); var dicFile = new Dictionary(); _repFile.AsQueryable().Where(x => x.BookingId == entity.Id).ForEach(x => dicFile.Add(x.Id, x.FileName)); outModel.Files = dicFile; outModel.LogList = _repStatuslog.AsQueryable().Where(x => x.BookingId == entity.Id && x.Category == StaLogCateAudit).OrderByDescending(x => x.OpTime).ToList().Adapt>(); outModel.ServiceItemList = _repServiceItem.AsQueryable().Where(x => x.BookingId == entity.Id).ToList().Adapt>(); return outModel; } /// /// 上传临时文件 /// /// /// [HttpPost("/BookingCustomerOrder/UploadTempFile")] public async Task UploadTempFile(IFormFile file) { //未上传文件 if (file == null || file.Length == 0) { throw Oops.Bah("未上传任何文件"); } var optTempFile = App.GetOptions().Path; var tempFilePath = $"{DateTime.Now.Ticks}"; //临时存放目录 var tempSavePath = Path.Combine(optTempFile, tempFilePath); Directory.CreateDirectory(tempSavePath); var fileFullPath = Path.Combine(tempSavePath, file.FileName);//服务器路径 using (var stream = File.Create(fileFullPath)) { await file.CopyToAsync(stream); } return Path.Combine(tempFilePath, file.FileName); } /// /// 下载查看上传的文件 /// /// /// [HttpGet("/BookingCustomerOrder/GetFile"), AllowAnonymous] public async Task GetFile(long id) { var savedFile = await _repFile.AsQueryable().Filter(null, true).FirstAsync(u => u.Id == id); if (savedFile == null) { throw Oops.Oh("文件不存在"); } var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } var fileFullPath = Path.Combine(dirAbs, savedFile.FilePath); if (!File.Exists(fileFullPath)) { throw Oops.Oh("文件不存在"); } //var fileName = HttpUtility.UrlEncode(savedFile.FileName, Encoding.GetEncoding("UTF-8")); var result = new FileStreamResult(new FileStream(fileFullPath, FileMode.Open), "application/octet-stream") { FileDownloadName = savedFile.FileName }; return result; } /// /// 删除 /// /// /// [HttpPost("/BookingCustomerOrder/Delete")] public async Task Delete(List ids) { var list = await _rep.AsQueryable().Filter(null, true).Where(x => ids.Contains(x.Id)).ToListAsync(); var canNotDelList = list.Where(x => x.BSSTATUS != "已录入" && x.BSSTATUS != "已驳回"); if (canNotDelList.Any()) { var errMsg = string.Join("\r\n", canNotDelList.Select(x => $"{x.BOOKINGNO}的数据当前状态不能删除").ToList()); throw Oops.Bah(errMsg); } list.ForEach(x => { x.IsDeleted = true; _rep.Update(x); }); } #endregion #region 客户订舱系统操作与接口 /// /// 提交订舱 /// /// [HttpPost("/BookingCustomerOrder/Submit")] public async Task Submit(List ids) { var recUrl = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingRequestReceiveUrl"); if (recUrl == null || string.IsNullOrEmpty(recUrl.Value)) { throw Oops.Bah("大简云接收订舱URL地址未配置,请联系管理员"); } var userId = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingReceiveUserId"); var userSecret = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingReceiveUserSecret"); if (userId == null || string.IsNullOrEmpty(userId.Value) || userSecret == null || string.IsNullOrEmpty(userSecret.Value)) { throw Oops.Bah("大简云接收订舱用户key和秘钥未配置,请联系管理员"); } //构建数据并发送 var orderList = _rep.AsQueryable().Where(x => ids.Contains(x.Id)).ToList(); var ordIdList = orderList.Select(o => o.Id).ToList(); var ctnList = _repCtn.AsQueryable().Where(x => ordIdList.Contains(x.BILLID.Value)).ToList(); var fileList = _repFile.AsQueryable().Where(x => ordIdList.Contains(x.BookingId)).ToList(); var serviceItemList = _repServiceItem.AsQueryable().Where(x => ordIdList.Contains(x.BookingId.Value)).ToList(); var sendList = new List(); var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } foreach (var order in orderList) { if (order.BSSTATUS != "已录入" && order.BSSTATUS != "已驳回") { throw Oops.Bah($"{order.BOOKINGNO} 当前状态为{order.BSSTATUS},不能提交"); } var dto = order.Adapt(); dto.BookingTenantId = UserManager.TENANT_ID; dto.BookingTenantName = UserManager.TENANT_NAME; dto.BookingCompanyId = UserManager.DjyCompanyId; dto.BookingUserId = UserManager.UserId; dto.BookingUserName = UserManager.Name; dto.BookingDjyUserId = UserManager.DjyUserId; dto.CtnList = ctnList.Where(x => x.BILLID == dto.Id).ToList().Adapt>(); dto.ServiceItemList = serviceItemList.Where(x => x.BookingId == dto.Id).ToList().Adapt>(); dto.Files = new Dictionary(); foreach (var file in fileList.Where(x => x.BookingId == dto.Id)) { var fileAbsPath = Path.Combine(dirAbs, file.FilePath); if (File.Exists(fileAbsPath)) { dto.Files.Add(file.FileName, Convert.ToBase64String(File.ReadAllBytes(fileAbsPath))); } } sendList.Add(dto); } //构建完整url var submitUrl = recUrl.Value; if (!submitUrl.EndsWith("/")) { submitUrl += "/"; } submitUrl += "BookingCustomerOrder/ReceiveBooking"; _logger.LogInformation($"提交订舱数据({submitUrl},{userId.Value},{userSecret.Value}):{JsonConvert.SerializeObject(sendList)}"); var rtn = await submitUrl .SetHeaders(new Dictionary { { CommonConst.API_USER_HEADER_KEY, userId.Value}, { CommonConst.API_USER_HEADER_SECRET, userSecret.Value} }) .SetBody(sendList) .PostAsStringAsync(); _logger.LogInformation($"返回数据:{rtn}"); var resultText = new StringBuilder(); var jobjRtn = JObject.Parse(rtn); if (jobjRtn.GetIntValue("code") != 200) { throw Oops.Bah(jobjRtn.GetStringValue("message")); } else { var arrData = jobjRtn.GetJArrayValue("data"); foreach (JObject item in arrData) { var id = item.GetLongValue("id"); var bookingno = item.GetStringValue("bookingno"); var message = item.GetStringValue("message"); var succ = item.GetBooleanValue("success"); if (succ) { var model = _rep.AsQueryable().First(x => x.Id == id); model.BSSTATUS = "已提交"; await _rep.UpdateAsync(model); //日志动态 SaveAuditLog("已提交", id); } else { //日志动态 SaveAuditLog($"提交失败:{item.GetBooleanValue("message")}", id); } resultText.AppendLine($"{bookingno}:{message}"); } return resultText.ToString(); } } /// /// 取消提交订舱 /// /// [HttpPost("/BookingCustomerOrder/CancelSubmit")] public async Task CancelSubmit(List ids) { var recUrl = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingRequestReceiveUrl"); if (recUrl == null || string.IsNullOrEmpty(recUrl.Value)) { throw Oops.Bah("大简云接收订舱URL地址未配置,请联系管理员"); } var userId = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingReceiveUserId"); var userSecret = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingReceiveUserSecret"); if (userId == null || string.IsNullOrEmpty(userId.Value) || userSecret == null || string.IsNullOrEmpty(userSecret.Value)) { throw Oops.Bah("大简云接收订舱用户key和秘钥未配置,请联系管理员"); } var orderList = _rep.AsQueryable().Where(x => ids.Contains(x.Id)).ToList(); var noSubmitList = orderList.Where(x => x.BSSTATUS != "已提交").Select(x => x.BOOKINGNO).ToList(); if (noSubmitList.Count > 0) { throw Oops.Bah($"编号为 {string.Join(",", noSubmitList)} 的状态不能取消订舱"); } var sendList = orderList.Select(x => new BookingCustomerCancelSubmitDto() { Id = x.Id, BOOKINGNO = x.BOOKINGNO }).ToList(); //构建完整url var submitUrl = recUrl.Value; if (!submitUrl.EndsWith("/")) { submitUrl += "/"; } submitUrl += "BookingCustomerOrder/CancelBooking"; _logger.LogInformation($"取消提交订舱数据({submitUrl},{userId.Value},{userSecret.Value}):{JsonConvert.SerializeObject(sendList)}"); var rtn = await submitUrl .SetHeaders(new Dictionary { { CommonConst.API_USER_HEADER_KEY, userId.Value}, { CommonConst.API_USER_HEADER_SECRET, userSecret.Value} }) .SetBody(sendList) .PostAsStringAsync(); _logger.LogInformation($"返回数据:{rtn}"); var resultText = new StringBuilder(); var jobjRtn = JObject.Parse(rtn); if (jobjRtn.GetIntValue("code") != 200) { throw Oops.Bah(jobjRtn.GetStringValue("message")); } else { var arrData = jobjRtn.GetJArrayValue("data"); foreach (JObject item in arrData) { var id = item.GetLongValue("id"); var bookingno = item.GetStringValue("bookingno"); var message = item.GetStringValue("message"); var succ = item.GetBooleanValue("success"); if (succ) { var model = _rep.AsQueryable().First(x => x.Id == id); model.BSSTATUS = "已录入"; await _rep.UpdateAsync(model); //日志动态 SaveAuditLog($"取消提交", id); } else { //日志动态 SaveAuditLog($"取消提交失败:{item.GetBooleanValue("message")}", id); } resultText.AppendLine($"{bookingno}:{message}"); } return resultText.ToString(); } } /// /// 接收反馈订舱审核回执 /// /// [HttpPost("/BookingCustomerOrder/RecBookingAuditFeedback"), AllowAnonymous, ApiUser(ApiCode = "BookingRecAuditFeedback")] public async Task RecBookingAuditFeedback(BookingCustomerRecAduitFeedbackDto dto) { var id = Convert.ToInt64(dto.Id); var model = _rep.AsQueryable().Filter(null, true).First(x => x.Id == id); if (model == null) { throw Oops.Bah("未找到数据"); } if (model.BSSTATUS != "已提交") { throw Oops.Bah("当前状态不能接受审核回推"); } if (dto.Accept) { model.BSSTATUS = "已审核"; } else { model.BSSTATUS = "已驳回"; } await _rep.UpdateAsync(model); //日志动态 SaveAuditLog($"{model.BSSTATUS},审核意见:{dto.Comment}", id, model.CreatedUserId.Value, model.TenantId.Value, "系统"); //进入客户订舱系统的订舱台账 if (dto.Accept) { var bkOrder = model.Adapt(); bkOrder.Id = YitIdHelper.NextId(); bkOrder.BSSTATUS = "已录入"; bkOrder.ParentId = 0; await _repOrder.InsertAsync(bkOrder); model.BookingId = bkOrder.Id; //客户订舱数据与订舱台账数据关联 await _rep.UpdateAsync(model); var ctnList = await _repCtn.AsQueryable().Filter(null, true).Where(x => x.BILLID == model.Id).ToListAsync(); foreach (var ctn in ctnList) { ctn.Id = YitIdHelper.NextId(); ctn.BILLID = bkOrder.Id; await _repCtn.InsertAsync(ctn); } //服务项目 var servList = await _repServiceItem.Where(x => x.BookingId == model.Id).ToListAsync(); foreach (var serv in servList) { serv.Id = YitIdHelper.NextId(); serv.BookingId = bkOrder.Id; await _repServiceItem.InsertAsync(serv); } return bkOrder.Id; } return 0; } /// /// 接收订舱数据的回推 /// /// [HttpPost("/BookingCustomerOrder/RecBookingDataFeedback"), AllowAnonymous, ApiUser(ApiCode = "BookingRecAuditFeedback")] public async Task RecBookingDataFeedback(BookingCustomerRecDataFeedbackDto recModel) { _logger.LogInformation($"收到订舱回推数据:{recModel.ToJsonString()}"); var dbOrder = await _repOrder.AsQueryable().Filter(null, true).FirstAsync(x => !x.IsDeleted && x.Id == recModel.Order.Id); if (dbOrder == null) { throw Oops.Bah($"未找到id为{recModel.Order.Id}的数据"); } if (!string.IsNullOrEmpty(dbOrder.MBLNO)) //提单号不覆盖 { recModel.Order.MBLNO = dbOrder.MBLNO; } //保存主表 recModel.Order.Adapt(dbOrder); await _repOrder.UpdateAsync(dbOrder); //更新箱信息 await _repCtn.DeleteAsync(x => x.BILLID == recModel.Order.Id); foreach (var ctn in recModel.Ctns) { var saveCtn = ctn.Adapt(); saveCtn.BILLID = recModel.Order.Id; saveCtn.CreatedUserId = dbOrder.CreatedUserId; saveCtn.CreatedUserName = "系统"; saveCtn.CreatedTime = DateTime.Now; saveCtn.TenantId = dbOrder.TenantId; await _repCtn.InsertAsync(saveCtn); } //货运动态 foreach (var sta in recModel.StatusLogs) { await _repStatuslogDetail.DeleteAsync(x => x.PId == sta.Id); await _repStatuslog.DeleteAsync(x => x.Id == sta.Id); var insStaLog = sta.Adapt(); insStaLog.BookingId = recModel.Order.Id; await _repStatuslog.InsertAsync(insStaLog); foreach (var staDetail in sta.Details) { var insStaDetail = staDetail.Adapt(); insStaDetail.PId = insStaLog.Id; await _repStatuslogDetail.InsertAsync(insStaDetail); } } //文件 var opt = App.GetOptions(); var dirAbs = string.Empty; if (string.IsNullOrEmpty(opt.basePath)) { dirAbs = Path.Combine(App.WebHostEnvironment.WebRootPath, opt.relativePath); } else { dirAbs = Path.Combine(opt.basePath, opt.relativePath); } if (!Directory.Exists(dirAbs)) Directory.CreateDirectory(dirAbs); var dbFiles = await _repFile.Where(f => f.BookingId == recModel.Order.Id).ToListAsync(); foreach (var file in recModel.Files) { if (dbFiles.Count(ff => ff.Id == file.Id) == 0) //新文件 { var insFile = file.Adapt(); insFile.BookingId = recModel.Order.Id; insFile.CreatedUserId = dbOrder.CreatedUserId; insFile.CreatedUserName = "系统"; insFile.CreatedTime = DateTime.Now; insFile.TenantId = dbOrder.TenantId; var saveFileName = $"{DateTime.Now.Ticks}{Path.GetExtension(file.FileName)}"; var fileRelaPath = Path.Combine(opt.relativePath, saveFileName).ToLower(); var fileAbsPath = Path.Combine(dirAbs, saveFileName).ToLower(); insFile.FilePath = fileRelaPath; File.WriteAllBytes(fileAbsPath, file.FileContent); await _repFile.InsertAsync(insFile); } } } #endregion #region 大简云订舱平台操作与接口 /// /// 接收客户订舱系统提交的数据 /// /// [HttpPost("/BookingCustomerOrder/ReceiveBooking"), AllowAnonymous, ApiUser(ApiCode = "DjyBookingReceiveApi")] public async Task> ReceiveBooking(List list) { _logger.LogInformation($"收到提交的订舱数据:{JsonConvert.SerializeObject(list)}"); var rtnList = new List(); foreach (var item in list) { var strId = item.Id.ToString(); var order = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.TenantId == UserManager.TENANT_ID && x.BSNO == strId); if (order == null) { order = item.Adapt(); order.BSNO = order.Id.ToString(); //客户订舱系统中的id order.Id = YitIdHelper.NextId(); order.BSSTATUS = "已接收"; await _rep.InsertAsync(order); } else { if (order.BSSTATUS == "已审核") { rtnList.Add(new BookingSubmitResultModel() { Id = item.Id, Success = false, BOOKINGNO = item.BOOKINGNO, Message = $"数据已审核,不能重复提交" }); ; continue; } var idBackup = order.Id; //防止覆盖 var bsnoBackup = order.BSNO; //防止覆盖 order = item.Adapt(order); order.Id = idBackup; order.BSNO = bsnoBackup; order.BSSTATUS = "已接收"; order.IsDeleted = false; await _rep.UpdateAsync(order); } //箱信息 await _repCtn.DeleteAsync(x => x.BILLID == order.Id); foreach (var ctn in item.CtnList) { var bkCtn = ctn.Adapt(); bkCtn.Id = YitIdHelper.NextId(); bkCtn.BILLID = order.Id; await _repCtn.InsertAsync(bkCtn); } //服务项目 await _repServiceItem.DeleteAsync(x => x.BookingId == order.Id); foreach (var serv in item.ServiceItemList) { var bkServ = serv.Adapt(); bkServ.Id = YitIdHelper.NextId(); bkServ.BookingId = order.Id; await _repServiceItem.InsertAsync(bkServ); } //文件 await _repFile.DeleteAsync(x => x.BookingId == order.Id); var opt = App.GetOptions(); var dirAbs = string.Empty; if (string.IsNullOrEmpty(opt.basePath)) { dirAbs = Path.Combine(App.WebHostEnvironment.WebRootPath, opt.relativePath); } else { dirAbs = Path.Combine(opt.basePath, opt.relativePath); } foreach (var file in item.Files) { var saveFileName = $"{DateTime.Now.Ticks}{Path.GetExtension(file.Key)}"; var fileRelaPath = Path.Combine(opt.relativePath, saveFileName).ToLower(); var fileAbsPath = Path.Combine(dirAbs, saveFileName).ToLower(); File.WriteAllBytes(fileAbsPath, Convert.FromBase64String(file.Value)); var bkFile = new BookingFile { Id = YitIdHelper.NextId(), FileName = Path.GetFileName(file.Key), FilePath = fileRelaPath, TypeCode = "tuodan", TypeName = "托单文件", BookingId = order.Id, }; await _repFile.InsertAsync(bkFile); } rtnList.Add(new BookingSubmitResultModel() { Id = item.Id, Success = true, BOOKINGNO = item.BOOKINGNO, Message = $"提交成功" }); //日志动态 SaveAuditLog($"已接收", order.Id); } return rtnList; } /// /// 审核订舱请求 /// /// [HttpPost("/BookingCustomerOrder/AuditBooking")] public async Task AuditBooking(long id, bool accept, string comment) { var model = _rep.FirstOrDefault(x => x.Id == id); if (model == null) { throw Oops.Bah("未找到业务信息"); } if (model.BSSTATUS != "已接收") { throw Oops.Bah("当前状态不能审核"); } if (accept) { model.BSSTATUS = "已审核"; } else { model.BSSTATUS = "已驳回"; } //回推回执 var recFeedbackConfig = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackURL"); if (recFeedbackConfig == null || string.IsNullOrEmpty(recFeedbackConfig.Value)) { throw Oops.Bah("回推订舱审核结果的URL地址未配置,请联系管理员"); } var recFeedbackUserKey = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackUserKey"); if (recFeedbackUserKey == null || string.IsNullOrEmpty(recFeedbackUserKey.Value)) { throw Oops.Bah("回推订舱审核结果的用户KEY未配置,请联系管理员"); } var recFeedbackUserSecret = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackUserSecret"); if (recFeedbackUserSecret == null || string.IsNullOrEmpty(recFeedbackUserSecret.Value)) { throw Oops.Bah("回推订舱审核结果的用户秘钥未配置,请联系管理员"); } var sendObj = new BookingCustomerRecAduitFeedbackDto() { Id = model.BSNO, Accept = accept, Comment = comment }; var feedbackUrl = recFeedbackConfig.Value; if (!feedbackUrl.EndsWith("/")) { feedbackUrl += "/"; } feedbackUrl += "BookingCustomerOrder/RecBookingAuditFeedback"; _logger.LogInformation($"回推审核数据:{JsonConvert.SerializeObject(sendObj)},URL:{feedbackUrl}"); var rtn = await feedbackUrl .SetHeaders(new Dictionary { { CommonConst.API_USER_HEADER_KEY, recFeedbackUserKey.Value}, { CommonConst.API_USER_HEADER_SECRET, recFeedbackUserSecret.Value} }) .SetBody(sendObj) .PostAsStringAsync(); _logger.LogInformation($"回推审核返回:{rtn}"); var jobjRtn = JObject.Parse(rtn); if (jobjRtn.GetIntValue("code") != 200) { throw Oops.Bah(jobjRtn.GetStringValue("message")); } await _rep.UpdateAsync(model); //回推成功后,存库 //日志动态 SaveAuditLog($"{(accept ? "审核通过" : "审核驳回")},审核意见:{comment}", id); //进入订舱台账 if (accept) { var custBookId = jobjRtn.GetStringValue("data"); //返回的客户订舱系统的订舱数据id var bkOrder = model.Adapt(); bkOrder.Id = YitIdHelper.NextId(); bkOrder.BSNO = custBookId; bkOrder.BSSTATUS = "已录入"; bkOrder.CUSTOMERNAME = model.BookingTenantName; bkOrder.ParentId = 0; await _repOrder.InsertAsync(bkOrder); model.BookingId = bkOrder.Id; //客户订舱数据与订舱台账数据关联 await _rep.UpdateAsync(model); var ctnList = await _repCtn.AsQueryable().Filter(null, true).Where(x => x.BILLID == model.Id).ToListAsync(); foreach (var ctn in ctnList) { ctn.Id = YitIdHelper.NextId(); ctn.BILLID = bkOrder.Id; await _repCtn.InsertAsync(ctn); } //服务项目 var servList = await _repServiceItem.Where(x => x.BookingId == model.Id).ToListAsync(); foreach (var serv in servList) { serv.Id = YitIdHelper.NextId(); serv.BookingId = bkOrder.Id; await _repServiceItem.InsertAsync(serv); } } } /// /// 接收客户订舱系统取消提交的数据 /// /// [HttpPost("/BookingCustomerOrder/CancelBooking"), AllowAnonymous, ApiUser(ApiCode = "DjyBookingReceiveApi")] public async Task> CancelBooking(List list) { _logger.LogInformation($"收到提交的订舱数据:{JsonConvert.SerializeObject(list)}"); var rtnList = new List(); foreach (var item in list) { var strId = item.Id.ToString(); var order = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.TenantId == UserManager.TENANT_ID && !x.IsDeleted && x.BSNO == strId); if (order == null) { rtnList.Add(new BookingSubmitResultModel() { Id = item.Id, Success = false, BOOKINGNO = item.BOOKINGNO, Message = $"未找到订舱数据" }); } else { if (order.BSSTATUS != "已接收") { rtnList.Add(new BookingSubmitResultModel() { Id = item.Id, Success = false, BOOKINGNO = item.BOOKINGNO, Message = $"当前状态不能取消" }); continue; } order.IsDeleted = true; await _rep.UpdateAsync(order); rtnList.Add(new BookingSubmitResultModel() { Id = item.Id, Success = true, BOOKINGNO = item.BOOKINGNO, Message = $"已成功取消" }); //日志动态 SaveAuditLog($"取消提交", order.Id); } } return rtnList; } #endregion #region 私有方法 /// /// 保存审核的日志动态(使用当前登录人信息) /// private void SaveAuditLog(string status, long bookId) { var staLog = new BookingStatusLog(); staLog.Status = status; staLog.CreatedUserId = UserManager.UserId; staLog.CreatedUserName = UserManager.Name; staLog.CreatedTime = DateTime.Now; staLog.OpTime = DateTime.Now; staLog.BookingId = bookId; staLog.Category = StaLogCateAudit; _repStatuslog.Insert(staLog); } /// /// 保存审核的日志动态 /// private void SaveAuditLog(string status, long bookId, long userId, long tenantId, string userName) { var staLog = new BookingStatusLog(); staLog.Status = status; staLog.CreatedUserId = userId; staLog.CreatedUserName = userName; staLog.CreatedTime = DateTime.Now; staLog.OpTime = DateTime.Now; staLog.BookingId = bookId; staLog.Category = StaLogCateAudit; staLog.TenantId = tenantId; _repStatuslog.Insert(staLog); } #endregion } }