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.

702 lines
31 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 EntrustSettle.Common;
using EntrustSettle.Controllers;
using EntrustSettle.IServices;
using EntrustSettle.Model;
using EntrustSettle.Model.Dtos;
using EntrustSettle.Model.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using RestSharp;
namespace EntrustSettle.Api.Controllers
{
/// <summary>
/// 对外提供的委托结算相关接口
/// </summary>
[AllowAnonymous]
public class OpenController : BaseApiController
{
private readonly IOrderService orderService;
private readonly IAnnexService annexService;
private readonly IOrderAnnexService orderAnnexService;
private readonly ILogger<OpenController> logger;
private readonly IOrderHistoryService orderHistoryService;
private readonly IQueueService queueService;
private readonly IOrderFeeService orderFeeService;
private readonly IInvoiceApplyService invoiceApplyService;
public OpenController(IOrderService orderService,
ILogger<OpenController> logger,
IOrderHistoryService orderHistoryService,
IQueueService queueService,
IOrderFeeService orderFeeService,
IAnnexService annexService,
IOrderAnnexService orderAnnexService,
IInvoiceApplyService invoiceApplyService)
{
this.orderService = orderService;
this.logger = logger;
this.orderHistoryService = orderHistoryService;
this.queueService = queueService;
this.orderFeeService = orderFeeService;
this.annexService = annexService;
this.orderAnnexService = orderAnnexService;
this.invoiceApplyService = invoiceApplyService;
}
/// <summary>
/// 下单
/// </summary>
[HttpPost]
[ApiUser(ApiCode = "EntrustSettle")]
public async Task<MessageModel<List<OrderSubmitResultDto>>> OrderSubmit(OrderSubmitDto inputDto)
{
var result = await App.GetService<OrderController>().Submit(inputDto);
return result;
}
/// <summary>
/// 附件上传
/// </summary>
/// <param name="file">附件文件</param>
/// <param name="fileType">文件类型</param>
[HttpPost]
[ApiUser(ApiCode = "EntrustSettle")]
public async Task<MessageModel<long>> AnnexUpload([FromForm] IFormFile file, [FromForm] FileTypeEnum fileType)
{
var result = await App.GetService<AnnexController>().Upload(file, fileType);
return result;
}
/// <summary>
/// 反馈信息(为订单追加附件或信息)
/// </summary>
/// <returns></returns>
[HttpPost]
[ApiUser(ApiCode = "EntrustSettle")]
public async Task<MessageModel> BindAnnexOrInfo([FromBody] BindAnnexOrInfoDto bindDto)
{
var result = await App.GetService<OrderController>().BindAnnexOrInfo(bindDto);
return result;
}
/// <summary>
/// 获取附件
/// </summary>
/// <param name="annexId">文件记录主键</param>
[HttpGet]
[ApiUser(ApiCode = "EntrustSettle")]
public async Task<IActionResult> AnnexDownload([FromQuery] long annexId)
{
var result = await App.GetService<AnnexController>().DownloadFile(annexId);
return result;
}
/// <summary>
/// 发票申请
/// </summary>
[HttpPost]
[ApiUser(ApiCode = "EntrustSettle")]
public async Task<MessageModel> ApplyInvoice(ApplyInvoiceDto input)
{
var result = await App.GetService<OrderController>().ApplyInvoice(input);
return result;
}
/// <summary>
/// 账单申请
/// </summary>
[HttpPost]
[ApiUser(ApiCode = "EntrustSettle")]
public async Task<MessageModel> ApplyBill(ApplyBillDto input)
{
var result = await App.GetService<OrderController>().ApplyBill(input);
return result;
}
/// <summary>
/// 海运达状态回推接口
/// </summary>
[HttpPost]
[ApiUser(ApiCode = "PushOrderStatus")]
public async Task<MessageModel> PushOrderStatus([FromBody] HydQueryResultDto input)
{
// 推送类型 1:订单状态、费用、账单、外部往来单据 2:发票
int pushType = 0;
List<InvoiceApply> invoiceApplyList = null;
var orderList = await orderService.Query(x => x.Bsno == input.id);
if (orderList != null && orderList.Count > 0)
{
pushType = 1;
logger.LogInformation($"订单Id[{input.id}]接收到回推后,判断操作类型为[反馈订单状态/费用/外部往来单据/账单]");
}
else
{
invoiceApplyList = await invoiceApplyService.Query(x => x.Bsno == input.id);
if (invoiceApplyList != null && invoiceApplyList.Count > 0)
{
pushType = 2;
logger.LogInformation($"订单Id[{input.id}]接收到回推后,判断操作类型为[反馈发票]");
}
else
{
string msg = $"订单Id[{input.id}]接收到回推后未查询到本地订单或发票申请订单";
logger.LogInformation(msg);
return FailedMsg(msg);
}
}
if (pushType == 1)
{
var order = orderList[0];
bool isHasBill = false;
// 保存【往来单据附件】或【账单附件】
if (input.feedbackList != null && input.feedbackList.Count > 0)
{
var outerFileIdList = input.feedbackList.Select(x => x.id).ToList();
var existsOuterFileIdList = await orderAnnexService.AsQueryable()
.LeftJoin<Annex>((o, a) => o.AnnexId == a.Id)
.Where((o, a) => o.OrderId == order.Id && outerFileIdList.Contains((long)a.OuterFileId))
.Select((o, a) => a.OuterFileId)
.ToListAsync();
foreach (var item in input.feedbackList)
{
// 如果文件不是外部推送的,不处理
if (item.sendType != 1)
continue;
// 如果文件信息已经存在,不处理
if (existsOuterFileIdList.Contains(item.id))
continue;
// 保存附件信息
var annex = new Annex()
{
OuterFileId = item.id,
Name = item.fileName,
Remark = item.remark,
BusinessTime = item.createTime,
//Path = relativePath
//Type
};
//if (item.billApplyFlag == 1 && item.remark?.StartsWith("[反馈账单]") == true)
// 海运达规定海运达返回的账单remark==“账单“
if (item.remark == "账单")
{
annex.Type = 3;
isHasBill = true;
}
else
{
annex.Type = 5;
}
string fullPath = null;
if (!string.IsNullOrEmpty(item.fileUrl))
{
// 检查文件保存目录
var dir = Path.Combine(App.WebHostEnvironment.WebRootPath, "files");
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
// 文件名
var newFileName = Guid.NewGuid().ToString("N") + Path.GetExtension(item.fileName);
// 相对路径
var relativePath = Path.Combine("files", newFileName);
// 完整路径
fullPath = Path.Combine(dir, newFileName);
annex.Path = relativePath;
}
await annexService.Add(annex);
var orderAnnex = new OrderAnnex()
{
OrderId = order.Id,
AnnexId = annex.Id
};
await orderAnnexService.Add(orderAnnex);
// 记录订单状态历史
var orderStatusModelList = new OrderHistory()
{
Pid = order.Id,
StatusTime = DateTime.Now,
Status = annex.Type switch
{
3 => 8,
5 => 9,
_ => -1
},
Remark = item.remark,
};
if (annex.Type == 3 && string.IsNullOrEmpty(item.fileUrl))
{
orderStatusModelList.Remark += "(附件为空)";
}
await orderHistoryService.Add(orderStatusModelList);
if (!string.IsNullOrEmpty(item.fileUrl))
{
var restClient = new RestClient(item.fileUrl);
var request = new RestRequest();
using var stream = await restClient.DownloadStreamAsync(request);
using FileStream fileStream = new FileStream(fullPath, FileMode.Create);
await stream.CopyToAsync(fileStream);
}
}
}
// 更新订单状态
bool isUpdate = false;
var orderUpdateable = orderService.AsUpdateable();
// 海运达正式环境上线后才提出:只有已接单和已完结两种状态,所以这里做了映射
if (input.status is 0 or 1 && input.status != order.Status)
{
isUpdate = true;
order.Status = input.status;
orderUpdateable.SetColumns(x => x.Status == order.Status);
// 记录订单状态变更历史
await orderHistoryService.Add(new OrderHistory()
{
Pid = order.Id,
Status = (int)order.Status,
StatusTime = DateTime.Now,
CreateBy = "系统",
Remark = "(状态接收)"
});
}
else if (input.status == 4 && order.Status is 0 or 1)
{
isUpdate = true;
order.Status = 2;
orderUpdateable.SetColumns(x => x.Status == 2);
// 记录订单状态变更历史
await orderHistoryService.Add(new OrderHistory()
{
Pid = order.Id,
Status = 2,
StatusTime = DateTime.Now,
CreateBy = "系统",
Remark = "(状态接收)"
});
}
if (isHasBill)
{
isUpdate = true;
orderUpdateable.SetColumns(x => x.IsApplyBill == false);
}
if (isUpdate)
{
await orderUpdateable.Where(x => x.Bsno == input.id).ExecuteCommandAsync();
}
// 将更新后的状态、费用、外部往来单据 推送到消息队列
// 将账单附件 推送到消息队列
if (AppSettings.app("RabbitMQ", "Enabled").ObjToBool())
{
string logTitle = $"Id[{order.Id}],提单号[{order.Mblno}],推送费用、状态、往来单据";
try
{
StatusPushDto pushDto = new()
{
OrderId = order.Id,
Mblno = order.Mblno,
MessageType = 1,
MessageDesc = "状态更新推送",
Remark = "",
Status = order.Status ?? 0,
StatusDesc = order.Status == null ? null : Enum.GetName(typeof(OrderStatusEnum), order.Status)
};
var feeList = orderFeeService.AsQueryable().Where(x => x.OrderId == order.Id).ToList();
if (feeList.Count > 0)
{
pushDto.FeeList = feeList.Select(x => new StatusPushDto.FeeDto()
{
FeeId = x.Id,
FeeName = x.Name,
FeeAmount = x.Amount
}).ToList();
}
var annexList = orderAnnexService.AsQueryable()
.LeftJoin<Annex>((o, a) => o.AnnexId == a.Id)
.Where((o, a) => o.OrderId == order.Id && a.Type == 5)
.Select((o, a) => a)
.ToList();
if (annexList.Count > 0)
{
pushDto.FeebackAnnexList = annexList.Select(x => new StatusPushDto.FeebackAnnex()
{
Id = x.Id,
BusinessTime = x.BusinessTime,
FileName = x.Name,
Remark = x.Remark
}).ToList();
}
var json = JsonConvert.SerializeObject(pushDto, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
queueService.Push(logTitle, order.CompanyId, json);
}
catch (Exception ex)
{
logger.LogError(ex, $"{logTitle}时发生未知异常");
}
if (isHasBill)
{
string logTitle2 = $"订单Id[{input.id}],提单号[{order.Mblno}],接收到账单然后推送账单";
try
{
var billIdList = await orderAnnexService.AsQueryable()
.LeftJoin<Annex>((o, a) => o.AnnexId == a.Id)
.Where((o, a) => o.OrderId == order.Id && a.Type == 3)
.Select((o, a) => a.Id)
.ToListAsync();
BillPushDto pushDto = new()
{
OrderId = order.Id,
Mblno = order.Mblno,
AnnexIdList = billIdList,
MessageType = 2,
MessageDesc = "账单附件信息推送"
};
var json = JsonConvert.SerializeObject(pushDto, Formatting.Indented, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
});
queueService.Push(logTitle2, order.CompanyId, json);
}
catch (Exception ex)
{
logger.LogError(ex, $"{logTitle2}时发生未知异常");
}
}
}
return SuccessMsg();
}
else if (pushType == 2)
{
// 保存【发票附件】
// 推送【发票附件】到消息队列
List<long> waitSendOrderIdList = new();
if (input.feedbackList != null && input.feedbackList.Count > 0)
{
var outerFileIdList = input.feedbackList.Select(x => x.id).ToList();
foreach (var feedbackItem in input.feedbackList)
{
// 如果文件不是外部推送的,不处理
if (feedbackItem.sendType != 1)
continue;
// 待绑定此发票附件的订单Id列表
List<long> waitBindOrderIdList = new();
// 如果文件信息已经存在,不处理
foreach (var applyItem in invoiceApplyList)
{
var isExists = await orderAnnexService.AsQueryable()
.LeftJoin<Annex>((o, a) => o.AnnexId == a.Id)
.Where((o, a) => a.OuterFileId == feedbackItem.id && o.OrderId == applyItem.OrderId)
.AnyAsync();
if (!isExists)
{
waitBindOrderIdList.Add(applyItem.OrderId);
}
}
if (waitBindOrderIdList.Count == 0)
{
continue;
}
waitSendOrderIdList.AddRange(waitBindOrderIdList);
// 保存附件信息
var annex = new Annex()
{
OuterFileId = feedbackItem.id,
Name = feedbackItem.fileName,
Remark = feedbackItem.remark,
BusinessTime = feedbackItem.createTime,
Type = 4,
//Path = relativePath
};
string fullPath = null;
if (!string.IsNullOrEmpty(feedbackItem.fileUrl))
{
// 检查文件保存目录
var dir = Path.Combine(App.WebHostEnvironment.WebRootPath, "files");
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
// 文件名
var newFileName = Guid.NewGuid().ToString("N") + Path.GetExtension(feedbackItem.fileName);
// 相对路径
var relativePath = Path.Combine("files", newFileName);
// 完整路径
fullPath = Path.Combine(dir, newFileName);
annex.Path = relativePath;
}
await annexService.Add(annex);
// 下载附件
if (!string.IsNullOrEmpty(feedbackItem.fileUrl))
{
var restClient = new RestClient(feedbackItem.fileUrl);
var request = new RestRequest();
using var stream = await restClient.DownloadStreamAsync(request);
using FileStream fileStream = new FileStream(fullPath, FileMode.Create);
await stream.CopyToAsync(fileStream);
}
// 为订单列表统一绑定此附件
var orderAnndexList = waitBindOrderIdList.Select(x => new OrderAnnex()
{
OrderId = x,
AnnexId = annex.Id
}).ToList();
await orderAnnexService.Add(orderAnndexList);
// 记录订单状态历史
var orderStatusModelList = waitBindOrderIdList.Select(x =>
{
var history = new OrderHistory()
{
Pid = x,
StatusTime = DateTime.Now,
Status = 7,
Remark = feedbackItem.remark,
};
if (string.IsNullOrEmpty(feedbackItem.fileUrl))
{
history.Remark += "(发票附件为空)";
}
return history;
}).ToList();
await orderHistoryService.Add(orderStatusModelList);
}
}
if (waitSendOrderIdList.Count != 0)
{
waitSendOrderIdList = waitSendOrderIdList.Distinct().ToList();
// 更新订单状态
await orderService.AsUpdateable()
.SetColumns(x => x.IsApplyInvoice == false)
.SetColumns(x => x.Status == 4) // 2024.6.18 上线后提出需求:收到海运达发票后,订单状态改为已完结
.Where(x => waitSendOrderIdList.Contains(x.Id))
.ExecuteCommandAsync();
// 将 发票附件 推送到消息队列
var orderInfoList = await orderService.AsQueryable().Where(x => waitSendOrderIdList.Contains(x.Id))
.Select(x => new
{
x.Id,
x.Mblno,
x.CompanyId,
x.MailBillNo,
x.MailFlag,
x.Status,
}).ToListAsync();
var logTitle = $"Id列表[{string.Join(',', orderInfoList.Select(x => x.Id))}],提单号列表:[{string.Join(',', orderInfoList.Select(x => x.Mblno))}],将每一票所有的发票及已完结状态推送队列";
logger.LogInformation(logTitle);
try
{
var invoiceAnnexList = await orderAnnexService.AsQueryable()
.LeftJoin<Annex>((o, a) => o.AnnexId == a.Id)
.Where((o, a) => waitSendOrderIdList.Contains(o.OrderId) && a.Type == 4)
.Select((o, a) => o)
.ToListAsync();
foreach (var item in orderInfoList)
{
var invoiceAnnexIdList = invoiceAnnexList.Where(x => x.OrderId == item.Id).Select(x => x.AnnexId).ToList();
if (invoiceAnnexIdList.Count == 0) continue;
var logItemTitle = $"Id[{item.Id}],提单号:[{item.Mblno}]附件Id列表[({string.Join(',', invoiceAnnexIdList)})]开始推送队列";
// 推送发票
BillPushDto pushDto1 = new()
{
MessageType = 3,
MessageDesc = "发票附件信息推送",
AnnexIdList = invoiceAnnexIdList,
OrderId = item.Id,
Mblno = item.Mblno,
MailFlag = item.MailFlag,
MailBillNo = item.MailBillNo,
};
var json1 = JsonConvert.SerializeObject(pushDto1, Formatting.Indented, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
});
queueService.Push(logItemTitle, item.CompanyId, json1);
// 推送状态
StatusPushDto pushDto2 = new()
{
OrderId = item.Id,
Mblno = item.Mblno,
MessageType = 1,
MessageDesc = "状态更新推送",
Remark = "",
Status = item.Status ?? 0,
StatusDesc = item.Status == null ? null : Enum.GetName(typeof(OrderStatusEnum), item.Status)
};
var feeList = orderFeeService.AsQueryable().Where(x => x.OrderId == item.Id).ToList();
if (feeList.Count > 0)
{
pushDto2.FeeList = feeList.Select(x => new StatusPushDto.FeeDto()
{
FeeId = x.Id,
FeeName = x.Name,
FeeAmount = x.Amount
}).ToList();
}
var annexList = orderAnnexService.AsQueryable()
.LeftJoin<Annex>((o, a) => o.AnnexId == a.Id)
.Where((o, a) => o.OrderId == item.Id && a.Type == 5)
.Select((o, a) => a)
.ToList();
if (annexList.Count > 0)
{
pushDto2.FeebackAnnexList = annexList.Select(x => new StatusPushDto.FeebackAnnex()
{
Id = x.Id,
BusinessTime = x.BusinessTime,
FileName = x.Name,
Remark = x.Remark
}).ToList();
}
var json2 = JsonConvert.SerializeObject(pushDto2, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
queueService.Push(logTitle, item.CompanyId, json2);
}
}
catch (Exception ex)
{
logger.LogError(ex, $"{logTitle}的过程中发生未知异常");
}
}
return SuccessMsg();
}
else
{
throw new Exception($"订单Id[{input.id}]接收到回推后,无法判断操作类型");
}
}
/// <summary>
/// 进口运踪接口推送状态
/// </summary>
[HttpPost]
[ApiUser(ApiCode = "PushBilltrace")]
public async Task<MessageModel> PushBilltrace([FromBody] List<PushBilltraceDto> input)
{
var gidList = input.Select(x => x.Gid);
var orderList = await orderService.AsQueryable().Where(x => gidList.Contains(x.BilltraceGid)).ToListAsync(x => new
{
x.Id,
x.Bsno,
x.BilltraceGid
});
foreach (var item in input)
{
var order = orderList.FirstOrDefault(x => x.BilltraceGid == item.Gid);
if (order == null)
{
string msg = $"进口运踪接口推送状态时未找到订单Gid{item.Gid}";
logger.LogInformation(msg);
continue;
}
// 记录订单状态历史(不在页面显示)
await orderHistoryService.Add(new OrderHistory()
{
Pid = order.Id,
StatusTime = DateTime.Now,
Status = 10,
IsDeleted = true,
Remark = "(状态接收)",
});
// 反馈陆海
var feedbackList = new List<HydFeedbackDto>()
{
new HydFeedbackDto()
{
orderNo = order.Bsno,
remark = "【集装箱已提取完毕】"
}
};
await App.GetService<IHYDService>().FeedBack(feedbackList);
// 记录反馈信息
var id = await annexService.Add(new Annex()
{
Remark = "【集装箱已提取完毕】",
Type = 2
});
await orderAnnexService.Add(new OrderAnnex()
{
AnnexId = id,
OrderId = order.Id
});
}
return SuccessMsg();
}
//[HttpGet]
//public string TestTime()
//{
// return DateTime.Now.ToString();
//}
//[HttpGet]
//public void TestError()
//{
// throw new Exception("测试异常");
//}
//[HttpGet]
//public async Task<MessageModel> TestSetRedis(string key, string value)
//{
// var caching = App.GetService<ICaching>();
// await caching.SetAsync(key, value, TimeSpan.FromHours(3));
// return SuccessMsg();
//}
//[HttpGet]
//public async Task<MessageModel<string>> TestGetRedis(string key)
//{
// var caching = App.GetService<ICaching>();
// var value = await caching.GetStringAsync(key);
// return Success(value);
//}
}
}