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.

644 lines
29 KiB
C#

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;
6 months ago
public OpenController(IOrderService orderService,
ILogger<OpenController> logger,
IOrderHistoryService orderHistoryService,
IQueueService queueService,
IOrderFeeService orderFeeService,
IAnnexService annexService,
6 months ago
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;
6 months ago
this.invoiceApplyService = invoiceApplyService;
}
/// <summary>
/// 下单
/// </summary>
[HttpPost]
[ApiUser(ApiCode = "EntrustSettle")]
8 months ago
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;
}
6 months ago
/// <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)
{
6 months ago
// 推送类型 1:订单状态、费用、账单、外部往来单据 2:发票
int pushType = 0;
List<InvoiceApply> invoiceApplyList = null;
var orderList = await orderService.Query(x => x.Bsno == input.id);
6 months ago
if (orderList != null && orderList.Count > 0)
{
6 months ago
pushType = 1;
logger.LogInformation($"订单Id[{input.id}]接收到回推后,判断操作类型为[反馈订单状态/费用/外部往来单据/账单]");
}
6 months ago
else
{
6 months ago
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);
}
}
6 months ago
if (pushType == 1)
{
6 months ago
var order = orderList[0];
6 months ago
bool isHasBill = false;
6 months ago
// 保存【往来单据附件】或【账单附件】
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)
{
6 months ago
// 如果文件不是外部推送的,不处理
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
};
// 海运达规定:海运达返回的账单会以“[反馈账单]”为开头同时billApplyFlag = 1
if (item.billApplyFlag == 1 && item.remark?.StartsWith("[反馈账单]") == true)
{
6 months ago
annex.Type = 3;
isHasBill = true;
}
else
{
annex.Type = 5;
}
6 months ago
string fullPath = null;
if (!string.IsNullOrEmpty(item.fileUrl))
{
// 检查文件保存目录
var dir = Path.Combine(App.WebHostEnvironment.WebRootPath, "files");
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
6 months ago
// 文件名
var newFileName = Guid.NewGuid().ToString("N") + Path.GetExtension(item.fileName);
6 months ago
// 相对路径
var relativePath = Path.Combine("files", newFileName);
6 months ago
// 完整路径
fullPath = Path.Combine(dir, newFileName);
6 months ago
annex.Path = relativePath;
}
await annexService.Add(annex);
6 months ago
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,
};
await orderHistoryService.Add(orderStatusModelList);
6 months ago
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);
}
}
}
6 months ago
// 更新订单状态
bool isUpdate = false;
var orderUpdateable = orderService.AsUpdateable();
// 海运达正式环境上线后才提出:只有已接单和已完结两种状态,所以这里做了映射
if (input.status is 0 or 1 && input.status != order.Status)
6 months ago
{
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 = "(状态接收)"
});
}
6 months ago
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 = "(状态接收)"
});
6 months ago
}
6 months ago
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())
{
6 months ago
string logTitle = $"Id[{order.Id}],提单号[{order.Mblno}],推送费用、状态、往来单据";
try
{
StatusPushDto pushDto = new()
{
OrderId = order.Id,
Mblno = order.Mblno,
MessageType = 1,
MessageDesc = "状态更新推送",
Remark = "",
6 months ago
Status = order.Status ?? 0,
StatusDesc = order.Status switch
{
0 => "已下单",
1 => "已接单",
2 => "待缴费",
3 => "已缴费",
4 => "已完结",
_ => "未知状态",
}
};
7 months ago
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();
}
7 months ago
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)
7 months ago
.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();
}
7 months ago
var json = JsonConvert.SerializeObject(pushDto, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
6 months ago
queueService.Push(logTitle, order.CompanyId, json);
}
catch (Exception ex)
{
6 months ago
logger.LogError(ex, $"{logTitle}时发生未知异常");
}
6 months ago
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)
{
6 months ago
// 保存【发票附件】
// 推送【发票附件】到消息队列
6 months ago
List<long> waitSendOrderIdList = new();
if (input.feedbackList != null && input.feedbackList.Count > 0)
{
6 months ago
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 => new OrderHistory()
{
Pid = x,
StatusTime = DateTime.Now,
Status = 7,
Remark = feedbackItem.remark,
}).ToList();
await orderHistoryService.Add(orderStatusModelList);
6 months ago
}
}
if (waitSendOrderIdList.Count != 0)
{
waitSendOrderIdList = waitSendOrderIdList.Distinct().ToList();
// 更新订单状态
await orderService.AsUpdateable()
.SetColumns(x => x.IsApplyInvoice == false)
.SetColumns(x => x.Status == 4) // 2024.6.18 上线后提出需求:收到海运达发票后,订单状态改为已完结
6 months ago
.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,
6 months ago
}).ToListAsync();
var logTitle = $"Id列表[{string.Join(',', orderInfoList.Select(x => x.Id))}],提单号列表:[{string.Join(',', orderInfoList.Select(x => x.Mblno))}],将每一票所有的发票及已完结状态推送队列";
6 months ago
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()
6 months ago
{
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()
6 months ago
{
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 switch
{
0 => "已下单",
1 => "已接单",
2 => "待缴费",
3 => "已缴费",
4 => "已完结",
_ => "未知状态",
}
};
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);
6 months ago
}
}
catch (Exception ex)
{
logger.LogError(ex, $"{logTitle}的过程中发生未知异常");
}
}
return SuccessMsg();
}
else
{
6 months ago
throw new Exception($"订单Id[{input.id}]接收到回推后,无法判断操作类型");
}
}
7 months ago
6 months ago
//[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);
//}
}
}