You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

711 lines
27 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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