using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest;
using Furion.RemoteRequest.Extensions;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Logging;
using Myshipping.Application.Entity;
using Myshipping.Application.Helper;
using Myshipping.Core;
using Myshipping.Core.Entity;
using Myshipping.Core.Service;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json.Linq;
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.Net.Http;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using static Aliyun.OSS.Model.CreateSelectObjectMetaInputFormatModel;
namespace Myshipping.Application
{
///
/// 任务管理
///
[ApiDescriptionSettings("Application", Name = "TaskManage", Order = 10)]
public class TaskManageService : ITaskManageService, IDynamicApiController
{
private readonly SqlSugarRepository _taskBaseInfoRepository;
private readonly SqlSugarRepository _taskSIFeedBackInfoRepository;
private readonly SqlSugarRepository _taskSIFeedBackContaInfoRepository;
private readonly SqlSugarRepository _taskBillFeeDetailInfoRepository;
private readonly SqlSugarRepository _taskFileInfoRepository;
private readonly SqlSugarRepository _taskEmailInfoRepository;
private readonly SqlSugarRepository _taskVGMFeedBackInfoRepository;
private readonly SqlSugarRepository _sysUserRepository;
private readonly SqlSugarRepository _taskStatManageInfoRepository;
private readonly SqlSugarRepository _taskOriginalDownloadHisInfoRepository;
private readonly SqlSugarRepository _taskChargesHisInfoRepository;
private readonly IDjyWebsiteAccountConfigService _webAccountConfig;
private readonly ISysCacheService _cache;
private readonly ILogger _logger;
const string CONST_WEB_ACCOUNT_TYPE = "CmaWeb";
const string CONST_BOOK_ORIGINAL_DOWN_URL_CODE = "bookOriginalDownUrl";
public TaskManageService(SqlSugarRepository taskBaseInfoRepository,
SqlSugarRepository taskSIFeedBackInfoRepository,
SqlSugarRepository taskSIFeedBackContaInfoRepository,
SqlSugarRepository taskBillFeeDetailInfoRepository,
SqlSugarRepository taskFileInfoRepository,
SqlSugarRepository taskEmailInfoRepository,
SqlSugarRepository taskVGMFeedBackInfoRepository,
SqlSugarRepository sysUserRepository,
SqlSugarRepository taskStatManageInfoRepository,
SqlSugarRepository taskOriginalDownloadHisInfoRepository,
SqlSugarRepository taskChargesHisInfoRepository,
IDjyWebsiteAccountConfigService webAccountConfig,
ISysCacheService cache,
ILogger logger)
{
_taskBaseInfoRepository = taskBaseInfoRepository;
_taskSIFeedBackInfoRepository = taskSIFeedBackInfoRepository;
_taskSIFeedBackContaInfoRepository = taskSIFeedBackContaInfoRepository;
_taskBillFeeDetailInfoRepository = taskBillFeeDetailInfoRepository;
_taskFileInfoRepository = taskFileInfoRepository;
_taskEmailInfoRepository = taskEmailInfoRepository;
_taskVGMFeedBackInfoRepository = taskVGMFeedBackInfoRepository;
_sysUserRepository = sysUserRepository;
_taskStatManageInfoRepository = taskStatManageInfoRepository;
_taskOriginalDownloadHisInfoRepository = taskOriginalDownloadHisInfoRepository;
_taskChargesHisInfoRepository = taskChargesHisInfoRepository;
_webAccountConfig = webAccountConfig;
_cache = cache;
_logger = logger;
}
///
/// 创建任务
///
/// 任务详情
/// 返回回执
[AllowAnonymous,HttpPost("/TaskManage/CreateTaskJob")]
public async Task CreateTaskJob(TaskManageOrderMessageInfo info)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
/*
创建任务
1、判断当前任务的主键是否已入库,已入库不允许重复,返回错误提示。
2、
*/
result = await InitTaskJob(info);
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"请求任务异常,{ex.Message}";
}
return result;
}
///
/// 新增任务
///
/// 任务详情
/// 返回回执
private async Task InitTaskJob(TaskManageOrderMessageInfo info)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.OUT_BUSI_NO == info.Head.GID);
if (taskInfo != null)
throw Oops.Oh($"任务已经存在不能重复提交");
taskInfo = new TaskBaseInfo
{
PK_ID = IDGen.NextID().ToString(),
TASK_NO = info.Head.GID,
STATUS = TaskStatusEnum.Create.ToString(),
IsDeleted = false,
IS_EXCEPT = 0,
IS_COMPLETE = 0,
MBL_NO = info.Main.MBlNo,
TASK_BASE_TYPE = info.Main.TaskType.ToString(),
CARRIER_ID = info.Main.CarrierId?.Trim(),
IS_PUBLIC = string.IsNullOrWhiteSpace(info.Main.TaskUserId) ? 1 : 0,
BOOK_ORDER_NO = info.Main.BookingOrderNo,
OUT_BUSI_NO = info.Head.GID,
TASK_TITLE = info.Main.TaskTitle,
TASK_DESP = info.Main.TaskDesp,
TASK_SOURCE = info.Main.TaskSource.ToString(),
TASK_TYPE = info.Main.TaskType.ToString(),
};
taskInfo.CreatedTime = DateTime.Now;
taskInfo.UpdatedTime = taskInfo.CreatedTime;
if (!string.IsNullOrWhiteSpace(taskInfo.CARRIER_ID)
&& taskInfo.CARRIER_ID == "MSC")
{
if (TaskBaseTypeEnum.BC.ToString() == taskInfo.TASK_BASE_TYPE)
taskInfo.TASK_TYPE = TaskBusiTypeEnum.MSC_BC.ToString();
if(taskInfo.IS_EXCEPT == 1)
taskInfo.TASK_TYPE = TaskBusiTypeEnum.MSC_EXCEPT.ToString();
}
//新增
await _taskBaseInfoRepository.InsertAsync(taskInfo);
//附件
if(info.Main.FileList != null && info.Main.FileList.Count > 0)
{
info.Main.FileList.ForEach(async file => {
var fileInfo = new TaskFileInfo();
fileInfo.PK_ID = IDGen.NextID().ToString();
fileInfo.TASK_PKID = taskInfo.PK_ID;
fileInfo.CreatedTime = taskInfo.CreatedTime;
fileInfo.UpdatedTime = taskInfo.CreatedTime;
fileInfo.FILE_PATH = file.FilePath;
fileInfo.FILE_NAME = file.FileName;
fileInfo.FILE_TYPE = file.FileType;
if(string.IsNullOrWhiteSpace(fileInfo.FILE_NAME))
{
var fileModel = new FileInfo(file.FilePath);
fileInfo.FILE_NAME = fileModel.Name;
fileInfo.FILE_TYPE = fileModel.Extension?.Replace(".","");
}
await _taskFileInfoRepository.InsertAsync(fileInfo);
});
}
//邮件
if (info.Main.EmailList != null && info.Main.EmailList.Count > 0)
{
info.Main.EmailList.ForEach(async email => {
var emailInfo = new TaskEmailInfo();
emailInfo.PK_ID = IDGen.NextID().ToString();
emailInfo.TASK_PKID = taskInfo.PK_ID;
emailInfo.CreatedTime = taskInfo.CreatedTime;
emailInfo.UpdatedTime = taskInfo.CreatedTime;
emailInfo.MAIL_PATH = email.MailPath;
await _taskEmailInfoRepository.InsertAsync(emailInfo);
});
}
//SI反馈入库
if (info.Main.TaskType == TaskBaseTypeEnum.SI_FEEDBACK)
{
if(info.Main.SIFeedBack == null)
throw Oops.Oh($"任务类型={info.Main.TaskType.ToString()} SIFeedBack信息必传");
TaskSIFeedBackInfo taskSIFeedBackInfo = info.Main.SIFeedBack.Adapt();
taskSIFeedBackInfo.PK_ID = IDGen.NextID().ToString();
taskSIFeedBackInfo.TASK_PKID = taskInfo.PK_ID;
taskSIFeedBackInfo.CreatedTime = taskInfo.CreatedTime;
taskSIFeedBackInfo.UpdatedTime = taskInfo.CreatedTime;
await _taskSIFeedBackInfoRepository.InsertAsync(taskSIFeedBackInfo);
//SI反馈箱信息入库
if(info.Main.SIFeedBack.ContaList != null && info.Main.SIFeedBack.ContaList.Count > 0)
{
info.Main.SIFeedBack.ContaList.ForEach( async ctn => {
var contaInfo = ctn.Adapt();
contaInfo.PK_ID = IDGen.NextID().ToString();
contaInfo.P_PKID = taskSIFeedBackInfo.PK_ID;
contaInfo.CreatedTime = taskInfo.CreatedTime;
contaInfo.UpdatedTime = taskInfo.CreatedTime;
await _taskSIFeedBackContaInfoRepository.InsertAsync(contaInfo);
});
}
}
//费用明细
if(info.Main.TaskType == TaskBaseTypeEnum.INVOICE_BILL_MAIL || info.Main.TaskType == TaskBaseTypeEnum.PER_BILL)
{
if (info.Main.FeeList != null && info.Main.FeeList.Count > 0)
{
info.Main.FeeList.ForEach(async fee => {
var feeInfo = fee.Adapt();
feeInfo.PK_ID = IDGen.NextID().ToString();
feeInfo.TASK_PKID = taskInfo.PK_ID;
feeInfo.CreatedTime = taskInfo.CreatedTime;
feeInfo.UpdatedTime = taskInfo.CreatedTime;
await _taskBillFeeDetailInfoRepository.InsertAsync(feeInfo);
});
}
}
//VGM反馈入库
if (info.Main.VGMFeedBackList != null && info.Main.VGMFeedBackList.Count > 0)
{
info.Main.VGMFeedBackList.ForEach(async vgm => {
var vgmInfo = vgm.Adapt();
vgmInfo.PK_ID = IDGen.NextID().ToString();
vgmInfo.TASK_PKID = taskInfo.PK_ID;
vgmInfo.CreatedTime = taskInfo.CreatedTime;
vgmInfo.UpdatedTime = taskInfo.CreatedTime;
await _taskVGMFeedBackInfoRepository.InsertAsync(vgmInfo);
});
}
result.succ = true;
result.msg = "新增任务成功";
}
catch (Exception ex)
{
throw Oops.Oh($"{ex.Message}");
}
return result;
}
///
/// 获取查询参数
///
/// 参数类型 STATUS-任务状态;TASK_TYPE-任务类型;SOURCE-任务来源
/// 返回回执
/// TASK_TYPE
[HttpGet("/TaskManage/GetParaInfo")]
public async Task GetParaInfo([QueryString]string ParaType)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
Dictionary dict = new Dictionary();
if (ParaType == "STATUS")
{
dict = EnumUtil.GetEnumDictionaryWithKey(typeof(TaskStatusEnum));
}
else if (ParaType == "TASK_TYPE")
{
dict = EnumUtil.GetEnumDictionaryWithKey(typeof(TaskBusiTypeEnum));
}
else if (ParaType == "SOURCE")
{
dict = EnumUtil.GetEnumDictionaryWithKey(typeof(TaskSourceEnum));
}
result.succ = true;
result.rows = dict.Select(t => new { Code = t.Key, Name = t.Value }).ToList();
}
catch (Exception ex)
{
result.succ = false;
result.msg = ex.Message;
}
return result;
}
#region 获取登陆人相关的任务统计信息
///
/// 获取登陆人相关的任务统计信息
///
/// 是否强制计算
/// 返回回执
[HttpGet("/TaskManage/GetCurrentTotalStat")]
public async Task GetCurrentTotalStat([FromQuery]bool isReCalc = false)
{
TaskUserStatResultInfo resultInfo = new TaskUserStatResultInfo {
LevelTop = new List(),
LevelNext = new List(),
LevelTree = new List()
};
/*
1、首先判断当前登陆人是否有统计记录,如果没有触发统计生成统计记录。
2、如果isReCalc=true,表示强制重新统计数据,并重新更新统计数据。
3、按照统计类型(个人/公共)、任务状态、是否异常分组汇总,并写入统计表。
*/
try
{
var userTendInfo = await _sysUserRepository.AsQueryable()
.LeftJoin((usr, ten) => usr.TenantId == ten.Id)
.Where(usr => usr.Id == UserManager.UserId)
.Select((usr, ten) => new { User = usr, Tend = ten }).FirstAsync();
if(userTendInfo == null)
throw Oops.Oh($"当前用户关联租户信息获取失败");
var statList = _taskStatManageInfoRepository.AsQueryable().Where(t => (t.USER_ID == userTendInfo.User.Id
&& t.STAT_TYPE == TaskStatLevelEnum.PERSON.ToString()) || (t.COMP_ID == userTendInfo.Tend.Id && t.STAT_TYPE == TaskStatLevelEnum.PUBLIC.ToString())).ToList();
if (isReCalc)
{
//任务列表分组统计
var groupList = _taskBaseInfoRepository.AsQueryable()
.Where(t => (t.CreatedUserId == UserManager.UserId && t.IS_PUBLIC == 0) || (t.TenantId == userTendInfo.Tend.Id && t.IS_PUBLIC == 1))
.GroupBy(p => new { p.TASK_TYPE, p.STATUS, p.IS_EXCEPT, p.IS_PUBLIC })
.Select(p => new
{
Total = SqlFunc.AggregateCount(p.PK_ID),
TaskType = p.TASK_TYPE,
Status = p.STATUS,
IsExcept = p.IS_EXCEPT,
IsPublic = p.IS_PUBLIC
}).ToList();
var exceptList = groupList
.Where(t => t.IsExcept == 1).ToList();
var personList = groupList
.Where(t => t.IsExcept == 0 && t.IsPublic == 0).ToList();
var publicList = groupList
.Where(t => t.IsExcept == 1 && t.IsPublic == 1).ToList();
#region 异常
if (exceptList.Count > 0)
{
resultInfo.LevelTop.Add(new TaskUserStatItem
{
Key = TaskStatLevelEnum.EXCPTION.ToString(),
Name = TaskStatLevelEnum.EXCPTION.GetDescription(),
Total = exceptList.Sum(t=>t.Total),
SortNo = (int)TaskStatLevelEnum.EXCPTION,
ActionKey = TaskStatLevelEnum.EXCPTION.ToString()
});
exceptList.GroupBy(t => t.Status)
.Select(t => new { Key = t.Key, Total = t.ToList().Sum(p => p.Total) })
.ToList().ForEach(t => {
TaskStatusEnum currEnum = (TaskStatusEnum)System.Enum.Parse(typeof(TaskStatusEnum), t.Key);
resultInfo.LevelNext.Add(new TaskUserStatItemNext
{
TopKey = TaskStatLevelEnum.EXCPTION.ToString(),
Key = currEnum.ToString(),
Name = currEnum.GetDescription(),
Total = t.Total,
SortNo = (int)currEnum,
ActionKey = $"{TaskStatLevelEnum.EXCPTION.ToString()}#{currEnum.ToString()}"
});
});
exceptList.GroupBy(t => new { t.Status,t.TaskType})
.Select(t => new { Key = t.Key, Total = t.ToList().Sum(p => p.Total) })
.ToList().ForEach(t => {
TaskBusiTypeEnum currEnum = (TaskBusiTypeEnum)System.Enum.Parse(typeof(TaskBusiTypeEnum), t.Key.TaskType);
resultInfo.LevelTree.Add(new TaskUserStatItemTree
{
TopKey = TaskStatLevelEnum.EXCPTION.ToString(),
NextKey = t.Key.Status,
Key = currEnum.ToString(),
Name = currEnum.GetDescription(),
Total = t.Total,
SortNo = (int)currEnum,
ActionKey = $"{TaskStatLevelEnum.EXCPTION.ToString()}#{t.Key.Status}#{currEnum.ToString()}"
});
});
}
#endregion
#region 个人
if (personList.Count > 0)
{
resultInfo.LevelTop.Add(new TaskUserStatItem
{
Key = TaskStatLevelEnum.PERSON.ToString(),
Name = TaskStatLevelEnum.PERSON.GetDescription(),
Total = personList.Sum(t => t.Total),
SortNo = (int)TaskStatLevelEnum.PERSON,
ActionKey = TaskStatLevelEnum.PERSON.ToString()
});
personList.GroupBy(t => t.Status)
.Select(t => new { Key = t.Key, Total = t.ToList().Sum(p => p.Total) })
.ToList().ForEach(t => {
TaskStatusEnum currEnum = (TaskStatusEnum)System.Enum.Parse(typeof(TaskStatusEnum), t.Key);
resultInfo.LevelNext.Add(new TaskUserStatItemNext
{
TopKey = TaskStatLevelEnum.PERSON.ToString(),
Key = currEnum.ToString(),
Name = currEnum.GetDescription(),
Total = t.Total,
SortNo = (int)currEnum,
ActionKey = $"{TaskStatLevelEnum.PERSON.ToString()}#{currEnum.ToString()}"
});
});
personList.GroupBy(t => new { t.Status, t.TaskType })
.Select(t => new { Key = t.Key, Total = t.ToList().Sum(p => p.Total) })
.ToList().ForEach(t => {
TaskBusiTypeEnum currEnum = (TaskBusiTypeEnum)System.Enum.Parse(typeof(TaskBusiTypeEnum), t.Key.TaskType);
resultInfo.LevelTree.Add(new TaskUserStatItemTree
{
TopKey = TaskStatLevelEnum.PERSON.ToString(),
NextKey = t.Key.Status,
Key = currEnum.ToString(),
Name = currEnum.GetDescription(),
Total = t.Total,
SortNo = (int)currEnum,
ActionKey = $"{TaskStatLevelEnum.PERSON.ToString()}#{t.Key.Status}#{currEnum.ToString()}"
});
});
}
#endregion
#region 公共
if (publicList.Count > 0)
{
resultInfo.LevelTop.Add(new TaskUserStatItem
{
Key = TaskStatLevelEnum.PUBLIC.ToString(),
Name = TaskStatLevelEnum.PUBLIC.GetDescription(),
Total = publicList.Sum(t => t.Total),
SortNo = (int)TaskStatLevelEnum.PUBLIC,
ActionKey = TaskStatLevelEnum.PUBLIC.ToString()
});
publicList.GroupBy(t => t.Status)
.Select(t => new { Key = t.Key, Total = t.ToList().Sum(p => p.Total) })
.ToList().ForEach(t => {
TaskStatusEnum currEnum = (TaskStatusEnum)System.Enum.Parse(typeof(TaskStatusEnum), t.Key);
resultInfo.LevelNext.Add(new TaskUserStatItemNext
{
TopKey = TaskStatLevelEnum.PUBLIC.ToString(),
Key = currEnum.ToString(),
Name = currEnum.GetDescription(),
Total = t.Total,
SortNo = (int)currEnum,
ActionKey = $"{TaskStatLevelEnum.PUBLIC.ToString()}#{currEnum.ToString()}"
});
});
publicList.GroupBy(t => new { t.Status, t.TaskType })
.Select(t => new { Key = t.Key, Total = t.ToList().Sum(p => p.Total) })
.ToList().ForEach(t => {
TaskBusiTypeEnum currEnum = (TaskBusiTypeEnum)System.Enum.Parse(typeof(TaskBusiTypeEnum), t.Key.TaskType);
resultInfo.LevelTree.Add(new TaskUserStatItemTree
{
TopKey = TaskStatLevelEnum.PUBLIC.ToString(),
NextKey = t.Key.Status,
Key = currEnum.ToString(),
Name = currEnum.GetDescription(),
Total = t.Total,
SortNo = (int)currEnum,
ActionKey = $"{TaskStatLevelEnum.PUBLIC.ToString()}#{t.Key.Status}#{currEnum.ToString()}"
});
});
}
#endregion
}
}
catch (Exception ex)
{
throw Oops.Bah($"获取登陆人相关的任务统计信息异常,{0}", ex.Message);
}
return resultInfo;
}
#endregion
///
/// 任务台账查询
///
/// 任务台账查询请求
/// 返回结果
[HttpPost("/TaskManage/GetPage")]
public async Task GetPageAsync(QueryTaskManageDto QuerySearch)
{
List mblList = new List();
if(!string.IsNullOrWhiteSpace(QuerySearch.MBlNo))
{
if (Regex.IsMatch(QuerySearch.MBlNo, "(\\t|\\n\\r|\\n)"))
{
mblList = Regex.Replace(QuerySearch.MBlNo, "(\\t |\\n\\r |\\n)", "#").Split(new char[] { '#' }).Select(t=>t?.Trim()).ToList();
}
else
{
mblList.Add(QuerySearch.MBlNo.Trim());
}
}
DateTime etdBegin = DateTime.MinValue;
DateTime etdEnd = DateTime.MinValue;
DateTime taskDateBegin = DateTime.MinValue;
DateTime taskDateEnd = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(QuerySearch.ETDBegin))
{
if(!DateTime.TryParse(QuerySearch.ETDBegin, out etdBegin))
throw Oops.Oh($"开船起始日期格式错误,{QuerySearch.ETDBegin}");
}
if (!string.IsNullOrWhiteSpace(QuerySearch.ETDEnd))
{
if (!DateTime.TryParse(QuerySearch.ETDEnd, out etdEnd))
throw Oops.Oh($"开船结束日期格式错误,{QuerySearch.ETDEnd}");
etdEnd = etdEnd.AddDays(1);
}
if (!string.IsNullOrWhiteSpace(QuerySearch.TaskDateBegin))
{
if (!DateTime.TryParse(QuerySearch.TaskDateBegin, out taskDateBegin))
throw Oops.Oh($"任务起始日期格式错误,{QuerySearch.TaskDateBegin}");
}
if (!string.IsNullOrWhiteSpace(QuerySearch.TaskDateEnd))
{
if (!DateTime.TryParse(QuerySearch.TaskDateEnd, out taskDateEnd))
throw Oops.Oh($"任务结束日期格式错误,{QuerySearch.TaskDateEnd}");
etdEnd = etdEnd.AddDays(1);
}
string entityOrderCol = "CreatedTime";
//这里因为返回给前端的台账数据是DTO,所以这里排序时候需要转换成Entity对应的字段
if (!string.IsNullOrWhiteSpace(QuerySearch.SortField))
entityOrderCol = MapsterExtHelper.GetAdaptProperty(QuerySearch.SortField);
var entities = await _taskBaseInfoRepository.AsQueryable().Filter(null, true)
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.MBlNo), t => mblList.Any(p => p.Contains(t.MBL_NO, StringComparison.OrdinalIgnoreCase)))
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TaskRecvName), t => t.CreatedUserName.Contains(QuerySearch.TaskRecvName.Trim(), StringComparison.OrdinalIgnoreCase))
.WhereIF(etdBegin != DateTime.MinValue, t => t.ETD.HasValue && t.ETD.Value >= etdBegin)
.WhereIF(etdEnd != DateTime.MinValue, t => t.ETD.HasValue && t.ETD.Value < etdEnd)
.WhereIF(taskDateBegin != DateTime.MinValue, t => t.CreatedTime >= taskDateBegin)
.WhereIF(taskDateEnd != DateTime.MinValue, t => t.CreatedTime < taskDateEnd)
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TaskType), t => t.TASK_TYPE.Equals(QuerySearch.TaskType, StringComparison.OrdinalIgnoreCase))
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TaskSource), t => t.TASK_SOURCE.Equals(QuerySearch.TaskSource, StringComparison.OrdinalIgnoreCase))
.OrderBy(entityOrderCol + (QuerySearch.descSort ? " asc " : " desc "))
.ToPagedListAsync(QuerySearch.PageNo, QuerySearch.PageSize);
return new
{
PageNo = entities.PageIndex,
PageSize = entities.PageSize,
TotalPage = entities.TotalPages,
TotalRows = entities.TotalCount,
Rows = entities.Items.Select(t => t.Adapt()).ToList()
};
}
#region 下载正本提单(可批量)
///
/// 下载正本提单(可批量)
///
/// 任务主键数组
/// 返回结果
[HttpPost("/TaskManage/DownloadOriginalTask")]
public async Task DownloadOriginalTask(string[] PKIds)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no} ids={ids} 下载正本提单开始", batchNo, string.Join(",", PKIds));
try
{
var taskList = _taskBaseInfoRepository.AsQueryable().Where(t => PKIds.Contains(t.PK_ID)).ToList();
_logger.LogInformation("批次={no} 获取任务完成,Num={Num}", batchNo, taskList.Count);
//获取个人对应的账户,这里GetAccountConfig逻辑优先取个人,个人没有配置取公司对应配置
var userWebAccountConfig = _webAccountConfig.GetAccountConfig(CONST_WEB_ACCOUNT_TYPE, UserManager.UserId).GetAwaiter().GetResult();
_logger.LogInformation("批次={no} 获取获取网站的账户完成,result={Num}", batchNo, JSON.Serialize(userWebAccountConfig));
if (userWebAccountConfig == null)
throw Oops.Bah($"个人/公司网站【{CONST_WEB_ACCOUNT_TYPE}】获取失败,请维护个人/公司网站账户信息");
taskList.ForEach(async tsk => {
await InnerDownloadOriginalTask(batchNo, tsk, userWebAccountConfig);
});
}
catch (Exception ex)
{
throw Oops.Bah($"下载正本提单异常,{0}", ex.Message);
}
return result;
}
#endregion
///
/// 单票正本下载
///
/// 批次号
/// 任务详情
/// 网站账户配置
/// 返回回执
private async Task InnerDownloadOriginalTask(string batchNo, TaskBaseInfo taskBaseInfo,
DjyWebsiteAccountConfig webAccountConfig)
{
var result = new TaskManageOrderResultDto();
/*
1、TaskOriginalDownloadHisInfo表中处理任务是succ/temp不允许重复下载。failure/timeout的记录可以再次发起下载。
2、从任务表提取RESULT_NOTE回执信息,里面包含了JSON数据 {"pageUrl":"http://www.cnc-ebusiness.com/ebusiness/bl/detail/AASM104300"}
3、异步请求正本下载的链接,有超时时间。
4、下载完成后写入记录
*/
//正本下载URL
string originalUrl = string.Empty;
try
{
var hisList = _taskOriginalDownloadHisInfoRepository
.Where(t => t.TASK_ID == taskBaseInfo.PK_ID).ToList();
if (hisList.Any(t => new string[] { "succ", "temp" }.Contains(t.STATUS)))
throw Oops.Bah("下载URL不存在,请用最新任务数据");
if (string.IsNullOrWhiteSpace(taskBaseInfo.RESULT_NOTE))
throw Oops.Bah("下载URL不存在,请用最新任务数据");
var resultObj = JSON.Deserialize(taskBaseInfo.RESULT_NOTE);
originalUrl = resultObj.pageUrl.ToString();
if (string.IsNullOrWhiteSpace(originalUrl))
throw Oops.Bah("解析下载URL不存在,请用最新任务数据");
DateTime startDate = DateTime.Now;
var downloadUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
.First(t => t.Code.Equals(CONST_BOOK_ORIGINAL_DOWN_URL_CODE, StringComparison.OrdinalIgnoreCase))?.Value;
if (string.IsNullOrWhiteSpace(downloadUrl))
throw Oops.Bah($"正本下载URL不存在,请确认字典是否配置 code={CONST_BOOK_ORIGINAL_DOWN_URL_CODE}");
TaskOriginalDownloadHisInfo taskOriginalDownloadHisInfo = new TaskOriginalDownloadHisInfo
{
PK_ID = IDGen.NextID().ToString(),
TASK_ID = taskBaseInfo.PK_ID,
REQUEST_URL = originalUrl,
CreatedUserId = UserManager.UserId,
CreatedUserName = UserManager.Name,
STATUS = "temp",
IS_TIMEOUT = 0,
START_DATE = startDate,
TenantId = UserManager.TENANT_ID,
TenantName = UserManager.TENANT_NAME
};
//写入记录
_taskOriginalDownloadHisInfoRepository.Insert(taskOriginalDownloadHisInfo);
//请求远程链接
Dictionary formDict = new Dictionary {
{"bno", taskBaseInfo.MBL_NO },
{"page_url", downloadUrl },
{"web_user", webAccountConfig.Account },
{"web_pwd", webAccountConfig.Password },
{"web_pwd", "myshipping_task" },
{"web_pwd", "" }
};
//请求下载正本
var postResult = await InnerRemoteDownOriginal(batchNo, downloadUrl, formDict);
//重新获取下载历史
var downloadHisInfo = _taskOriginalDownloadHisInfoRepository.AsQueryable()
.First(t => t.PK_ID == taskOriginalDownloadHisInfo.PK_ID);
//更新任务状态
var taskModel = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskBaseInfo.PK_ID);
downloadHisInfo.END_DATE = (DateTime)postResult.ext;
downloadHisInfo.RESULT_NOTE = postResult.msg;
bool isDownSucc = false;
//下载返回成功后,更新记录并生成扣费记录
if (postResult.succ)
{
downloadHisInfo.STATUS = "succ";
downloadHisInfo.RESULT_URL = postResult.msg;
taskModel.COMPLETE_DEAL = TaskCompleteDealEnum.MANUAL.ToString();
taskModel.COMPLETE_DEAL_NAME = TaskCompleteDealEnum.MANUAL.GetDescription();
taskModel.COMPLETE_DATE = DateTime.Now;
taskModel.STATUS = TaskStatusEnum.Complete.ToString();
taskModel.IS_COMPLETE = 1;
isDownSucc = true;
}
else
{
if(postResult.isTimeout)
{
downloadHisInfo.STATUS = "timeout";
}
else
{
downloadHisInfo.STATUS = "failure";
}
}
//更新下载历史
await _taskOriginalDownloadHisInfoRepository.AsUpdateable(downloadHisInfo).IgnoreColumns(it => new
{
it.TenantId,
it.CreatedUserId,
it.CreatedUserName
}).ExecuteCommandAsync();
//异步扣费,这里不管是否失败都生成扣费记录,只在状态上做标识。
var chargeResult = await InnerChargeFee(taskBaseInfo, isDownSucc);
_taskBaseInfoRepository.AsUpdateable(taskModel).UpdateColumns(it => new {
it.COMPLETE_DATE,
it.COMPLETE_DEAL,
it.COMPLETE_DEAL_NAME
}).ExecuteCommand();
}
catch (Exception ex)
{
result.succ = false;
result.msg = ex.Message;
}
return result;
}
#region 远程请求正本下载
///
/// 远程请求正本下载
///
/// 批次号
/// 请求URL
/// 请求参数
///
private async Task InnerRemoteDownOriginal(string batchNo, string url, Dictionary dic)
{
var result = new TaskManageOrderResultDto();
DateTime bDate = DateTime.Now;
try
{
_logger.LogInformation("批次={no} 请求报文开始", batchNo);
var res = await url.SetHttpMethod(HttpMethod.Post)
.SetBody(dic, "application/x-www-form-urlencoded")
.SetContentEncoding(Encoding.UTF8)
.PostAsync();
DateTime eDate = DateTime.Now;
TimeSpan ts = eDate.Subtract(bDate);
var timeDiff = ts.TotalMilliseconds;
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg}", batchNo, timeDiff, JSON.Serialize(res));
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
var userResult = await res.Content.ReadAsStringAsync();
var downResult = JSON.Deserialize(userResult);
//返回详情
result.msg = downResult.message.ToString();
//返回代码
if (downResult.status.ToString() == "1")
{
result.succ = true;
}
else
{
result.succ = false;
}
}
result.ext = eDate;
}
catch(Exception ex)
{
//如果有异常直接抛出错误
throw Oops.Bah(ex.Message);
}
return result;
}
#endregion
#region 扣费
///
/// 扣费
///
/// 任务信息
/// 是否执行扣费 true-执行扣费 false-不执行扣费(主要是符合扣费条件但是由于超时没有得到准确回执)
/// 返回回执
private async Task InnerChargeFee(TaskBaseInfo taskBaseInfo,bool isCharge = true)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto { succ = false };
try
{
decimal balance = 0;
decimal price = 0;
decimal total = 0;
TaskChargesHisInfo model = new TaskChargesHisInfo {
PK_ID = IDGen.NextID().ToString(),
TASK_ID = taskBaseInfo.PK_ID,
BEFORE_BALANCE = balance,
PRICE = price,
BUSI_TYPE = "21",
BUSI_TYPE_NAME = String.Empty,
SEND_TYPE = "1001",
SEND_TYPE_NAME = String.Empty,
REMARK = "正本下载",
QTY = 1,
TOTAL_AMOUNT = total,
};
if(!isCharge)
{
model.STATUS = TaskChargeStatusEnum.UNKNOW_RESULT.ToString();
model.STATUS_NAME = TaskChargeStatusEnum.UNKNOW_RESULT.GetDescription();
}
//写入记录
await _taskChargesHisInfoRepository.InsertAsync(model);
result.succ = false;
result.msg = "扣费失败";
}
catch(Exception ex)
{
result.succ = false;
result.msg = ex.Message;
}
return result;
}
#endregion
#region 完成任务(可批量)
///
/// 完成任务(可批量)
///
/// 任务主键数组
/// 返回结果
[HttpPost("/TaskManage/CompleteTask")]
public async Task CompleteTask(string[] PKIds)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no} ids={ids} 完成任务开始", batchNo, string.Join(",", PKIds));
try
{
var taskList = _taskBaseInfoRepository.AsQueryable().Where(t => PKIds.Contains(t.PK_ID)).ToList();
_logger.LogInformation("批次={no} 获取任务完成,Num={Num}", batchNo, taskList.Count);
taskList.ForEach(async tsk => {
await InnerManualTask(batchNo, tsk, TaskOperTypeEnum.COMPLETE_TASK);
});
}
catch (Exception ex)
{
throw Oops.Bah($"完成任务异常,{0}", ex.Message);
}
return result;
}
#endregion
private async Task InnerManualTask(string batchNo, TaskBaseInfo taskBaseInfo, TaskOperTypeEnum taskOperTypeEnum)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var model = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskBaseInfo.PK_ID);
if (taskOperTypeEnum == TaskOperTypeEnum.COMPLETE_TASK)
{
if (taskBaseInfo.TASK_TYPE == TaskBusiTypeEnum.CANCELLATION.ToString())
{
//收到订舱已被取消邮件后生成的任务,如果点击完成,(订舱状态变为【退舱】,注意这里还需要确认)
}
model.COMPLETE_DATE = DateTime.Now;
model.COMPLETE_DEAL = TaskCompleteDealEnum.MANUAL.ToString();
model.COMPLETE_DEAL = TaskCompleteDealEnum.MANUAL.GetDescription();
model.IS_COMPLETE = 1;
_taskBaseInfoRepository.AsUpdateable(model).UpdateColumns(it => new
{
it.COMPLETE_DATE,
it.COMPLETE_DEAL,
it.COMPLETE_DEAL_NAME,
it.IS_COMPLETE
}).ExecuteCommand();
}
else if (taskOperTypeEnum == TaskOperTypeEnum.CANCEL_TASK)
{
if (taskBaseInfo.TASK_TYPE == TaskBusiTypeEnum.CHANGE_SHIP.ToString())
{
model.STATUS = TaskStatusEnum.Cancel.ToString();
}
else if(taskBaseInfo.TASK_TYPE == TaskBusiTypeEnum.ABORT_CHANGE_SHIP.ToString())
{
/*
1.如果原换船通知已经接受,需要把原船名航次恢复并通知客户取消换船。
2.如果原换船通知未作处理,点击接受或者结束任务时提示:本票货存在未处理换船通知,请先结束原换船任务然后结束本任务。
3.如果原换船任务为结束任务,在取消换船任务点接受时,提示未做换船,请点击结束任务。
*/
//查询同票主单的是否有未处理的换船通知
//_taskBaseInfoRepository.AsQueryable().Where(t=>t.MBL_NO.Equals(taskBaseInfo.MBL_NO) && )
}
}
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"异常,{ex.Message}";
}
return result;
}
#region 取消任务(可批量)
///
/// 取消任务(可批量)
///
/// 任务主键数组
/// 返回结果
[HttpPost("/TaskManage/CancelTask")]
public async Task CancelTask(string[] PKIds)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no} ids={ids} 取消任务开始", batchNo, string.Join(",", PKIds));
try
{
var taskList = _taskBaseInfoRepository.AsQueryable().Where(t => PKIds.Contains(t.PK_ID)).ToList();
_logger.LogInformation("批次={no} 获取任务完成,Num={Num}", batchNo, taskList.Count);
taskList.ForEach(async tsk => {
await InnerManualTask(batchNo, tsk, TaskOperTypeEnum.CANCEL_TASK);
});
}
catch (Exception ex)
{
throw Oops.Bah($"完成任务异常,{0}", ex.Message);
}
return result;
}
#endregion
#region 挂起任务(可批量)
///
/// 挂起任务(可批量)
///
/// 任务主键数组
/// 返回结果
[HttpPost("/TaskManage/PendingTask")]
public async Task PendingTask(string[] PKIds)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no} ids={ids} 挂起任务开始", batchNo, string.Join(",", PKIds));
try
{
var taskList = _taskBaseInfoRepository.AsQueryable().Where(t => PKIds.Contains(t.PK_ID)).ToList();
_logger.LogInformation("批次={no} 获取任务完成,Num={Num}", batchNo, taskList.Count);
taskList.ForEach(async tsk => {
await InnerManualTask(batchNo, tsk, TaskOperTypeEnum.PENDING_TASK);
});
}
catch (Exception ex)
{
throw Oops.Bah($"完成任务异常,{0}", ex.Message);
}
return result;
}
#endregion
///
/// 提单纸页数计算
///
/// 任务主键数组
/// 返回结果
public async Task> LaraPaperCalc(string[] PKIds)
{
List list = new List();
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no} ids={ids} 提单纸页数计算开始", batchNo, string.Join(",", PKIds));
try
{
//根据任务主键获取所有主单号列表
var mblnoList = _taskBaseInfoRepository.AsQueryable().Where(t => PKIds.Contains(t.PK_ID) && !string.IsNullOrWhiteSpace(t.MBL_NO))
.Select(t => t.MBL_NO).Distinct().ToList();
if (mblnoList.Count > 0)
{
//根据主单号获取任务类型是DRAFT的任务,取时间最新的
var taskList = _taskBaseInfoRepository.AsQueryable()
.LeftJoin(_taskFileInfoRepository.AsQueryable(), (tsk, file) => tsk.PK_ID == file.TASK_PKID)
.Where((tsk, file) => PKIds.Contains(tsk.PK_ID) && tsk.TASK_TYPE == TaskBusiTypeEnum.DRAFT.ToString() && file != null)
.OrderByDescending(tsk => tsk.CreatedTime)
.Select((tsk, file) => new { tsk = tsk, file = file }).ToList();
list = mblnoList.Select((mbl,idx) => {
var calcInfo = new LaraPaperCalcInfo();
calcInfo.Indx = idx + 1;
return calcInfo;
}).ToList();
}
}
catch (Exception ex)
{
throw Oops.Bah($"完成任务异常,{0}", ex.Message);
}
return list;
}
}
}