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.

2361 lines
97 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.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.EDI;
using Myshipping.Application.Entity;
using Myshipping.Application.Helper;
using Myshipping.Core;
using Myshipping.Core.Entity;
using Myshipping.Core.Helper;
using Myshipping.Core.Service;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Npoi.Mapper;
using NPOI.HPSF;
using NPOI.SS.Formula.Functions;
using NPOI.XSSF.Model;
using Org.BouncyCastle.Asn1.X500;
using SixLabors.ImageSharp.Processing.Processors.Transforms;
using SqlSugar;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.DirectoryServices.ActiveDirectory;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Net;
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
{
/// <summary>
/// 任务管理
/// </summary>
[ApiDescriptionSettings("Application", Name = "TaskManage", Order = 10)]
public class TaskManageService : ITaskManageService, IDynamicApiController
{
private readonly SqlSugarRepository<TaskBaseInfo> _taskBaseInfoRepository;
private readonly SqlSugarRepository<TaskSIFeedBackInfo> _taskSIFeedBackInfoRepository;
private readonly SqlSugarRepository<TaskSIFeedBackContaInfo> _taskSIFeedBackContaInfoRepository;
private readonly SqlSugarRepository<TaskBillFeeDetailInfo> _taskBillFeeDetailInfoRepository;
private readonly SqlSugarRepository<TaskFileInfo> _taskFileInfoRepository;
private readonly SqlSugarRepository<TaskEmailInfo> _taskEmailInfoRepository;
private readonly SqlSugarRepository<TaskVGMFeedBackInfo> _taskVGMFeedBackInfoRepository;
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
private readonly SqlSugarRepository<TaskStatManageInfo> _taskStatManageInfoRepository;
private readonly SqlSugarRepository<TaskOriginalDownloadHisInfo> _taskOriginalDownloadHisInfoRepository;
private readonly SqlSugarRepository<TaskChargesHisInfo> _taskChargesHisInfoRepository;
private readonly SqlSugarRepository<TaskLARAPaperInfo> _taskLARAPaperInfoRepository;
private readonly SqlSugarRepository<BookingOrder> _bookingOrderRepository;
private readonly SqlSugarRepository<BookingCtn> _bookingOrderContaRepository;
private readonly SqlSugarRepository<BookingCtnDetail> _bookingOrderContaCargoRepository;
private readonly SqlSugarRepository<BookingStatus> _bookingStatusRepository;
private readonly SqlSugarRepository<DjyUserMailAccount> _djyUserMailAccountRepository;
private readonly IDjyWebsiteAccountConfigService _webAccountConfig;
private readonly ISysCacheService _cache;
private readonly ILogger<BookingOrderService> _logger;
const string CONST_WEB_ACCOUNT_TYPE = "CmaWeb";
const string CONST_BOOK_ORIGINAL_DOWN_URL_CODE = "bookOriginalDownUrl";
const string CONST_WEB_LARA_ACCOUNT_TYPE = "LaraWeb";
const string CONST_LARA_DOWN_URL_CODE = "LaraPaperPostUrl";
public TaskManageService(SqlSugarRepository<TaskBaseInfo> taskBaseInfoRepository,
SqlSugarRepository<TaskSIFeedBackInfo> taskSIFeedBackInfoRepository,
SqlSugarRepository<TaskSIFeedBackContaInfo> taskSIFeedBackContaInfoRepository,
SqlSugarRepository<TaskBillFeeDetailInfo> taskBillFeeDetailInfoRepository,
SqlSugarRepository<TaskFileInfo> taskFileInfoRepository,
SqlSugarRepository<TaskEmailInfo> taskEmailInfoRepository,
SqlSugarRepository<TaskVGMFeedBackInfo> taskVGMFeedBackInfoRepository,
SqlSugarRepository<SysUser> sysUserRepository,
SqlSugarRepository<TaskStatManageInfo> taskStatManageInfoRepository,
SqlSugarRepository<TaskOriginalDownloadHisInfo> taskOriginalDownloadHisInfoRepository,
SqlSugarRepository<TaskChargesHisInfo> taskChargesHisInfoRepository,
SqlSugarRepository<BookingOrder> bookingOrderRepository,
SqlSugarRepository<TaskLARAPaperInfo> taskLARAPaperInfoRepository,
SqlSugarRepository<BookingCtn> bookingOrderContaRepository,
SqlSugarRepository<BookingCtnDetail> bookingOrderContaCargoRepository,
SqlSugarRepository<BookingStatus> bookingStatusRepository,
SqlSugarRepository<DjyUserMailAccount> djyUserMailAccountRepository,
IDjyWebsiteAccountConfigService webAccountConfig,
ISysCacheService cache,
ILogger<BookingOrderService> logger)
{
_taskBaseInfoRepository = taskBaseInfoRepository;
_taskSIFeedBackInfoRepository = taskSIFeedBackInfoRepository;
_taskSIFeedBackContaInfoRepository = taskSIFeedBackContaInfoRepository;
_taskBillFeeDetailInfoRepository = taskBillFeeDetailInfoRepository;
_taskFileInfoRepository = taskFileInfoRepository;
_taskEmailInfoRepository = taskEmailInfoRepository;
_taskVGMFeedBackInfoRepository = taskVGMFeedBackInfoRepository;
_sysUserRepository = sysUserRepository;
_taskStatManageInfoRepository = taskStatManageInfoRepository;
_taskOriginalDownloadHisInfoRepository = taskOriginalDownloadHisInfoRepository;
_taskChargesHisInfoRepository = taskChargesHisInfoRepository;
_bookingOrderRepository = bookingOrderRepository;
_taskLARAPaperInfoRepository = taskLARAPaperInfoRepository;
_bookingOrderContaRepository = bookingOrderContaRepository;
_bookingOrderContaCargoRepository = bookingOrderContaCargoRepository;
_bookingStatusRepository = bookingStatusRepository;
_djyUserMailAccountRepository = djyUserMailAccountRepository;
_webAccountConfig = webAccountConfig;
_cache = cache;
_logger = logger;
}
#region 创建任务
/// <summary>
/// 创建任务
/// </summary>
/// <param name="info">任务详情</param>
/// <returns>返回回执</returns>
[AllowAnonymous, HttpPost("/TaskManage/CreateTaskJob")]
public async Task<TaskManageOrderResultDto> 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;
}
#endregion
#region 新增任务
/// <summary>
/// 新增任务
/// </summary>
/// <param name="info">任务详情</param>
/// <returns>返回回执</returns>
private async Task<TaskManageOrderResultDto> 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>();
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<TaskSIFeedBackContaInfo>();
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<TaskBillFeeDetailInfo>();
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<TaskVGMFeedBackInfo>();
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;
}
#endregion
#region 获取查询参数
/// <summary>
/// 获取查询参数
/// </summary>
/// <param name="ParaType">参数类型 STATUS-任务状态;TASK_TYPE-任务类型;SOURCE-任务来源 CATEGORY-分类</param>
/// <returns>返回回执</returns>
/// <example>TASK_TYPE</example>
[HttpGet("/TaskManage/GetParaInfo")]
public async Task<TaskManageOrderResultDto> GetParaInfo([QueryString] string ParaType)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
Dictionary<string, string> dict = new Dictionary<string, string>();
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));
}
else if (ParaType == "CATEGORY")
{
dict = EnumUtil.GetEnumDictionaryWithKey(typeof(TaskStatLevelEnum));
}
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;
}
#endregion
#region 获取登陆人相关的任务统计信息
/// <summary>
/// 获取登陆人相关的任务统计信息
/// </summary>
/// <param name="isReCalc">是否强制计算</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManage/GetCurrentTotalStat")]
public async Task<TaskUserStatResultInfo> GetCurrentTotalStat([FromQuery] bool isReCalc = false)
{
TaskUserStatResultInfo resultInfo = new TaskUserStatResultInfo
{
LevelTop = new List<TaskUserStatItem>(),
LevelNext = new List<TaskUserStatItemNext>(),
LevelTree = new List<TaskUserStatItemTree>()
};
/*
1、首先判断当前登陆人是否有统计记录如果没有触发统计生成统计记录。
2、如果isReCalc=true表示强制重新统计数据并重新更新统计数据。
3、按照统计类型个人/公共)、任务状态、是否异常分组汇总,并写入统计表。
*/
try
{
var userTendInfo = await _sysUserRepository.AsQueryable()
.LeftJoin<SysTenant>((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 (true)
{
//任务列表分组统计
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 == 0 && 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
#region 任务台账查询
/// <summary>
/// 任务台账查询
/// </summary>
/// <param name="QuerySearch">任务台账查询请求</param>
/// <returns>返回结果</returns>
[HttpPost("/TaskManage/GetPage")]
public async Task<SqlSugarPagedList<TaskBaseInfoDto>> GetPageAsync(QueryTaskManageDto QuerySearch)
{
List<string> mblList = new List<string>();
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<TaskBaseInfoDto, TaskBaseInfo>(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))
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TaskCategory) && QuerySearch.TaskCategory == TaskStatLevelEnum.EXCPTION.ToString(), t => t.IS_EXCEPT == 1)
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TaskCategory) && QuerySearch.TaskCategory == TaskStatLevelEnum.PUBLIC.ToString(), t => t.IS_PUBLIC == 1)
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TaskCategory) && QuerySearch.TaskCategory == TaskStatLevelEnum.PERSON.ToString(), t => t.IS_PUBLIC == 0 && t.IS_EXCEPT == 0)
.WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.Status), t => t.STATUS.Equals(QuerySearch.Status, StringComparison.OrdinalIgnoreCase))
.OrderBy(entityOrderCol + (QuerySearch.descSort ? " asc " : " desc "))
.ToPagedListAsync(QuerySearch.PageNo, QuerySearch.PageSize);
return entities.Adapt<SqlSugarPagedList<TaskBaseInfoDto>>();
}
#endregion
#region 下载正本提单(可批量)
/// <summary>
/// 下载正本提单(可批量)
/// </summary>
/// <param name="PKIds">任务主键数组</param>
/// <returns>返回结果</returns>
[HttpPost("/TaskManage/DownloadOriginalTask")]
public async Task<TaskManageOrderResultDto> 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
#region 单票正本下载
/// <summary>
/// 单票正本下载
/// </summary>
/// <param name="batchNo">批次号</param>
/// <param name="taskBaseInfo">任务详情</param>
/// <param name="webAccountConfig">网站账户配置</param>
/// <returns>返回回执</returns>
private async Task<TaskManageOrderResultDto> 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<dynamic>(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<string, string> formDict = new Dictionary<string, string> {
{"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;
}
#endregion
#region 远程请求正本下载
/// <summary>
/// 远程请求正本下载
/// </summary>
/// <param name="batchNo">批次号</param>
/// <param name="url">请求URL</param>
/// <param name="dic">请求参数</param>
/// <returns></returns>
private async Task<TaskManageOrderResultDto> InnerRemoteDownOriginal(string batchNo, string url, Dictionary<string, string> 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<dynamic>(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 扣费
/// <summary>
/// 扣费
/// </summary>
/// <param name="taskBaseInfo">任务信息</param>
/// <param name="isCharge">是否执行扣费 true-执行扣费 false-不执行扣费(主要是符合扣费条件但是由于超时没有得到准确回执)</param>
/// <returns>返回回执</returns>
private async Task<TaskManageOrderResultDto> 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 完成任务(可批量)
/// <summary>
/// 完成任务(可批量)
/// </summary>
/// <param name="PKIds">任务主键数组</param>
/// <returns>返回结果</returns>
[HttpPost("/TaskManage/CompleteTask")]
public async Task<TaskManageOrderResultDto> 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<TaskManageOrderResultDto> 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 取消任务(可批量)
/// <summary>
/// 取消任务(可批量)
/// </summary>
/// <param name="PKIds">任务主键数组</param>
/// <returns>返回结果</returns>
[HttpPost("/TaskManage/CancelTask")]
public async Task<TaskManageOrderResultDto> 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 挂起任务(可批量)
/// <summary>
/// 挂起任务(可批量)
/// </summary>
/// <param name="PKIds">任务主键数组</param>
/// <returns>返回结果</returns>
[HttpPost("/TaskManage/PendingTask")]
public async Task<TaskManageOrderResultDto> 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
#region 提单纸页数计算
/// <summary>
/// 提单纸页数计算
/// </summary>
/// <param name="PKIds">任务主键数组</param>
/// <returns>返回结果</returns>
[HttpPost("/TaskManage/LaraPaperCalc")]
public async Task<List<LaraPaperCalcInfo>> LaraPaperCalc(string[] PKIds)
{
List<LaraPaperCalcInfo> list = new List<LaraPaperCalcInfo>();
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 fileList = _taskBaseInfoRepository.EntityContext.Queryable<TaskBaseInfo>()
.InnerJoin<TaskFileInfo>((tsk, file) => tsk.PK_ID == file.TASK_PKID)
.Where((tsk, file) =>
tsk.TASK_TYPE == TaskBusiTypeEnum.DRAFT.ToString() && mblnoList.Contains(tsk.MBL_NO))
.Select((tsk, file) => new { tsk = tsk, file = file }).ToList();
var calcList = fileList.GroupBy(t => t.tsk.PK_ID)
.Select(a =>
{
var currList = a.ToList();
return new
{
tsk = currList.FirstOrDefault().tsk,
clist = a.Select(x => x.file).ToList()
};
}).OrderByDescending(t => t.tsk.CreatedTime).ToList();
list = mblnoList.Select((mbl, idx) =>
{
var calcInfo = new LaraPaperCalcInfo();
calcInfo.MBLNo = mbl;
calcInfo.Indx = idx + 1;
var files = calcList.FirstOrDefault(t => t.tsk.MBL_NO.Equals(mbl, StringComparison.OrdinalIgnoreCase));
if (files != null)
{
calcInfo.DraftNum = files.clist.Select(t => t.FILE_NAME.GetPageNum()).Sum();
}
calcInfo.PaperNum = calcInfo.DraftNum * 3;
return calcInfo;
}).ToList();
}
}
catch (Exception ex)
{
throw Oops.Bah($"提单纸页数计算异常,{0}", ex.Message);
}
return list;
}
#endregion
#region 请求提单纸登记
/// <summary>
/// 请求提单纸登记
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <param name="model">提单纸登记请求参数</param>
/// <returns></returns>
[HttpPost("/TaskManage/LaraPaperRegistPost")]
public async Task<TaskManageOrderResultDto> LaraPaperRegistPost(string taskPKId, LaraPaperRegistPostDto model)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no} id={id} LARA提单纸登记开始", batchNo, taskPKId);
/*
1、读取LARA网站的配置账户。
2、读取字典的URL。
3、组织请求参数。
4、写入TASK_LARA_PAPER。
5、远程请求。
6、更新状态
*/
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
_logger.LogInformation("批次={no} 获取任务完成", batchNo);
//获取个人对应的账户,这里GetAccountConfig逻辑优先取个人个人没有配置取公司对应配置
var userWebAccountConfig = _webAccountConfig.GetAccountConfig(CONST_WEB_LARA_ACCOUNT_TYPE, UserManager.UserId).GetAwaiter().GetResult();
_logger.LogInformation("批次={no} 获取获取网站的账户完成result={Num}", batchNo, JSON.Serialize(userWebAccountConfig));
if (userWebAccountConfig == null)
throw Oops.Bah($"个人/公司网站【{CONST_WEB_LARA_ACCOUNT_TYPE}】获取失败,请维护个人/公司网站账户信息");
await InnerDownloadOriginalTask(batchNo, taskInfo, userWebAccountConfig);
}
catch (Exception ex)
{
throw Oops.Bah($"请求提单纸登记异常,{0}", ex.Message);
}
return result;
}
#endregion
//LaraPaperPostUrl
private async Task<TaskManageOrderResultDto> InnerLaraPaperRegistPost(string batchNo, TaskBaseInfo taskBaseInfo, LaraPaperRegistPostDto model,
DjyWebsiteAccountConfig webAccountConfig)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
//正本下载URL
string originalUrl = string.Empty;
try
{
DateTime startDate = DateTime.Now;
var downloadUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
.First(t => t.Code.Equals(CONST_LARA_DOWN_URL_CODE, StringComparison.OrdinalIgnoreCase))?.Value;
if (string.IsNullOrWhiteSpace(downloadUrl))
throw Oops.Bah($"正本下载URL不存在请确认字典是否配置 code={CONST_BOOK_ORIGINAL_DOWN_URL_CODE}");
TaskLARAPaperInfo taskLARAPaperInfo = new TaskLARAPaperInfo
{
PK_ID = IDGen.NextID().ToString(),
TASK_ID = taskBaseInfo.PK_ID,
BOOKING_ORDER_NO = "",
CreatedUserId = UserManager.UserId,
CreatedUserName = UserManager.Name,
STATUS = "temp",
IS_TIMEOUT = 0,
START_DATE = startDate,
TenantId = UserManager.TENANT_ID,
TenantName = UserManager.TENANT_NAME
};
//写入记录
_taskLARAPaperInfoRepository.Insert(taskLARAPaperInfo);
//请求远程链接
Dictionary<string, string> formDict = new Dictionary<string, string> {
{"bno", taskBaseInfo.MBL_NO },
{"num_from", model.NumberFrom },
{"num_to", model.NumberTo },
{"numbers", model.PageNumbers },
{"vessel_code", "" },
{"voyage_code", "" },
{"bl_status", "All" },
{"bl_type", "Original Bill" },
{"issue_code", "ALL" },
{"web_user", webAccountConfig.Account },
{"web_pwd", webAccountConfig.Password },
{"customer_user", "myshipping" },
{"customer_pwd", "" },
};
//请求
var postResult = await InnerRemoteDownLaraPaper(batchNo, downloadUrl, formDict);
//重新获取下载历史
var downloadHisInfo = _taskOriginalDownloadHisInfoRepository.AsQueryable()
.First(t => t.PK_ID == taskLARAPaperInfo.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();
}
catch (Exception ex)
{
result.succ = false;
result.msg = ex.Message;
}
return result;
}
#region 远程请求请求提单纸登记
/// <summary>
/// 远程请求请求提单纸登记
/// </summary>
/// <param name="batchNo">批次号</param>
/// <param name="url">请求URL</param>
/// <param name="dic">请求参数</param>
/// <returns></returns>
private async Task<TaskManageOrderResultDto> InnerRemoteDownLaraPaper(string batchNo, string url, Dictionary<string, string> 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<dynamic>(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 LARA提单纸登记
/// <summary>
/// LARA提单纸登记
/// </summary>
/// <param name="PKIds">任务主键数组</param>
/// <returns>返回结果</returns>
[HttpPost("/TaskManage/LaraPaperRegist")]
public async Task<LaraPaperRegistDto> LaraPaperRegist(string[] PKIds)
{
LaraPaperRegistDto result = new LaraPaperRegistDto();
List<LaraPaperRegistDetailDto> list = new List<LaraPaperRegistDetailDto>();
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no} ids={ids} LARA提单纸登记开始", batchNo, string.Join(",", PKIds));
/*
1、通过任务主键记录关联所有相同订舱主键相同并且任务类型是DRAFT的记录。
2、关联任务正本下载运行表结束时间
问题提单纸页数计算是通过主单号来最新记录提取文件页数为什么LARA提单纸登记没有用这个模式。没理解
*/
try
{
//
var List = _taskBaseInfoRepository.EntityContext.Queryable<TaskBaseInfo>()
.InnerJoin<TaskBaseInfo>((tsk, tsk2) => tsk.BOOK_ORDER_NO == tsk2.BOOK_ORDER_NO)
.Where((tsk, tsk2) => PKIds.Contains(tsk.PK_ID) && tsk2.TASK_TYPE == TaskBusiTypeEnum.DRAFT.ToString())
.Select((tsk, tsk2) => new { tsk = tsk, tsk2 = tsk2 }).ToList();
var list2 = List.GroupBy(t => t.tsk.PK_ID).Select(t =>
{
var curList = t.ToList();
if (curList.Count > 0)
{
return new { tsk = curList.FirstOrDefault().tsk, tsk2 = curList.OrderByDescending(a => a.tsk2.CreatedTime).FirstOrDefault().tsk2 };
}
return null;
}).Where(t => t != null).ToList();
if (list2.Count > 0)
{
var taskPKIdList = list2.Select(t => t.tsk2.PK_ID).Distinct().ToArray();
var originalDownloadHisInfo = _taskOriginalDownloadHisInfoRepository.AsQueryable()
.Where(t => taskPKIdList.Contains(t.TASK_ID))
.OrderByDescending(t => t.END_DATE)
.First();
var fileList = _taskBaseInfoRepository.EntityContext.Queryable<TaskBaseInfo>()
.InnerJoin<TaskFileInfo>((tsk, file) => tsk.PK_ID == file.TASK_PKID)
.Where((tsk, file) =>
tsk.TASK_TYPE == TaskBusiTypeEnum.DRAFT.ToString() && taskPKIdList.Contains(tsk.PK_ID))
.Select((tsk, file) => new { tsk = tsk, file = file }).ToList();
var calcList = fileList.GroupBy(t => t.tsk.PK_ID)
.Select(a =>
{
var currList = a.ToList();
return new
{
tsk = currList.FirstOrDefault().tsk,
clist = a.Select(x => x.file).ToList()
};
}).OrderByDescending(t => t.tsk.CreatedTime).ToList();
list2.ForEach(t =>
{
LaraPaperRegistDetailDto laraInfo = new LaraPaperRegistDetailDto();
laraInfo.OrderNo = t.tsk.BOOK_ORDER_NO;
laraInfo.TaskId = t.tsk.PK_ID;
laraInfo.MBLNo = t.tsk.MBL_NO;
var files = calcList.FirstOrDefault(a => a.tsk.PK_ID.Equals(t.tsk.PK_ID));
if (files != null)
{
laraInfo.DraftNum = files.clist.Select(t => t.FILE_NAME.GetPageNum()).Sum();
}
laraInfo.OriginalDownTime = originalDownloadHisInfo.END_DATE;
laraInfo.IssueType = t.tsk.ISSUE_TYPE;
laraInfo.IssueTypeName = t.tsk2.ISSUE_TYPE_NAME;
list.Add(laraInfo);
});
result.DetailList = list;
}
var laraPaperInfo = _taskLARAPaperInfoRepository.AsQueryable()
.Where(t => t.CreatedUserId == UserManager.UserId)
.OrderByDescending(t => t.NUMBER_TO).First();
result.NumberTo = laraPaperInfo != null ? Int32.Parse(laraPaperInfo.NUMBER_TO) : 0;
}
catch (Exception ex)
{
throw Oops.Bah($"LARA提单纸登记异常,{0}", ex.Message);
}
return result;
}
#endregion
#region 下载任务附件
/// <summary>
/// 下载任务附件
/// </summary>
/// <param name="taskPKId"></param>
/// <returns>返回文件流</returns>
[HttpGet("/TaskManage/DownloadTaskAttach")]
public IActionResult DownloadTaskAttach([FromQuery] string taskPKId)
{
FileStreamResult result = null;
var fileList = _taskFileInfoRepository.AsQueryable().Where(t => t.TASK_PKID == taskPKId).ToList();
var fileInfo = fileList.FirstOrDefault();
if (fileInfo.FILE_PATH.StartsWith("http://"))
{
WebClient wc = new WebClient();
var data = wc.DownloadData(fileInfo.FILE_PATH);
result = new FileStreamResult(new MemoryStream(data), "application/octet-stream") { FileDownloadName = fileInfo.FILE_NAME };
}
else if (System.IO.File.Exists(fileInfo.FILE_PATH))
{
result = new FileStreamResult(new FileStream(fileInfo.FILE_PATH, FileMode.Open), "application/octet-stream") { FileDownloadName = fileInfo.FILE_NAME };
}
return result;
}
#endregion
#region 正本附件批量打印
/// <summary>
/// 正本附件批量打印
/// </summary>
/// <param name="PKIds">任务主键数组</param>
/// <returns>返回文件流</returns>
[HttpPost("/TaskManage/PrintBatch")]
public async Task<IActionResult> PrintBatch(string[] PKIds)
{
FileStreamResult result = null;
/*
1、通过任务主键获取所有的文件列表。只合并PDF文件其他的文件不处理。
2、创建临时文件存放目录。
3、如果是http://开头的文档,需要使用下载文件,并变更为本地文件
4、PDF合成所有文件。
5、写入下载记录表。
6、返回文件流。
*/
try
{
var fileList = _taskBaseInfoRepository.EntityContext.Queryable<TaskBaseInfo>()
.InnerJoin<TaskFileInfo>((tsk, file) => tsk.PK_ID == file.TASK_PKID)
.Where((tsk, file) => PKIds.Contains(tsk.PK_ID) && file.FILE_TYPE.Equals(".pdf"))
.Select((tsk, file) => new { tsk = tsk, file = file }).ToList();
var calcList = fileList.GroupBy(t => t.tsk.PK_ID)
.Select(a =>
{
var currList = a.ToList();
return new
{
tsk = currList.FirstOrDefault().tsk,
clist = a.Select(x => x.file).ToList()
};
}).OrderByDescending(t => t.tsk.CreatedTime).ToList();
var pdfList = calcList.SelectMany(t => t.clist).Select((t, idx) => new
{
Idx = idx,
file = t
}).ToList();
if (pdfList.Count == 0)
throw Oops.Oh($"没有可以合并的PDF文件");
string filePath = string.Empty;
string tempFileName = IDGen.NextID().ToString();
var opt = App.GetOptions<TempFileOptions>().Path;
filePath = $"{Path.Combine(App.WebHostEnvironment.WebRootPath, opt)}\\TempPDFMerge\\";//服务器路径
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
filePath = filePath.Replace("\\", "/");
}
//预先创建目录
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
var mergePdfPath = Path.Combine(filePath, $"{tempFileName}.pdf");
/*
Document document = null;
PdfCopy copy = null;
pdfList.ForEach(t => {
if(t.Idx == 0)
{
if(t.file.FILE_PATH.IndexOf("http://") >=0)
{
//var dw = InnerRemoteDownFile(t.file.FILE_PATH).GetAwaiter().GetResult();
WebClient wc = new WebClient();
wc.DownloadFile(t.file.FILE_PATH, Path.Combine(filePath, $"{tempFileName}abc.pdf"));
//document = new Document(new PdfReader(dw).GetPageSize(1));
}
else
{
document = new Document(new PdfReader(t.file.FILE_PATH).GetPageSize(1));
}
copy = new PdfCopy(document, new FileStream(mergePdfPath, FileMode.Create));
}
else
{
PdfReader reader = null;
if (t.file.FILE_PATH.IndexOf("http://") >= 0)
{
var dw = InnerRemoteDownFile(t.file.FILE_PATH).GetAwaiter().GetResult();
reader = new PdfReader(dw);
}
else
{
reader = new PdfReader(t.file.FILE_PATH);
}
int n = reader.NumberOfPages;
for (int j = 1; j <= n; j++)
{
document.NewPage();
PdfImportedPage page = copy.GetImportedPage(reader, j);
copy.AddPage(page);
}
reader.Close();
}
});
document.Close();
*/
result = new FileStreamResult(new FileStream(mergePdfPath, FileMode.Open), "application/octet-stream") { FileDownloadName = $"{tempFileName}.pdf" };
}
catch (Exception ex)
{
throw Oops.Bah($"LARA提单纸登记异常,{0}", ex.Message);
}
return result;
}
#endregion
#region 下载文件
private async Task<Stream> InnerRemoteDownFile(string filePath)
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(filePath);
if (response.IsSuccessStatusCode)
{
System.Net.Http.HttpContent content = response.Content;
var contentStream = await content.ReadAsStreamAsync(); // get the actual content stream
return contentStream;
}
else
{
throw new FileNotFoundException($"{filePath} 文件下载失败");
}
}
}
#endregion
#region 接收换船
/// <summary>
/// 接收换船
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <returns>返回结果</returns>
[HttpGet("/TaskManage/AcceptChangeShip")]
public async Task<TaskManageOrderResultDto> AcceptChangeShip([FromQuery]string taskPKId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
if (taskInfo == null)
Oops.Oh($"任务信息获取失败");
if (taskInfo.TASK_TYPE != TaskBusiTypeEnum.TELEX_NOTICE.ToString() || taskInfo.TASK_TYPE != TaskBusiTypeEnum.SEAWAYBILL_DOWN.ToString())
Oops.Oh($"当前任务类型不是{TaskBusiTypeEnum.TELEX_NOTICE.GetDescription()}、{TaskBusiTypeEnum.SEAWAYBILL_DOWN.GetDescription()},不能转发邮件");
if (string.IsNullOrWhiteSpace(taskInfo.BOOK_ORDER_NO))
Oops.Oh($"任务信息的订舱主键不存在");
var orderInfo = _bookingOrderRepository.AsQueryable()
.First(t => t.Id == long.Parse(taskInfo.BOOK_ORDER_NO));
if (orderInfo == null)
Oops.Oh($"订舱信息获取失败");
var userMail = _djyUserMailAccountRepository.AsQueryable().First(x => x.CreatedUserId == orderInfo.CreatedUserId);
if (userMail == null || string.IsNullOrWhiteSpace(userMail.SmtpServer) || userMail.SmtpPort == 0)
{
Oops.Oh($"发件邮箱未配置,或者配置不完整");
}
string emailSubject = string.Empty;
string emailBody = string.Empty;
//var sendResult = await MailSendHelper.SendMail(userMail, emailSubject, emailBody, toMail);
//if (!sendResult.Key)
//{
// Oops.Oh(sendResult.Value);
//}
}
catch (Exception ex)
{
throw Oops.Bah($"获取发送下货纸异常,{0}", ex.Message);
}
return result;
}
#endregion
#region 取消换船
/// <summary>
/// 取消换船
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <returns>返回结果</returns>
[HttpGet("/TaskManage/AcceptCancelChangeShip")]
public async Task<TaskManageOrderResultDto> AcceptCancelChangeShip([FromQuery] string taskPKId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
if (taskInfo == null)
Oops.Oh($"任务信息获取失败");
if (taskInfo.TASK_TYPE != TaskBusiTypeEnum.TELEX_NOTICE.ToString() || taskInfo.TASK_TYPE != TaskBusiTypeEnum.SEAWAYBILL_DOWN.ToString())
Oops.Oh($"当前任务类型不是{TaskBusiTypeEnum.TELEX_NOTICE.GetDescription()}、{TaskBusiTypeEnum.SEAWAYBILL_DOWN.GetDescription()},不能转发邮件");
if (string.IsNullOrWhiteSpace(taskInfo.BOOK_ORDER_NO))
Oops.Oh($"任务信息的订舱主键不存在");
var orderInfo = _bookingOrderRepository.AsQueryable()
.First(t => t.Id == long.Parse(taskInfo.BOOK_ORDER_NO));
if (orderInfo == null)
Oops.Oh($"订舱信息获取失败");
var userMail = _djyUserMailAccountRepository.AsQueryable().First(x => x.CreatedUserId == orderInfo.CreatedUserId);
if (userMail == null || string.IsNullOrWhiteSpace(userMail.SmtpServer) || userMail.SmtpPort == 0)
{
Oops.Oh($"发件邮箱未配置,或者配置不完整");
}
string emailSubject = string.Empty;
string emailBody = string.Empty;
//var sendResult = await MailSendHelper.SendMail(userMail, emailSubject, emailBody, toMail);
//if (!sendResult.Key)
//{
// Oops.Oh(sendResult.Value);
//}
}
catch (Exception ex)
{
throw Oops.Bah($"获取发送下货纸异常,{0}", ex.Message);
}
return result;
}
#endregion
#region 转发电放邮件
/// <summary>
/// 转发电放邮件
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <param name="toMail">指定邮件地址</param>
/// <returns>返回结果</returns>
[HttpGet("/TaskManage/SendTelexEmail")]
public async Task<TaskManageOrderResultDto> SendTelexEmail([FromQuery] string taskPKId, [FromQuery] string toMail)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
if (taskInfo == null)
Oops.Oh($"任务信息获取失败");
if (taskInfo.TASK_TYPE != TaskBusiTypeEnum.TELEX_NOTICE.ToString() || taskInfo.TASK_TYPE != TaskBusiTypeEnum.SEAWAYBILL_DOWN.ToString())
Oops.Oh($"当前任务类型不是{TaskBusiTypeEnum.TELEX_NOTICE.GetDescription()}、{TaskBusiTypeEnum.SEAWAYBILL_DOWN.GetDescription()},不能转发邮件");
if (string.IsNullOrWhiteSpace(taskInfo.BOOK_ORDER_NO))
Oops.Oh($"任务信息的订舱主键不存在");
var orderInfo = _bookingOrderRepository.AsQueryable()
.First(t => t.Id == long.Parse(taskInfo.BOOK_ORDER_NO));
if (orderInfo == null)
Oops.Oh($"订舱信息获取失败");
var userMail = _djyUserMailAccountRepository.AsQueryable().First(x => x.CreatedUserId == orderInfo.CreatedUserId);
if (userMail == null || string.IsNullOrWhiteSpace(userMail.SmtpServer) || userMail.SmtpPort == 0)
{
Oops.Oh($"发件邮箱未配置,或者配置不完整");
}
string emailSubject = string.Empty;
string emailBody = string.Empty;
var sendResult = await MailSendHelper.SendMail(userMail, emailSubject, emailBody, toMail);
if (!sendResult.Key)
{
Oops.Oh(sendResult.Value);
}
}
catch(Exception ex)
{
throw Oops.Bah($"获取发送下货纸异常,{0}", ex.Message);
}
return result;
}
#endregion
#region 发送下货纸
/// <summary>
/// 发送下货纸
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <param name="fileRole">文件功能 (9原始)</param>
/// <returns>返回结果</returns>
[HttpGet("/TaskManage/SendShippingOrder")]
public async Task<TaskManageOrderResultDto> SendShippingOrder([FromQuery] string taskPKId, [FromQuery] string fileRole = "9")
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
string batchNo = IDGen.NextID().ToString();
/*
1、查询任务关联的订舱信息。
2、触发下货纸发送。
3、发送成功更新任务状态为成功。
4、查看用户公司是否配置了反馈地址如果有配置则触发反馈推送否则显示反馈失败提示。
5、触发扣费
*/
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
if (taskInfo == null)
Oops.Oh($"任务信息获取失败");
if(taskInfo.TASK_TYPE != TaskBusiTypeEnum.SHIPPING_ORDER.ToString())
Oops.Oh($"当前任务类型不是{TaskBusiTypeEnum.SHIPPING_ORDER.GetDescription()},不能发送下货纸");
if (string.IsNullOrWhiteSpace(taskInfo.BOOK_ORDER_NO))
Oops.Oh($"任务信息的订舱主键不存在");
var orderInfo = _bookingOrderRepository.AsQueryable()
.First(t => t.Id == long.Parse(taskInfo.BOOK_ORDER_NO));
if (orderInfo == null)
Oops.Oh($"订舱信息获取失败");
//推送下货纸业务
var rtn = await XiahuozhiHelpler.Send(orderInfo.Id, fileRole);
if (!rtn.Key)
{
throw Oops.Bah($"发送失败:{rtn.Value}");
}
//订舱状态写入
await SaveBookingStatus(orderInfo.Id, "sta_xhz", "下货纸");
taskInfo.STATUS = TaskStatusEnum.Complete.ToString();
taskInfo.STATUS_NAME = TaskStatusEnum.Complete.GetDescription();
taskInfo.COMPLETE_DATE = DateTime.Now;
taskInfo.COMPLETE_DEAL = TaskCompleteDealEnum.MANUAL.ToString();
taskInfo.COMPLETE_DEAL_NAME = TaskCompleteDealEnum.MANUAL.GetDescription();
taskInfo.UpdatedTime = DateTime.Now;
taskInfo.UpdatedUserId = UserManager.UserId;
taskInfo.UpdatedUserName = UserManager.Name;
//更新任务表
await _taskBaseInfoRepository.AsUpdateable(taskInfo).UpdateColumns(it => new
{
it.STATUS,
it.STATUS_NAME,
it.COMPLETE_DATE,
it.COMPLETE_DEAL,
it.COMPLETE_DEAL_NAME,
it.UpdatedTime,
it.UpdatedUserId,
it.UpdatedUserName
}).ExecuteCommandAsync();
await InnerChargeFeeShippingOrder(taskInfo);
//反馈用户(这里预留,主要考虑是否通过用户配置确定是否需要推送回执)
await FeedbackXiaHuoZhi("");
}
catch(Exception ex)
{
throw Oops.Bah($"发送下货纸异常,{0}", ex.Message);
}
return result;
}
#endregion
#region 更新订舱的状态
/// <summary>
/// 更新订舱的状态
/// </summary>
/// <param name="bookingId">订舱主键</param>
/// <param name="code">状态代码</param>
/// <param name="name">状态名称</param>
/// <returns></returns>
private async Task SaveBookingStatus(long bookingId, string code, string name)
{
var bookSta = _bookingStatusRepository.FirstOrDefault(x => x.BookingId == bookingId && x.StaCode == code);
if (bookSta == null)
{
//记录状态
bookSta = new BookingStatus();
bookSta.BookingId = bookingId;
bookSta.StaCode = code;
bookSta.StaName = name;
bookSta.StaTime = DateTime.Now;
await _bookingStatusRepository.InsertAsync(bookSta);
}
else
{
bookSta.StaTime = DateTime.Now;
await _bookingStatusRepository.UpdateAsync(bookSta);
}
}
#endregion
#region 扣费
/// <summary>
/// 扣费
/// </summary>
/// <param name="taskBaseInfo">任务信息</param>
/// <param name="isCharge">是否执行扣费 true-执行扣费 false-不执行扣费(主要是符合扣费条件但是由于超时没有得到准确回执)</param>
/// <returns>返回回执</returns>
private async Task<TaskManageOrderResultDto> InnerChargeFeeShippingOrder(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 获取订舱详情
/// <summary>
/// 获取订舱详情
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <returns>返回结果</returns>
[HttpGet("/TaskManage/GetBookingOrderInfo")]
public async Task<TaskBookingOrderDto> GetBookingOrderInfo([FromQuery]string taskPKId)
{
TaskBookingOrderDto model = new TaskBookingOrderDto();
string batchNo = IDGen.NextID().ToString();
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
if (taskInfo == null)
Oops.Oh($"任务信息获取失败");
if (string.IsNullOrWhiteSpace(taskInfo.BOOK_ORDER_NO))
Oops.Oh($"任务信息的订舱主键不存在");
var orderInfo = _bookingOrderRepository.AsQueryable()
.First(t => t.Id == long.Parse(taskInfo.BOOK_ORDER_NO));
if(orderInfo != null)
{
//订舱
model = orderInfo.Adapt<TaskBookingOrderDto>();
var contaList = await _bookingOrderContaRepository.AsQueryable().Where(x => x.BILLID == orderInfo.Id).ToListAsync();
//获取集装箱的主键
var ctnArg = contaList.Select(t => t.Id).ToArray();
//查询集装箱所有的货物信息
var cargoList = await _bookingOrderContaCargoRepository.AsQueryable()
.Where(x => ctnArg.Contains(x.CTNID.Value)).ToListAsync();
_logger.LogInformation("批次={no} 提取货物明细完成 数量={total}", batchNo, cargoList.Count);
if (cargoList.Count > 0)
{
model.ContaList = contaList.GroupJoin(cargoList, l => l.Id, r => r.CTNID, (l, r) => {
var currList = r.ToList();
if (currList.Count > 0)
{
var info = l.Adapt<TaskBookingOrderContaDto>();
info.CargoList = currList.Adapt<List<TaskBookingOrderCargoDto>>();
return info;
}
return l.Adapt<TaskBookingOrderContaDto>();
}).ToList();
}
else
{
model.ContaList = contaList.Adapt<List<TaskBookingOrderContaDto>>();
}
//任务
model.TaskBaseInfo = taskInfo.Adapt<TaskBaseInfoDto>();
}
}
catch (Exception ex)
{
throw Oops.Bah($"获取订舱详情异常,{0}", ex.Message);
}
return model;
}
#endregion
#region 下货纸反馈
/// <summary>
/// 下货纸反馈
/// </summary>
/// <param name="bsno"></param>
/// <returns></returns>
private async Task FeedbackXiaHuoZhi(string bsno)
{
/*
var para = commonData.ParamValues.AsNoTracking().FirstOrDefault(x => x.CompId == compid && x.ParaCode == "XHZ_FEEDBACK_URL");
if (para == null || string.IsNullOrEmpty(para.ItemCode))
{
msg = "下货纸反馈地址未配置";
return false;
}
var feedbask = new BackgroundTaskCommon();
feedbask.GID = Guid.NewGuid().ToString();
feedbask.Status = BackgroundTaskCommon.StatusCreate;
feedbask.Type = BackgroundTaskCommon.TypeHttpFeedback;
feedbask.CreateTime = DateTime.Now;
feedbask.ParamData = JsonConvert.SerializeObject(new
{
url = para.ItemCode,
method = "POST",
json = JsonConvert.SerializeObject(new
{
bsno,
status
})
});
commonData.BackgroundTaskCommon.Add(feedbask);
msg = "成功";
return true;
*/
}
#endregion
#region 获取航次账单详情
/// <summary>
/// 获取航次账单详情
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <returns>返回结果</returns>
[HttpGet("/TaskManage/GetInvoiceBillInfo")]
public async Task<TaskInvoiceBillBaseInfo> GetInvoiceBillInfo([FromQuery] string taskPKId)
{
TaskInvoiceBillBaseInfo model = new TaskInvoiceBillBaseInfo();
string batchNo = IDGen.NextID().ToString();
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
if (taskInfo == null)
Oops.Oh($"任务信息获取失败");
if (string.IsNullOrWhiteSpace(taskInfo.BOOK_ORDER_NO))
Oops.Oh($"任务信息的订舱主键不存在");
if(taskInfo.TASK_TYPE != TaskBusiTypeEnum.INVOICE_BILL_MAIL.ToString())
Oops.Oh($"当前任务类型不是{TaskBusiTypeEnum.INVOICE_BILL_MAIL.GetDescription()}");
var orderInfo = _bookingOrderRepository.AsQueryable()
.First(t => t.Id == long.Parse(taskInfo.BOOK_ORDER_NO));
model.TaskId = taskInfo.PK_ID;
if (orderInfo != null)
{
//订舱
model.BookingOrder = orderInfo.Adapt<TaskBookingOrderDto>();
}
//获取文件
var fileList = _taskFileInfoRepository.AsQueryable().Where(t => t.TASK_PKID == taskInfo.PK_ID).ToList();
model.TaskFile = fileList.Adapt<List<TaskManageOrderFileInfo>>();
var feeList = _taskBillFeeDetailInfoRepository.AsQueryable().Where(t => t.TASK_PKID == taskInfo.PK_ID).ToList();
model.FeeList = feeList.Where(t => t.IS_TOTAL == 0).Select(t=>t.Adapt<TaskInvoiceBillFeeDto>()).ToList();
var totalUSD = feeList.FirstOrDefault(t => t.IS_TOTAL == 1 && t.FEE_NAME == "TotalUSD" && t.CURRENCY == "USD");
model.TotalAmountUSD = totalUSD != null ? totalUSD.TOTAL_AMOUNT : 0;
var totalCNY = feeList.FirstOrDefault(t => t.IS_TOTAL == 1 && t.FEE_NAME == "TotalCNY" && t.CURRENCY == "CNY");
model.TotalAmountCNY = totalCNY != null ? totalCNY.TOTAL_AMOUNT : 0;
model.InvoiceBillSendList = new List<TaskInvoiceBillFileHis>();
}
catch (Exception ex)
{
throw Oops.Bah($"获取获取航次账单详情异常,{0}", ex.Message);
}
return model;
}
#endregion
/// <summary>
/// 获取单票账单详情
/// </summary>
/// <param name="taskPKId">任务主键</param>
/// <returns>返回结果</returns>
public async Task<TaskPerBillResultInfo> GetTaskPerBillInfo(string taskPKId)
{
TaskPerBillResultInfo model = new TaskPerBillResultInfo();
string batchNo = IDGen.NextID().ToString();
try
{
var taskInfo = _taskBaseInfoRepository.AsQueryable().First(t => t.PK_ID == taskPKId);
if (taskInfo == null)
Oops.Oh($"任务信息获取失败");
if (string.IsNullOrWhiteSpace(taskInfo.BOOK_ORDER_NO))
Oops.Oh($"任务信息的订舱主键不存在");
if (taskInfo.TASK_TYPE != TaskBusiTypeEnum.PER_BILL.ToString())
Oops.Oh($"当前任务类型不是{TaskBusiTypeEnum.PER_BILL.GetDescription()}");
var orderInfo = _bookingOrderRepository.AsQueryable()
.First(t => t.Id == long.Parse(taskInfo.BOOK_ORDER_NO));
model.TaskId = taskInfo.PK_ID;
if (orderInfo != null)
{
//订舱
model.BookingOrder = orderInfo.Adapt<TaskBookingOrderDto>();
}
//获取文件
var fileList = _taskFileInfoRepository.AsQueryable().Where(t => t.TASK_PKID == taskInfo.PK_ID).ToList();
model.TaskFile = fileList.Adapt<List<TaskManageOrderFileInfo>>();
var feeList = _taskBillFeeDetailInfoRepository.AsQueryable().Where(t => t.TASK_PKID == taskInfo.PK_ID).ToList();
model.FeeList = feeList.Where(t => t.IS_TOTAL == 0).Select(t => t.Adapt<TaskPerBillFeeDto>()).ToList();
}
catch (Exception ex)
{
throw Oops.Bah($"获取获取单票账单详情异常,{0}", ex.Message);
}
return model;
}
}
#region 样本业务提取帮助类
/// <summary>
/// 样本业务提取帮助类
/// </summary>
public static class DraftPaperExtension
{
public static int GetPageNum(this string Name)
{
try
{
if (string.IsNullOrWhiteSpace(Name))
return 0;
string s = Regex.Replace(Name.Substring(Name.LastIndexOf('-') + 1), "\\.[a-zA-Z]+", "");
return int.Parse(s);
}
catch(Exception ex)
{
throw Oops.Bah($"文件名{0} 取页数异常,{1}", Name, ex.Message);
}
}
}
#endregion
}