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.

534 lines
26 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 System.Text;
using DS.Module.Core;
using DS.Module.Core.Enums;
using DS.Module.Core.Extensions;
using DS.WMS.Core.Application.Dtos;
using DS.WMS.Core.Application.Entity;
using DS.WMS.Core.Application.Interface;
using DS.WMS.Core.Fee.Dtos;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Info.Entity;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
using SqlSugar;
namespace DS.WMS.Core.Application.Method
{
/// <summary>
/// 付费申请实现
/// </summary>
public class PaymentApplicationService : ApplicationService<PaymentApplication>, IPaymentApplicationService
{
/// <summary>
/// 初始化
/// </summary>
/// <param name="serviceProvider"></param>
public PaymentApplicationService(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
/// <summary>
/// 获取分页列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<PaymentApplicationDto>>> GetListAsync(PageRequest request)
{
var query = CreateListQuery();
if (!request.QueryCondition.IsNullOrEmpty())
{
var whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition);
query = query.Where(whereList);
}
var result = await query.GroupBy(x => x.Id).ToQueryPageAsync(request.PageCondition);
if (result.Data.Count > 0)
{
//关联用户名称
var userIds = result.Data.Select(x => x.CreateBy).Distinct();
var users = await Db.Queryable<SysUser>().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync();
var orgIds = result.Data.Select(x => x.SaleDeptId).Distinct().ToList();
var orgs = await Db.Queryable<SysOrg>().Where(x => orgIds.Contains(x.Id)).Select(x => new { x.Id, x.OrgName }).ToListAsync();
foreach (var item in result.Data)
{
item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName;
item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
}
}
return result;
}
internal ISugarQueryable<PaymentApplicationDto> CreateListQuery()
{
var query1 = TenantDb.Queryable<PaymentApplication>()
.LeftJoin<ApplicationDetail>((a, d) => a.Id == d.ApplicationId)
.LeftJoin<SeaExport>((a, d, s) => d.BusinessId == s.Id)
.Select((a, d, s) => new PaymentApplicationDto
{
Id = a.Id,
ApplicationNO = a.ApplicationNO,
CustomerId = a.CustomerId,
CustomerName = a.CustomerName,
AmountOther = a.AmountOther,
AmountRMB = a.AmountRMB,
AmountUSD = a.AmountUSD,
SaleDeptId = a.SaleDeptId,
SettlementTypeId = a.SettlementTypeId,
SettlementTypeName = a.SettlementType.StlName,
CreateBy = a.CreateBy,
CreateTime = a.CreateTime,
Currency = a.Currency,
ExchangeRate = a.ExchangeRate,
Reason = a.Reason,
Status = a.Status,
AuditerId = a.AuditerId,
AuditerName = a.AuditerName,
AuditTime = a.AuditTime,
IsInvoiceReceived = a.IsInvoiceReceived,
ClientName = s.CustomerName,
IsPrinted = a.IsPrinted,
PrintTimes = a.PrintTimes,
InvoiceAmount = a.InvoiceAmount,
InvoiceDate = a.InvoiceDate,
InvoiceNO = a.InvoiceNO,
PaymentDate = a.PaymentDate,
Note = a.Note,
BillNO = s.CustomerNo, //业务编号=委托编号
CustomerBankId = a.CustomerBankId,
CustomerBank = a.CustomerBank.BankName,
CustomerAccount = a.CustomerBank.Account,
//汇总项
RestAmountRMB = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.Id == d.RecordId && f.FeeStatus == FeeStatus.AuditPassed
&& f.Currency == RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount)),
RestAmountUSD = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.Id == d.RecordId && f.FeeStatus == FeeStatus.AuditPassed
&& f.Currency == USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount)),
RestAmountOther = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.Id == d.RecordId && f.FeeStatus == FeeStatus.AuditPassed
&& f.Currency != RMB_CODE && f.Currency != USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount))
});
return TenantDb.UnionAll(new List<ISugarQueryable<PaymentApplicationDto>> { query1 });
}
/// <summary>
/// 获取待付费的业务列表(编辑用)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<BizPaymentApplication>>> GetBizListAsync(PageRequest request)
{
var queryList = CreateBizQuery();
if (!request.QueryCondition.IsNullOrEmpty())
{
var whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition);
queryList = queryList.Where(whereList);
}
var result = await queryList.ToQueryPageAsync(request.PageCondition);
if (result.Data.Count > 0)
{
//关联用户名称
var userIds = result.Data.Where(x => x.OperatorId.HasValue).Select(x => x.OperatorId.Value)
.Union(result.Data.Select(x => x.CreateBy))
.Distinct();
var users = await Db.Queryable<SysUser>().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync();
//关联机构名称
var orgIds = result.Data.Select(x => x.SaleDeptId).Distinct();
var orgs = await Db.Queryable<SysOrg>().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.OrgName }).ToListAsync();
foreach (var item in result.Data)
{
item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName;
if (item.OperatorId.HasValue)
item.Operator = users.Find(x => x.Id == item.OperatorId.Value)?.UserName;
item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
}
}
return result;
}
//创建各项业务数据的查询并集
internal ISugarQueryable<BizPaymentApplication> CreateBizQuery()
{
//海运出口
var query1 = TenantDb.Queryable<SeaExport>()
.InnerJoin<FeeRecord>((s, f) => s.Id == f.BusinessId && f.BusinessType == BusinessType.OceanShippingExport)
.Where((s, f) => f.FeeStatus == FeeStatus.AuditPassed)
.GroupBy((s, f) => s.Id)
.Select((s, f) => new BizPaymentApplication
{
Id = s.Id,
AccountDate = s.AccountDate,
BusinessType = BusinessType.OceanShippingExport,
CntrTotal = s.CntrTotal,
CreateBy = s.CreateBy,
CustomerId = s.CustomerId,
CustomerName = s.CustomerName,//费用对象
CustomerNo = s.CustomerNo,
DischargePort = s.DischargePort,
ETD = s.ETD,
HBLNO = s.HBLNO,
LoadPort = s.LoadPort,
MBLNO = s.MBLNO,
OperatorId = s.OperatorId,
SaleDeptId = s.SaleDeptId,
SaleId = s.SaleId,
SaleName = s.Sale,//揽货人
Vessel = s.Vessel,//船名
Voyage = s.Voyno,//航次
BookingNO = s.BookingNo,
StlName = s.StlName,
FeeType = f.FeeType,
FeeId = f.FeeId,
Currency = f.Currency,
IsAdvancedPay = f.IsAdvancedPay,
IsInvoice = f.IsInvoice,
//统计项
UnpaidRMB = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
f.FeeType == FeeType.Payable && f.Currency == RMB_CODE).Select(f => SqlFunc.AggregateSumNoNull(f.Amount)),
UnpaidUSD = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
f.FeeType == FeeType.Payable && f.Currency == USD_CODE).Select(f => SqlFunc.AggregateSumNoNull(f.Amount)),
UnpaidOther = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
f.FeeType == FeeType.Payable && f.Currency != USD_CODE && f.Currency != RMB_CODE).Select(f => SqlFunc.AggregateSumNoNull(f.Amount)),
UnreceivedRMB = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
f.FeeType == FeeType.Receivable && f.Currency == RMB_CODE).Select(f => SqlFunc.AggregateSumNoNull(f.Amount)),
UnreceivedUSD = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
f.FeeType == FeeType.Receivable && f.Currency == USD_CODE).Select(f => SqlFunc.AggregateSumNoNull(f.Amount)),
UnreceivedOther = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
f.FeeType == FeeType.Receivable && f.Currency != USD_CODE && f.Currency != RMB_CODE).Select(f => SqlFunc.AggregateSumNoNull(f.Amount)),
//UnpaidRMBInv = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
// f.FeeType == FeeType.Payable && f.Currency == "CNY").Select(f => SqlFunc.AggregateSumNoNull(f.InvoiceAmount.Value)),
//UnpaidUSDInv = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed &&
// f.FeeType == FeeType.Payable && f.Currency == "USD").Select(f => SqlFunc.AggregateSumNoNull(f.InvoiceAmount.Value))
});
//海运进口
return TenantDb.UnionAll(new List<ISugarQueryable<BizPaymentApplication>> { query1 });
}
/// <summary>
/// 根据业务编号及类型获取关联费用记录
/// </summary>
/// <param name="items">业务ID与业务类型</param>
/// <returns></returns>
public async Task<DataResult<PaymentApplicaitonBiz>> GetFeesAsync(params BizItem[] items)
{
var bizIds = items.Select(x => x.Id).ToList();
var types = items.Select(x => x.BusinessType).ToList();
var list = await TenantDb.Queryable<FeeRecord>()
.Where(f => bizIds.Contains(f.BusinessId) && types.Contains(f.BusinessType) && f.FeeStatus == FeeStatus.AuditPassed)
.Select(f => new FeePaymentDto
{
RecordId = f.Id,
BusinessId = f.BusinessId,
BusinessType = f.BusinessType,
CustomerName = f.CustomerName,
FeeId = f.FeeId,
FeeName = f.FeeName,
FeeType = f.FeeType,
Amount = f.Amount,
Currency = f.Currency,
OriginalCurrency = f.Currency,
OriginalRate = f.ExchangeRate,
RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount,
InvoiceAmount = f.InvoiceAmount,
Remark = f.Remark,
CreateBy = f.CreateBy,
TaxRate = f.TaxRate
}).ToListAsync();
//移除未接金额为0的项
list.RemoveAll(f => f.RestAmount == 0);
if (list.Count > 0)
{
//关联用户名称
var userIds = list.Select(x => x.CreateBy).Distinct();
var users = await Db.Queryable<SysUser>().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync();
foreach (var item in list)
{
item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName;
item.ApplyAmount = item.RestAmount; //申请金额默认=剩余金额
}
}
return DataResult<PaymentApplicaitonBiz>.Success(new PaymentApplicaitonBiz(list));
}
/// <summary>
/// 获取申请单详情
/// </summary>
/// <param name="id">申请单ID</param>
/// <returns></returns>
public async Task<DataResult<PaymentApplicationDto>> GetAsync(long id)
{
var dto = await TenantDb.Queryable<PaymentApplication>().LeftJoin<InfoClientBank>((a, b) => a.CustomerBankId == b.Id)
.Where((a, b) => a.Id == id).Select((a, b) => new PaymentApplicationDto
{
Id = a.Id,
ApplicationNO = a.ApplicationNO,
Currency = a.Currency,
CustomerId = a.CustomerId,
CustomerName = a.CustomerName,
CustomerBankId = a.CustomerBankId,
CustomerBank = b.BankAccountNo,
Status = a.Status,
CreateTime = a.CreateTime,
CreateBy = a.CreateBy,
AmountRMB = a.AmountRMB,
AmountUSD = a.AmountUSD,
AmountOther = a.AmountOther,
SettlementTypeId = a.SettlementTypeId,
PaymentDate = a.PaymentDate,
ChequeRemarks = a.ChequeRemarks,
InvoiceDate = a.InvoiceDate,
InvoiceAmount = a.InvoiceAmount,
SaleDeptId = a.SaleDeptId,
Note = a.Note
}).FirstAsync();
if (dto != null)
{
dto.Details = await TenantDb.Queryable<ApplicationDetail>()
.InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id)
.LeftJoin<BusinessFeeStatus>((d, f, b) => f.BusinessId == b.BusinessId && f.BusinessType == b.BusinessType)
.Where(d => d.ApplicationId == id)
.Select((d, f, b) => new ApplicationDetailDto
{
Id = d.Id,
RecordId = f.Id,
AccTaxRate = f.AccTaxRate,
Amount = d.Amount,
FeeId = d.FeeId,
FeeName = d.FeeName,
FeeType = d.FeeType,
CustomerId = f.CustomerId,
CustomerName = d.CustomerName,
OriginalCurrency = d.OriginalCurrency,
OriginalRate = f.ExchangeRate,
ExchangeRate = d.ExchangeRate,
OriginalAmount = d.OriginalAmount,
//未申请金额=(金额-结算金额-申请金额+申请金额已结算)
RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount,
BusinessId = d.BusinessId,
BusinessType = d.BusinessType,
IsBusinessLocking = b.IsBusinessLocking,
IsFeeLocking = b.IsFeeLocking
}).ToListAsync();
var gList = dto.Details.GroupBy(x => x.BusinessType).ToList();
foreach (var g in gList)
{
var ids = g.Select(x => x.BusinessId).ToList();
switch (g.Key)
{
case BusinessType.OceanShippingExport:
var list1 = await TenantDb.Queryable<SeaExport>().Where(x => ids.Contains(x.Id)).Select(x => new
{
x.Id,
x.MBLNO,
x.CustomerNo,
x.CustomerName,
x.ETD,
x.CntrTotal,
x.AccountDate,
x.OperatorCode,
x.Vessel,
x.Voyno,
x.Carrier,
x.Forwarder
}).ToListAsync();
foreach (var item in g)
{
var biz = list1.Find(x => x.Id == item.BusinessId);
if (biz != null)
{
item.MBLNO = biz.MBLNO;
item.CustomerName = biz.CustomerName;
item.CustomerNo = biz.CustomerNo;
item.ETD = biz.ETD;
item.CntrTotal = biz.CntrTotal;
item.AccountDate = biz.AccountDate;
item.Operator = biz.OperatorCode;
item.Vessel = biz.Vessel;
item.Voyage = biz.Voyno;
item.Carrier = biz.Carrier;
item.Forwarder = biz.Forwarder;
}
}
break;
case BusinessType.OceanShippingImport:
break;
}
}
dto.RestAmountRMB = dto.Details.FindAll(x => x.OriginalCurrency == RMB_CODE).Sum(x => x.RestAmount);
dto.RestAmountUSD = dto.Details.FindAll(x => x.OriginalCurrency == USD_CODE).Sum(x => x.RestAmount);
dto.AmountOther = dto.Details.FindAll(x => x.OriginalCurrency != RMB_CODE && x.OriginalCurrency != USD_CODE).Sum(x => x.RestAmount);
}
return DataResult<PaymentApplicationDto>.Success(dto);
}
protected override async Task<List<ApplicationDetail>> GetDetailsAsync(IEnumerable<BizItem> items)
{
var ids1 = items.Select(x => x.Id);
var ids2 = items.Select(x => x.BusinessType);
var list = await TenantDb.Queryable<FeeRecord>().Where(x =>
ids1.Contains(x.BusinessId) && ids2.Contains(x.BusinessType) && x.FeeStatus == FeeStatus.AuditPassed)
.Select(x => new ApplicationDetail
{
RecordId = x.Id,
Amount = x.Amount - x.SettlementAmount - x.OrderAmount + x.OrderSettlementAmount,
Currency = x.Currency,
ExchangeRate = x.ExchangeRate,
OriginalCurrency = x.Currency
}).ToListAsync();
list.RemoveAll(x => x.Amount == 0);
foreach (var item in list)
item.OriginalAmount = item.Amount;
return list;
}
protected override DataResult PreSave(PaymentApplication application, PaymentApplication dbValue)
{
if (dbValue != null)
{
if (dbValue.Status == PaymentApplicationStatus.AuditSubmittd || dbValue.Status == PaymentApplicationStatus.AuditPassed)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSaveStatusError));
if (application.Id > 0 && !string.Equals(dbValue.Currency, application.Currency, StringComparison.OrdinalIgnoreCase))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSaveCurrencyError));
}
return DataResult.Success;
}
protected override DataResult CalculateAmount(PaymentApplication application, List<FeeRecord> fees)
{
if (fees == null)
return DataResult.Success;
//非原币申请且原始金额为0则禁止提交
if (application.Details.Any(x => x.OriginalAmount == 0 && !application.Currency.IsNullOrEmpty()))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.OriginalAmountCannotBeZero));
StringBuilder sb = new();
foreach (var detail in application.Details)
{
var fee = fees.Find(x => x.Id == detail.RecordId);
if (fee == null)
{
sb.AppendFormat(MultiLanguageConst.ApplicationCannotRelateFee, detail.FeeName);
sb.Append("");
continue;
}
detail.Record = fee;
//未申请金额=总金额-结算金额-申请金额+申请金额已结算
var restAmount = fee.Amount - fee.SettlementAmount - fee.OrderAmount + fee.OrderSettlementAmount;
if (restAmount == 0)
{
sb.AppendFormat(MultiLanguageConst.FeeNobalance, fee.FeeName);
sb.Append("");
continue;
}
if (detail.OriginalAmount > 0 && detail.OriginalAmount > restAmount)
{
sb.AppendFormat(MultiLanguageConst.DetailExceedingLimit, fee.FeeName);
sb.Append("");
continue;
}
if (detail.OriginalAmount < 0 && detail.OriginalAmount < restAmount)
{
sb.AppendFormat(MultiLanguageConst.DetailExceedingLimit, fee.FeeName);
sb.Append("");
continue;
}
//更新费用记录的已申请金额
fee.OrderAmount += detail.OriginalAmount;
//类别固定为付费申请
detail.Category = FeeCategory.PaidApplication;
}
if (sb.Length > 0)
return DataResult.Failed(sb.ToString());
application.AmountRMB = application.Details.Where(x => x.Currency == RMB_CODE).Sum(x => x.Amount);
application.AmountUSD = application.Details.Where(x => x.Currency == USD_CODE).Sum(x => x.Amount);
application.AmountOther = application.Details.Where(x => x.Currency != RMB_CODE && x.Currency != USD_CODE).Sum(x => x.Amount);
return DataResult.Success;
}
protected override async Task OnSaveAsync(PaymentApplication application, List<FeeRecord>? fees)
{
if (fees != null && fees.Count > 0)
await TenantDb.Updateable(fees).UpdateColumns(x => new { x.OrderAmount }).ExecuteCommandAsync();
}
protected override DataResult PreDelete(List<PaymentApplication> applications)
{
if (applications.Any(x => x.Status != PaymentApplicationStatus.Pending && x.Status != PaymentApplicationStatus.AuditRejected))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationDeleteStatusError));
return DataResult.Success;
}
protected override async Task OnDeleteDetailAsync(List<ApplicationDetail> details)
{
//还原费用表的已申请金额
var fees = details.Select(x => new FeeRecord { Id = x.RecordId, OrderAmount = x.OriginalAmount }).ToList();
await TenantDb.Updateable(fees)
.PublicSetColumns(it => it.OrderAmount, "-")
.UpdateColumns(x => new { x.OrderAmount })
.ExecuteCommandAsync();
}
protected override DataResult PreSubmitApproval(List<PaymentApplication> applications)
{
if (applications.Exists(x => x.Status == PaymentApplicationStatus.AuditSubmittd || x.Status == PaymentApplicationStatus.AuditPassed))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationIsAuditing));
return DataResult.Success;
}
protected override void OnSubmitApproval(PaymentApplication application)
{
application.Status = PaymentApplicationStatus.AuditSubmittd;
}
/// <summary>
/// 设置是否收到发票
/// </summary>
/// <param name="isInvoiceReceived"></param>
/// <param name="ids"></param>
/// <returns></returns>
public async Task<DataResult> SetInvoiceReceivedAsync(bool isInvoiceReceived, params long[] ids)
{
var list = ids.Select(x => new PaymentApplication { Id = x, IsInvoiceReceived = isInvoiceReceived }).ToList();
int rows = await TenantDb.Updateable(list)
.UpdateColumns(x => new { x.IsInvoiceReceived })
.ExecuteCommandAsync();
return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
}