using Furion;
using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Myshipping.Application.Entity;
using Myshipping.Core;
using Myshipping.Core.Entity;
using Myshipping.Core.Service;
using Org.BouncyCastle.Asn1.X9;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Myshipping.Application
{
///
/// 请求下货纸比对
///
[ApiDescriptionSettings("Application", Name = "TaskShippingOrderCompare", Order = 9)]
public class TaskShippingOrderCompareService : ITaskShippingOrderCompareService, IDynamicApiController, ITransient
{
private readonly ISysCacheService _cache;
private readonly ILogger _logger;
private readonly SqlSugarRepository _bookingOrderRepository;
private readonly SqlSugarRepository _bookingOrderContaRepository;
//private readonly SqlSugarRepository _userRepository;
private readonly IBookingValueAddedService _bookingValueAddedService;
public TaskShippingOrderCompareService(ISysCacheService cache, ILogger logger,
SqlSugarRepository bookingOrderRepository, SqlSugarRepository bookingOrderContaRepository,
IBookingValueAddedService bookingValueAddedService)
{
_cache = cache;
_logger = logger;
_bookingOrderRepository = bookingOrderRepository;
_bookingOrderContaRepository = bookingOrderContaRepository;
_bookingValueAddedService = bookingValueAddedService;
}
///
/// 执行下货纸比对
///
/// 订舱主键
/// 返回回执
[HttpGet("/TaskShippingOrderCompare/ExcuteShippingOrderCompare")]
public async Task ExcuteShippingOrderCompareAsync(string bookingId)
{
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no}获取订舱数据请求规则 {id}", batchNo, bookingId);
/*
处理逻辑
1、台账触发单票下货纸比对
2、调取订舱的详情。
3、对应请求报文。
4、请求比对接口。
5、返回回执。
*/
return await InnerExcuteShippingOrderCompareAsync(bookingId);
}
private async Task InnerExcuteShippingOrderCompareAsync(string bookingId)
{
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no}获取订舱数据请求规则 {id}", batchNo, bookingId);
/*
处理逻辑
1、台账触发单票下货纸比对
2、调取订舱的详情。
3、对应请求报文。
4、请求比对接口。
5、返回回执。
*/
TaskManageExcuteResultDto result = new TaskManageExcuteResultDto();
try
{
DateTime nowDate = DateTime.Now;
var model = _bookingOrderRepository.AsQueryable().InSingle(long.Parse(bookingId));
if (model == null)
throw Oops.Oh($"订舱主键{bookingId}无法获取业务信息");
_logger.LogInformation("批次={no}获取订舱数据完成", batchNo);
//附主信息
var mainInfo = model.Adapt();
mainInfo.BusiPKId = model.Id.ToString();
mainInfo.UserId = UserManager.UserId.ToString();
mainInfo.UserName = UserManager.Name;
mainInfo.UserEmail = UserManager.Email;
var contaList = await _bookingOrderContaRepository.AsQueryable().Where(x => x.BILLID == model.Id).ToListAsync();
_logger.LogInformation("批次={no} 提取箱完成 数量={total}", batchNo, contaList.Count);
if (contaList.Count > 0)
{
mainInfo.ContaList = contaList.Adapt>();
}
var msgModel = GetMessageInfo(batchNo, mainInfo);
_logger.LogInformation("批次={no} 对应请求报文完成 msg={msg}", batchNo, JSON.Serialize(msgModel));
DateTime bDate = DateTime.Now;
var compareResult = await ExcuteCompare(msgModel);
DateTime eDate = DateTime.Now;
TimeSpan ts = eDate.Subtract(bDate);
var timeDiff = ts.TotalMilliseconds;
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg}", batchNo, timeDiff, compareResult.succ ? "成功" : "失败");
if (compareResult == null)
throw Oops.Oh($"订舱主键{bookingId}请求下货纸比对失败,返回为空");
var orderInfo = _bookingOrderRepository.AsQueryable().First(x => x.Id == long.Parse(bookingId));
if (orderInfo != null)
{
orderInfo.LstShipOrderCompareDate = bDate;
if (compareResult.succ)
{
orderInfo.LstShipOrderCompareMode = "MANUAL";
if (compareResult.extra.IsExistsDiff)
{
orderInfo.LstShipOrderCompareRlt = "DIFF";
orderInfo.LstShipOrderCompareRltName = "有差异";
}
else
{
orderInfo.LstShipOrderCompareRlt = "NO_DIFF";
orderInfo.LstShipOrderCompareRltName = "正常";
//推送状态JHQ
if (App.Configuration["ServiceStatusOpenAuto"] == "1")
{
//比对成功后触发下货纸比对状态
var saveStatusRlt = await _bookingValueAddedService.SaveServiceStatus(new ModifyServiceProjectStatusDto
{
BookingId = long.Parse(bookingId),
SourceType = TrackingSourceTypeEnum.AUTO,
StatusCodes = new List {
new ModifyServiceProjectStatusDetailDto { StatusCode = "XHZBDCHG" } }
});
_logger.LogInformation("批次={no} 异步推送下货纸比对状态完成,结果={rlt}", batchNo, JSON.Serialize(saveStatusRlt));
}
}
}
else
{
orderInfo.LstShipOrderCompareRlt = "NO_YARD";
orderInfo.LstShipOrderCompareRltName = "无动态";
}
if (compareResult.extra != null)
orderInfo.LstShipOrderCompareId = compareResult.extra.TaskCompareId;
//更新
await _bookingOrderRepository.AsUpdateable(orderInfo).UpdateColumns(it => new
{
it.LstShipOrderCompareId,
it.LstShipOrderCompareDate,
it.LstShipOrderCompareRlt,
it.LstShipOrderCompareRltName,
it.LstShipOrderCompareMode,
}).ExecuteCommandAsync();
}
result.succ = compareResult.succ;
result.msg = compareResult.msg;
result.extra = compareResult.extra;
result.extra2 = compareResult.extra2;
result.total = compareResult.total;
_logger.LogInformation("批次={no} 请求下货纸比对返回结果{msg}", batchNo, JSON.Serialize(compareResult));
_logger.LogInformation("批次={no} 返回结果{msg}", batchNo, JSON.Serialize(result));
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"请求下货纸比对异常,{ex.Message}";
}
return result;
}
///
/// 批量执行下货纸比对
///
/// 订舱主键组
/// 返回回执
[HttpPost("/TaskShippingOrderCompare/ExcuteShippingOrderCompareBatch")]
public async Task ExcuteShippingOrderCompareBatchAsync([FromBody] string[] bookingIds)
{
TaskManageExcuteResultDto result = new TaskManageExcuteResultDto();
try
{
var ids = bookingIds.Select(a => long.Parse(a)).Distinct().ToArray();
var list = _bookingOrderRepository.AsQueryable().Where(t => ids.Contains(t.Id)).ToList();
if (list.Count != ids.Length)
{
var noRecord = string.Join(",", ids.GroupJoin(list, l => l, r => r.Id, (l, r) =>
{
var currList = r.ToList();
if (r.Count() > 0)
return 0;
return l;
}).Where(t => t > 0).ToArray());
throw Oops.Oh($"以下主键信息 {noRecord} 检索失败或者已作废过");
}
//这里单票下货纸比对时,等待结果返回
if(ids.Length == 1)
{
result = await InnerExcuteShippingOrderCompareAsync(list.FirstOrDefault().Id.ToString());
}
else
{
List> listOfTasks = new List>();
list.ForEach(entity =>
{
listOfTasks.Add(InnerExcuteShippingOrderCompareAsync(entity.Id.ToString()));
});
await Task.WhenAll(listOfTasks);
result.succ = true;
result.msg = "比对完成";
string rltMsg = string.Empty;
result.rows = listOfTasks.Select(a =>
{
var origId = a.Result.extra.OrigPKId;
var order = list.FirstOrDefault(x => x.Id == long.Parse(origId));
if (a.Result.succ)
{
if (a.Result.total > 0)
{
return new { MblNo = order.MBLNO, Msg = "比对异常", IsDiff = true, rlt = a.Result.succ };
}
return new { MblNo = order.MBLNO, Msg = "比对一致", IsDiff = false, rlt = a.Result.succ };
}
return new { MblNo = order?.MBLNO, Msg = "比对一致", IsDiff = false, rlt = a.Result.succ };
}).ToList();
}
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"请求下货纸比对异常,{ex.Message}";
}
return result;
}
///
/// 下货纸自动比对回写状态
///
/// 比对回写详情
/// 返回回执
[AllowAnonymous, HttpPost("/TaskShippingOrderCompare/AutoTaskShippingOrderCompareCallBack")]
public async Task AutoTaskShippingOrderCompareCallBackAsync([FromBody] ShippingOrderCompareCallBackInfo model)
{
TaskManageExcuteResultDto result = new TaskManageExcuteResultDto();
try
{
if(string.IsNullOrWhiteSpace(model.reqBusiId))
throw Oops.Oh($"订舱主键{model.reqBusiId}不能为空");
if (string.IsNullOrWhiteSpace(model.compareId))
throw Oops.Oh($"比对ID{model.compareId}不能为空");
if (string.IsNullOrWhiteSpace(model.compareMode))
throw Oops.Oh($"下货纸比对方式不能为空{model.compareMode}不能为空");
if (string.IsNullOrWhiteSpace(model.compareRltCode))
throw Oops.Oh($"比对结果代码{model.compareRltCode}不能为空");
if (string.IsNullOrWhiteSpace(model.compareRltName))
throw Oops.Oh($"比对结果名称{model.compareId}不能为空");
var bookingOrder = await _bookingOrderRepository.AsQueryable()
.FirstAsync(a => a.Id == long.Parse(model.reqBusiId));
if (bookingOrder == null)
{
throw Oops.Oh($"订舱信息检索失败,ID={model.reqBusiId}");
}
bookingOrder.LstShipOrderCompareId = model.compareId;
bookingOrder.LstShipOrderCompareDate = model.compareDate;
bookingOrder.LstShipOrderCompareRlt = model.compareRltCode;
bookingOrder.LstShipOrderCompareRltName = model.compareRltName;
bookingOrder.LstShipOrderCompareMode = model.compareMode;
//更新
await _bookingOrderRepository.AsUpdateable(bookingOrder).UpdateColumns(it => new
{
it.LstShipOrderCompareId,
it.LstShipOrderCompareDate,
it.LstShipOrderCompareRlt,
it.LstShipOrderCompareRltName,
it.LstShipOrderCompareMode,
}).ExecuteCommandAsync();
result.succ = true;
result.msg = "更新完成";
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"下货纸自动比对回写状态失败,{ex.Message}";
}
return result;
}
///
/// 生成请求规则报文
///
/// 批次号
/// 订舱主业务信息
/// 返回请求报文类
[NonAction]
private TaskMessageInfoDto GetMessageInfo(string batchNo, TaskMessageMain mainInfo)
{
DateTime nowDate = DateTime.Now;
TaskMessageInfoDto msgModel = new TaskMessageInfoDto();
msgModel.Head = new TaskMessageHead
{
GID = batchNo,
MessageType = "SHIP_ORDER_COMPARE",
SenderId = App.Configuration["RulesEngineSender"],
SenderName = App.Configuration["RulesEngineSenderName"],
ReceiverId = "RulesEngine",
ReceiverName = "大简云规则引擎",
Version = "1.0",
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "Compare",
};
msgModel.Main = mainInfo;
return msgModel;
}
#region 请求下货纸比对
///
/// 请求下货纸比对
///
///
///
[NonAction]
private async Task ExcuteCompare(TaskMessageInfoDto info)
{
TaskManageExcuteResultDto model = null;
/*
1、读取配置文件中的规则引擎URL
2、填充请求的类,并生成JSON报文
3、POST请求接口,并记录回执。
4、返回信息。
*/
var url = App.Configuration["ShippingOrderCompareUrl"];
try
{
var res = await url.OnClientCreating(client => {
// client 为 HttpClient 对象
client.Timeout = TimeSpan.FromMinutes(15); // 设置超时时间 15分钟
}).SetHttpMethod(HttpMethod.Post)
.SetBody(JSON.Serialize(info), "application/json")
.SetContentEncoding(Encoding.UTF8)
.PostAsync();
_logger.LogInformation("批次={no} 对应请求报文完成 res={res}", info.Head.GID, JSON.Serialize(res));
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
var userResult = await res.Content.ReadAsStringAsync();
model = JSON.Deserialize(userResult);
}
}
catch (Exception ex)
{
//写日志
if (ex is HttpRequestException)
throw Oops.Oh(10000002);
}
return model;
}
#endregion
}
}