From ed04c415e51e8d6e8984c990b7e72c04298bc5b0 Mon Sep 17 00:00:00 2001 From: jianghaiqing Date: Mon, 19 Jun 2023 17:07:42 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9TSL=20EDI=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=94=B6=E3=80=81=E5=8F=91=E3=80=81=E9=80=9A=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E8=A1=8C=E6=95=B08=E6=94=B9=E4=B8=BA10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Myshipping.Application/EDI/TSLEdiHelper.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Myshipping.Application/EDI/TSLEdiHelper.cs b/Myshipping.Application/EDI/TSLEdiHelper.cs index cc4adc5f..8b0c73bf 100644 --- a/Myshipping.Application/EDI/TSLEdiHelper.cs +++ b/Myshipping.Application/EDI/TSLEdiHelper.cs @@ -441,7 +441,8 @@ namespace Myshipping.Application.EDI.TSL else { //2023-03-02 测试发现与东胜的限制行数不同,东胜是8行,跟韩工确认限制从6改为8 - error += formatlengthError("txt", headData.SHIPPER, 35, headData.MBLNO, "发货人", 8, "*", false); + //2023-06-19 合川操作提出收、发、通需要能录超过最大8行,查看TSL报文,允许最大10行,将最大8行改为10行 + error += formatlengthError("txt", headData.SHIPPER, 35, headData.MBLNO, "发货人", 10, "*", false); } } } @@ -468,7 +469,8 @@ namespace Myshipping.Application.EDI.TSL else { //2023-03-02 测试发现与东胜的限制行数不同,东胜是8行,跟韩工确认限制从6改为8 - error += formatlengthError("txt", headData.CONSIGNEE, 35, headData.MBLNO, "收货人", 8, "**", false); + //2023-06-19 合川操作提出收、发、通需要能录超过最大8行,查看TSL报文,允许最大10行,将最大8行改为10行 + error += formatlengthError("txt", headData.CONSIGNEE, 35, headData.MBLNO, "收货人", 10, "**", false); } } } @@ -523,7 +525,8 @@ namespace Myshipping.Application.EDI.TSL else { //2023-03-02 测试发现与东胜的限制行数不同,东胜是8行,跟韩工确认限制从6改为8 - error += formatlengthError("txt", headData.NOTIFYPARTY, 35, headData.MBLNO, "通知人", 8, "***", false); + //2023-06-19 合川操作提出收、发、通需要能录超过最大8行,查看TSL报文,允许最大10行,将最大8行改为10行 + error += formatlengthError("txt", headData.NOTIFYPARTY, 35, headData.MBLNO, "通知人", 10, "***", false); } } } From b6ea79ab8bc5753a0184c3582def906046646dd3 Mon Sep 17 00:00:00 2001 From: wanghaomei Date: Tue, 20 Jun 2023 09:08:57 +0800 Subject: [PATCH 2/2] =?UTF-8?q?code=E7=99=BB=E5=BD=95=20=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E8=AE=A2=E8=88=B1=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/BookingCustomerOrder.cs | 40 ++ .../BookingCustomerOrderService.cs | 534 +++++++++++++++++- .../Service/BookingCustomerOrder/Dto/Dtos.cs | 204 +++++++ Myshipping.Core/Const/ClaimConst.cs | 5 + Myshipping.Core/Entity/SysTenant.cs | 6 + Myshipping.Core/Extension/JsonExtension.cs | 20 + Myshipping.Core/Filter/ApiUserFilter.cs | 1 + Myshipping.Core/Manager/UserManager.cs | 5 + Myshipping.Core/Myshipping.Core.xml | 30 + Myshipping.Core/Service/Auth/AuthService.cs | 109 +++- 10 files changed, 929 insertions(+), 25 deletions(-) diff --git a/Myshipping.Application/Entity/BookingCustomerOrder.cs b/Myshipping.Application/Entity/BookingCustomerOrder.cs index 361e9c44..c9ff45b9 100644 --- a/Myshipping.Application/Entity/BookingCustomerOrder.cs +++ b/Myshipping.Application/Entity/BookingCustomerOrder.cs @@ -11,6 +11,10 @@ namespace Myshipping.Application.Entity [Description("客户订舱")] public class BookingCustomerOrder : DBEntityTenant { + /// + /// 其他业务系统ID + /// + public string BSNO { get; set; } /// /// 业务状态 /// @@ -188,5 +192,41 @@ namespace Myshipping.Application.Entity /// 租户名称 /// public string TenantName { get; set; } + + /// + /// 订舱台账ID + /// + public long BookingId { get; set; } + + /// + /// 订舱租户id + /// + public long BookingTenantId { get; set; } + + /// + /// 订舱租户名称 + /// + public string BookingTenantName { get; set; } + + /// + /// 订舱租户大简云公司id + /// + public string BookingCompanyId { get; set; } + + /// + /// 订舱用户id + /// + public long BookingUserId { get; set; } + + /// + /// 订舱用户名称 + /// + public string BookingUserName { get; set; } + + /// + /// 订舱大简云用户id + /// + public string BookingDjyUserId { get; set; } } + } \ No newline at end of file diff --git a/Myshipping.Application/Service/BookingCustomerOrder/BookingCustomerOrderService.cs b/Myshipping.Application/Service/BookingCustomerOrder/BookingCustomerOrderService.cs index 38e1a850..d7a769be 100644 --- a/Myshipping.Application/Service/BookingCustomerOrder/BookingCustomerOrderService.cs +++ b/Myshipping.Application/Service/BookingCustomerOrder/BookingCustomerOrderService.cs @@ -2,6 +2,7 @@ using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; +using Furion.RemoteRequest.Extensions; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -11,6 +12,8 @@ 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; @@ -34,9 +37,13 @@ namespace Myshipping.Application private readonly ISysCacheService _cache; private readonly SqlSugarRepository _repFile; private readonly SqlSugarRepository _repStatuslog; + private readonly SqlSugarRepository _repServiceItem; + private readonly SqlSugarRepository _repOrder; public BookingCustomerOrderService(SqlSugarRepository rep, SqlSugarRepository repCtn, - ILogger logger, ISysCacheService cache, SqlSugarRepository repFile, SqlSugarRepository statuslog) + ILogger logger, ISysCacheService cache, SqlSugarRepository repFile, + SqlSugarRepository statuslog, SqlSugarRepository repServiceItem, + SqlSugarRepository repOrder) { this._logger = logger; this._rep = rep; @@ -44,23 +51,62 @@ namespace Myshipping.Application this._cache = cache; this._repFile = repFile; this._repStatuslog = statuslog; - + this._repServiceItem = repServiceItem; + this._repOrder = repOrder; } - //查询台账 + #region 订舱草稿及附件 + /// + /// 订舱草稿台账 + /// + /// + /// [HttpPost("/BookingCustomerOrder/PageData")] public async Task> PageData(BookingCustomerOrderQueryInput input) { - var query = _rep.AsQueryable(); + var query = _rep.AsQueryable().Filter(null, true).Where(x => x.TenantId == UserManager.TENANT_ID) + .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(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.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)).ToList(); + foreach (var item in list.Items) + { + item.LogList = staLogList.Where(x => x.BookingId == item.Id).OrderBy(x => x.OpTime).Adapt>(); + } + return list; } + /// - /// 保存数据 + /// 保存草稿数据 /// /// /// @@ -95,7 +141,7 @@ namespace Myshipping.Application else { entity = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == input.Id); - if (entity.BSSTATUS != "已录入" || entity.BSSTATUS != "已驳回") + if (entity.BSSTATUS != "已录入" && entity.BSSTATUS != "已驳回") { throw Oops.Bah("当前状态不允许修改"); } @@ -123,6 +169,25 @@ namespace Myshipping.Application 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); } //文件 @@ -141,6 +206,17 @@ namespace Myshipping.Application 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) { @@ -171,17 +247,6 @@ namespace Myshipping.Application } } - //清除前端已删除的文件 - 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); - } - //日志动态 var staLog = new BookingStatusLog(); @@ -193,14 +258,15 @@ namespace Myshipping.Application staLog.BookingId = entity.Id; _repStatuslog.Insert(staLog); + + //返回给前端数据 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).ToList().Adapt>(); + outModel.ServiceItemList = _repServiceItem.AsQueryable().Where(x => x.BookingId == entity.Id).ToList().Adapt>(); return outModel; } @@ -221,8 +287,8 @@ namespace Myshipping.Application 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).ToList().Adapt>(); + outModel.ServiceItemList = _repServiceItem.AsQueryable().Where(x => x.BookingId == entity.Id).ToList().Adapt>(); return outModel; } @@ -283,19 +349,441 @@ namespace Myshipping.Application 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 = fileName }; + //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; } + #endregion + + #region 客户订舱系统操作与接口 /// /// 提交订舱 /// /// [HttpPost("/BookingCustomerOrder/Submit")] - public async Task 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.GetAllTenantParam().Result.FirstOrDefault(x => x.TenantId == UserManager.TENANT_ID && x.ParaCode == "DjyBookingReceiveUserId"); + var userSecret = _cache.GetAllTenantParam().Result.FirstOrDefault(x => x.TenantId == UserManager.TENANT_ID && x.ParaCode == "DjyBookingReceiveUserSecret"); + if (userId == null || string.IsNullOrEmpty(userId.ItemCode) || userSecret == null || string.IsNullOrEmpty(userSecret.ItemCode)) + { + 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); + } + + _logger.LogInformation($"提交订舱数据({recUrl.Value},{userId.ItemCode},{userSecret.ItemCode}):{JsonConvert.SerializeObject(sendList)}"); + + var rtn = await recUrl.Value + .SetHeaders(new Dictionary { + { CommonConst.API_USER_HEADER_KEY, userId.ItemCode}, + { CommonConst.API_USER_HEADER_SECRET, userSecret.ItemCode} + }) + .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); + + //日志动态 + var staLog = new BookingStatusLog(); + staLog.Status = "已提交"; + staLog.CreatedUserId = UserManager.UserId; + staLog.CreatedUserName = UserManager.Name; + staLog.CreatedTime = DateTime.Now; + staLog.OpTime = DateTime.Now; + staLog.BookingId = id; + _repStatuslog.Insert(staLog); + } + else + { + //日志动态 + var staLog = new BookingStatusLog(); + staLog.Status = $"提交失败:{item.GetBooleanValue("message")}"; + staLog.CreatedUserId = UserManager.UserId; + staLog.CreatedUserName = UserManager.Name; + staLog.CreatedTime = DateTime.Now; + staLog.OpTime = DateTime.Now; + staLog.BookingId = id; + _repStatuslog.Insert(staLog); + } + + 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); + + //日志动态 + var staLog = new BookingStatusLog(); + staLog.Status = $"{model.BSSTATUS},审核意见:{dto.Comment}"; + staLog.CreatedUserId = UserManager.UserId; + staLog.CreatedUserName = UserManager.Name; + staLog.CreatedTime = DateTime.Now; + staLog.OpTime = DateTime.Now; + staLog.BookingId = id; + _repStatuslog.Insert(staLog); + + //进入客户订舱系统的订舱台账 + if (dto.Accept) + { + var bkOrder = model.Adapt(); + bkOrder.Id = YitIdHelper.NextId(); + bkOrder.BSSTATUS = "已录入"; + await _repOrder.InsertAsync(bkOrder); + + model.BookingId = bkOrder.Id; //客户订舱数据与订舱台账数据关联 + await _rep.UpdateAsync(model); + + var ctnList = await _repCtn.Where(x => x.BILLID == model.Id).ToListAsync(); + foreach (var ctn in ctnList) + { + ctn.Id = YitIdHelper.NextId(); + ctn.BILLID = bkOrder.Id; + await _repCtn.InsertAsync(ctn); + } + + return bkOrder.Id; + } + + return 0; + } + + #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.IsDeleted && 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 = order.Adapt(order); + order.Id = idBackup; + order.BSNO = bsnoBackup; + order.BSSTATUS = "已接收"; + 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 = $"提交成功" + }); + + + //日志动态 + var staLog = new BookingStatusLog(); + staLog.Status = "已接收"; + staLog.CreatedUserId = UserManager.UserId; + staLog.CreatedUserName = UserManager.Name; + staLog.CreatedTime = DateTime.Now; + staLog.OpTime = DateTime.Now; + staLog.BookingId = order.Id; + _repStatuslog.Insert(staLog); + } + + 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 == "DjyBookingCustomerRecAuditFeedbackURL"); + if (recFeedbackConfig == null || string.IsNullOrEmpty(recFeedbackConfig.Value)) + { + throw Oops.Bah("回推订舱审核结果的URL地址未配置,请联系管理员"); + } + + var recFeedbackUserKey = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecAuditFeedbackUserKey"); + if (recFeedbackUserKey == null || string.IsNullOrEmpty(recFeedbackUserKey.Value)) + { + throw Oops.Bah("回推订舱审核结果的用户KEY未配置,请联系管理员"); + } + + var recFeedbackUserSecret = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecAuditFeedbackUserSecret"); + if (recFeedbackUserSecret == null || string.IsNullOrEmpty(recFeedbackUserSecret.Value)) + { + throw Oops.Bah("回推订舱审核结果的用户秘钥未配置,请联系管理员"); + } + + var sendObj = new BookingCustomerRecAduitFeedbackDto() + { + Id = model.BSNO, + Accept = accept, + Comment = comment + }; + + _logger.LogInformation($"回推审核数据:{JsonConvert.SerializeObject(sendObj)}"); + + var rtn = await recFeedbackConfig.Value + .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); //回推成功后,存库 + + //日志动态 + var staLog = new BookingStatusLog(); + staLog.Status = $"{(accept ? "审核通过" : "审核驳回")},审核意见:{comment}"; + staLog.CreatedUserId = UserManager.UserId; + staLog.CreatedUserName = UserManager.Name; + staLog.CreatedTime = DateTime.Now; + staLog.OpTime = DateTime.Now; + staLog.BookingId = id; + _repStatuslog.Insert(staLog); + + //进入订舱台账 + if (accept) + { + var custBookId = jobjRtn.GetStringValue("data"); //返回的客户订舱系统的订舱数据id + var bkOrder = model.Adapt(); + bkOrder.Id = YitIdHelper.NextId(); + bkOrder.BSNO = custBookId; + bkOrder.BSSTATUS = "已录入"; + await _repOrder.InsertAsync(bkOrder); + + model.BookingId = bkOrder.Id; //客户订舱数据与订舱台账数据关联 + await _rep.UpdateAsync(model); + + var ctnList = await _repCtn.Where(x => x.BILLID == model.Id).ToListAsync(); + foreach (var ctn in ctnList) + { + ctn.Id = YitIdHelper.NextId(); + ctn.BILLID = bkOrder.Id; + await _repCtn.InsertAsync(ctn); + } + } + + } + #endregion + } } diff --git a/Myshipping.Application/Service/BookingCustomerOrder/Dto/Dtos.cs b/Myshipping.Application/Service/BookingCustomerOrder/Dto/Dtos.cs index 374a17d3..28c8731a 100644 --- a/Myshipping.Application/Service/BookingCustomerOrder/Dto/Dtos.cs +++ b/Myshipping.Application/Service/BookingCustomerOrder/Dto/Dtos.cs @@ -9,6 +9,66 @@ namespace Myshipping.Application { public class BookingCustomerOrderQueryInput : PageInputBase { + /// + /// 系统编号(订舱编号) + /// + public string BOOKINGNO { get; set; } + + /// + /// 船名 + /// + public string VESSEL { get; set; } + /// + /// 海关航次 + /// + public string VOYNO { get; set; } + + /// + /// 场站代码 + /// + public string YARDID { get; set; } + /// + /// 场站 + /// + public string YARD { get; set; } + /// + /// 开船日期起始 + /// + public DateTime? ETDStart { get; set; } + /// + /// 开船日期截止 + /// + public DateTime? ETDEnd { get; set; } + /// + /// 卸货港代码 + /// + public string PORTDISCHARGEID { get; set; } + /// + /// 卸货港 + /// + public string PORTDISCHARGE { get; set; } + /// + /// 船公司代号 + /// + public string CARRIERID { get; set; } + /// + /// 船公司 + /// + public string CARRIER { get; set; } + + /// + /// 录入日期起始 + /// + public DateTime? CreatedTimeStart { get; set; } + /// + /// 录入日期截止 + /// + public DateTime? CreatedTimeEnd { get; set; } + + /// + /// 业务状态 + /// + public List BSStatusList { get; set; } } //dto @@ -197,6 +257,11 @@ namespace Myshipping.Application /// 箱信息 /// public List CtnList { get; set; } + + /// + /// 服务项目 + /// + public List ServiceItemList { get; set; } } //台账返回dto @@ -206,7 +271,16 @@ namespace Myshipping.Application /// 系统编号 /// public string BOOKINGNO { get; set; } + /// + /// 业务状态 + /// + public string BSSTATUS { get; set; } + + /// + /// 日志信息 + /// + public List LogList { get; set; } } //保存返回dto @@ -217,6 +291,11 @@ namespace Myshipping.Application /// public string BOOKINGNO { get; set; } + /// + /// 业务状态 + /// + public string BSSTATUS { get; set; } + /// /// 文件列表 /// @@ -231,6 +310,11 @@ namespace Myshipping.Application /// 日志信息 /// public List LogList { get; set; } + + /// + /// 服务项目 + /// + public List ServiceItemList { get; set; } } /// @@ -279,4 +363,124 @@ namespace Myshipping.Application public virtual string CreatedUserName { get; set; } } + + + /// + /// 大简云客户订舱发送与接收dto + /// + public class BookingCustomerSubmitReceiveDto : BookingCustomerOrderDto + { + /// + /// 系统编号(订舱编号) + /// + public string BOOKINGNO { get; set; } + + /// + /// 订舱租户id + /// + public long BookingTenantId { get; set; } + + /// + /// 订舱租户名称 + /// + public string BookingTenantName { get; set; } + + /// + /// 订舱租户大简云公司id + /// + public string BookingCompanyId { get; set; } + + /// + /// 订舱用户id + /// + public long BookingUserId { get; set; } + + /// + /// 订舱用户名称 + /// + public string BookingUserName { get; set; } + + /// + /// 订舱大简云用户id + /// + public string BookingDjyUserId { get; set; } + + /// + /// 文件列表(key:文件名称,value:文件内容base64) + /// + public Dictionary Files { get; set; } + + /// + /// 箱信息 + /// + public List CtnList { get; set; } + + /// + /// 服务项目 + /// + public List ServiceItemList { get; set; } + + } + + /// + /// 提交订舱返回对象 + /// + public class BookingSubmitResultModel + { + /// + /// ID + /// + public long Id { get; set; } + + /// + /// 客户订舱系统中的订舱编号 + /// + public string BOOKINGNO { get; set; } + + /// + /// 是否成功 + /// + public bool Success { get; set; } + + /// + /// 消息内容 + /// + public string Message { get; set; } + } + + /// + /// 服务项目 + /// + public class BookingServiceItemCustomerDto + { + /// + /// 状态代码 + /// + public string Code { get; set; } + /// + /// 状态名称 + /// + public string Value { get; set; } + } + + /// + /// 接收(发送)客户订舱审核结果 + /// + public class BookingCustomerRecAduitFeedbackDto + { + /// + /// 客户订舱系统中的ID + /// + public string Id { get; set; } + + /// + /// 是否接收订舱 + /// + public bool Accept { get; set; } + + /// + /// 审核意见 + /// + public string Comment { get; set; } + } } diff --git a/Myshipping.Core/Const/ClaimConst.cs b/Myshipping.Core/Const/ClaimConst.cs index fd027310..4c025861 100644 --- a/Myshipping.Core/Const/ClaimConst.cs +++ b/Myshipping.Core/Const/ClaimConst.cs @@ -36,6 +36,11 @@ public class ClaimConst /// public const string TENANT_NAME = "TenantName"; + /// + /// 大简云companyid + /// + public const string DjyCompanyId = "DjyCompanyId"; + /// /// 大简云userid /// diff --git a/Myshipping.Core/Entity/SysTenant.cs b/Myshipping.Core/Entity/SysTenant.cs index d8cd157b..a30e2662 100644 --- a/Myshipping.Core/Entity/SysTenant.cs +++ b/Myshipping.Core/Entity/SysTenant.cs @@ -62,4 +62,10 @@ public class SysTenant : DEntityBase /// 租户类型 /// public TenantTypeEnum TenantType { get; set; } + + /// + /// 大简云公司ID + /// + [MaxLength(50)] + public string CompId { get; set; } } diff --git a/Myshipping.Core/Extension/JsonExtension.cs b/Myshipping.Core/Extension/JsonExtension.cs index 5c6accc1..c4180248 100644 --- a/Myshipping.Core/Extension/JsonExtension.cs +++ b/Myshipping.Core/Extension/JsonExtension.cs @@ -80,6 +80,26 @@ namespace Myshipping.Core return rtnVal; } + /// + /// 获取long值 + /// + /// + /// + /// + public static long GetLongValue(this JObject jobj, string prop) + { + var jt = jobj[prop]; + if (jt == null) + { + return 0; + } + + var strVal = jt.ToString(); + long rtnVal = 0; + long.TryParse(strVal, out rtnVal); + return rtnVal; + } + /// /// 获取decimal值 /// diff --git a/Myshipping.Core/Filter/ApiUserFilter.cs b/Myshipping.Core/Filter/ApiUserFilter.cs index f0b13404..e9715be0 100644 --- a/Myshipping.Core/Filter/ApiUserFilter.cs +++ b/Myshipping.Core/Filter/ApiUserFilter.cs @@ -65,6 +65,7 @@ namespace Myshipping.Core identity.AddClaim(new Claim(type: ClaimConst.CLAINM_TENANT_TYPE, value: tenant.TenantType.ToString())); identity.AddClaim(new Claim(type: ClaimConst.TENANT_ID, value: tenant.Id.ToString())); identity.AddClaim(new Claim(type: ClaimConst.TENANT_NAME, value: tenant.Name)); + identity.AddClaim(new Claim(type: ClaimConst.DjyCompanyId, value: tenant.CompId == null ? string.Empty : tenant.CompId)); identity.AddClaim(new Claim(type: ClaimConst.DjyUserId, value: user.DjyUserId)); ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity); httpContext.User = claimsPrincipal; diff --git a/Myshipping.Core/Manager/UserManager.cs b/Myshipping.Core/Manager/UserManager.cs index ece8eb6c..841c00d0 100644 --- a/Myshipping.Core/Manager/UserManager.cs +++ b/Myshipping.Core/Manager/UserManager.cs @@ -42,6 +42,11 @@ public static class UserManager /// public static string TENANT_NAME => App.User.FindFirst(ClaimConst.TENANT_NAME)?.Value; + /// + /// 大简云公司id + /// + public static string DjyCompanyId => App.User.FindFirst(ClaimConst.DjyCompanyId)?.Value; + /// /// 大简云userid /// diff --git a/Myshipping.Core/Myshipping.Core.xml b/Myshipping.Core/Myshipping.Core.xml index e964f7ed..178880d6 100644 --- a/Myshipping.Core/Myshipping.Core.xml +++ b/Myshipping.Core/Myshipping.Core.xml @@ -537,6 +537,11 @@ 租户名称 + + + 大简云companyid + + 大简云userid @@ -3860,6 +3865,11 @@ 租户类型 + + + 大简云公司ID + + 定时任务 @@ -5389,6 +5399,14 @@ + + + 获取long值 + + + + + 获取decimal值 @@ -5829,6 +5847,11 @@ 租户名称 + + + 大简云公司id + + 大简云userid @@ -6144,6 +6167,13 @@ + + + 使用跳转code登录 + + + + 登录输入参数 diff --git a/Myshipping.Core/Service/Auth/AuthService.cs b/Myshipping.Core/Service/Auth/AuthService.cs index 9bb7dc89..41a1bd7b 100644 --- a/Myshipping.Core/Service/Auth/AuthService.cs +++ b/Myshipping.Core/Service/Auth/AuthService.cs @@ -15,6 +15,9 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using UAParser; +using Furion.RemoteRequest.Extensions; +using Newtonsoft.Json.Linq; +using Microsoft.Extensions.Logging; namespace Myshipping.Core.Service; @@ -27,6 +30,7 @@ public class AuthService : IAuthService, IDynamicApiController, ITransient private readonly SqlSugarRepository _sysUserRep; // 用户表仓储 private readonly SqlSugarRepository _sysLogVisRep; private readonly SqlSugarRepository _sysTenantRep; + private readonly ISysCacheService _cache; private readonly IHttpContextAccessor _httpContextAccessor; private readonly ISysEmpService _sysEmpService; // 系统员工服务 @@ -37,12 +41,14 @@ public class AuthService : IAuthService, IDynamicApiController, ITransient private readonly ISysConfigService _sysConfigService; // 验证码服务 private readonly IEventPublisher _eventPublisher; + private readonly ILogger _logger; public AuthService(SqlSugarRepository sysUserRep, SqlSugarRepository sysLogVisRep, SqlSugarRepository sysTenantRep, - IHttpContextAccessor httpContextAccessor, + IHttpContextAccessor httpContextAccessor, ISysCacheService cache, ISysEmpService sysEmpService, ISysRoleService sysRoleService, ISysMenuService sysMenuService, ISysAppService sysAppService, IClickWordCaptcha captchaHandle, ISysConfigService sysConfigService, - IEventPublisher eventPublisher + IEventPublisher eventPublisher, + ILogger logger ) { _sysUserRep = sysUserRep; @@ -56,6 +62,8 @@ public class AuthService : IAuthService, IDynamicApiController, ITransient _captchaHandle = captchaHandle; _sysConfigService = sysConfigService; _eventPublisher = eventPublisher; + _logger = logger; + _cache = cache; } /// @@ -83,6 +91,12 @@ public class AuthService : IAuthService, IDynamicApiController, ITransient throw Oops.Oh(ErrorCode.D1017); //获取对应租户 var tenant = _sysTenantRep.Single(user.TenantId); + // 生成Token令牌 + return await GetLoginToken(user, tenant); + } + + private async Task GetLoginToken(SysUser user, SysTenant tenant) + { // 生成Token令牌 //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user); var accessToken = JWTEncryption.Encrypt(new Dictionary @@ -94,6 +108,7 @@ public class AuthService : IAuthService, IDynamicApiController, ITransient {ClaimConst.CLAINM_SUPERADMIN, user.AdminType}, { ClaimConst.CLAINM_TENANT_TYPE, tenant.TenantType }, { ClaimConst.TENANT_NAME, tenant.Name }, + { ClaimConst.DjyCompanyId, tenant.CompId == null ? string.Empty : tenant.CompId }, { ClaimConst.DjyUserId, user.DjyUserId }, { ClaimConst.Tel, user.Tel }, { ClaimConst.Phone, user.Phone }, @@ -152,6 +167,7 @@ public class AuthService : IAuthService, IDynamicApiController, ITransient { ClaimConst.CLAINM_SUPERADMIN, user.AdminType }, { ClaimConst.CLAINM_TENANT_TYPE, tenant.TenantType }, { ClaimConst.TENANT_NAME, tenant.Name }, + { ClaimConst.DjyCompanyId, tenant.CompId == null ? string.Empty : tenant.CompId }, { ClaimConst.DjyUserId, user.DjyUserId }, { ClaimConst.Tel, user.Tel }, { ClaimConst.Phone, user.Phone }, @@ -298,4 +314,93 @@ public class AuthService : IAuthService, IDynamicApiController, ITransient { return await Task.FromResult(_captchaHandle.CheckCode(input)); } + + + + /// + /// 使用跳转code登录 + /// + /// + /// + [AllowAnonymous] + [HttpPost("/loginWithCode")] + public async Task LoginWithCode(string code) + { + var cfg = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyAuthUrl"); + if (cfg == null || string.IsNullOrEmpty(cfg.Value)) + { + throw Oops.Bah("未找到大简云授权登录URL配置,请联系管理员"); + } + + var djyAuthUrl = cfg.Value; + if (!djyAuthUrl.EndsWith("/")) + { + djyAuthUrl += "/"; + } + + var loginUrl = djyAuthUrl + "user/login"; + var infoUrl = djyAuthUrl + "user/info"; + + _logger.LogInformation($"统一登录:{loginUrl}"); + + //跳转登录 + var result = await loginUrl + .SetBody(new { code }, "application/json") + .PostAsStringAsync(); + + _logger.LogInformation($"登录返回:{result}"); + + var jRtn = JObject.Parse(result); + if (jRtn.GetIntValue("code") == 200) + { + var jData = jRtn.GetJObjectValue("data"); + var token = jData.GetStringValue("token"); + + var headers = new Dictionary(); + headers.Add("Authorization", $"Bearer {token}"); + + _logger.LogInformation($"获取登录信息:{infoUrl}"); + + //获取登录信息 + result = await infoUrl + .SetHeaders(headers) + .GetAsStringAsync(); + _logger.LogInformation($"登录信息返回:{result}"); + jRtn = JObject.Parse(result); + if (jRtn.GetIntValue("code") == 200) + { + + jData = jRtn.GetJObjectValue("data"); + + var compId = jData.GetStringValue("compId"); + var comname = jData.GetStringValue("comname"); + var userId = jData.GetStringValue("gid"); + var showname = jData.GetStringValue("showname"); + + var tenant = _sysTenantRep.AsQueryable().Filter(null, true).First(x => x.CompId == compId); + if (tenant == null) + { + throw Oops.Bah($"{comname}不存在,请先完成公司认证!"); + } + + var user = _sysUserRep.AsQueryable().Filter(null, true).First(u => u.DjyUserId == userId); + if (tenant == null) + { + throw Oops.Bah($"{showname}不存在,请先加入公司{comname}!"); + } + + return await GetLoginToken(user, tenant); + + } + else + { + throw Oops.Bah(jRtn.GetStringValue("message")); + } + } + else + { + throw Oops.Bah(jRtn.GetStringValue("message")); + } + + } }