|
|
using Furion;
|
|
|
using Furion.DependencyInjection;
|
|
|
using Furion.DynamicApiController;
|
|
|
using Furion.EventBus;
|
|
|
using Furion.FriendlyException;
|
|
|
using Furion.LinqBuilder;
|
|
|
using Furion.RemoteRequest.Extensions;
|
|
|
using Mapster;
|
|
|
using MathNet.Numerics.LinearAlgebra.Factorization;
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
using MiniExcelLibs;
|
|
|
using Myshipping.Application.ConfigOption;
|
|
|
using Myshipping.Application.EDI;
|
|
|
using Myshipping.Application.Entity;
|
|
|
using Myshipping.Application.Enum;
|
|
|
using Myshipping.Application.Helper;
|
|
|
using Myshipping.Application.Service.BookingOrder.Dto;
|
|
|
using Myshipping.Core;
|
|
|
using Myshipping.Core.Entity;
|
|
|
using Myshipping.Core.Extension;
|
|
|
using Myshipping.Core.Helper;
|
|
|
using Myshipping.Core.Service;
|
|
|
using Newtonsoft.Json;
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
using NPOI.SS.Formula.PTG;
|
|
|
using NPOI.XWPF.UserModel;
|
|
|
using RabbitMQ.Client;
|
|
|
using StackExchange.Profiling.Internal;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Data;
|
|
|
using System.Drawing.Drawing2D;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Net.Http;
|
|
|
using System.Text;
|
|
|
using System.Text.RegularExpressions;
|
|
|
using System.Threading.Tasks;
|
|
|
using Yitter.IdGenerator;
|
|
|
|
|
|
namespace Myshipping.Application
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 客户订舱
|
|
|
/// </summary>
|
|
|
[ApiDescriptionSettings("Application", Name = "BookingCustomerOrder", Order = 1)]
|
|
|
public class BookingCustomerOrderService : IDynamicApiController, ITransient
|
|
|
{
|
|
|
private const string StaLogCateAudit = "cust_audit";
|
|
|
|
|
|
private readonly SqlSugarRepository<BookingCustomerOrder> _rep;
|
|
|
private readonly SqlSugarRepository<BookingCtn> _repCtn;
|
|
|
private readonly ILogger<BookingOrderService> _logger;
|
|
|
private readonly ISysCacheService _cache;
|
|
|
private readonly SqlSugarRepository<BookingFile> _repFile;
|
|
|
private readonly SqlSugarRepository<BookingStatusLog> _repStatuslog;
|
|
|
private readonly SqlSugarRepository<BookingStatusLogDetail> _repStatuslogDetail;
|
|
|
private readonly SqlSugarRepository<BookingServiceItem> _repServiceItem;
|
|
|
private readonly SqlSugarRepository<BookingOrder> _repOrder;
|
|
|
private readonly SqlSugarRepository<BookingCustomerOrderTemplate> _repOrderTempl;
|
|
|
private readonly SqlSugarRepository<BookingEDIExt> _repEdiExt;
|
|
|
private readonly SqlSugarRepository<BookingGoodsStatus> _goodsStatus;
|
|
|
private readonly SqlSugarRepository<BookingGoodsStatusConfig> _goodsStatusConfig;
|
|
|
private readonly IEventPublisher _publisher;
|
|
|
private readonly SqlSugarRepository<DjyApiAuth> _repApiAuth;
|
|
|
private readonly SqlSugarRepository<DjyMessage> _repMessage;
|
|
|
private readonly IBookingOrderService bookingOrderService;
|
|
|
private readonly SqlSugarRepository<DjyCustomer> _repCustomer;
|
|
|
private readonly SqlSugarRepository<DjyCustomerParamValue> _repCustomerParamValue;
|
|
|
private readonly SqlSugarRepository<DjyCustomerContact> _repCustomerContact;
|
|
|
private readonly SqlSugarRepository<BookingFeeRecord> _repFeeRecord;
|
|
|
private readonly IDjyWebsiteAccountConfigService _webAccountConfig;
|
|
|
|
|
|
public BookingCustomerOrderService(SqlSugarRepository<BookingCustomerOrder> rep, SqlSugarRepository<BookingCtn> repCtn,
|
|
|
ILogger<BookingOrderService> logger, ISysCacheService cache, SqlSugarRepository<BookingFile> repFile,
|
|
|
SqlSugarRepository<BookingStatusLog> statuslog, SqlSugarRepository<BookingServiceItem> repServiceItem,
|
|
|
SqlSugarRepository<BookingOrder> repOrder, SqlSugarRepository<BookingStatusLogDetail> repStatuslogDetail,
|
|
|
SqlSugarRepository<BookingCustomerOrderTemplate> repOrderTempl,
|
|
|
SqlSugarRepository<BookingEDIExt> repEdiExt, SqlSugarRepository<BookingGoodsStatus> goodsStatus, SqlSugarRepository<BookingGoodsStatusConfig> goodsStatusConfig,
|
|
|
IEventPublisher publisher, SqlSugarRepository<DjyApiAuth> repApiAuth, SqlSugarRepository<DjyMessage> repMessage, IBookingOrderService bookingOrderService,
|
|
|
SqlSugarRepository<DjyCustomer> repCustomer, SqlSugarRepository<DjyCustomerParamValue> repCustomerParamValue, SqlSugarRepository<DjyCustomerContact> repCustomerContact,
|
|
|
SqlSugarRepository<BookingFeeRecord> repFeeRecord, IDjyWebsiteAccountConfigService webAccountConfig)
|
|
|
{
|
|
|
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;
|
|
|
this._repOrderTempl = repOrderTempl;
|
|
|
this._repEdiExt = repEdiExt;
|
|
|
this._goodsStatus = goodsStatus;
|
|
|
this._goodsStatusConfig = goodsStatusConfig;
|
|
|
this._publisher = publisher;
|
|
|
this._repApiAuth = repApiAuth;
|
|
|
this._repMessage = repMessage;
|
|
|
this.bookingOrderService = bookingOrderService;
|
|
|
this._repCustomer = repCustomer;
|
|
|
this._repCustomerParamValue = repCustomerParamValue;
|
|
|
this._repCustomerContact = repCustomerContact;
|
|
|
this._repFeeRecord = repFeeRecord;
|
|
|
_webAccountConfig = webAccountConfig;
|
|
|
}
|
|
|
|
|
|
#region 订舱草稿及附件
|
|
|
/// <summary>
|
|
|
/// 订舱草稿台账
|
|
|
/// </summary>
|
|
|
/// <param name="input"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/PageData")]
|
|
|
public async Task<SqlSugarPagedList<BookingCustomerOrderListOutput>> PageData(BookingCustomerOrderQueryInput input)
|
|
|
{
|
|
|
var query = _rep.AsQueryable().Filter(null, true).Where(x => x.TenantId == UserManager.TENANT_ID)
|
|
|
.Where(x => !x.IsDeleted)
|
|
|
.WhereIF(input.Id > 0, x => x.Id == input.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(!string.IsNullOrEmpty(input.ShipperName), x => x.ShipperName.Contains(input.ShipperName))
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.ConsigneeName), x => x.ConsigneeName.Contains(input.ConsigneeName))
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.NotifypartName), x => x.NotifypartName.Contains(input.NotifypartName))
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.BookingName), x => x.BookingName.Contains(input.BookingName))
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.BookingTenantName), x => x.BookingTenantName.Contains(input.BookingTenantName))
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.ParentBookingNO), x => x.BOOKINGNO.Contains(input.ParentBookingNO) || x.ParentBookingNO.Contains(input.ParentBookingNO))
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.CustNO), x => x.CustNO.Contains(input.CustNO))
|
|
|
.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<SqlSugarPagedList<BookingCustomerOrderListOutput>>();
|
|
|
|
|
|
//动态日志
|
|
|
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<List<BookingCustomerLogDto>>();
|
|
|
}
|
|
|
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 保存草稿数据
|
|
|
/// </summary>
|
|
|
/// <param name="input"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/Save")]
|
|
|
public async Task<BookingCustomerOrderSaveOutput> 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<BookingCtn> ctnList = new List<BookingCtn>();
|
|
|
if (input.Id == 0)
|
|
|
{
|
|
|
entity = input.Adapt<BookingCustomerOrder>();
|
|
|
if (string.IsNullOrEmpty(entity.VOYNO))
|
|
|
{
|
|
|
entity.VOYNO = entity.VOYNOINNER;
|
|
|
}
|
|
|
|
|
|
entity.BSSTATUS = "已录入";
|
|
|
entity.BOOKINGNO = $"BK{YitIdHelper.NextId()}";
|
|
|
|
|
|
//EMC需要把收发通拼接起来
|
|
|
if (input.CARRIERID == "EMC")
|
|
|
{
|
|
|
ContactSFT(entity);
|
|
|
}
|
|
|
|
|
|
await _rep.InsertAsync(entity);
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
entity = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == input.Id);
|
|
|
if (entity.BSSTATUS == "已提交")
|
|
|
{
|
|
|
throw Oops.Bah("请先撤销提交后再修改");
|
|
|
}
|
|
|
|
|
|
if (entity.BSSTATUS == "已审核")
|
|
|
{
|
|
|
throw Oops.Bah("已审核的数据不允许修改");
|
|
|
}
|
|
|
|
|
|
entity = input.Adapt(entity);
|
|
|
|
|
|
//EMC需要把收发通拼接起来
|
|
|
if (input.CARRIERID == "EMC")
|
|
|
{
|
|
|
ContactSFT(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<BookingCtn>();
|
|
|
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<BookingServiceItem>();
|
|
|
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<BookingAttachOptions>();
|
|
|
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<TempFileOptions>().Path;
|
|
|
foreach (var tmpFile in input.TempFileNames)
|
|
|
{
|
|
|
var tempPath = Path.Combine(App.WebHostEnvironment.WebRootPath, 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);
|
|
|
|
|
|
//EMC需要保存船期原始数据
|
|
|
if (input.CARRIERID == "EMC" && input.ShipData != null)
|
|
|
{
|
|
|
_logger.LogInformation($"保存船期数据EMC:{input.ShipData}");
|
|
|
JObject jobjExt = new JObject();
|
|
|
if (!string.IsNullOrEmpty(entity.ExtendData))
|
|
|
{
|
|
|
jobjExt = JObject.Parse(entity.ExtendData);
|
|
|
}
|
|
|
|
|
|
jobjExt["shipInfo"] = input.ShipData;
|
|
|
entity.ExtendData = jobjExt.ToString();
|
|
|
await _rep.AsUpdateable(entity).UpdateColumns(x => new { x.ExtendData }).ExecuteCommandAsync();
|
|
|
}
|
|
|
|
|
|
|
|
|
//返回给前端数据
|
|
|
var outModel = entity.Adapt<BookingCustomerOrderSaveOutput>();
|
|
|
outModel.CtnList = ctnList.Adapt<List<BookingCustomerCtnDto>>();
|
|
|
var dicFile = new Dictionary<long, string>();
|
|
|
_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<List<BookingCustomerLogDto>>();
|
|
|
outModel.ServiceItemList = _repServiceItem.AsQueryable().Where(x => x.BookingId == entity.Id).ToList().Adapt<List<BookingServiceItemCustomerDto>>();
|
|
|
|
|
|
return outModel;
|
|
|
}
|
|
|
|
|
|
private async Task SaveData(BookingCustomerOrder entity, List<BookingCtn> ctns, List<BookingServiceItem> servList, bool ins)
|
|
|
{
|
|
|
if (ins)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(entity.VOYNO))
|
|
|
{
|
|
|
entity.VOYNO = entity.VOYNOINNER;
|
|
|
}
|
|
|
|
|
|
entity.Id = YitIdHelper.NextId();
|
|
|
entity.BSSTATUS = "已录入";
|
|
|
entity.BOOKINGNO = $"BK{YitIdHelper.NextId()}";
|
|
|
await _rep.InsertAsync(entity);
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (entity.BSSTATUS != "已录入" && entity.BSSTATUS != "已驳回")
|
|
|
{
|
|
|
throw Oops.Bah("当前状态不允许修改");
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(entity.VOYNO))
|
|
|
{
|
|
|
entity.VOYNO = entity.VOYNOINNER;
|
|
|
}
|
|
|
|
|
|
await _rep.UpdateAsync(entity);
|
|
|
await _repCtn.DeleteAsync(x => x.BILLID == entity.Id);
|
|
|
|
|
|
}
|
|
|
|
|
|
//箱信息保存
|
|
|
if (ctns != null)
|
|
|
{
|
|
|
foreach (var ctn in ctns)
|
|
|
{
|
|
|
ctn.Id = YitIdHelper.NextId();
|
|
|
ctn.BILLID = entity.Id;
|
|
|
await _repCtn.InsertAsync(ctn);
|
|
|
}
|
|
|
|
|
|
var groupList = ctns.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);
|
|
|
|
|
|
if (servList == null || servList.Count == 0)
|
|
|
{
|
|
|
throw Oops.Bah("必须选择服务项目");
|
|
|
}
|
|
|
|
|
|
//服务项目
|
|
|
_repServiceItem.Delete(x => x.BookingId == entity.Id);
|
|
|
foreach (var srv in servList)
|
|
|
{
|
|
|
srv.Id = YitIdHelper.NextId();
|
|
|
srv.BookingId = entity.Id;
|
|
|
await _repServiceItem.InsertAsync(srv);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取详情
|
|
|
/// </summary>
|
|
|
/// <param name="id"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/Get")]
|
|
|
public async Task<BookingCustomerOrderSaveOutput> Get(long id)
|
|
|
{
|
|
|
var entity = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == id);
|
|
|
|
|
|
var outModel = entity.Adapt<BookingCustomerOrderSaveOutput>();
|
|
|
outModel.CtnList = _repCtn.Where(x => x.BILLID == id).ToList().Adapt<List<BookingCustomerCtnDto>>();
|
|
|
|
|
|
var dicFile = new Dictionary<long, string>();
|
|
|
_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<List<BookingCustomerLogDto>>();
|
|
|
outModel.ServiceItemList = _repServiceItem.AsQueryable().Where(x => x.BookingId == entity.Id).ToList().Adapt<List<BookingServiceItemCustomerDto>>();
|
|
|
|
|
|
|
|
|
return outModel;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 上传临时文件
|
|
|
/// </summary>
|
|
|
/// <param name="file"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/UploadTempFile")]
|
|
|
public async Task<string> UploadTempFile(IFormFile file)
|
|
|
{
|
|
|
//未上传文件
|
|
|
if (file == null || file.Length == 0)
|
|
|
{
|
|
|
throw Oops.Bah("未上传任何文件");
|
|
|
}
|
|
|
|
|
|
|
|
|
var optTempFile = App.GetOptions<TempFileOptions>().Path;
|
|
|
var tempFilePath = $"{DateTime.Now.Ticks}"; //临时存放目录
|
|
|
var tempSavePath = Path.Combine(App.WebHostEnvironment.WebRootPath, 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);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 下载查看上传的文件
|
|
|
/// </summary>
|
|
|
/// <param name="id"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpGet("/BookingCustomerOrder/GetFile"), AllowAnonymous]
|
|
|
public async Task<IActionResult> 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<BookingAttachOptions>();
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 根据文件名称下载查看上传的文件
|
|
|
/// </summary>
|
|
|
/// <param name="fn">文件路径名称</param>
|
|
|
/// <param name="isTemp">是否为临时文件</param>
|
|
|
/// <returns></returns>
|
|
|
[HttpGet("/BookingCustomerOrder/GetFileByName"), AllowAnonymous]
|
|
|
public async Task<IActionResult> GetFileByName(string fn, bool isTemp = true)
|
|
|
{
|
|
|
|
|
|
var fileFullPath = "";
|
|
|
if (isTemp)
|
|
|
{
|
|
|
var optTempFile = App.GetOptions<TempFileOptions>().Path;
|
|
|
fileFullPath = Path.Combine(App.WebHostEnvironment.WebRootPath, optTempFile, fn);//服务器路径
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
if (string.IsNullOrEmpty(opt.basePath))
|
|
|
{
|
|
|
fileFullPath = Path.Combine(App.WebHostEnvironment.WebRootPath, fn);//服务器路径
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
fileFullPath = Path.Combine(opt.basePath, fn);//服务器路径
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!File.Exists(fileFullPath))
|
|
|
{
|
|
|
_logger.LogError($"未能找到文件:{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 = Path.GetFileName(fn) };
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 删除
|
|
|
/// </summary>
|
|
|
/// <param name="ids"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/Delete")]
|
|
|
public async Task Delete(List<long> 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 客户端操作与接口
|
|
|
/// <summary>
|
|
|
/// 提交订舱
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/Submit")]
|
|
|
public async Task<string> Submit(List<long> ids)
|
|
|
{
|
|
|
var allSysConfig = await _cache.GetAllSysConfig();
|
|
|
var recUrl = allSysConfig.FirstOrDefault(x => x.Code == "DjyBookingRequestReceiveUrl");
|
|
|
if (recUrl == null || string.IsNullOrEmpty(recUrl.Value))
|
|
|
{
|
|
|
throw Oops.Bah("大简云接收订舱URL地址未配置,请联系管理员");
|
|
|
}
|
|
|
|
|
|
var userId = allSysConfig.FirstOrDefault(x => x.Code == "DjyBookingReceiveUserId");
|
|
|
var userSecret = allSysConfig.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().Filter(null, true).Where(x => ids.Contains(x.Id)).ToList();
|
|
|
|
|
|
//2023-9-1,衣国豪:点击发送订舱时,最少得填写船公司,船期,目的地,品名,箱型,箱量,重量,如果以上信息没填,允许保存,但是发送订舱时给出提示: XXX不能为空,请补充后重新发送
|
|
|
var emptyCarrList = orderList.Where(x => string.IsNullOrEmpty(x.CARRIERID)).Select(x => x.BOOKINGNO).ToList();
|
|
|
if (emptyCarrList.Any())
|
|
|
{
|
|
|
throw Oops.Bah($"船公司不能为空:\r\n{string.Join("\r\n ", emptyCarrList)}\r\n请补充后重新发送");
|
|
|
}
|
|
|
|
|
|
var emptyETD = orderList.Where(x => !x.ETD.HasValue).Select(x => x.BOOKINGNO).ToList();
|
|
|
if (emptyETD.Any())
|
|
|
{
|
|
|
throw Oops.Bah($"船期不能为空:\r\n{string.Join("\r\n ", emptyETD)}\r\n请补充后重新发送");
|
|
|
}
|
|
|
|
|
|
var emptyDischarge = orderList.Where(x => string.IsNullOrEmpty(x.PORTDISCHARGEID)).Select(x => x.BOOKINGNO).ToList();
|
|
|
if (emptyDischarge.Any())
|
|
|
{
|
|
|
throw Oops.Bah($"目的地不能为空:\r\n{string.Join("\r\n ", emptyDischarge)}\r\n请补充后重新发送");
|
|
|
}
|
|
|
|
|
|
var emptyDescrip = orderList.Where(x => string.IsNullOrEmpty(x.DESCRIPTION)).Select(x => x.BOOKINGNO).ToList();
|
|
|
if (emptyDescrip.Any())
|
|
|
{
|
|
|
throw Oops.Bah($"品名不能为空:\r\n{string.Join("\r\n ", emptyDescrip)}\r\n请补充后重新发送");
|
|
|
}
|
|
|
|
|
|
var emptyKgs = orderList.Where(x => !x.KGS.HasValue).Select(x => x.BOOKINGNO).ToList();
|
|
|
if (emptyKgs.Any())
|
|
|
{
|
|
|
throw Oops.Bah($"重量不能为空:\r\n{string.Join("\r\n ", emptyKgs)}\r\n请补充后重新发送");
|
|
|
}
|
|
|
|
|
|
var ordIdList = orderList.Select(o => o.Id).ToList();
|
|
|
var ctnList = _repCtn.AsQueryable().Filter(null, true).Where(x => ordIdList.Contains(x.BILLID.Value)).ToList();
|
|
|
|
|
|
//2023-9-1,衣国豪:点击发送订舱时,最少得填写船公司,船期,目的地,品名,箱型,箱量,重量,如果以上信息没填,允许保存,但是发送订舱时给出提示: XXX不能为空,请补充后重新发送
|
|
|
var emptyCtn = ctnList.Where(x => string.IsNullOrEmpty(x.CTNALL) || !x.CTNNUM.HasValue).Select(x => x.BILLID).Distinct().ToList();
|
|
|
if (emptyCtn.Any())
|
|
|
{
|
|
|
var emptyCtnOrd = orderList.Where(x => emptyCtn.Contains(x.Id)).Select(x => x.BOOKINGNO).ToList();
|
|
|
throw Oops.Bah($"箱型箱量不能为空:\r\n{string.Join("\r\n", emptyCtnOrd)}\r\n请补充后重新发送");
|
|
|
}
|
|
|
|
|
|
var distinctCarr = orderList.Select(x => x.CARRIERID).Distinct().ToList();
|
|
|
if (distinctCarr.Count > 1)
|
|
|
{
|
|
|
throw Oops.Bah($"批量发送时,只能选择同一船司的数据");
|
|
|
}
|
|
|
|
|
|
var fileList = _repFile.AsQueryable().Filter(null, true).Where(x => ordIdList.Contains(x.BookingId)).ToList();
|
|
|
var serviceItemList = _repServiceItem.AsQueryable().Filter(null, true).Where(x => ordIdList.Contains(x.BookingId.Value)).ToList();
|
|
|
var sendList = new List<BookingCustomerSubmitDto>();
|
|
|
|
|
|
var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
var dirAbs = opt.basePath;
|
|
|
if (string.IsNullOrEmpty(dirAbs))
|
|
|
{
|
|
|
dirAbs = App.WebHostEnvironment.WebRootPath;
|
|
|
}
|
|
|
|
|
|
//当前系统的url
|
|
|
var sysUrlCfg = allSysConfig.FirstOrDefault(x => x.Code == "SystemUrl");
|
|
|
var sysUrl = sysUrlCfg.Value;
|
|
|
if (!sysUrl.EndsWith("/"))
|
|
|
{
|
|
|
sysUrl += "/";
|
|
|
}
|
|
|
|
|
|
//接收回推数据的接口key和秘钥 RecBookingFeedback
|
|
|
var apiAuth = _repApiAuth.AsQueryable().Filter(null, true).First(x => x.ApiCode == "RecBookingFeedback" && x.TenantId == UserManager.TENANT_ID);
|
|
|
if (apiAuth == null)
|
|
|
{
|
|
|
throw Oops.Bah("回推数据接收接口授权未配置");
|
|
|
}
|
|
|
|
|
|
foreach (var order in orderList)
|
|
|
{
|
|
|
if (order.BSSTATUS == "已审核")
|
|
|
{
|
|
|
throw Oops.Bah($"{order.BOOKINGNO} 当前状态为{order.BSSTATUS},不能提交");
|
|
|
}
|
|
|
|
|
|
var dto = order.Adapt<BookingCustomerSubmitDto>();
|
|
|
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.FeedbackUrl = $"{sysUrl}BookingCustomerOrder/RecBookingFeedback";
|
|
|
dto.FeedbackKey = apiAuth.ApiKey;
|
|
|
dto.FeedbackSecret = apiAuth.ApiSecret;
|
|
|
|
|
|
dto.CtnList = ctnList.Where(x => x.BILLID == order.Id).ToList().Adapt<List<BookingCustomerCtnDto>>();
|
|
|
dto.ServiceItemList = serviceItemList.Where(x => x.BookingId == order.Id).ToList().Adapt<List<BookingServiceItemCustomerDto>>();
|
|
|
dto.Files = fileList.Where(x => x.BookingId == order.Id).ToList().Adapt<List<BookingFileSyncCustomerDto>>();
|
|
|
|
|
|
sendList.Add(dto);
|
|
|
}
|
|
|
|
|
|
//构建完整url
|
|
|
var submitUrl = recUrl.Value;
|
|
|
|
|
|
// 如果当前环境为开发环境,则请求本机运营端程序的接口地址,来进行调试
|
|
|
if (App.HostEnvironment.IsDevelopment())
|
|
|
{
|
|
|
submitUrl = "http://localhost:5130";
|
|
|
|
|
|
// 更改回推接收地址
|
|
|
sendList.ForEach(x => x.FeedbackUrl = $"{App.Configuration["Url"]}/BookingCustomerOrder/RecBookingFeedback");
|
|
|
}
|
|
|
|
|
|
if (!submitUrl.EndsWith("/"))
|
|
|
{
|
|
|
submitUrl += "/";
|
|
|
}
|
|
|
|
|
|
submitUrl += "BookingCustomerOrder/ReceiveBooking";
|
|
|
|
|
|
_logger.LogInformation($"提交订舱数据({submitUrl},{userId.Value},{userSecret.Value}):{JsonConvert.SerializeObject(sendList)}");
|
|
|
|
|
|
var rtn = await submitUrl
|
|
|
.SetHeaders(new Dictionary<string, object> {
|
|
|
{ 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().Filter(null, true).First(x => x.Id == id);
|
|
|
model.BSSTATUS = "已提交";
|
|
|
await _rep.AsUpdateable(model).UpdateColumns(x => new { x.BSSTATUS }).ExecuteCommandAsync();
|
|
|
|
|
|
//日志动态
|
|
|
SaveAuditLog("已提交", id);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//日志动态
|
|
|
SaveAuditLog($"提交失败", id, remark: item.GetStringValue("message"));
|
|
|
}
|
|
|
|
|
|
resultText.AppendLine($"{bookingno}:{message}");
|
|
|
}
|
|
|
|
|
|
return resultText.ToString();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 取消提交订舱
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/CancelSubmit")]
|
|
|
public async Task<string> CancelSubmit(List<long> 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().Filter(null, true).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.ToString(),
|
|
|
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<string, object> {
|
|
|
{ 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().Filter(null, true).First(x => x.Id == id);
|
|
|
model.BSSTATUS = "已录入";
|
|
|
await _rep.UpdateAsync(model);
|
|
|
|
|
|
//日志动态
|
|
|
SaveAuditLog($"取消提交", id);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//日志动态
|
|
|
SaveAuditLog($"取消提交失败", id, remark: item.GetStringValue("message"));
|
|
|
}
|
|
|
|
|
|
resultText.AppendLine($"{bookingno}:{message}");
|
|
|
}
|
|
|
|
|
|
return resultText.ToString();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 查询船期数据
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpGet("/BookingCustomerOrder/QueryShipInfo")]
|
|
|
public async Task<dynamic> QueryShipInfo(long custOrdId, string carr = "EMC")
|
|
|
{
|
|
|
var allSysConfig = await _cache.GetAllSysConfig();
|
|
|
var sCfgSpiderUrl = allSysConfig.FirstOrDefault(x => x.Code == "BookingPostApiServerAddr" && x.GroupCode == "DJY_CONST");
|
|
|
if (sCfgSpiderUrl == null)
|
|
|
{
|
|
|
throw Oops.Bah("订舱API的爬虫URL地址未配置,请联系管理员");
|
|
|
}
|
|
|
|
|
|
var sCfgUserKey = allSysConfig.FirstOrDefault(x => x.Code == "BookingPostApiKey" && x.GroupCode == "DJY_CONST");
|
|
|
var sCfgUserSecret = allSysConfig.FirstOrDefault(x => x.Code == "BookingPostApiSecret" && x.GroupCode == "DJY_CONST");
|
|
|
if (sCfgUserKey == null || sCfgUserSecret == null)
|
|
|
{
|
|
|
throw Oops.Bah("订舱API的KEY和密钥未配置,请联系管理员");
|
|
|
}
|
|
|
|
|
|
var custOrder = await _rep.AsQueryable().FirstAsync(x => x.Id == custOrdId);
|
|
|
var ctns = await _repCtn.AsQueryable().Where(x => x.BILLID == custOrdId).ToListAsync();
|
|
|
var mappingPortLoad = await _cache.GetAllMappingPortLoad();
|
|
|
var mappingPort = await _cache.GetAllMappingPort();
|
|
|
var mappingCtn = await _cache.GetAllMappingCtn();
|
|
|
var mappingService = await _cache.GetAllMappingService();
|
|
|
|
|
|
#region EMC
|
|
|
if (carr == "EMC")
|
|
|
{
|
|
|
var apiUrl = sCfgSpiderUrl.Value;
|
|
|
if (!apiUrl.EndsWith("/"))
|
|
|
{
|
|
|
apiUrl += "/";
|
|
|
}
|
|
|
apiUrl += "v1/emc/ship/query";
|
|
|
|
|
|
|
|
|
//收货地
|
|
|
var mapPlaceReceipt = mappingPortLoad.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "EMC" && x.Code == custOrder.PLACERECEIPTCODE);
|
|
|
if (mapPlaceReceipt == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到收货地映射信息:{custOrder.PLACERECEIPTCODE}");
|
|
|
}
|
|
|
|
|
|
//起运港
|
|
|
var mapPortLoad = mappingPortLoad.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "EMC" && x.Code == custOrder.PORTLOADCODE);
|
|
|
if (mapPortLoad == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到起运港映射信息:{custOrder.PORTLOADCODE}");
|
|
|
}
|
|
|
|
|
|
//卸货港
|
|
|
var mapPort = mappingPort.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "EMC" && x.Code == custOrder.PORTDISCHARGECODE);
|
|
|
if (mapPort == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到卸货港映射信息:{custOrder.PORTDISCHARGECODE}");
|
|
|
}
|
|
|
|
|
|
//目的地
|
|
|
var mapDestination = mappingPort.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "EMC" && x.Code == custOrder.DESTINATIONCODE);
|
|
|
if (mapDestination == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到目的地映射信息:{custOrder.DESTINATIONCODE}");
|
|
|
}
|
|
|
|
|
|
//箱型转换
|
|
|
var disCtnCode = ctns.Select(x => x.CTNCODE).Distinct().ToList();
|
|
|
var mapCtnCode = new List<string>();
|
|
|
foreach (var ctnall in disCtnCode)
|
|
|
{
|
|
|
var mapCtn = mappingCtn.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "EMC" && x.Code == ctnall);
|
|
|
if (mapCtn == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到箱型映射信息:{ctnall}");
|
|
|
}
|
|
|
|
|
|
mapCtnCode.Add(mapCtn.MapName);
|
|
|
}
|
|
|
|
|
|
var postModel = new
|
|
|
{
|
|
|
userKey = sCfgUserKey.Value,
|
|
|
userSecret = sCfgUserSecret.Value,
|
|
|
webAccount = custOrder.BookingAccount,
|
|
|
webPassword = custOrder.BookingPassword,
|
|
|
searchConditionDate = custOrder.ETD.Value.AddDays(-7).ToString("yyyy-MM-dd"),
|
|
|
originName = mapPlaceReceipt.MapName,
|
|
|
destinationName = mapDestination.MapName,
|
|
|
polPortName = mapPortLoad.MapName,
|
|
|
podPortName = mapPort.MapName,
|
|
|
serviceType = custOrder.ServiceType,
|
|
|
serviceMode = custOrder.ServiceMode,
|
|
|
bookingOffice = custOrder.BookingAddr,
|
|
|
isReefer = "N",
|
|
|
contractType = custOrder.ContractType,
|
|
|
contractNo = custOrder.CONTRACTNO,
|
|
|
containerTypeList = mapCtnCode
|
|
|
};
|
|
|
|
|
|
_logger.LogInformation($"发送查询API数据给爬虫({apiUrl}):{postModel.ToJsonString()}");
|
|
|
var rtnQuery = await apiUrl.SetBody(postModel)
|
|
|
.PostAsStringAsync();
|
|
|
|
|
|
_logger.LogInformation($"爬虫返回:{rtnQuery}");
|
|
|
var jobjRtnQuery = JObject.Parse(rtnQuery);
|
|
|
if (jobjRtnQuery.GetIntValue("code") != 200)
|
|
|
{
|
|
|
throw Oops.Bah($"查询船期数据出错:{jobjRtnQuery.GetStringValue("msg")}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var jarrVessel = jobjRtnQuery.GetJArrayValue("data");
|
|
|
return jarrVessel;
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region COSCO
|
|
|
else if (carr == "COSCO")
|
|
|
{
|
|
|
var apiUrl = sCfgSpiderUrl.Value;
|
|
|
if (!apiUrl.EndsWith("/"))
|
|
|
{
|
|
|
apiUrl += "/";
|
|
|
}
|
|
|
apiUrl += "v1/cosco/ship/schedule";
|
|
|
|
|
|
//起运港
|
|
|
var mapPortLoad = mappingPortLoad.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == custOrder.PORTLOADCODE);
|
|
|
if (mapPortLoad == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到起运港映射信息:{custOrder.PORTLOADCODE}");
|
|
|
}
|
|
|
|
|
|
//目的地
|
|
|
var mapDestination = mappingPort.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == custOrder.DESTINATIONCODE);
|
|
|
if (mapDestination == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到目的地映射信息:{custOrder.DESTINATIONCODE}");
|
|
|
}
|
|
|
|
|
|
//运输方式
|
|
|
var mapService = mappingService.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == custOrder.SERVICE);
|
|
|
string[] arrService = null;
|
|
|
if (mapService == null)
|
|
|
{
|
|
|
arrService = custOrder.SERVICE.Split('-');
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
arrService = mapService.MapCode.Split('-');
|
|
|
}
|
|
|
|
|
|
var postModel = new
|
|
|
{
|
|
|
userKey = sCfgUserKey.Value,
|
|
|
userSecret = sCfgUserSecret.Value,
|
|
|
webAccount = custOrder.BookingAccount,
|
|
|
webPassword = custOrder.BookingPassword,
|
|
|
numberOfWeeks = 2,
|
|
|
searchConditionDate = custOrder.ETD.Value.AddDays(-2).ToString("yyyy-MM-dd"),
|
|
|
originName = mapPortLoad.MapName,
|
|
|
destinationName = mapDestination.MapName,
|
|
|
cargoNature = "BOTH",
|
|
|
outboundHaulage = arrService[0],
|
|
|
inboundHaulage = arrService[1]
|
|
|
};
|
|
|
|
|
|
_logger.LogInformation($"发送查询API数据给爬虫({apiUrl}):{postModel.ToJsonString()}");
|
|
|
var rtnQuery = await apiUrl.SetBody(postModel)
|
|
|
.PostAsStringAsync();
|
|
|
|
|
|
_logger.LogInformation($"爬虫返回:{rtnQuery}");
|
|
|
var jobjRtnQuery = JObject.Parse(rtnQuery);
|
|
|
if (jobjRtnQuery.GetIntValue("code") != 200)
|
|
|
{
|
|
|
throw Oops.Bah($"查询船期数据出错:{jobjRtnQuery.GetStringValue("msg")}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var jarrVessel = jobjRtnQuery.GetJArrayValue("data");
|
|
|
return jarrVessel;
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
else
|
|
|
{
|
|
|
throw Oops.Bah("不支持的船公司");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#region 客户订舱模板
|
|
|
/// <summary>
|
|
|
/// 客户订舱模板列表
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/OrderTemplateList")]
|
|
|
public async Task<SqlSugarPagedList<BookingCustomerTemplateQueryOutput>> OrderTemplateList(BookingCustomerTemplateQueryInput input)
|
|
|
{
|
|
|
var query = _repOrderTempl.AsQueryable()
|
|
|
.Where(t => t.CreatedUserId == UserManager.UserId)
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.Title), t => t.Title.Contains(input.Title))
|
|
|
.Select(t => new BookingCustomerTemplateQueryOutput()
|
|
|
{
|
|
|
Id = t.Id,
|
|
|
Title = t.Title,
|
|
|
});
|
|
|
|
|
|
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));
|
|
|
}
|
|
|
|
|
|
return await query.ToPagedListAsync(input.PageNo, input.PageSize);
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 客户订舱模板删除
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/OrderTemplateDel")]
|
|
|
public async Task OrderTemplateDel(long id)
|
|
|
{
|
|
|
await _repOrderTempl.DeleteAsync(id);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 客户订舱模板保存
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/OrderTemplateSave")]
|
|
|
public async Task OrderTemplateSave(BookingCustomerTemplateSaveInput model)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(model.Title))
|
|
|
{
|
|
|
throw Oops.Bah("请输入模板名称");
|
|
|
}
|
|
|
|
|
|
var template = model.Adapt<BookingCustomerOrderTemplate>();
|
|
|
await _repOrderTempl.InsertAsync(template);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 客户订舱模板内容
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpGet("/BookingCustomerOrder/GetOrderTemplate")]
|
|
|
public async Task<string> GetOrderTemplate(long id)
|
|
|
{
|
|
|
var objTemp = await _repOrderTempl.FirstOrDefaultAsync(x => x.Id == id);
|
|
|
if (objTemp == null)
|
|
|
{
|
|
|
throw Oops.Bah("模板未找到");
|
|
|
}
|
|
|
|
|
|
return objTemp.JsonContent;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
//[HttpPost("/BookingCustomerOrder/FeedbackTest"), AllowAnonymous]
|
|
|
//public async Task FeedbackTest(string json)
|
|
|
//{
|
|
|
|
|
|
//}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 接收订舱回推统一接口
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/RecBookingFeedback"), AllowAnonymous, ApiUser(ApiCode = "RecBookingFeedback")]
|
|
|
public async Task<dynamic> RecBookingFeedback(string feedbackType, string jsonContent, string syncType)
|
|
|
{
|
|
|
_logger.LogInformation($"收到订舱回推数据,feedbackType:{feedbackType},jsonContent:{jsonContent},syncType:{syncType}");
|
|
|
|
|
|
if (string.IsNullOrEmpty(feedbackType) || string.IsNullOrEmpty(jsonContent))
|
|
|
{
|
|
|
throw Oops.Bah("参数有误");
|
|
|
}
|
|
|
|
|
|
#region 审核反馈
|
|
|
if (feedbackType == BookingFeedbackType.Audit.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<BookingCustomerRecAduitFeedbackDto>(jsonContent);
|
|
|
|
|
|
var id = Convert.ToInt64(recModel.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 (recModel.Accept)
|
|
|
{
|
|
|
model.BSSTATUS = "已审核";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
model.BSSTATUS = "已驳回";
|
|
|
}
|
|
|
|
|
|
await _rep.UpdateAsync(model);
|
|
|
|
|
|
//日志动态
|
|
|
SaveAuditLog($"{model.BSSTATUS}", id, model.CreatedUserId.Value, model.TenantId.Value, "系统", remark: $"审核意见:{recModel.Comment}");
|
|
|
|
|
|
long bookingId = 0;
|
|
|
|
|
|
//进入客户订舱系统的订舱台账
|
|
|
if (recModel.Accept)
|
|
|
{
|
|
|
var ord = await CustomerToOrder(model);
|
|
|
bookingId = ord.Id;
|
|
|
|
|
|
model.BookingId = bookingId; //客户订舱数据与订舱台账数据关联
|
|
|
await _rep.UpdateAsync(model);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
// 接收到订舱需求审核后推送东胜
|
|
|
_ = Task.Run(() =>
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
string json = null;
|
|
|
if (recModel.Accept)
|
|
|
{
|
|
|
var body = new
|
|
|
{
|
|
|
Type = "CustOrderStatusAccept",
|
|
|
Data = new
|
|
|
{
|
|
|
model.BSNO,
|
|
|
BSSTATUS = "已审核",
|
|
|
BookingOrderId = bookingId
|
|
|
}
|
|
|
};
|
|
|
json = body.ToJsonString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var body = new
|
|
|
{
|
|
|
Type = "CustOrderStatusReject",
|
|
|
Data = new
|
|
|
{
|
|
|
model.BSNO,
|
|
|
BSSTATUS = "已驳回",
|
|
|
COMMENT = recModel.Comment
|
|
|
}
|
|
|
};
|
|
|
json = body.ToJsonString();
|
|
|
}
|
|
|
|
|
|
var mqUrl = _cache.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "AuditBookingMqUrl")?.Value ?? throw new Exception("需配置接收订舱需求审核后推送东胜MQ连接串:[AuditBookingMqUrl]");
|
|
|
|
|
|
const string MqActionExchangeName = "amq.direct";
|
|
|
const string MqActionQueueName = "auditbooking.output.ds";
|
|
|
|
|
|
ConnectionFactory factory = new ConnectionFactory();
|
|
|
factory.Uri = new Uri(mqUrl);
|
|
|
|
|
|
using (IConnection conn = factory.CreateConnection())
|
|
|
using (IModel mqModel = conn.CreateModel())
|
|
|
{
|
|
|
mqModel.ExchangeDeclare(MqActionExchangeName, ExchangeType.Direct, true);
|
|
|
|
|
|
var queueName = $"{MqActionQueueName}.{model.TenantId}";
|
|
|
mqModel.QueueDeclare(queueName, false, false, false, null);
|
|
|
|
|
|
mqModel.QueueBind(queueName, MqActionExchangeName, queueName, null);
|
|
|
|
|
|
IBasicProperties props = mqModel.CreateBasicProperties();
|
|
|
props.DeliveryMode = 2;
|
|
|
|
|
|
byte[] messageBodyBytes = Encoding.UTF8.GetBytes(SharpZipLib.Compress(json));
|
|
|
|
|
|
mqModel.BasicPublish(MqActionExchangeName, queueName, props, messageBodyBytes);
|
|
|
|
|
|
conn.Close();
|
|
|
|
|
|
_logger.LogInformation($"接收到订舱需求审核后推送东胜,已发送数据到消息队列【{mqUrl}】,队列名称:【{queueName}】,数据内容:【{json}】");
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.LogError(ex, "接收到订舱需求审核后推送东胜时发生异常");
|
|
|
}
|
|
|
});
|
|
|
|
|
|
if (recModel.Accept)
|
|
|
{
|
|
|
return bookingId;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 订舱完整数据
|
|
|
else if (feedbackType == BookingFeedbackType.BookingAll.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<BookingCustomerRecDataFeedbackDto>(jsonContent);
|
|
|
|
|
|
var dbOrder = await _repOrder.AsQueryable().Filter(null, true).FirstAsync(x => !x.IsDeleted && x.Id == recModel.Order.Id);
|
|
|
if (dbOrder == null)
|
|
|
{
|
|
|
if (syncType == BookingOrderSyncTypeEnum.BC.ToString())
|
|
|
{
|
|
|
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}的数据");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
dbOrder.IsDeleted = false;
|
|
|
_logger.LogInformation($"从已删除订单中找到:{recModel.Order.Id},恢复为未删除");
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
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<BookingCtn>();
|
|
|
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<BookingStatusLog>();
|
|
|
insStaLog.BookingId = recModel.Order.Id;
|
|
|
await _repStatuslog.InsertAsync(insStaLog);
|
|
|
foreach (var staDetail in sta.Details)
|
|
|
{
|
|
|
var insStaDetail = staDetail.Adapt<BookingStatusLogDetail>();
|
|
|
insStaDetail.PId = insStaLog.Id;
|
|
|
await _repStatuslogDetail.InsertAsync(insStaDetail);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//文件
|
|
|
//var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
//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.AsQueryable().Filter(null, true).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<BookingFile>();
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BookingOrderSyncTypeEnum? syncTypeEnum = syncType switch
|
|
|
{
|
|
|
"BC" => BookingOrderSyncTypeEnum.BC,
|
|
|
"CC" => BookingOrderSyncTypeEnum.CC,
|
|
|
"REJECT" => BookingOrderSyncTypeEnum.REJECT,
|
|
|
//"FILE" => BookingOrderSyncTypeEnum.FILE,
|
|
|
_ => null,
|
|
|
};
|
|
|
|
|
|
await bookingOrderService.SendBookingOrder(new long[] { dbOrder.Id }, syncTypeEnum);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 订舱货物状态回推
|
|
|
else if (feedbackType == BookingFeedbackType.GoodsStatus.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<GoodsStatusSyncDto>(jsonContent);
|
|
|
|
|
|
var dbOrder = await _repOrder.AsQueryable().Filter(null, true).FirstAsync(x => !x.IsDeleted && x.Id == recModel.Id);
|
|
|
if (dbOrder == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到id为{recModel.Id}的数据");
|
|
|
}
|
|
|
|
|
|
var gsCfg = await _goodsStatusConfig.AsQueryable().Filter(null, true)
|
|
|
.FirstAsync(x => x.CreatedUserId == dbOrder.CreatedUserId
|
|
|
&& x.IsDeleted == false
|
|
|
&& x.SystemCode == recModel.Code);
|
|
|
if (gsCfg == null)
|
|
|
{
|
|
|
throw Oops.Bah($"用户{dbOrder.CreatedUserName}的货物状态配置数据未找到:{recModel.Code}");
|
|
|
}
|
|
|
|
|
|
if (recModel.IsCancel) //取消货物状态
|
|
|
{
|
|
|
_logger.LogInformation($"取消货物状态{gsCfg.SystemCode} {dbOrder.Id}");
|
|
|
await _goodsStatus.DeleteAsync(x => x.ConfigId == gsCfg.Id
|
|
|
&& x.bookingId == dbOrder.Id
|
|
|
&& x.CreatedUserId == dbOrder.CreatedUserId);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var gs = await _goodsStatus.AsQueryable().Filter(null, true)
|
|
|
.FirstAsync(x => x.ConfigId == gsCfg.Id
|
|
|
&& x.bookingId == dbOrder.Id
|
|
|
&& x.CreatedUserId == dbOrder.CreatedUserId
|
|
|
&& x.IsDeleted == false);
|
|
|
if (gs == null)
|
|
|
{
|
|
|
gs = new BookingGoodsStatus();
|
|
|
gs.Id = YitIdHelper.NextId();
|
|
|
gs.bookingId = dbOrder.Id;
|
|
|
gs.ConfigId = gsCfg.Id;
|
|
|
gs.TenantId = dbOrder.TenantId;
|
|
|
gs.CreatedUserId = dbOrder.CreatedUserId;
|
|
|
gs.CreatedUserName = dbOrder.CreatedUserName;
|
|
|
gs.FinishUserId = dbOrder.CreatedUserId;
|
|
|
gs.FinishUser = "系统";
|
|
|
gs.FinishTime = string.IsNullOrEmpty(recModel.FinishTime) ? DateTime.Now : Convert.ToDateTime(recModel.FinishTime);
|
|
|
await _goodsStatus.InsertAsync(gs);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
gs.FinishUserId = dbOrder.CreatedUserId;
|
|
|
gs.FinishUser = "系统";
|
|
|
gs.FinishTime = string.IsNullOrEmpty(recModel.FinishTime) ? DateTime.Now : Convert.ToDateTime(recModel.FinishTime);
|
|
|
await _goodsStatus.UpdateAsync(gs);
|
|
|
|
|
|
}
|
|
|
|
|
|
await _publisher.PublishAsync(new ChannelEventSource("GoodsStatusSubscribeNotify:Book", new { BookingId = dbOrder.Id, StatusCode = gsCfg.SystemCode, StatusName = gsCfg.StatusName }));
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 服务项目审核回推
|
|
|
else if (feedbackType == BookingFeedbackType.ServiceItemAudit.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<ChangeServiceItemResponseDto>(jsonContent);
|
|
|
var ordId = Convert.ToInt64(recModel.Dto.Id);
|
|
|
var order = await _repOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == ordId);
|
|
|
if (recModel.IsReject) //驳回
|
|
|
{
|
|
|
if (recModel.Dto.IsCancel) //申请的是取消,需要恢复服务项目显示
|
|
|
{
|
|
|
var servItm = await _repServiceItem.AsQueryable().Filter(null, true).FirstAsync(x => x.BookingId == ordId && x.Code == recModel.Dto.ServiceCode);
|
|
|
if (servItm == null)
|
|
|
{
|
|
|
servItm = new BookingServiceItem();
|
|
|
servItm.Id = YitIdHelper.NextId();
|
|
|
servItm.BookingId = Convert.ToInt64(recModel.Dto.Id);
|
|
|
servItm.Code = recModel.Dto.ServiceCode;
|
|
|
servItm.Value = recModel.Dto.ServiceName;
|
|
|
await _repServiceItem.InsertAsync(servItm);
|
|
|
}
|
|
|
}
|
|
|
else //申请的是新增,则删掉服务项目
|
|
|
{
|
|
|
await _repServiceItem.DeleteAsync(x => x.BookingId == ordId && x.Code == recModel.Dto.ServiceCode);
|
|
|
}
|
|
|
}
|
|
|
else //通过
|
|
|
{
|
|
|
if (!recModel.Dto.IsCancel) //申请的新增,将未确认状态置为确认
|
|
|
{
|
|
|
var servItm = await _repServiceItem.AsQueryable().Filter(null, true).FirstAsync(x => x.BookingId == ordId && x.Code == recModel.Dto.ServiceCode);
|
|
|
if (servItm != null)
|
|
|
{
|
|
|
servItm.UnConfirm = false;
|
|
|
await _repServiceItem.UpdateAsync(servItm);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
var serItm = _cache.GetAllDictData().Result.FirstOrDefault(x => x.TypeCode == "booking_service_item" && x.Code == recModel.Dto.ServiceCode);
|
|
|
|
|
|
var mess = new DjyMessage();
|
|
|
mess.Module = MessageModule.Booking.ToString();
|
|
|
mess.TypeCode = MessageType.ChangeServiceItem.ToString();
|
|
|
mess.TypeName = EnumHelper.GetDescription(typeof(MessageType), mess.TypeCode);
|
|
|
mess.RelativeId = ordId;
|
|
|
mess.RelativeCode = order.BOOKINGNO;
|
|
|
if (recModel.IsReject)
|
|
|
{
|
|
|
mess.Content = $"{recModel.AuditName} 退回了您{(recModel.Dto.IsCancel ? "取消" : "新增")}服务项目 {serItm.Value},原因是:{recModel.ProcResult}";
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
mess.Content = $"{recModel.AuditName} 同意了您{(recModel.Dto.IsCancel ? "取消" : "新增")}服务项目 {serItm.Value}";
|
|
|
|
|
|
}
|
|
|
mess.FromName = "大简云";
|
|
|
mess.ProcStatus = MessageProcessStatus.UnProcess.ToString();
|
|
|
await this._repMessage.InsertAsync(mess);
|
|
|
await _publisher.PublishAsync(new ChannelEventSource("Message:NotifyReceiveNew"));
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 服务项目手工修改通知回推
|
|
|
else if (feedbackType == BookingFeedbackType.ServiceItemChange.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<DjyChangeServiceItemDto>(jsonContent);
|
|
|
var ordId = Convert.ToInt64(recModel.Id);
|
|
|
var order = await _repOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == ordId);
|
|
|
var serItm = _cache.GetAllDictData().Result.FirstOrDefault(x => x.TypeCode == "booking_service_item" && x.Code == recModel.ServiceCode);
|
|
|
if (recModel.IsCancel)
|
|
|
{
|
|
|
await _repServiceItem.DeleteAsync(x => x.BookingId == ordId && x.Code == recModel.ServiceCode);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var servItm = await _repServiceItem.AsQueryable().Filter(null, true).FirstAsync(x => x.BookingId == ordId && x.Code == recModel.ServiceCode);
|
|
|
if (servItm != null)
|
|
|
{
|
|
|
servItm.UnConfirm = false;
|
|
|
await _repServiceItem.UpdateAsync(servItm);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
servItm = new BookingServiceItem();
|
|
|
servItm.Id = YitIdHelper.NextId();
|
|
|
servItm.BookingId = ordId;
|
|
|
servItm.Code = recModel.ServiceCode;
|
|
|
servItm.Value = serItm.Value;
|
|
|
await _repServiceItem.InsertAsync(servItm);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
var mess = new DjyMessage();
|
|
|
mess.Module = MessageModule.Booking.ToString();
|
|
|
mess.TypeCode = MessageType.ChangeServiceItem.ToString();
|
|
|
mess.TypeName = EnumHelper.GetDescription(typeof(MessageType), mess.TypeCode);
|
|
|
mess.RelativeId = ordId;
|
|
|
mess.RelativeCode = order.BOOKINGNO;
|
|
|
mess.Content = $"{recModel.UserName} {(recModel.IsCancel ? "取消" : "新增")}服务项目 {serItm.Value},原因是:{recModel.Remark}";
|
|
|
mess.FromName = "大简云";
|
|
|
mess.ProcStatus = MessageProcessStatus.UnProcess.ToString();
|
|
|
await this._repMessage.InsertAsync(mess);
|
|
|
await _publisher.PublishAsync(new ChannelEventSource("Message:NotifyReceiveNew"));
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 单证补料审核通知回推
|
|
|
else if (feedbackType == BookingFeedbackType.DocSupplementAudit.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<DocSupplementResponseDto>(jsonContent);
|
|
|
var ordId = Convert.ToInt64(recModel.Dto.Id);
|
|
|
var order = await _repOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == ordId);
|
|
|
if (!recModel.IsReject) //审核通过,挂载附件
|
|
|
{
|
|
|
//进入订舱附件
|
|
|
foreach (var ff in recModel.Dto.FileList)
|
|
|
{
|
|
|
var fileSuffix = Path.GetFileName(ff.FileName);
|
|
|
var newFile = new BookingFile
|
|
|
{
|
|
|
Id = ff.Id,
|
|
|
FileName = ff.FileName,
|
|
|
FilePath = ff.FilePath,
|
|
|
TypeCode = ff.TypeCode,
|
|
|
TypeName = ff.TypeName,
|
|
|
BookingId = ordId,
|
|
|
TenantId = order.TenantId,
|
|
|
TenantName = order.TenantName,
|
|
|
};
|
|
|
await _repFile.InsertAsync(newFile);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var mess = new DjyMessage();
|
|
|
mess.Module = MessageModule.Booking.ToString();
|
|
|
mess.TypeCode = MessageType.DocSupplement.ToString();
|
|
|
mess.TypeName = EnumHelper.GetDescription(typeof(MessageType), mess.TypeCode);
|
|
|
mess.RelativeId = ordId;
|
|
|
mess.RelativeCode = order.BOOKINGNO;
|
|
|
if (recModel.IsReject)
|
|
|
{
|
|
|
mess.Content = $"{recModel.AuditName} 退回了提交的 {recModel.Dto.DocTypeName},原因是:{recModel.ProcResult}";
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
mess.Content = $"{recModel.AuditName} 通过了提交的 {recModel.Dto.DocTypeName}";
|
|
|
|
|
|
}
|
|
|
mess.FromName = "大简云";
|
|
|
mess.ProcStatus = MessageProcessStatus.UnProcess.ToString();
|
|
|
await this._repMessage.InsertAsync(mess);
|
|
|
await _publisher.PublishAsync(new ChannelEventSource("Message:NotifyReceiveNew"));
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 作废
|
|
|
else if (feedbackType == BookingFeedbackType.CancelBook.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<BookingCustomerRecCancelDto>(jsonContent);
|
|
|
|
|
|
var id = Convert.ToInt64(recModel.Id);
|
|
|
var model = _rep.AsQueryable().Filter(null, true).First(x => x.Id == id);
|
|
|
if (model == null)
|
|
|
{
|
|
|
throw Oops.Bah("未找到数据");
|
|
|
}
|
|
|
|
|
|
model.IsDeleted = true;
|
|
|
await _rep.AsUpdateable(model).UpdateColumns(x => new { x.IsDeleted }).ExecuteCommandAsync();
|
|
|
|
|
|
//删除订舱台账数据
|
|
|
var order = await _repOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == model.BookingId);
|
|
|
if (order != null)
|
|
|
{
|
|
|
order.IsDeleted = true;
|
|
|
await _repOrder.AsUpdateable(order).UpdateColumns(x => new { x.IsDeleted }).ExecuteCommandAsync();
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 多订舱编号
|
|
|
else if (feedbackType == BookingFeedbackType.OneToMulti.ToString())
|
|
|
{
|
|
|
var recModel = JsonConvert.DeserializeObject<BookingCustomerMultiCustNODto>(jsonContent);
|
|
|
|
|
|
var id = Convert.ToInt64(recModel.Id);
|
|
|
var model = _rep.AsQueryable().Filter(null, true).First(x => x.Id == id);
|
|
|
if (model == null)
|
|
|
{
|
|
|
throw Oops.Bah("未找到数据");
|
|
|
}
|
|
|
|
|
|
var lstResp = new List<BookingCustomerMultiCustNORespDto>();
|
|
|
|
|
|
var ctns = await _repCtn.AsQueryable().Filter(null, true).Where(x => x.BILLID == id && x.IsDeleted == false).ToListAsync();
|
|
|
var parentBookingNO = model.BOOKINGNO;
|
|
|
foreach (var bookNO in recModel.ListCustNO)
|
|
|
{
|
|
|
var respDtO = new BookingCustomerMultiCustNORespDto();
|
|
|
lstResp.Add(respDtO);
|
|
|
|
|
|
//生成id并插入客户订舱数据
|
|
|
model.Id = YitIdHelper.NextId();
|
|
|
model.BOOKINGNO = $"BK{YitIdHelper.NextId()}";
|
|
|
model.ParentBookingNO = parentBookingNO;
|
|
|
JObject jobjExt = null;
|
|
|
if (!string.IsNullOrEmpty(model.ExtendData))
|
|
|
{
|
|
|
jobjExt = JObject.Parse(model.ExtendData);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
jobjExt = new JObject();
|
|
|
}
|
|
|
|
|
|
jobjExt["CustNO"] = bookNO;
|
|
|
model.ExtendData = jobjExt.ToString();
|
|
|
|
|
|
await _rep.InsertAsync(model);
|
|
|
|
|
|
foreach (var ctn in ctns)
|
|
|
{
|
|
|
ctn.Id = YitIdHelper.NextId();
|
|
|
ctn.BILLID = model.Id;
|
|
|
await _repCtn.InsertAsync(ctn);
|
|
|
}
|
|
|
|
|
|
respDtO.CustOrderId = model.Id;
|
|
|
respDtO.BookingNO = model.BOOKINGNO;
|
|
|
respDtO.CustNO = bookNO;
|
|
|
|
|
|
_logger.LogInformation($"根据客户订舱 {recModel.Id} 生成了相同的数据 {model.Id}");
|
|
|
|
|
|
//插入订舱台账
|
|
|
var ord = await CustomerToOrder(model);
|
|
|
model.BookingId = ord.Id;
|
|
|
await _rep.AsUpdateable(model).UpdateColumns(x => new { x.BookingId }).ExecuteCommandAsync();
|
|
|
|
|
|
//订舱编号
|
|
|
ord.CUSTNO = bookNO;
|
|
|
await _repOrder.AsUpdateable(ord).UpdateColumns(x => new { x.CUSTNO }).ExecuteCommandAsync();
|
|
|
|
|
|
respDtO.OrderId = ord.Id;
|
|
|
|
|
|
_logger.LogInformation($"生成了订舱台账数据 {ord.Id}");
|
|
|
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation($"反馈给运营端生成的数据 {lstResp.ToJsonString()}");
|
|
|
|
|
|
return lstResp;
|
|
|
}
|
|
|
#endregion
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 客户订舱数据生成订舱台账
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[NonAction]
|
|
|
public async Task<BookingOrder> CustomerToOrder(BookingCustomerOrder custOrd)
|
|
|
{
|
|
|
_logger.LogInformation($"准备根据客户订舱数据生成订舱台账:{custOrd.BOOKINGNO}");
|
|
|
var bkOrder = custOrd.Adapt<BookingOrder>();
|
|
|
bkOrder.Id = YitIdHelper.NextId();
|
|
|
bkOrder.BSSTATUS = "已录入";
|
|
|
bkOrder.ParentId = 0;
|
|
|
bkOrder.LANENAME = bkOrder.LANECODE;
|
|
|
await _repOrder.InsertAsync(bkOrder);
|
|
|
|
|
|
custOrd.BookingId = bkOrder.Id; //客户订舱数据与订舱台账数据关联
|
|
|
await _rep.UpdateAsync(custOrd);
|
|
|
|
|
|
var bkEdiExt = new BookingEDIExt();
|
|
|
bkEdiExt.Id = YitIdHelper.NextId();
|
|
|
bkEdiExt.BookingId = bkOrder.Id;
|
|
|
bkEdiExt.SalerCode = custOrd.SaleCode;
|
|
|
await _repEdiExt.InsertAsync(bkEdiExt);
|
|
|
|
|
|
var ctnList = await _repCtn.AsQueryable().Filter(null, true).Where(x => x.BILLID == custOrd.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 == custOrd.Id).ToListAsync();
|
|
|
foreach (var serv in servList)
|
|
|
{
|
|
|
serv.Id = YitIdHelper.NextId();
|
|
|
serv.BookingId = bkOrder.Id;
|
|
|
await _repServiceItem.InsertAsync(serv);
|
|
|
}
|
|
|
|
|
|
//附件
|
|
|
var files = await _repFile.AsQueryable().Filter(null, true).Where(x => x.BookingId == custOrd.Id && x.IsDeleted == false).ToListAsync();
|
|
|
foreach (var file in files)
|
|
|
{
|
|
|
file.Id = YitIdHelper.NextId();
|
|
|
file.BookingId = bkOrder.Id;
|
|
|
|
|
|
await _repFile.InsertAsync(file);
|
|
|
}
|
|
|
|
|
|
return bkOrder;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 导入
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/ImportBooking")]
|
|
|
public async Task ImportBooking(IFormFile file, [FromForm] string carrierId)
|
|
|
{
|
|
|
//未上传文件
|
|
|
if (file == null || file.Length == 0)
|
|
|
{
|
|
|
throw Oops.Bah("未上传任何文件");
|
|
|
}
|
|
|
|
|
|
var ms = new MemoryStream();
|
|
|
await file.CopyToAsync(ms);
|
|
|
ms.Position = 0;
|
|
|
|
|
|
var dicIns = new Dictionary<BookingCustomerOrder, List<BookingCtn>>();
|
|
|
if (carrierId == "COSCO")
|
|
|
{
|
|
|
var data = MiniExcel.QueryAsDataTable(ms);
|
|
|
var colNames = new string[] { "COSCO账号", "密码", "约号", "船名", "航次", "航线", "ETD", "运输条款", "付费方式", "品名", "起运港", "卸货港", "目的地", "货物类型", "箱型箱量", "单箱重量", "订舱备注", "放舱通知邮箱", "航管" };
|
|
|
//DataRow drHead = data.Rows[0];
|
|
|
foreach (var cn in colNames)
|
|
|
{
|
|
|
if (!data.Columns.Contains(cn))
|
|
|
{
|
|
|
throw Oops.Bah($"文件格式有误,未找到列:{cn}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var carrList = await _cache.GetAllCodeCarrier();
|
|
|
var portLoadList = await _cache.GetAllCodePortLoad();
|
|
|
var portDestList = await _cache.GetAllCodePort();
|
|
|
var serviceList = await _cache.GetAllCodeService();
|
|
|
var frtList = await _cache.GetAllCodeFrt();
|
|
|
var ctnList = await _cache.GetAllCodeCtn();
|
|
|
|
|
|
var errList = new List<string>();
|
|
|
for (var idx = 0; idx < data.Rows.Count; idx++)
|
|
|
{
|
|
|
var custOrder = new BookingCustomerOrder();
|
|
|
|
|
|
custOrder.CARRIERID = carrierId;
|
|
|
custOrder.CARRIER = carrierId;
|
|
|
custOrder.CONTRACTNO = data.Rows[idx]["约号"].ToString();
|
|
|
custOrder.VESSEL = data.Rows[idx]["船名"].ToString();
|
|
|
custOrder.VOYNO = data.Rows[idx]["航次"].ToString();
|
|
|
custOrder.LANECODE = data.Rows[idx]["航线"].ToString();
|
|
|
|
|
|
var strETD = data.Rows[idx]["ETD"].ToString();
|
|
|
if (DateTime.TryParse(strETD, out DateTime etd))
|
|
|
{
|
|
|
custOrder.ETD = etd;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未能识别ETD:{strETD}");
|
|
|
}
|
|
|
|
|
|
var serCode = data.Rows[idx]["运输条款"].ToString();
|
|
|
var service = serviceList.FirstOrDefault(x => x.Code == serCode);
|
|
|
if (service == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到运输条款:{serCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.SERVICECODE = service.Code;
|
|
|
custOrder.SERVICE = service.Name;
|
|
|
}
|
|
|
|
|
|
var frtCode = data.Rows[idx]["付费方式"].ToString();
|
|
|
var frt = frtList.FirstOrDefault(x => x.Code == frtCode);
|
|
|
if (frt == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到付费方式:{frtCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.FRTCODE = frt.Code;
|
|
|
custOrder.BLFRT = frt.EnName;
|
|
|
}
|
|
|
|
|
|
custOrder.DESCRIPTION = data.Rows[idx]["品名"].ToString();
|
|
|
|
|
|
var portLoadCode = data.Rows[idx]["起运港"].ToString();
|
|
|
var portLoad = portLoadList.FirstOrDefault(x => x.Code == portLoadCode);
|
|
|
if (portLoad == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到起运港:{portLoadCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.PORTLOADID = portLoad.EdiCode;
|
|
|
custOrder.PORTLOAD = portLoad.EnName;
|
|
|
custOrder.PORTLOADCODE = portLoad.Code;
|
|
|
}
|
|
|
|
|
|
var portCode = data.Rows[idx]["卸货港"].ToString();
|
|
|
var portDest = portDestList.FirstOrDefault(x => x.Code == portCode);
|
|
|
if (portLoad == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到卸货港:{portCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.PORTDISCHARGEID = portLoad.EdiCode;
|
|
|
custOrder.PORTDISCHARGE = portLoad.EnName;
|
|
|
custOrder.PORTDISCHARGECODE = portLoad.Code;
|
|
|
}
|
|
|
|
|
|
var destina = data.Rows[idx]["目的地"].ToString();
|
|
|
var destinaFind = portDestList.FirstOrDefault(x => x.Code == destina);
|
|
|
if (portLoad == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到卸货港:{portCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.DESTINATIONID = portLoad.EdiCode;
|
|
|
custOrder.DESTINATION = portLoad.EnName;
|
|
|
custOrder.DESTINATIONCODE = portLoad.Code;
|
|
|
}
|
|
|
|
|
|
var cargoId = data.Rows[idx]["货物类型"].ToString();
|
|
|
custOrder.CARGOID = cargoId.Substring(0, 1);
|
|
|
|
|
|
custOrder.SOREMARK = data.Rows[idx]["订舱备注"].ToString();
|
|
|
custOrder.SaleCode = data.Rows[idx]["航管"].ToString();
|
|
|
|
|
|
//订舱账号、密码
|
|
|
var jobj = new JObject();
|
|
|
jobj["Account"] = data.Rows[idx]["COSCO账号"].ToString();
|
|
|
jobj["Password"] = data.Rows[idx]["密码"].ToString();
|
|
|
jobj["OpMail"] = data.Rows[idx]["放舱通知邮箱"].ToString();
|
|
|
custOrder.ExtendData = jobj.ToJsonString();
|
|
|
|
|
|
//箱信息
|
|
|
var ctnStr = data.Rows[idx]["箱型箱量"].ToString();
|
|
|
var arrCtn = ctnStr.Split("*".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
|
|
var ctns = new List<BookingCtn>();
|
|
|
if (arrCtn.Length == 2)
|
|
|
{
|
|
|
var ctn = ctnList.FirstOrDefault(x => x.Code == arrCtn[0]);
|
|
|
if (ctn == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到箱型:{arrCtn[0]}");
|
|
|
}
|
|
|
else if (int.TryParse(arrCtn[1], out int num))
|
|
|
{
|
|
|
var ctnAdd = new BookingCtn()
|
|
|
{
|
|
|
CTNALL = ctn.Name,
|
|
|
CTNNUM = num,
|
|
|
CTNCODE = ctn.Code
|
|
|
};
|
|
|
ctns.Add(ctnAdd);
|
|
|
|
|
|
var ctnKGS = data.Rows[idx]["单箱重量"].ToString();
|
|
|
if (decimal.TryParse(ctnKGS, out decimal cw))
|
|
|
{
|
|
|
ctnAdd.KGS = cw;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
dicIns.Add(custOrder, ctns);
|
|
|
}
|
|
|
|
|
|
if (errList.Count > 0)
|
|
|
{
|
|
|
throw Oops.Bah(string.Join("\r\n", errList));
|
|
|
}
|
|
|
}
|
|
|
else if (carrierId == "EMC")
|
|
|
{
|
|
|
var data = MiniExcel.QueryAsDataTable(ms);
|
|
|
var colNames = new string[] { "POL", "卸货港", "交货地", "运送方式", "运送型态", "SIZE", "WEIGHT(单箱)", "description of goods", "合约类型", "合约号", "运费付款方式", "船名", "航次", "航线", "ETD", "订舱确认邮箱", "备注 (其它注意事项)" };
|
|
|
//DataRow drHead = data.Rows[0];
|
|
|
foreach (var cn in colNames)
|
|
|
{
|
|
|
if (!data.Columns.Contains(cn))
|
|
|
{
|
|
|
throw Oops.Bah($"文件格式有误,未找到列:{cn}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var carrList = await _cache.GetAllCodeCarrier();
|
|
|
var portLoadList = await _cache.GetAllCodePortLoad();
|
|
|
var portDestList = await _cache.GetAllCodePort();
|
|
|
var serviceList = await _cache.GetAllCodeService();
|
|
|
var frtList = await _cache.GetAllCodeFrt();
|
|
|
var ctnList = await _cache.GetAllCodeCtn();
|
|
|
|
|
|
var errList = new List<string>();
|
|
|
for (var idx = 0; idx < data.Rows.Count; idx++)
|
|
|
{
|
|
|
var custOrder = new BookingCustomerOrder();
|
|
|
|
|
|
custOrder.CARRIERID = carrierId;
|
|
|
custOrder.CARRIER = carrierId;
|
|
|
custOrder.CONTRACTNO = data.Rows[idx]["合约号"].ToString();
|
|
|
custOrder.VESSEL = data.Rows[idx]["船名"].ToString();
|
|
|
custOrder.VOYNO = data.Rows[idx]["航次"].ToString();
|
|
|
custOrder.LANECODE = data.Rows[idx]["航线"].ToString();
|
|
|
|
|
|
var strETD = data.Rows[idx]["ETD"].ToString();
|
|
|
if (Regex.IsMatch(strETD, "^\\d+$"))
|
|
|
{
|
|
|
custOrder.ETD = DateTime.FromOADate(Convert.ToDouble(strETD));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (DateTime.TryParse(strETD, out DateTime etd))
|
|
|
{
|
|
|
custOrder.ETD = etd;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未能识别ETD:{strETD}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
var frtCode = data.Rows[idx]["运费付款方式"].ToString();
|
|
|
var frt = frtList.FirstOrDefault(x => x.Code == frtCode);
|
|
|
if (frt == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到付费方式:{frtCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.FRTCODE = frt.Code;
|
|
|
custOrder.BLFRT = frt.EnName;
|
|
|
}
|
|
|
|
|
|
custOrder.DESCRIPTION = data.Rows[idx]["description of goods"].ToString();
|
|
|
|
|
|
var portLoadCode = data.Rows[idx]["POL"].ToString();
|
|
|
var portLoad = portLoadList.FirstOrDefault(x => x.Code == portLoadCode || x.EnName == portLoadCode);
|
|
|
if (portLoad == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到起运港:{portLoadCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.PORTLOADID = portLoad.EdiCode;
|
|
|
custOrder.PORTLOAD = portLoad.EnName;
|
|
|
custOrder.PORTLOADCODE = portLoad.Code;
|
|
|
}
|
|
|
|
|
|
var portCode = data.Rows[idx]["卸货港"].ToString();
|
|
|
var portDest = portDestList.FirstOrDefault(x => x.Code == portCode || x.EnName == portCode);
|
|
|
if (portDest == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到卸货港:{portCode}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.PORTDISCHARGEID = portDest.EdiCode;
|
|
|
custOrder.PORTDISCHARGE = portDest.EnName;
|
|
|
custOrder.PORTDISCHARGECODE = portDest.Code;
|
|
|
}
|
|
|
|
|
|
var destina = data.Rows[idx]["交货地"].ToString();
|
|
|
var destinaFind = portDestList.FirstOrDefault(x => x.Code == destina || x.EnName == destina);
|
|
|
if (destinaFind == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到交货地:{destina}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder.DESTINATIONID = destinaFind.EdiCode;
|
|
|
custOrder.DESTINATION = destinaFind.EnName;
|
|
|
custOrder.DESTINATIONCODE = destinaFind.Code;
|
|
|
}
|
|
|
|
|
|
custOrder.SOREMARK = data.Rows[idx]["备注 (其它注意事项)"].ToString();
|
|
|
|
|
|
//订舱账号、密码
|
|
|
//custOrder.BookingAccount = data.Rows[idx]["EMC账号"].ToString();
|
|
|
//custOrder.BookingPassword = data.Rows[idx]["EMC密码"].ToString();
|
|
|
|
|
|
//2024年6月17日,衣国豪:导入时一定会先设置用户的账号密码,因此取用户设置中的账密
|
|
|
var webAccountConfig = await _webAccountConfig.GetAccountConfigByTenantId("EmcWeb", UserManager.UserId, UserManager.TENANT_ID);
|
|
|
if (webAccountConfig != null)
|
|
|
{
|
|
|
custOrder.BookingAccount = webAccountConfig.Account;
|
|
|
custOrder.BookingPassword = webAccountConfig.Password;
|
|
|
}
|
|
|
|
|
|
custOrder.OpMail = data.Rows[idx]["订舱确认邮箱"].ToString();
|
|
|
//custOrder.ContactName = data.Rows[idx]["联系人"].ToString();
|
|
|
//custOrder.ContactTel = data.Rows[idx]["联系电话"].ToString();
|
|
|
custOrder.ServiceType = data.Rows[idx]["运送方式"].ToString();
|
|
|
custOrder.ServiceMode = data.Rows[idx]["运送型态"].ToString();
|
|
|
custOrder.ContractType = data.Rows[idx]["合约类型"].ToString();
|
|
|
|
|
|
/*
|
|
|
* 2024年6月17日:
|
|
|
* 模板导入后,收货地默认同装货港,签约方默认forwarder,提单数量默认1
|
|
|
* 订舱网点,提单签发地,发货人信息,货物代理人信息,默认调用该用户最近一票订舱业务信息。
|
|
|
*/
|
|
|
custOrder.PLACERECEIPT = custOrder.PORTLOAD;
|
|
|
custOrder.PLACERECEIPTID = custOrder.PORTLOADID;
|
|
|
custOrder.PLACERECEIPTCODE = custOrder.PORTLOADCODE;
|
|
|
custOrder.SignType = "Forwarder";
|
|
|
custOrder.BillCount = 1;
|
|
|
|
|
|
var lastOrder = await _rep.AsQueryable().Where(x => x.CreatedUserId == UserManager.UserId).OrderByDescending(x => x.CreatedTime).FirstAsync();
|
|
|
custOrder.BookingAddr = lastOrder.BookingAddr;
|
|
|
custOrder.BillSignLoc = lastOrder.BillSignLoc;
|
|
|
custOrder.SHIPPER = lastOrder.SHIPPER;
|
|
|
custOrder.ShipperAddress = lastOrder.ShipperAddress;
|
|
|
custOrder.ShipperCity = lastOrder.ShipperCity;
|
|
|
custOrder.ShipperCountry = lastOrder.ShipperCountry;
|
|
|
custOrder.ShipperCounty = lastOrder.ShipperCounty;
|
|
|
custOrder.ShipperEmail = lastOrder.ShipperEmail;
|
|
|
custOrder.ShipperFirstName = lastOrder.ShipperFirstName;
|
|
|
custOrder.ShipperInnerCode = lastOrder.ShipperInnerCode;
|
|
|
custOrder.ShipperLastName = lastOrder.ShipperLastName;
|
|
|
custOrder.ShipperName = lastOrder.ShipperName;
|
|
|
custOrder.ShipperPhone = lastOrder.ShipperPhone;
|
|
|
custOrder.ShipperPhoneCode = lastOrder.ShipperPhoneCode;
|
|
|
custOrder.ShipperPhoneCountryCode = lastOrder.ShipperPhoneCountryCode;
|
|
|
custOrder.ShipperPhoneExtension = lastOrder.ShipperPhoneExtension;
|
|
|
custOrder.ShipperPostCode = lastOrder.ShipperPostCode;
|
|
|
custOrder.ShipperProvince = lastOrder.ShipperProvince;
|
|
|
custOrder.ShipperSex = lastOrder.ShipperSex;
|
|
|
|
|
|
custOrder.BookingAddress = lastOrder.BookingAddress;
|
|
|
custOrder.BookingCity = lastOrder.BookingCity;
|
|
|
custOrder.BookingCountry = lastOrder.BookingCountry;
|
|
|
custOrder.BookingCounty = lastOrder.BookingCounty;
|
|
|
custOrder.BookingEmail = lastOrder.BookingEmail;
|
|
|
custOrder.BookingFirstName = lastOrder.BookingFirstName;
|
|
|
custOrder.BookingInnerCode = lastOrder.BookingInnerCode;
|
|
|
custOrder.BookingLastName = lastOrder.BookingLastName;
|
|
|
custOrder.BookingName = lastOrder.BookingName;
|
|
|
custOrder.BookingPhone = lastOrder.BookingPhone;
|
|
|
custOrder.BookingPhoneCode = lastOrder.BookingPhoneCode;
|
|
|
custOrder.BookingPhoneCountryCode = lastOrder.BookingPhoneCountryCode;
|
|
|
custOrder.BookingPhoneExtension = lastOrder.BookingPhoneExtension;
|
|
|
custOrder.BookingPostCode = lastOrder.BookingPostCode;
|
|
|
custOrder.BookingProvince = lastOrder.BookingProvince;
|
|
|
custOrder.BookingSex = lastOrder.BookingSex;
|
|
|
|
|
|
//箱信息
|
|
|
var ctnStr = data.Rows[idx]["SIZE"].ToString();
|
|
|
var arrCtn = ctnStr.Split("*".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
|
|
var ctns = new List<BookingCtn>();
|
|
|
if (arrCtn.Length == 2)
|
|
|
{
|
|
|
var ctn = ctnList.FirstOrDefault(x => x.Code == arrCtn[0] || x.Name == arrCtn[0]);
|
|
|
if (ctn == null)
|
|
|
{
|
|
|
errList.Add($"第{idx + 1}行,未找到箱型:{arrCtn[0]}");
|
|
|
}
|
|
|
else if (int.TryParse(arrCtn[1], out int num))
|
|
|
{
|
|
|
var ctnAdd = new BookingCtn()
|
|
|
{
|
|
|
CTNALL = ctn.Name,
|
|
|
CTNNUM = num,
|
|
|
CTNCODE = ctn.Code
|
|
|
};
|
|
|
ctns.Add(ctnAdd);
|
|
|
|
|
|
var ctnKGS = data.Rows[idx]["WEIGHT(单箱)"].ToString();
|
|
|
if (decimal.TryParse(ctnKGS, out decimal cw))
|
|
|
{
|
|
|
ctnAdd.KGS = cw;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
dicIns.Add(custOrder, ctns);
|
|
|
}
|
|
|
|
|
|
if (errList.Count > 0)
|
|
|
{
|
|
|
throw Oops.Bah(string.Join("\r\n", errList));
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw Oops.Bah("当前不支持的该船司");
|
|
|
}
|
|
|
|
|
|
foreach (var k in dicIns)
|
|
|
{
|
|
|
await SaveData(k.Key, k.Value, new List<BookingServiceItem>() { new BookingServiceItem() { Code = "dingcang", Value = "订舱" } }, true);
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 运营端操作与接口
|
|
|
/// <summary>
|
|
|
/// 接收客户订舱系统提交的数据
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/ReceiveBooking"), AllowAnonymous, ApiUser(ApiCode = "DjyBookingReceiveApi")]
|
|
|
public async Task<List<BookingSubmitResultModel>> ReceiveBooking(List<BookingCustomerSubmitDto> list)
|
|
|
{
|
|
|
_logger.LogInformation($"收到提交的订舱数据:{JsonConvert.SerializeObject(list)}");
|
|
|
|
|
|
var rtnList = new List<BookingSubmitResultModel>();
|
|
|
|
|
|
var ordOkList = new List<BookingCustomerOrder>();
|
|
|
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<BookingCustomerOrder>();
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
ordOkList.Add(order);
|
|
|
|
|
|
//箱信息
|
|
|
await _repCtn.DeleteAsync(x => x.BILLID == order.Id);
|
|
|
foreach (var ctn in item.CtnList)
|
|
|
{
|
|
|
var bkCtn = ctn.Adapt<BookingCtn>();
|
|
|
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<BookingServiceItem>();
|
|
|
bkServ.Id = YitIdHelper.NextId();
|
|
|
bkServ.BookingId = order.Id;
|
|
|
await _repServiceItem.InsertAsync(bkServ);
|
|
|
}
|
|
|
|
|
|
//文件
|
|
|
await _repFile.DeleteAsync(x => x.BookingId == order.Id);
|
|
|
foreach (var file in item.Files)
|
|
|
{
|
|
|
var bkFile = file.Adapt<BookingFile>();
|
|
|
bkFile.Id = YitIdHelper.NextId();
|
|
|
bkFile.BookingId = order.Id;
|
|
|
await _repFile.InsertAsync(bkFile);
|
|
|
}
|
|
|
|
|
|
rtnList.Add(new BookingSubmitResultModel()
|
|
|
{
|
|
|
Id = item.Id,
|
|
|
Success = true,
|
|
|
BOOKINGNO = item.BOOKINGNO,
|
|
|
Message = $"提交成功"
|
|
|
});
|
|
|
|
|
|
|
|
|
//日志动态
|
|
|
SaveAuditLog($"待审核", order.Id);
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation($"rtnList:{rtnList.ToJsonString()}");
|
|
|
|
|
|
//全部成功后,才能自动订舱和审核
|
|
|
if (rtnList.Count(x => x.Success == false) == 0)
|
|
|
{
|
|
|
var tCustId = list.First().BookingTenantId;
|
|
|
_logger.LogInformation($"提交成功,准备自动订舱和审核");
|
|
|
|
|
|
//自动订舱和自动审核
|
|
|
var cust = await _repCustomer.AsQueryable().Filter(null, true).FirstAsync(x => x.CustSysId == tCustId);
|
|
|
if (cust != null)
|
|
|
{
|
|
|
_logger.LogInformation($"找到客户端租户对应客户:{cust.FullName}");
|
|
|
|
|
|
var paraCallApiAuditAuto = await _repCustomerParamValue.AsQueryable().FirstAsync(x => x.CustomerId == cust.Id && x.ParaCode == "BookingCallApiAndAuditAuto");
|
|
|
if (paraCallApiAuditAuto != null && !string.IsNullOrEmpty(paraCallApiAuditAuto.ItemCode))
|
|
|
{
|
|
|
foreach (var ord in ordOkList)
|
|
|
{
|
|
|
if (!paraCallApiAuditAuto.ItemCode.Contains(ord.CARRIERID))
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//异步执行自动订舱和审核,并带有延时
|
|
|
Task.Run(async () =>
|
|
|
{
|
|
|
Task.Delay(2000);
|
|
|
var succ = false;
|
|
|
try
|
|
|
{
|
|
|
_logger.LogInformation($"自动订舱:{ord}");
|
|
|
await PostApiSO(ord.Id);
|
|
|
succ = true;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.LogError($"自动订舱失败:{ord},错误信息:{ex.Message}");
|
|
|
_logger.LogError(ex.StackTrace);
|
|
|
await AuditBooking(ord.Id, false, ex.Message);
|
|
|
}
|
|
|
|
|
|
if (succ)
|
|
|
{
|
|
|
_logger.LogInformation($"自动审核:{ord}");
|
|
|
await AuditBooking(ord.Id, true, "系统自动审核");
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
_logger.LogWarning($"未找到客户,CustSysId:{tCustId}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return rtnList;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 审核订舱请求
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/AuditBooking")]
|
|
|
public async Task AuditBooking(long id, bool accept, string comment)
|
|
|
{
|
|
|
var model = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == id);
|
|
|
if (model == null)
|
|
|
{
|
|
|
throw Oops.Bah("未找到业务信息");
|
|
|
}
|
|
|
|
|
|
if (model.BSSTATUS != "待审核")
|
|
|
{
|
|
|
throw Oops.Bah("当前状态不能审核");
|
|
|
}
|
|
|
|
|
|
if (accept)
|
|
|
{
|
|
|
model.BSSTATUS = "已审核";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
model.BSSTATUS = "已驳回";
|
|
|
}
|
|
|
|
|
|
//回推回执
|
|
|
var feedbackData = new BookingCustomerRecAduitFeedbackDto()
|
|
|
{
|
|
|
Id = model.BSNO,
|
|
|
Accept = accept,
|
|
|
Comment = comment
|
|
|
};
|
|
|
|
|
|
var feedbackObj = new BookingFeedbackDto(BookingFeedbackType.Audit.ToString());
|
|
|
feedbackObj.JsonContent = feedbackData.ToJsonString();
|
|
|
|
|
|
_logger.LogInformation($"回推审核数据:{JsonConvert.SerializeObject(feedbackObj)},URL:{model.FeedbackUrl}");
|
|
|
|
|
|
var rtn = await model.FeedbackUrl
|
|
|
.SetHeaders(new Dictionary<string, object> {
|
|
|
{ CommonConst.API_USER_HEADER_KEY, model.FeedbackKey},
|
|
|
{ CommonConst.API_USER_HEADER_SECRET, model.FeedbackSecret}
|
|
|
})
|
|
|
.SetBody(feedbackObj, "application/x-www-form-urlencoded")
|
|
|
.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 ? "审核通过" : "审核驳回")}", id, remark: $"审核意见:{comment}");
|
|
|
|
|
|
//进入订舱台账
|
|
|
if (accept)
|
|
|
{
|
|
|
var custBookId = jobjRtn.GetStringValue("data"); //返回的客户订舱系统的订舱数据id
|
|
|
_logger.LogInformation($"收到客户端返回的订舱台账id:{custBookId}");
|
|
|
|
|
|
var bkOrder = await CustomerToOrder(model);
|
|
|
bkOrder.BSNO = custBookId;
|
|
|
bkOrder.CUSTOMERNAME = model.BookingTenantName;
|
|
|
bkOrder.LANENAME = bkOrder.LANECODE;
|
|
|
await _repOrder.AsUpdateable(bkOrder).UpdateColumns(x => new { x.BSNO, x.CUSTOMERNAME, x.LANENAME }).ExecuteCommandAsync();
|
|
|
|
|
|
model.BookingId = bkOrder.Id; //客户订舱数据与订舱台账数据关联
|
|
|
await _rep.UpdateAsync(model);
|
|
|
|
|
|
_logger.LogInformation($"审核通过,进入订舱台账,客户订舱ID:{model.Id},订舱台账ID:{bkOrder.Id},系统编号:{model.BOOKINGNO}");
|
|
|
|
|
|
|
|
|
//订舱编号回写
|
|
|
JObject extObj = null;
|
|
|
if (!string.IsNullOrEmpty(model.ExtendData))
|
|
|
{
|
|
|
extObj = JObject.Parse(model.ExtendData);
|
|
|
if (model.CARRIERID == "COSCO")
|
|
|
{
|
|
|
var custNO = extObj.GetStringValue("CustNO");
|
|
|
if (!string.IsNullOrEmpty(custNO))
|
|
|
{
|
|
|
_logger.LogInformation($"回写订舱编号:{custNO},系统编号:{model.BOOKINGNO}");
|
|
|
|
|
|
bkOrder.CUSTNO = custNO;
|
|
|
bkOrder.BSSTATUS = "已订舱";
|
|
|
await _repOrder.AsUpdateable(bkOrder).UpdateColumns(x => new { x.CUSTNO, x.BSSTATUS }).ExecuteCommandAsync();
|
|
|
CustomerBookingSyncHelper.SendCustomerBookingSync(bkOrder.Id, BookingOrderSyncTypeEnum.CC.ToString());
|
|
|
_logger.LogInformation($"回写订舱号并回推客户端:{bkOrder.Id} {custNO}");
|
|
|
|
|
|
//2024年7月17日,增加了单独的订舱编号字段,方便运营端查询
|
|
|
model.CustNO = custNO;
|
|
|
await _rep.AsUpdateable(model).UpdateColumns(x => new { x.CustNO }).ExecuteCommandAsync();
|
|
|
}
|
|
|
}
|
|
|
else if (model.CARRIERID == "EMC")
|
|
|
{
|
|
|
var custNOArr = extObj.GetJArrayValue("CustNO");
|
|
|
if (custNOArr != null && custNOArr.Count > 0)
|
|
|
{
|
|
|
var custNO = custNOArr.First().ToString();
|
|
|
_logger.LogInformation($"回写订舱编号:{custNO},系统编号:{model.BOOKINGNO}");
|
|
|
|
|
|
bkOrder.CUSTNO = custNO;
|
|
|
bkOrder.BSSTATUS = "已订舱";
|
|
|
await _repOrder.AsUpdateable(bkOrder).UpdateColumns(x => new { x.CUSTNO, x.BSSTATUS }).ExecuteCommandAsync();
|
|
|
CustomerBookingSyncHelper.SendCustomerBookingSync(bkOrder.Id, BookingOrderSyncTypeEnum.CC.ToString());
|
|
|
_logger.LogInformation($"回写订舱号并回推客户端:{bkOrder.Id} {bkOrder.CUSTNO}");
|
|
|
|
|
|
//2024年7月17日,增加了单独的订舱编号字段,方便运营端查询
|
|
|
model.CustNO = custNO;
|
|
|
await _rep.AsUpdateable(model).UpdateColumns(x => new { x.CustNO }).ExecuteCommandAsync();
|
|
|
|
|
|
//有多票订舱编号,后台自动创建数据并对应
|
|
|
custNOArr.RemoveAt(0);
|
|
|
if (custNOArr.Count > 0)
|
|
|
{
|
|
|
_logger.LogInformation($"多订舱编号回写,系统编号:{model.BOOKINGNO}");
|
|
|
CustomerBookingSyncHelper.SendCustomerMultiCustNOSync(new BookingCustomerMultiCustNODto()
|
|
|
{
|
|
|
Id = model.BSNO,
|
|
|
ListCustNO = custNOArr.Select(x => x.ToString()).ToList()
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//扣费
|
|
|
if (accept)
|
|
|
{
|
|
|
await FeeSo(model.Id);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 测试多票订舱编号
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpGet("/BookingCustomerOrder/TestMultiBookingNO"), AllowAnonymous]
|
|
|
public async Task TestMultiBookingNO(long id)
|
|
|
{
|
|
|
JArray bookingNOArr = new JArray
|
|
|
{
|
|
|
"Test001",
|
|
|
"Test002"
|
|
|
};
|
|
|
CustomerBookingSyncHelper.SendCustomerMultiCustNOSync(new BookingCustomerMultiCustNODto()
|
|
|
{
|
|
|
Id = id.ToString(),
|
|
|
ListCustNO = bookingNOArr.Select(x => x.ToString()).ToList()
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 接收客户订舱系统取消提交的数据
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/CancelBooking"), AllowAnonymous, ApiUser(ApiCode = "DjyBookingReceiveApi")]
|
|
|
public async Task<List<BookingSubmitResultModel>> CancelBooking(List<BookingCustomerCancelSubmitDto> list)
|
|
|
{
|
|
|
_logger.LogInformation($"收到提交的订舱数据:{JsonConvert.SerializeObject(list)}");
|
|
|
|
|
|
var rtnList = new List<BookingSubmitResultModel>();
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 接收客户端修改服务项目
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/ChangeServiceItem"), AllowAnonymous, ApiUser(ApiCode = "DjyBookingReceiveApi")]
|
|
|
public async Task ChangeServiceItem(ChangeServiceItemDto dto)
|
|
|
{
|
|
|
var model = await _rep.AsQueryable().Filter(null, true)
|
|
|
.InnerJoin(_repOrder.AsQueryable().Filter(null, true), (custOrd, ord) => custOrd.BookingId == ord.Id)
|
|
|
.Where((custOrd, ord) => custOrd.BookingTenantName == dto.CompanyName && ord.BSNO == dto.Id)
|
|
|
.Select((custOrd, ord) => new { ord, custOrd })
|
|
|
.FirstAsync();
|
|
|
|
|
|
if (model == null)
|
|
|
{
|
|
|
throw Oops.Bah("未找到业务数据");
|
|
|
}
|
|
|
|
|
|
var serItm = _cache.GetAllDictData().Result.FirstOrDefault(x => x.TypeCode == "booking_service_item" && x.Code == dto.ServiceCode);
|
|
|
|
|
|
var mess = new DjyMessage();
|
|
|
mess.Module = MessageModule.Booking.ToString();
|
|
|
mess.TypeCode = MessageType.ChangeServiceItem.ToString();
|
|
|
mess.TypeName = EnumHelper.GetDescription(typeof(MessageType), mess.TypeCode);
|
|
|
mess.RelativeId = model.ord.Id;
|
|
|
mess.RelativeCode = model.ord.BOOKINGNO;
|
|
|
mess.Content = $"{dto.UserName} {(dto.IsCancel ? "取消" : "增加")}了服务项目:{serItm.Value}";
|
|
|
mess.ExtData = new ChangeServiceItemExtModel() { Dto = dto, OrderId = model.ord.Id, CustomerOrderId = model.custOrd.Id }.ToJsonString();
|
|
|
mess.FromName = dto.CompanyName;
|
|
|
mess.ProcStatus = MessageProcessStatus.UnProcess.ToString();
|
|
|
await this._repMessage.InsertAsync(mess);
|
|
|
await _publisher.PublishAsync(new ChannelEventSource("Message:NotifyReceiveNew"));
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 接收客户端提交的单证补料
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/RecDocSupplement"), AllowAnonymous, ApiUser(ApiCode = "DjyBookingReceiveApi")]
|
|
|
public async Task RecDocSupplement(DocSupplementSubmitDto dto)
|
|
|
{
|
|
|
var model = await _rep.AsQueryable().Filter(null, true)
|
|
|
.InnerJoin(_repOrder.AsQueryable().Filter(null, true), (custOrd, ord) => custOrd.BookingId == ord.Id)
|
|
|
.Where((custOrd, ord) => custOrd.BookingTenantName == dto.CompanyName && ord.BSNO == dto.Id)
|
|
|
.Select((custOrd, ord) => new { ord, custOrd })
|
|
|
.FirstAsync();
|
|
|
|
|
|
if (model == null)
|
|
|
{
|
|
|
throw Oops.Bah("未找到业务数据");
|
|
|
}
|
|
|
|
|
|
|
|
|
var mess = new DjyMessage();
|
|
|
mess.Module = MessageModule.Booking.ToString();
|
|
|
mess.TypeCode = MessageType.DocSupplement.ToString();
|
|
|
mess.TypeName = EnumHelper.GetDescription(typeof(MessageType), mess.TypeCode);
|
|
|
mess.RelativeId = model.ord.Id;
|
|
|
mess.RelativeCode = model.ord.BOOKINGNO;
|
|
|
mess.Content = $"{dto.UserName} 增加了 {dto.DocTypeName}";
|
|
|
mess.ExtData = new DocSupplementExtModel() { Dto = dto, OrderId = model.ord.Id, CustomerOrderId = model.custOrd.Id }.ToJsonString();
|
|
|
mess.FromName = dto.CompanyName;
|
|
|
mess.ProcStatus = MessageProcessStatus.UnProcess.ToString();
|
|
|
await this._repMessage.InsertAsync(mess);
|
|
|
await _publisher.PublishAsync(new ChannelEventSource("Message:NotifyReceiveNew"));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 扣费
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/DoFee")]
|
|
|
public async Task DoFee(long custOrdId)
|
|
|
{
|
|
|
await FeeSo(custOrdId);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 作废
|
|
|
/// </summary>
|
|
|
/// <param name="id"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/CancelBook")]
|
|
|
public async Task CancelBook(long id)
|
|
|
{
|
|
|
var model = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == id);
|
|
|
if (model == null)
|
|
|
{
|
|
|
throw Oops.Bah("未找到业务信息");
|
|
|
}
|
|
|
|
|
|
if (model.BSSTATUS != "已审核")
|
|
|
{
|
|
|
throw Oops.Bah("当前状态不能作废");
|
|
|
}
|
|
|
|
|
|
model.BSSTATUS = "已作废";
|
|
|
|
|
|
//回推回执
|
|
|
var feedbackData = new BookingCustomerCancelSubmitDto()
|
|
|
{
|
|
|
Id = model.BSNO
|
|
|
};
|
|
|
|
|
|
var feedbackObj = new BookingFeedbackDto(BookingFeedbackType.CancelBook.ToString());
|
|
|
feedbackObj.JsonContent = feedbackData.ToJsonString();
|
|
|
|
|
|
_logger.LogInformation($"回推作废数据:{JsonConvert.SerializeObject(feedbackObj)},URL:{model.FeedbackUrl}");
|
|
|
|
|
|
var rtn = await model.FeedbackUrl
|
|
|
.SetHeaders(new Dictionary<string, object> {
|
|
|
{ CommonConst.API_USER_HEADER_KEY, model.FeedbackKey},
|
|
|
{ CommonConst.API_USER_HEADER_SECRET, model.FeedbackSecret}
|
|
|
})
|
|
|
.SetBody(feedbackObj, "application/x-www-form-urlencoded")
|
|
|
.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 order = await _repOrder.FirstOrDefaultAsync(x => x.Id == model.BookingId);
|
|
|
if (order != null)
|
|
|
{
|
|
|
order.IsDeleted = true;
|
|
|
await _repOrder.AsUpdateable(order).UpdateColumns(x => new { x.IsDeleted }).ExecuteCommandAsync();
|
|
|
}
|
|
|
|
|
|
//日志动态
|
|
|
SaveAuditLog($"作废", id, remark: $"");
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 私有方法
|
|
|
|
|
|
/// <summary>
|
|
|
/// 保存审核的日志动态(使用当前登录人信息)
|
|
|
/// </summary>
|
|
|
private void SaveAuditLog(string status, long bookId, string remark = null)
|
|
|
{
|
|
|
var staLog = new BookingStatusLog();
|
|
|
staLog.Status = status;
|
|
|
if (App.User == null)
|
|
|
{
|
|
|
staLog.CreatedUserId = 0;
|
|
|
staLog.CreatedUserName = "系统";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
staLog.CreatedUserId = UserManager.UserId;
|
|
|
staLog.CreatedUserName = UserManager.Name;
|
|
|
}
|
|
|
staLog.CreatedTime = DateTime.Now;
|
|
|
staLog.OpTime = DateTime.Now;
|
|
|
staLog.BookingId = bookId;
|
|
|
staLog.Category = StaLogCateAudit;
|
|
|
staLog.Remark = remark;
|
|
|
_repStatuslog.Insert(staLog);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 保存审核的日志动态
|
|
|
/// </summary>
|
|
|
private void SaveAuditLog(string status, long bookId, long userId, long tenantId, string userName, string remark = null)
|
|
|
{
|
|
|
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;
|
|
|
staLog.Remark = remark;
|
|
|
_repStatuslog.Insert(staLog);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 订舱审核后自动扣费
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
private async Task FeeSo(long id)
|
|
|
{
|
|
|
var model = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == id);
|
|
|
var cust = await _repCustomer.AsQueryable().Filter(null, true).FirstAsync(x => x.CustSysId == model.BookingTenantId);
|
|
|
var custParaList = await _repCustomerParamValue.AsQueryable().Filter(null, true).Where(x => x.CustomerId == cust.Id && (x.ParaCode == "DjyFeeApiUserId" || x.ParaCode == "DjyFeeApiUserSecret")).ToListAsync();
|
|
|
|
|
|
var bsType = 32;
|
|
|
var sendType = 0;
|
|
|
var typeStr = $"{bsType}_{sendType}";
|
|
|
var sysCfg = await _cache.GetAllSysConfig();
|
|
|
var feeUrl = sysCfg.FirstOrDefault(x => x.Code == "djyFeeApiUrl");
|
|
|
if (feeUrl == null || string.IsNullOrEmpty(feeUrl.Value))
|
|
|
{
|
|
|
var errMsg = "大简云扣费URL未配置";
|
|
|
_logger.LogError(errMsg);
|
|
|
SaveAuditLog($"扣费失败", model.Id, model.CreatedUserId.Value, model.TenantId.Value, "系统", remark: errMsg);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//扣费接口用户id和key
|
|
|
var feeUserId = custParaList.FirstOrDefault(x => x.ParaCode == "DjyFeeApiUserId")?.ItemCode;
|
|
|
var feeUserKey = custParaList.FirstOrDefault(x => x.ParaCode == "DjyFeeApiUserSecret")?.ItemCode;
|
|
|
if (string.IsNullOrEmpty(feeUserId) || string.IsNullOrEmpty(feeUserKey))
|
|
|
{
|
|
|
var errMsg = $"未找到{model.BOOKINGNO}({model.Id})所在客户的授权userid和key,无法调用扣费";
|
|
|
_logger.LogError(errMsg);
|
|
|
SaveAuditLog($"扣费失败", model.Id, model.CreatedUserId.Value, model.TenantId.Value, "系统", remark: "未找到扣费接口授权信息");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//判断重复扣费
|
|
|
var c = _repFeeRecord.AsQueryable().Filter(null, true).Count(x => x.TenantId == model.BookingTenantId && x.MBLNO == model.BOOKINGNO);
|
|
|
if (c > 0)
|
|
|
{
|
|
|
_logger.LogInformation($"已存在扣费记录,id:{model.Id},订舱号:{model.BOOKINGNO},租户:{model.BookingTenantId}");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//客户联系人
|
|
|
var contact = await _repCustomerContact.AsQueryable().Filter(null, true).FirstAsync(x => x.CustSysId == model.BookingUserId);
|
|
|
if (contact == null)
|
|
|
{
|
|
|
var errMsg = $"未找到{model.BOOKINGNO}({model.Id})的客户联系人";
|
|
|
_logger.LogError(errMsg);
|
|
|
SaveAuditLog($"扣费失败", model.Id, model.CreatedUserId.Value, model.TenantId.Value, "系统", remark: "未找到客户联系人");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//扣费时记录订舱编号
|
|
|
var lstBookNO = new List<string>();
|
|
|
if (!string.IsNullOrEmpty(model.ExtendData))
|
|
|
{
|
|
|
var extObj = JObject.Parse(model.ExtendData);
|
|
|
if (model.CARRIERID == "COSCO")
|
|
|
{
|
|
|
lstBookNO.Add(extObj.GetStringValue("CustNO"));
|
|
|
}
|
|
|
else if (model.CARRIERID == "EMC")
|
|
|
{
|
|
|
var custNOArr = extObj.GetJArrayValue("CustNO");
|
|
|
if (custNOArr != null && custNOArr.Count > 0)
|
|
|
{
|
|
|
lstBookNO.AddRange(custNOArr.Select(x => x.ToString()));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//扣费dto
|
|
|
foreach (var bookingNO in lstBookNO)
|
|
|
{
|
|
|
var seconds = DateTime.Now.ToTimeStamp();
|
|
|
var runId = Guid.NewGuid().ToString();
|
|
|
var srcBeforMD5 = $"{runId}{feeUserId}expend{bsType}{sendType}{model.Id}{model.BOOKINGNO}{seconds}{feeUserKey}";
|
|
|
var postObj = new
|
|
|
{
|
|
|
runId,
|
|
|
userId = feeUserId,
|
|
|
module = "expend",//固定
|
|
|
bsType = $"{bsType}",
|
|
|
sendType = $"{sendType}",
|
|
|
timestamp = seconds,//秒级时间戳
|
|
|
md5 = srcBeforMD5.ToMd5(),// 加密字符串小写 RunId + UserId + Module + BsType + SendType+Timestamp+ Key
|
|
|
Data = new
|
|
|
{
|
|
|
BSNO = model.Id.ToString(),
|
|
|
MBLNO = model.BOOKINGNO,
|
|
|
CtnrInfo = "",
|
|
|
CtnrCount = 1,
|
|
|
IsCredit = 0,//是否是信用支付 1 信用支付 0不允许信用支付默认值为0,
|
|
|
LURURENID = contact.DjyGid,
|
|
|
SENDUSERID = contact.DjyGid,
|
|
|
VESSEL = model.VESSEL,
|
|
|
VOYNO = model.VOYNO,
|
|
|
ETD = model.ETD,
|
|
|
CARRIER = model.CARRIER,
|
|
|
BEIZHU = bookingNO
|
|
|
}
|
|
|
};
|
|
|
|
|
|
_logger.LogInformation($"调用扣费:{postObj.ToJsonString()}");
|
|
|
var apiRtn = await feeUrl.Value
|
|
|
.SetHttpMethod(HttpMethod.Post)
|
|
|
.SetBody(postObj)
|
|
|
.SetRetryPolicy(3, 5000)
|
|
|
.OnException((c, m, errMsg) =>
|
|
|
{
|
|
|
_logger.LogError($"扣费失败:{errMsg}");
|
|
|
SaveAuditLog($"扣费失败", model.Id, model.CreatedUserId.Value, model.TenantId.Value, "系统", remark: errMsg);
|
|
|
})
|
|
|
.SendAsStringAsync();
|
|
|
_logger.LogInformation($"调用扣费返回:{apiRtn}");
|
|
|
var jobjApiRtn = JObject.Parse(apiRtn);
|
|
|
var code = jobjApiRtn.GetIntValue("code");
|
|
|
var jobjApiRtnData = jobjApiRtn.GetValue("data") as JObject;
|
|
|
if (code == 200 || code == 450)
|
|
|
{
|
|
|
var jobjApiRtnDataPayInfo = jobjApiRtnData.GetValue("payInfo") as JObject;
|
|
|
var price = Convert.ToDecimal(jobjApiRtnDataPayInfo.GetValue("price").ToString());
|
|
|
var total = Convert.ToDecimal(jobjApiRtnDataPayInfo.GetValue("total").ToString());
|
|
|
|
|
|
//记录扣费
|
|
|
var fr = new BookingFeeRecord();
|
|
|
fr.Id = YitIdHelper.NextId();
|
|
|
fr.BillId = model.Id;
|
|
|
fr.MBLNO = model.BOOKINGNO;
|
|
|
fr.TenantId = model.BookingTenantId;
|
|
|
fr.Type = typeStr;
|
|
|
fr.Amount = total;
|
|
|
fr.Remark = bookingNO;
|
|
|
await _repFeeRecord.InsertAsync(fr);
|
|
|
|
|
|
SaveAuditLog($"扣费成功", model.Id, model.CreatedUserId.Value, model.TenantId.Value, "系统", remark: bookingNO);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var errMsg = jobjApiRtn.GetValue("message").ToString();
|
|
|
_logger.LogError($"扣费失败:{errMsg}");
|
|
|
SaveAuditLog($"扣费失败", model.Id, model.CreatedUserId.Value, model.TenantId.Value, "系统", remark: errMsg);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 外部开放接口
|
|
|
|
|
|
/// <summary>
|
|
|
/// 接收外部调用生成客户订舱需求
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/ReceiveCustomerOrder"), AllowAnonymous, ApiUser]
|
|
|
public async Task ReceiveCustomerOrder([FromForm] BookingCustomerApiSaveInput input, IFormFile[] files)
|
|
|
{
|
|
|
var carrList = await _cache.GetAllCodeCarrier();
|
|
|
var portLoadList = await _cache.GetAllCodePortLoad();
|
|
|
var portDestList = await _cache.GetAllCodePort();
|
|
|
var serviceList = await _cache.GetAllCodeService();
|
|
|
var frtList = await _cache.GetAllCodeFrt();
|
|
|
var ctnList = await _cache.GetAllCodeCtn();
|
|
|
|
|
|
#region 校验
|
|
|
/*
|
|
|
1.必填字段:船公司,开船日期,起运港,目的港,箱型箱量,服务项目,运输条款,付费方式,件数,毛重,包装,货物标识,品名,HSCODE。
|
|
|
2.条件字段1:若货物标识为冻柜,温度,通风,湿度必填。
|
|
|
3.条件字段2:若货物标识为危险品,危险品编号,危险品等级,联系人,电话,HSCODE必填。
|
|
|
*/
|
|
|
/*
|
|
|
必填字段:去掉 件数、包装、HSCODE,增加合约号,订舱账号,订舱密码
|
|
|
*/
|
|
|
if (string.IsNullOrEmpty(input.BSNO))
|
|
|
{
|
|
|
throw Oops.Bah("未提供业务ID");
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(input.CONTRACTNO))
|
|
|
{
|
|
|
throw Oops.Bah("合约号不能为空");
|
|
|
}
|
|
|
|
|
|
//if (string.IsNullOrEmpty(input.BOOKINGACCOUNT))
|
|
|
//{
|
|
|
// throw Oops.Bah("订舱账号不能为空");
|
|
|
//}
|
|
|
//if (string.IsNullOrEmpty(input.BOOKINGPASSWORD))
|
|
|
//{
|
|
|
// throw Oops.Bah("订舱密码不能为空");
|
|
|
//}
|
|
|
|
|
|
//2024-4-2,为保证后面自动化订舱需要,船司、港口、箱型等信息改为传公共库中的唯一代码
|
|
|
if (string.IsNullOrEmpty(input.CARRIERID))
|
|
|
{
|
|
|
throw Oops.Bah("船司代码不能为空");
|
|
|
}
|
|
|
|
|
|
var carr = carrList.FirstOrDefault(x => x.Code == input.CARRIERID);
|
|
|
if (carr == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到匹配的船司代码:{input.CARRIERID}");
|
|
|
}
|
|
|
|
|
|
// 2024-4-9:中远约号最长8位
|
|
|
if (input.CARRIERID == "COSCO" && input.CONTRACTNO.Length > 8)
|
|
|
{
|
|
|
throw Oops.Bah($"约号超长,【中远】约号最长8位,请检查");
|
|
|
}
|
|
|
|
|
|
if (!input.ETD.HasValue)
|
|
|
{
|
|
|
throw Oops.Bah("开船日期不能为空");
|
|
|
}
|
|
|
|
|
|
//2024-4-2,为保证后面自动化订舱需要,船司、港口、箱型等信息改为传公共库中的唯一代码,名称和五字码根据唯一代码匹配写入,无需传递
|
|
|
//if (string.IsNullOrEmpty(input.PORTLOADID) || string.IsNullOrEmpty(input.PORTLOAD))
|
|
|
//{
|
|
|
// throw Oops.Bah("起运港代码和名称不能为空");
|
|
|
//}
|
|
|
|
|
|
//if (string.IsNullOrEmpty(input.PORTDISCHARGEID) || string.IsNullOrEmpty(input.PORTDISCHARGE))
|
|
|
//{
|
|
|
// throw Oops.Bah("目的港代码和名称不能为空");
|
|
|
//}
|
|
|
|
|
|
|
|
|
//起运港校验
|
|
|
if (string.IsNullOrEmpty(input.PORTLOADCODE))
|
|
|
{
|
|
|
throw Oops.Bah("起运港代码不能为空");
|
|
|
}
|
|
|
|
|
|
var portLoad = portLoadList.FirstOrDefault(x => x.Code == input.PORTLOADCODE);
|
|
|
if (portLoad == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到匹配的起运港:{input.PORTLOADCODE}");
|
|
|
}
|
|
|
|
|
|
|
|
|
//目的港校验
|
|
|
if (string.IsNullOrEmpty(input.PORTDISCHARGECODE))
|
|
|
{
|
|
|
throw Oops.Bah("目的港代码不能为空");
|
|
|
}
|
|
|
|
|
|
var portDest = portDestList.FirstOrDefault(x => x.Code == input.PORTDISCHARGECODE);
|
|
|
if (portDest == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到匹配的目的港:{input.PORTDISCHARGECODE}");
|
|
|
}
|
|
|
|
|
|
|
|
|
//收货地校验
|
|
|
if (input.CARRIERID == "EMC" && string.IsNullOrEmpty(input.PLACERECEIPTCODE))
|
|
|
{
|
|
|
throw Oops.Bah("收货地代码不能为空");
|
|
|
}
|
|
|
|
|
|
var placereceipt = portLoadList.FirstOrDefault(x => x.Code == input.PLACERECEIPTCODE);
|
|
|
if (input.CARRIERID == "EMC" && placereceipt == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到匹配的收货地:{input.PLACERECEIPTCODE}");
|
|
|
}
|
|
|
|
|
|
|
|
|
//目的地校验
|
|
|
if (string.IsNullOrEmpty(input.DESTINATIONCODE))
|
|
|
{
|
|
|
throw Oops.Bah("目的地代码不能为空");
|
|
|
}
|
|
|
|
|
|
var destination = portDestList.FirstOrDefault(x => x.Code == input.DESTINATIONCODE);
|
|
|
if (destination == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到匹配的目的地:{input.DESTINATIONCODE}");
|
|
|
}
|
|
|
|
|
|
//中远的运输方式不能为空
|
|
|
CodeService service = null;
|
|
|
if (input.CARRIERID == "COSCO")
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(input.SERVICECODE))
|
|
|
{
|
|
|
throw Oops.Bah("运输条款代码不能为空");
|
|
|
}
|
|
|
|
|
|
service = serviceList.FirstOrDefault(x => x.Code == input.SERVICECODE);
|
|
|
if (service == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到匹配的运输条款:{input.SERVICECODE}");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
else if (input.CARRIERID == "EMC") //长荣运送方式和运输形态不能为空
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(input.ServiceMode) || string.IsNullOrEmpty(input.ServiceType))
|
|
|
{
|
|
|
throw Oops.Bah("运送方式和运输形态都不能为空");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(input.FRTCODE))
|
|
|
{
|
|
|
throw Oops.Bah("付费方式代码不能为空");
|
|
|
}
|
|
|
|
|
|
var frt = frtList.FirstOrDefault(x => x.Code == input.FRTCODE);
|
|
|
if (frt == null)
|
|
|
{
|
|
|
throw Oops.Bah($"未找到匹配的付费方式:{input.FRTCODE}");
|
|
|
}
|
|
|
|
|
|
if (!input.KGS.HasValue)
|
|
|
{
|
|
|
throw Oops.Bah("重量不能为空");
|
|
|
}
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(input.CARGOID))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识不能为空");
|
|
|
}
|
|
|
|
|
|
if (input.CARGOID == "R")
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(input.TEMPSET))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识为冻柜的情况下,温度不能为空");
|
|
|
}
|
|
|
if (string.IsNullOrEmpty(input.REEFERF))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识为冻柜的情况下,通风度不能为空");
|
|
|
}
|
|
|
if (string.IsNullOrEmpty(input.HUMIDITY))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识为冻柜的情况下,湿度不能为空");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
else if (input.CARGOID == "D")
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(input.DUNNO))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识为危险品的情况下,危险品编号不能为空");
|
|
|
}
|
|
|
if (string.IsNullOrEmpty(input.DCLASS))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识为危险品的情况下,危险品等级不能为空");
|
|
|
}
|
|
|
if (string.IsNullOrEmpty(input.LINKMAN))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识为危险品的情况下,危险品联系人不能为空");
|
|
|
}
|
|
|
if (string.IsNullOrEmpty(input.DTEL))
|
|
|
{
|
|
|
throw Oops.Bah("货物标识为危险品的情况下,危险品联系电话不能为空");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(input.DESCRIPTION))
|
|
|
{
|
|
|
throw Oops.Bah("品名不能为空");
|
|
|
}
|
|
|
|
|
|
if (input.CtnList == null || input.CtnList.Count == 0)
|
|
|
{
|
|
|
throw Oops.Bah("箱信息不能为空");
|
|
|
}
|
|
|
|
|
|
var notExistCode = input.CtnList.Where(x => ctnList.Count(y => y.Code == x.CTNCODE) == 0).Select(x => x.CTNCODE).ToList();
|
|
|
if (notExistCode.Any())
|
|
|
{
|
|
|
throw Oops.Bah($"未找到箱型:{string.Join(",", notExistCode)}");
|
|
|
}
|
|
|
|
|
|
if (input.ServiceItemList == null || input.ServiceItemList.Count == 0)
|
|
|
{
|
|
|
throw Oops.Bah("服务项目不能为空");
|
|
|
}
|
|
|
|
|
|
if (input.CARRIERID == "EMC" && string.IsNullOrEmpty(input.ShipInfoJson))
|
|
|
{
|
|
|
throw Oops.Bah($"长荣订舱需提供船期数据");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
var custOrder = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.TenantId == UserManager.TENANT_ID && x.BSNO == input.BSNO && x.IsDeleted == false);
|
|
|
var ins = false;
|
|
|
if (custOrder != null)
|
|
|
{
|
|
|
if (custOrder.BSSTATUS == "已审核")
|
|
|
{
|
|
|
throw Oops.Bah("已审核的数据不能修改");
|
|
|
}
|
|
|
|
|
|
if (custOrder.BSSTATUS == "已提交")
|
|
|
{
|
|
|
await CancelSubmit(new List<long>() { custOrder.Id });
|
|
|
custOrder = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == custOrder.Id); //取消后重新拉取一遍数据
|
|
|
}
|
|
|
|
|
|
|
|
|
input.Id = custOrder.Id;
|
|
|
input.Adapt(custOrder);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
custOrder = input.Adapt<BookingCustomerOrder>();
|
|
|
ins = true;
|
|
|
}
|
|
|
|
|
|
//订舱船期数据
|
|
|
JObject jobjExt = new JObject();
|
|
|
if (!string.IsNullOrEmpty(custOrder.ExtendData))
|
|
|
{
|
|
|
jobjExt = JObject.Parse(custOrder.ExtendData);
|
|
|
}
|
|
|
|
|
|
if (custOrder.CARRIERID == "EMC")
|
|
|
{
|
|
|
jobjExt["shipInfo"] = JObject.Parse(input.ShipInfoJson);
|
|
|
}
|
|
|
|
|
|
custOrder.ExtendData = jobjExt.ToString();
|
|
|
|
|
|
//赋值根据唯一代码匹配后的代码、名称等信息
|
|
|
custOrder.CARRIER = carr.EnName;
|
|
|
custOrder.PORTLOAD = portLoad.EnName;
|
|
|
custOrder.PORTLOADID = portLoad.EdiCode;
|
|
|
custOrder.PORTDISCHARGE = portDest.EnName;
|
|
|
custOrder.PORTDISCHARGEID = portDest.EdiCode;
|
|
|
custOrder.PLACERECEIPT = placereceipt?.EnName;
|
|
|
custOrder.PLACERECEIPTID = placereceipt?.EdiCode;
|
|
|
custOrder.DESTINATION = destination.EnName;
|
|
|
custOrder.DESTINATIONID = destination.EdiCode;
|
|
|
custOrder.BLFRT = frt.EnName;
|
|
|
if (custOrder.CARRIERID == "COSCO")
|
|
|
{
|
|
|
custOrder.SERVICE = service.Name;
|
|
|
}
|
|
|
|
|
|
//2024年4月19日,将分拆的收发通拼接到大文本的收发通中
|
|
|
ContactSFT(custOrder);
|
|
|
|
|
|
|
|
|
var ctns = input.CtnList.Adapt<List<BookingCtn>>();
|
|
|
foreach (var ctn in ctns)
|
|
|
{
|
|
|
ctn.CTNALL = ctnList.First(x => x.Code == ctn.CTNCODE).Name;
|
|
|
}
|
|
|
var servList = input.ServiceItemList.Adapt<List<BookingServiceItem>>();
|
|
|
|
|
|
await SaveData(custOrder, ctns, servList, ins);
|
|
|
|
|
|
#region 处理附件
|
|
|
var dbFiles = _repFile.AsQueryable().Where(x => x.BookingId == custOrder.Id).ToList();
|
|
|
var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
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);
|
|
|
|
|
|
foreach (var upFile in files)
|
|
|
{
|
|
|
var extName = Path.GetExtension(upFile.FileName);
|
|
|
if (opt.fileType.Contains(extName.ToLower()))
|
|
|
{
|
|
|
throw Oops.Bah($"不允许的文件类型:{extName}");
|
|
|
}
|
|
|
|
|
|
var dbFile = dbFiles.FirstOrDefault(x => x.BookingId == custOrder.Id && x.FileName == upFile.FileName);
|
|
|
|
|
|
if (dbFile == null)
|
|
|
{
|
|
|
var saveFileName = $"{DateTime.Now.Ticks}{extName}";
|
|
|
var fileRelaPath = Path.Combine(opt.relativePath, saveFileName).ToLower();
|
|
|
var fileAbsPath = Path.Combine(dirAbs, saveFileName).ToLower();
|
|
|
|
|
|
using (var stream = File.Create(fileAbsPath))
|
|
|
{
|
|
|
await upFile.CopyToAsync(stream);
|
|
|
}
|
|
|
|
|
|
var newFile = new BookingFile
|
|
|
{
|
|
|
Id = YitIdHelper.NextId(),
|
|
|
FileName = Path.GetFileName(upFile.FileName),
|
|
|
FilePath = fileRelaPath,
|
|
|
TypeCode = "tuodan",
|
|
|
TypeName = "托单文件",
|
|
|
BookingId = custOrder.Id,
|
|
|
};
|
|
|
await _repFile.InsertAsync(newFile);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var fileFullPath = Path.Combine(dirAbs, dbFile.FilePath);
|
|
|
using (var stream = File.Create(fileFullPath))
|
|
|
{
|
|
|
await upFile.CopyToAsync(stream);
|
|
|
}
|
|
|
await _repFile.UpdateAsync(dbFile);
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
await Submit(new List<long> { custOrder.Id });
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 拼接收发通
|
|
|
/// </summary>
|
|
|
/// <param name="custOrder"></param>
|
|
|
private void ContactSFT(BookingCustomerOrder custOrder)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(custOrder.SHIPPER) && !string.IsNullOrEmpty(custOrder.ShipperName))
|
|
|
{
|
|
|
custOrder.SHIPPER = @$"{custOrder.ShipperName}
|
|
|
{custOrder.ShipperAddress}
|
|
|
{custOrder.ShipperCountry} {custOrder.ShipperProvince} {custOrder.ShipperCity} {custOrder.ShipperCounty} {custOrder.ShipperPostCode}
|
|
|
{custOrder.ShipperLastName} {custOrder.ShipperFirstName} {custOrder.ShipperPhoneCountryCode} {custOrder.ShipperPhoneCode} {custOrder.ShipperPhone}".ToUpper();
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(custOrder.CONSIGNEE) && !string.IsNullOrEmpty(custOrder.ConsigneeName))
|
|
|
{
|
|
|
custOrder.CONSIGNEE = @$"{custOrder.ConsigneeName}
|
|
|
{custOrder.ConsigneeAddress}
|
|
|
{custOrder.ConsigneeCountry} {custOrder.ConsigneeProvince} {custOrder.ConsigneeCity} {custOrder.ConsigneeCounty} {custOrder.ConsigneePostCode}
|
|
|
{custOrder.ConsigneeLastName} {custOrder.ConsigneeFirstName} {custOrder.ConsigneePhoneCountryCode} {custOrder.ConsigneePhoneCode} {custOrder.ConsigneePhone}".ToUpper();
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(custOrder.NOTIFYPARTY) && !string.IsNullOrEmpty(custOrder.NotifypartName))
|
|
|
{
|
|
|
custOrder.NOTIFYPARTY = @$"{custOrder.NotifypartName}
|
|
|
{custOrder.NotifypartAddress}
|
|
|
{custOrder.NotifypartCountry} {custOrder.NotifypartProvince} {custOrder.NotifypartCity} {custOrder.NotifypartCounty} {custOrder.NotifypartPostCode}
|
|
|
{custOrder.NotifypartLastName} {custOrder.NotifypartFirstName} {custOrder.NotifypartPhoneCountryCode} {custOrder.NotifypartPhoneCode} {custOrder.NotifypartPhone}".ToUpper();
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 发送订舱
|
|
|
|
|
|
/// <summary>
|
|
|
/// 发送Api订舱
|
|
|
/// </summary>
|
|
|
/// <param name="id"></param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingCustomerOrder/PostApiSO")]
|
|
|
public async Task PostApiSO(long id)
|
|
|
{
|
|
|
var order = await _rep.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == id);
|
|
|
|
|
|
KeyValuePair<bool, string> rtn = new KeyValuePair<bool, string>(false, "不支持的船司");
|
|
|
if (order.CARRIERID == "COSCO")
|
|
|
{
|
|
|
rtn = await ZhongYuanSoApiHelper.DoPost(id);
|
|
|
}
|
|
|
else if (order.CARRIERID == "EMC")
|
|
|
{
|
|
|
rtn = await EMCSoApiHelper.DoPost(id);
|
|
|
}
|
|
|
|
|
|
if (!rtn.Key)
|
|
|
{
|
|
|
SaveAuditLog("发送订舱", id, remark: rtn.Value);
|
|
|
throw Oops.Bah(rtn.Value);
|
|
|
}
|
|
|
|
|
|
SaveAuditLog("发送订舱", id, remark: rtn.Value);
|
|
|
}
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
|
|
|
}
|