using EntrustSettle.Common;
using EntrustSettle.Common.Const;
using EntrustSettle.Common.Extensions;
using EntrustSettle.Common.Helper;
using EntrustSettle.Controllers;
using EntrustSettle.IServices;
using EntrustSettle.IServices.Base;
using EntrustSettle.Model;
using EntrustSettle.Model.Dtos;
using EntrustSettle.Model.Models;
using EntrustSettle.Model.Models.DJY;
using EntrustSettle.Model.Validator;
using EntrustSettle.Repository.UnitOfWorks;
using FluentValidation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace EntrustSettle.Api.Controllers
{
///
/// 订单
///
public class OrderController : BaseApiController
{
private readonly IOrderService orderService;
private readonly IOrderAnnexService orderAnnexService;
private readonly IAnnexService annexService;
private readonly ILogger logger;
private readonly IUnitOfWorkManage unitOfWorkManage;
private readonly IOrderHistoryService orderHistoryService;
private readonly IHYDService hydService;
private readonly IOrderFeeService orderFeeService;
private readonly IQueueService queueService;
public OrderController(IOrderService orderService,
IOrderAnnexService orderFileService,
ILogger logger,
IUnitOfWorkManage unitOfWorkManage,
IOrderHistoryService orderHistoryService,
IHYDService hydService,
IAnnexService annexService,
IOrderFeeService orderFeeService,
IQueueService queueService)
{
this.orderService = orderService;
this.orderAnnexService = orderFileService;
this.logger = logger;
this.unitOfWorkManage = unitOfWorkManage;
this.orderHistoryService = orderHistoryService;
this.hydService = hydService;
this.annexService = annexService;
this.orderFeeService = orderFeeService;
this.queueService = queueService;
}
///
/// 获取订单列表
///
[HttpGet]
public async Task>> List([FromQuery] OrderListInputDto input)
{
if (input.QueryType == 2)
{
if (!App.User.CompanyName.Contains("东胜伟业") && !App.User.CompanyName.Contains("大简云"))
{
throw new Exception("访问权限与实际拥有菜单权限不符");
}
}
PageModel result = await orderService.AsQueryable()
.WhereIF(input.QueryType != 2, x => x.CompanyId == App.User.CompanyId)
.WhereIF(!string.IsNullOrWhiteSpace(input.Mblno), x => x.Mblno.Contains(input.Mblno))
.WhereIF(!string.IsNullOrWhiteSpace(input.CompanyName), x => x.CompanyName.Contains(input.CompanyName))
.WhereIF(!string.IsNullOrWhiteSpace(input.Remark), x => x.Remark.Contains(input.Remark))
.WhereIF(input.ServiceType != null, x => x.ServiceType == input.ServiceType)
.WhereIF(input.Status != null, x => x.Status == (int)input.Status)
.WhereIF(input.CreateTimeStart != null, x => x.CreateTime >= input.CreateTimeStart)
.WhereIF(input.CreateTimeEnd != null, x => x.CreateTime <= input.CreateTimeEnd)
.Select()
.OrderBy("id desc")
.ToPageListAsyncExtension(input.pageIndex, input.pageSize);
var orderIdList = result.data.Select(x => x.Id).ToList();
if (orderIdList.Count > 0)
{
var orderWithTypeList = await orderAnnexService.AsQueryable()
.LeftJoin((o, a) => o.AnnexId == a.Id)
.Where((o, a) => orderIdList.Contains(o.OrderId) && (a.Type == 3 || a.Type == 4))
.Select((o, a) => new { o.OrderId, a.Type })
.Distinct()
.ToListAsync();
var group = orderWithTypeList.GroupBy(x => x.OrderId).ToList();
foreach (var item in group)
{
var order = result.data.FirstOrDefault(x => x.Id == item.Key);
if (item.Any(x => x.Type == 3))
{
order.IsHasBillAnnex = true;
}
if (item.Any(x => x.Type == 4))
{
order.IsHasInvoiceAnnex = true;
}
}
result.data.ForEach(x =>
{
if (!string.IsNullOrWhiteSpace(x.MailBillNo))
{
x.IsHasInvoiceAnnex = true;
}
});
}
return SuccessPage(result);
}
[HttpGet]
[AllowAnonymous]
//[ApiUser(ApiCode = "OrderSubmit")]
public async Task Test()
{
CustFee custFeeModel = new CustFee()
{
SENDTYPE = 0,
SENDTIME = DateTime.Now,
CtnrInfo = string.Empty,
CtnrCount = 0,
GID = Guid.NewGuid().ToString(),
};
string msg = "123";
logger.LogInformation($"{msg},扣费记录内容:{{custFeeModel}}", custFeeModel.ToJson());
var a = App.User.Name;
var b = App.User.ID;
await Task.CompletedTask;
var c = new { a, b };
return Success(c);
}
///
/// 下单
///
[HttpPost]
//[UseTran]
public async Task>> Submit(OrderSubmitDto inputDto)
{
var validator = new OrderSubmitDtoValidator();
validator.ValidateAndThrow(inputDto);
// 订单信息保存
inputDto.MblnoList = inputDto.MblnoList.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).ToArray();
StringHelper.TrimStringProperties(inputDto);
// 查询税号
var custBalanceService = App.GetService>();
var taxCode = await custBalanceService.Db.Queryable().Where(x => x.CompId == inputDto.CompanyId).Select(x => x.TaxCode).FirstAsync();
var orderList = new List();
foreach (var item in inputDto.MblnoList)
{
var order = new Order
{
Mblno = item,
CompanyId = inputDto.CompanyId,
CompanyName = inputDto.CompanyName,
TaxCode = taxCode,
ServiceType = inputDto.ServiceType,
ProjectType = inputDto.ProjectType,
IsSend = false,
Status = null,
ContactId = inputDto.ContactId,
ContactName = inputDto.ContactName,
ContactTel = inputDto.ContactTel,
Remark = inputDto.Remark
};
orderList.Add(order);
}
unitOfWorkManage.BeginTran();
foreach (var item in orderList)
{
var id = await orderService.AsInsertable(item).ExecuteReturnSnowflakeIdAsync();
item.Id = id;
}
var orderIdList = orderList.Select(x => x.Id).ToList();
// 附件关联信息保存
if (inputDto.AnnexIdList?.Count > 0)
{
var orderFileModelList = new List();
foreach (var orderId in orderIdList)
{
foreach (var annexId in inputDto.AnnexIdList)
{
orderFileModelList.Add(new OrderAnnex()
{
OrderId = orderId,
AnnexId = annexId
});
}
};
await orderAnnexService.Add(orderFileModelList);
}
// 状态历史保存
//var historyModelList = new List();
//foreach (var item in orderIdList)
//{
// historyModelList.Add(new OrderHistory
// {
// Pid = item,
// Status = (int)OrderStatusEnum.已下单,
// StatusTime = DateTime.Now
// });
//}
//await orderHistoryService.Add(historyModelList);
unitOfWorkManage.CommitTran();
// 查询所有待处理订单列表
var pendingOrderList = await orderService.Query(x => x.IsSend == false && orderIdList.Contains(x.Id));
var result = orderList.Select(x => new OrderSubmitResultDto() { OrderId = x.Id, Mblno = x.Mblno }).ToList();
if (pendingOrderList.Count == 0)
{
return Success(result);
}
string domainUrl = AppSettings.app(["Startup", "Domain"]);
foreach (Order orderItem in pendingOrderList)
{
try
{
List annexList = await orderAnnexService.AsQueryable()
.InnerJoin((o, a) => o.AnnexId == a.Id)
.Where(o => o.OrderId == orderItem.Id)
.Select((o, a) => a)
.ToListAsync();
// 构建提交数据
string fileNameStr = string.Join(",", annexList.Select(x => x.Name));
string fileUrl = string.Join(",", annexList.Select(x => $"{domainUrl}/api/Annex/Download?key={x.Key}"));
string remark = "备注:客户所选服务:";
var projects = orderItem.ProjectType.Split(",");
foreach (var project in projects)
{
remark += project switch
{
"1" => "港杂费代结,",
"2" => "堆存费代结,",
_ => "(未维护),",
};
}
remark = remark.Remove(remark.Length - 1, 1);
remark += Environment.NewLine;
remark += "客户备注:" + orderItem.Remark;
HydSubmitDto submitDto = new HydSubmitDto()
{
billNoList = new List() { orderItem.Mblno },
customerName = orderItem.CompanyName,
tel = orderItem.ContactTel,
fileName = fileNameStr,
fileUrl = fileUrl,
remark = remark,
registerFlag = 1,
registerUser = new HydSubmitDto.RegisterUser()
{
phone = orderItem.ContactTel?.Trim(),
userName = orderItem.ContactName?.Trim(),
enterpriseName = orderItem.CompanyName?.Trim(),
sex = 1,
dutyNo = orderItem.TaxCode?.Trim() ?? ""
}
};
// 开始提交
long bsno = await hydService.Submit(submitDto);
// 更新订单状态
orderItem.Status = (int)OrderStatusEnum.已下单;
orderItem.Bsno = bsno;
orderItem.IsSend = true;
await orderService.Update(orderItem, x => new { x.Status, x.Bsno, x.IsSend });
// 记录状态历史
await orderHistoryService.Add(new OrderHistory()
{
Pid = orderItem.Id,
StatusTime = DateTime.Now,
Status = (int)OrderStatusEnum.已下单,
Remark = orderItem.Remark
});
}
catch (Exception ex)
{
logger.LogError(ex, $"提单号{orderItem.Mblno}下单时发生未知异常,继续处理下一票");
continue;
}
}
return Success(result);
}
///
/// 获取订单附件信息列表
///
/// 订单Id
/// 附件类型
[HttpGet]
public async Task>> GetAnnexInfoList(long id, FileTypeEnum fileType)
{
var result = await orderAnnexService.Db.Queryable((o, a) => o.AnnexId == a.Id)
.Where((o, a) => o.OrderId == id && a.Type == (int)fileType)
.Select((o, a) => new AnnexDto()
{
Name = a.Name,
Type = a.Type,
Id = a.Id
})
.ToListAsync();
return Success(result);
}
///
/// 订单状态变更
///
[HttpPost]
public async Task ChangeStatus(ChangeStatusDto changeStatusDto)
{
new ChangeStatusDtoValidator().ValidateAndThrow(changeStatusDto);
var order = await orderService.QueryById(changeStatusDto.Id);
if (order == null)
{
throw new Exception("未找到该订单");
}
order.Status = (int)changeStatusDto.Status;
decimal sumAmount = 0;
bool isBeginTran = false;
try
{
// 执行扣费
if (changeStatusDto.FeeList != null && changeStatusDto.FeeList.Count > 0)
{
string logMsg = $"订单Id:{changeStatusDto.Id},提单号:{order.Mblno}";
try
{
sumAmount = changeStatusDto.FeeList.Select(x => x.Amount).Sum();
logger.LogInformation($"{logMsg}, 手动更新状态时,需要扣费,总金额:{sumAmount}");
var custBalanceService = App.GetService>();
var balance = await custBalanceService.AsQueryable().FirstAsync(x => x.COMNAME == order.CompanyName);
if (balance == null)
{
logger.LogInformation($"{logMsg},扣费失败:没有账户钱包!");
throw new Exception("扣费失败:没有账户钱包!");
}
if (balance.Balance < sumAmount)
{
logger.LogInformation($"{logMsg},扣费失败:账户余额不足!{sumAmount}");
throw new Exception($"账户余额不足!{sumAmount} {order.CompanyName}");
}
logger.LogInformation($"{logMsg},开始写入消费记录");
var custFeeService = App.GetService>();
var beizhu = string.Join(',', changeStatusDto.FeeList.Select(x => x.Name + ":" + x.Amount));
CustFee custFeeModel = new CustFee()
{
BEIZHU = beizhu,
BSNO = order.Id.ToString(),
COMNAME = order.CompanyName,
MBLNO = order.Mblno,
BSTYPE = CommonConst.WEITUOJIESUAN,
CREATETIME = DateTime.Now,
LURURENID = order.ContactId,
LURUREN = order.ContactName,
COMID = order.CompanyId,
SENDUSERID = order.ContactId,
SENDUSER = order.ContactName,
SENDCOM = order.CompanyName,
SENDTYPE = 0,
SENDTIME = DateTime.Now,
CtnrInfo = string.Empty,
CtnrCount = 0,
GID = Guid.NewGuid().ToString(),
PRICE = sumAmount
};
logger.LogInformation($"{logMsg},扣费记录内容:{{custFeeModel}}", custFeeModel.ToJson());
unitOfWorkManage.BeginTran();
isBeginTran = true;
// 添加扣费记录
var num = await custFeeService.AsInsertable(custFeeModel).ExecuteCommandAsync();
if (num <= 0)
{
unitOfWorkManage.RollbackTran();
throw new Exception($"{logMsg},添加扣费记录失败!");
}
else
{
logger.LogInformation($"{logMsg},添加扣费记录成功");
}
// 更新余额
num = await custBalanceService.AsUpdateable()
.SetColumns(x => x.Balance == x.Balance - sumAmount)
.Where(x => x.COMNAME == order.CompanyName)
.ExecuteCommandAsync();
if (num <= 0)
{
unitOfWorkManage.RollbackTran();
throw new Exception($"{logMsg},更新余额失败!");
}
else
{
logger.LogInformation($"{logMsg},更新余额成功");
}
}
catch (Exception ex)
{
logger.LogError(ex, $"{logMsg},执行扣费时发生未知异常");
throw;
}
}
if (!isBeginTran)
{
unitOfWorkManage.BeginTran();
}
// 添加新的费用信息
if (changeStatusDto.FeeList != null && changeStatusDto.FeeList.Count > 0)
{
// 清除原有费用信息
//await orderFeeService.Delete(x => x.OrderId == changeStatusDto.Id);
//order.Amount = order.Amount == null ? null : 0;
var orderFeeModelList = changeStatusDto.FeeList.Select(x => new OrderFee()
{
Name = x.Name,
Amount = x.Amount,
OrderId = changeStatusDto.Id
}).ToList();
await orderFeeService.Add(orderFeeModelList);
// 查出来现有的费用记录,更新
var sumAllAmount = await orderFeeService.AsQueryable()
.Where(x => x.OrderId == changeStatusDto.Id)
.SumAsync(x => x.Amount);
order.Amount = sumAllAmount;
}
await orderService.Update(order, x => new { x.Status, x.Amount });
var orderHistory = new OrderHistory
{
Pid = order.Id,
Status = (int)changeStatusDto.Status,
Remark = changeStatusDto.Remark,
Amount = sumAmount,
StatusTime = DateTime.Now,
};
await orderHistoryService.Add(orderHistory);
unitOfWorkManage.CommitTran();
}
catch (Exception)
{
unitOfWorkManage.RollbackTran();
throw;
}
// 将更新后的状态及费用推送到消息队列
if (AppSettings.app("RabbitMQ", "Enabled").ObjToBool())
{
_ = Task.Run(() =>
{
string msg = $"Id:[{order.Id}],提单号:[{order.Mblno}],手动更新状态后推送队列";
try
{
StatusPushDto pushDto = new()
{
OrderId = order.Id,
Mblno = order.Mblno,
MessageType = 1,
MessageDesc = "状态更新推送",
Remark = changeStatusDto.Remark,
Status = (int)changeStatusDto.Status,
StatusDesc = changeStatusDto.Status.ToString()
};
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((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();
}
//if (changeStatusDto.FeeList != null && changeStatusDto.FeeList.Count > 0)
//{
// pushDto.FeeList = changeStatusDto.FeeList.Select(x => new StatusPushDto.FeeDto()
// {
// //Id = x.
// FeeName = x.Name,
// FeeAmount = x.Amount
// }).ToList();
//}
var json = JsonConvert.SerializeObject(pushDto, Formatting.Indented, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
});
queueService.Push(msg, order.CompanyId, json);
}
catch (Exception ex)
{
logger.LogError(ex, $"{msg},失败");
}
});
}
return SuccessMsg();
}
///
/// 为订单追加附件或信息
///
///
[HttpPost]
public async Task BindAnnexOrInfo(BindAnnexOrInfoDto bindDto)
{
var order = await orderService.QueryById(bindDto.OrderId);
if (order == null)
{
throw new Exception("未找到该订单");
}
// 反馈附件需要请求海运达接口,所以需要先判断是否反馈成功,成功后再执行后续操作
if (bindDto.OperType == FileTypeEnum.反馈附件)
{
if (order.Status == null)
{
throw new Exception("请等待具有已下单状态后再进行反馈");
}
if (order.Status == (int)OrderStatusEnum.已完结)
{
throw new Exception("该订单已完结,无法进行反馈");
}
List hydFeedbackDtoList = new List();
if (bindDto.AnnexIdList != null && bindDto.AnnexIdList.Count > 0)
{
string domainUrl = AppSettings.app(["Startup", "Domain"]);
var annexList = await annexService.Query(x => bindDto.AnnexIdList.Contains(x.Id));
foreach (Annex item in annexList)
{
string fileUrl = string.Join(",", annexList.Select(x => $"{domainUrl}/api/Annex/Download?key={x.Key}"));
hydFeedbackDtoList.Add(new HydFeedbackDto()
{
fileName = item.Name,
fileUrl = fileUrl,
orderNo = (long)order.Bsno,
remark = bindDto.Remark
});
}
}
else
{
hydFeedbackDtoList.Add(new HydFeedbackDto()
{
orderNo = (long)order.Bsno,
remark = bindDto.Remark
});
}
bool isSuccess = await hydService.FeedBack(hydFeedbackDtoList);
if (!isSuccess)
{
logger.LogError($"提单号:{order.Mblno}向海运达反馈时发生异常");
throw new Exception("反馈失败,请稍后重试");
}
else
{
logger.LogInformation($"提单号:{order.Mblno}向海运达反馈成功");
}
}
unitOfWorkManage.BeginTran();
// 如果操作类型为账单或发票,则先删除原有的绑定信息
if (bindDto.OperType == FileTypeEnum.反馈附件)
{
if (bindDto.AnnexIdList != null && bindDto.AnnexIdList.Count > 0)
{
// 添加要新增绑定的附件信息
var orderAnnexModelList = bindDto.AnnexIdList.Select(x => new OrderAnnex()
{
AnnexId = x,
OrderId = bindDto.OrderId
}).ToList();
await orderAnnexService.Add(orderAnnexModelList);
}
}
else if (bindDto.OperType == FileTypeEnum.账单 || bindDto.OperType == FileTypeEnum.发票)
{
var oldAnnexIdList = await orderAnnexService.AsQueryable()
.InnerJoin((o, a) => o.AnnexId == a.Id)
.Where((o, a) => o.OrderId == bindDto.OrderId && a.Type == (int)bindDto.OperType)
.Select((o, a) => a.Id)
.ToListAsync();
// 处理要删除的
var waitDelAnndexIdList = oldAnnexIdList.Except(bindDto.AnnexIdList).ToList();
if (waitDelAnndexIdList.Any())
{
await orderAnnexService.Delete(x => x.OrderId == bindDto.OrderId && waitDelAnndexIdList.Contains(x.AnnexId));
await annexService.Delete(x => waitDelAnndexIdList.Contains(x.Id));
}
// 处理要新增的
var waitAddAnnexIdList = bindDto.AnnexIdList.Except(oldAnnexIdList);
if (waitAddAnnexIdList.Any())
{
var orderAnnexModelList = waitAddAnnexIdList.Select(x => new OrderAnnex()
{
AnnexId = x,
OrderId = bindDto.OrderId
}).ToList();
await orderAnnexService.Add(orderAnnexModelList);
}
}
orderService.Db.Tracking(order);
if (bindDto.OperType == FileTypeEnum.反馈附件)
{
if (!string.IsNullOrWhiteSpace(bindDto.Remark))
{
string remark = string.IsNullOrEmpty(order.Remark) ?
bindDto.Remark :
order.Remark += (Environment.NewLine + bindDto.Remark);
order.Remark = remark;
}
}
else if (bindDto.OperType == FileTypeEnum.发票)
{
if (bindDto.MailFlag != null)
{
order.MailFlag = bindDto.MailFlag;
}
order.MailBillNo = bindDto.MailBillNo;
}
await orderService.Db.Updateable(order).ExecuteCommandAsync();
unitOfWorkManage.CommitTran();
// 如果操作类型为发票或账单,将反馈推送到消息队列
if ((bindDto.OperType is FileTypeEnum.发票 or FileTypeEnum.账单)
&& AppSettings.app("RabbitMQ", "Enabled").ObjToBool())
{
_ = Task.Run(() =>
{
string msg = $"Id:[{order.Id}],提单号:[{order.Mblno}],更新账单或发票后推送队列";
try
{
BillPushDto pushDto = new()
{
OrderId = order.Id,
Mblno = order.Mblno,
AnnexIdList = bindDto.AnnexIdList,
};
if (bindDto.OperType == FileTypeEnum.账单)
{
pushDto.MessageType = 2;
pushDto.MessageDesc = "账单附件信息推送";
}
else if (bindDto.OperType == FileTypeEnum.发票)
{
pushDto.MessageType = 3;
pushDto.MessageDesc = "发票附件信息推送";
pushDto.MailFlag = bindDto.MailFlag;
pushDto.MailBillNo = bindDto.MailBillNo;
}
var json = JsonConvert.SerializeObject(pushDto, Formatting.Indented, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
});
queueService.Push(msg, order.CompanyId, json);
}
catch (Exception ex)
{
logger.LogError(ex, $"{msg},失败");
}
});
}
return SuccessMsg();
}
///
/// 获取订单详情
///
[HttpGet]
public async Task> Detail(long id)
{
var result = await orderService.AsQueryable()
.Where(x => x.Id == id)
.Select()
.FirstAsync();
if (result == null)
{
throw new Exception("为找到该订单,请刷新后重试");
}
var annexList = await orderAnnexService.Db.Queryable((o, a) => o.AnnexId == a.Id)
.Where((o, a) => o.OrderId == id)
.Where((o, a) => a.Type == (int)FileTypeEnum.原始附件 || a.Type == (int)FileTypeEnum.反馈附件 || a.Type == (int)FileTypeEnum.外部往来单据)
.Select((o, a) => new AnnexDto()
{
Id = a.Id,
Name = a.Name,
Type = a.Type,
Remark = a.Remark,
CreateTime = a.CreateTime,
CreateBy = a.CreateBy
})
.ToListAsync();
result.AnnexList = annexList;
return Success(result);
}
///
/// 获取订单费用列表
///
[HttpGet]
public async Task>> FeeList(long id)
{
var result = await orderFeeService.AsQueryable()
.Where(x => x.OrderId == id)
.Select()
.ToListAsync();
return Success(result);
}
}
}