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.

667 lines
32 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.Code.Entity;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Settlement.Dtos;
using DS.WMS.Core.Settlement.Entity;
using DS.WMS.Core.Settlement.Interface;
using DS.WMS.Core.Sys.Entity;
using SqlSugar;
namespace DS.WMS.Core.Settlement.Method
{
/// <summary>
/// 付费结算服务
/// </summary>
public class PaymentSettlementService : SettlementService<PaymentSettlement>, IPaymentSettlementService
{
/// <summary>
/// 初始化
/// </summary>
/// <param name="provider"></param>
public PaymentSettlementService(IServiceProvider provider) : base(provider)
{
}
/// <summary>
/// 获取分页列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<PaymentSettlementDto>>> GetListAsync(PageRequest request)
{
var query = TenantDb.Queryable<PaymentSettlement>().Select(x => new PaymentSettlementDto
{
Id = x.Id,
ApplicationNO = x.ApplicationNO, //申请编号
SettlementNO = x.SettlementNO, //结算单号
CustomerId = x.CustomerId, //结算单位
CustomerName = x.CustomerName,
Mode = x.Mode, //结算类型
SettlementTypeName = x.SettlementType.StlName, //结算方式
RMBAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.Currency == RMB_CODE)
.Select(y => SqlFunc.AggregateSum(y.ApplyAmount)),
USDAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.Currency == USD_CODE)
.Select(y => SqlFunc.AggregateSum(y.ApplyAmount)),
OtherAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.Currency != RMB_CODE && y.Currency != USD_CODE)
.Select(y => SqlFunc.AggregateSum(y.ApplyAmount)),
Note = x.Note, //备注
CustomerAccount = x.CustomerBank.AccountName + "/" + x.CustomerBank.Currency,
CustomerBank = x.CustomerBank.BankName,
//未开票
UnInvoiceList = SqlFunc.Subqueryable<ApplicationDetail>().InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id && (f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount) != 0)
.GroupBy((d, f) => f.Currency).ToList((d, f) => new CurrencyAmount { Currency = f.Currency, Amount = f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount }),
CreateBy = x.CreateBy, //结算人
CreateTime = x.CreateTime, //创建日期
SettlementDate = x.SettlementDate, //结算日期
IsExportVoucher = default, //是否导出凭证
Currency = x.Currency, //币别
Amount = x.Amount, //原始金额
AccountAmount = x.AccountAmount, //记账资料
PrePayAmount = x.PrePayAmount, //预付支资料
AHSRAmount = x.AHSRAmount, //实收支资料
FinancialAmount = x.FinancialAmount,//财务费用
AdvanceAmount = x.AdvanceAmount, //预收支资料
IsLocked = x.IsLocked, //锁定状态
LockTime = x.LockTime,
LockUserId = x.LockUserId,
UnlockTime = x.UnlockTime,
UnlockUserId = x.UnlockUserId,
IsVoucherDisabled = x.IsVoucherDisabled, //禁用凭证
SaleDeptId = x.SaleDeptId, //所属分部
LedgerVoucherNO = x.LedgerVoucherNO //总账凭证号
});
var whereList = request.GetConditionalModels(Db);
var result = await query.Where(whereList).ToQueryPageAsync(request.PageCondition);
if (result.Data.Count > 0)
{
//关联用户名称
var userIds = result.Data.Select(x => x.CreateBy)
.Union(result.Data.Where(x => x.LockUserId.HasValue).Select(x => x.LockUserId.Value))
.Union(result.Data.Where(x => x.UnlockUserId.HasValue).Select(x => x.UnlockUserId.Value))
.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.LockUser = users.Find(x => x.Id == item.LockUserId)?.UserName;
item.UnlockUser = users.Find(x => x.Id == item.UnlockUserId)?.UserName;
item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
}
}
return result;
}
/// <summary>
/// 获取付费结算及其明细
/// </summary>
/// <param name="id">结算单ID</param>
/// <returns></returns>
public async Task<DataResult<PaymentSettlementDto>> GetAsync(long id)
{
var model = await TenantDb.Queryable<PaymentSettlement>().Select(x => new PaymentSettlementDto
{
Id = x.Id,
ApplicationNO = x.ApplicationNO, //申请编号
SettlementNO = x.SettlementNO, //结算单号
CustomerId = x.CustomerId, //结算单位
CustomerName = x.CustomerName,
Mode = x.Mode, //结算类型
SettlementDate = x.SettlementDate, //结算日期
SettlementTypeId = x.SettlementTypeId, //结算方式
CustomerBankId = x.CustomerBankId, //客户银行
Account = x.Account, //客户账户
Currency = x.Currency, //币别
Amount = x.Amount, //金额
ExchangeRate = x.ExchangeRate, //汇率
IsLocked = x.IsLocked, //锁定状态
SaleDeptId = x.SaleDeptId, //所属分部
BillType = x.BillType, //单据类型
Category = x.Category, //业务类别
LedgerVoucherNO = x.LedgerVoucherNO, //总账凭证号
RelativeNO = x.RelativeNO, //相关号码
InvoiceAmount = x.InvoiceAmount,
InvoiceDate = x.InvoiceDate,
InvoiceNO = x.InvoiceNO,
Note = x.Note, //备注
AccountAmount = x.AccountAmount, //记账资料
AccountCurrency = x.AccountCurrency,
AccountRate = x.AccountRate,
PrePayAmount = x.PrePayAmount, //预付支资料
PrePayCurrency = x.PrePayCurrency,
PrePayRate = x.PrePayRate,
AHSRAmount = x.AHSRAmount, //实收支资料
AHSRCurrency = x.AHSRCurrency,
AHSRRate = x.AHSRRate,
FinancialAmount = x.FinancialAmount,//财务费用
FinancialCurrency = x.FinancialCurrency,
FinancialRate = x.FinancialRate,
AdvanceAmount = x.AdvanceAmount, //预收支资料
AdvanceCurrency = x.AdvanceCurrency,
AdvanceRate = x.AdvanceRate,
}).FirstAsync();
if (model != null)
{
var details = await TenantDb.Queryable<ApplicationDetail>().Where(d => d.ApplicationId == id)
.LeftJoin<ApplicationDetail>((d, pd) => d.DetailId == pd.Id)
.LeftJoin<PaymentApplication>((d, pd, pa) => pd.ApplicationId == pa.Id)
.Select((d, pd, pa) => new
{
d.Id,
d.ApplicationId,
d.ApplyAmount,
//d.Currency,
d.OriginalCurrency,
d.OriginalAmount,
pa.CreateTime,
pa.CreateBy,
pa.PaymentDate,
pa.Note
}).ToListAsync();
var gp = details.GroupBy(x => x.ApplicationId);
model.Details = new List<SettlementDetailDto>();
foreach (var g in gp)
{
var firstItem = g.FirstOrDefault();
var dto = new SettlementDetailDto
{
ApplicationId = g.Key,
Ids = g.Select(x => x.Id),
RMBApplyAmount = g.Where(x => x.OriginalCurrency == RMB_CODE).Sum(x => x.ApplyAmount),
USDApplyAmount = g.Where(x => x.OriginalCurrency == USD_CODE).Sum(x => x.ApplyAmount),
CreateTime = firstItem?.CreateTime,
CreateBy = firstItem?.CreateBy,
PaymentDate = firstItem?.PaymentDate,
Note = firstItem?.Note
};
//包含多个币别
if (g.GroupBy(x => x.OriginalCurrency).Select(x => x.Key).Count() > 1)
{
//原始币别=不等于结算单币别的首个币别参考DS7
dto.OriginalCurrency = g.Where(x => x.OriginalCurrency != model.Currency).Select(x => x.OriginalCurrency).FirstOrDefault();
//原始金额=当前结算单的币别合计
dto.OriginalAmount = g.Where(x => x.OriginalCurrency == model.Currency).Sum(x => x.ApplyAmount);
}
else
{
dto.OriginalCurrency = firstItem?.OriginalCurrency;
dto.OriginalAmount = g.Where(x => x.OriginalCurrency == dto.OriginalCurrency).Sum(x => x.ApplyAmount);
}
//结算金额=原申请的原始币别合计
dto.SettlementAmount = g.Where(x => x.OriginalCurrency == dto.OriginalCurrency).Sum(x => x.ApplyAmount);
model.Details.Add(dto);
}
if (model.Details.Count > 0)
{
//关联用户名称
var userIds = model.Details.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 model.Details)
{
item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName;
}
}
}
return DataResult<PaymentSettlementDto>.Success(model);
}
/// <summary>
/// 获取付费申请分页列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<PaymentApplicationDto>>> GetApplicationListAsync(PageRequest<ApplicationListQuery> request)
{
var query = TenantDb.Queryable<PaymentApplication>().Where(a => a.Status == PaymentApplicationStatus.AuditPassed || a.Status == PaymentApplicationStatus.PartialSettlement)
.WhereIF(request.OtherQueryCondition != null && request.OtherQueryCondition.UnsettledOnly,
a => a.Status != PaymentApplicationStatus.SettlementCompleted && SqlFunc.Subqueryable<ApplicationDetail>().Where(d => d.ApplicationId == a.Id && (d.ApplyAmount - d.ProcessedAmount) != 0).Any())
.InnerJoinIF<ApplicationDetail>(request.OtherQueryCondition != null && request.OtherQueryCondition.PortId.HasValue,
(a, d) => d.ApplicationId == a.Id)
.InnerJoinIF<SeaExport>(request.OtherQueryCondition != null && request.OtherQueryCondition.PortId.HasValue,
(a, d, s) => s.Id == d.BusinessId && (s.LoadPortId == request.OtherQueryCondition.PortId.Value || s.DischargePortId == request.OtherQueryCondition.PortId.Value))
.Select(a => new PaymentApplicationDto
{
Id = a.Id,
ApplicationNO = a.ApplicationNO,
Status = a.Status,
CustomerId = a.CustomerId,
CustomerName = a.CustomerName, //结算单位
CustomerBankId = a.CustomerBankId,
CustomerBank = a.CustomerBank.BankName, //结算对象银行
CustomerAccount = a.CustomerBank.Account, //结算对象账号
Currency = a.Currency,
AmountRMB = a.AmountRMB, //RMB申请金额
AmountUSD = a.AmountUSD, //USD申请金额
//RMB未结金额
UnSettlementRMB = SqlFunc.Subqueryable<ApplicationDetail>().Where(d => d.Currency == RMB_CODE)
.Select(d => SqlFunc.AggregateSum(d.ApplyAmount - d.ProcessedAmount)),
//USD未结金额
UnSettlementUSD = SqlFunc.Subqueryable<ApplicationDetail>().Where(d => d.Currency == USD_CODE)
.Select(d => SqlFunc.AggregateSum(d.ApplyAmount - d.ProcessedAmount)),
SaleDeptId = a.SaleDeptId, //所属分部
SettlementTypeId = a.SettlementTypeId,
SettlementTypeName = a.SettlementType.StlName, //结算方式
CreateBy = a.CreateBy, //申请人
CreateTime = a.CreateTime, //申请日期
PayAmount = 0, //审核实付金额
PaymentDate = a.PaymentDate, //申请支付日期
AuditerId = a.AuditerId,
AuditerName = a.AuditerName,
AuditTime = a.AuditTime,
Note = a.Note
});
var whereList = request.GetConditionalModels(Db);
var result = await query.Where(whereList).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).Where(x => x.HasValue).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;
}
/// <summary>
/// 获取费用明细
/// </summary>
/// <param name="id">申请单ID</param>
/// <returns></returns>
public async Task<DataResult<List<PaymentApplicationDetailDto>>> GetApplicationDetailsAsync(long id)
{
var details = await TenantDb.Queryable<ApplicationDetail>().Where(d => d.ApplicationId == id && d.Category == FeeCategory.PaidApplication && (d.ApplyAmount - d.ProcessedAmount) != 0)
.LeftJoin<FeeRecord>((d, f) => d.RecordId == f.Id)
.LeftJoin<BusinessFeeStatus>((d, f, b) => f.BusinessId == b.BusinessId && f.BusinessType == b.BusinessType)
.Select((d, f, b) => new PaymentApplicationDetailDto
{
Id = d.Id,
ApplicationId = d.ApplicationId,
BusinessId = d.BusinessId,
BusinessType = d.BusinessType,
RecordId = d.RecordId,
FeeName = d.FeeName,
FeeType = d.FeeType, //收付
Amount = d.ApplyAmount, //申请金额
SettlementAmount = f.SettlementAmount, //已结算金额
RestAmount = d.ApplyAmount - d.ProcessedAmount, //剩余结算金额
CustomerId = f.CustomerId,
CustomerName = d.CustomerName,
OriginalCurrency = d.OriginalCurrency, //原始币别
OriginalRate = f.ExchangeRate, //原始汇率
ExchangeRate = d.ExchangeRate, //折算汇率
OriginalAmount = d.OriginalAmount //原始金额
}).ToListAsync();
await FulfillDetailsAsync(details);
return DataResult<List<PaymentApplicationDetailDto>>.Success(details);
}
/// <summary>
/// 获取费用明细
/// </summary>
/// <param name="ids">申请单明细ID</param>
/// <returns></returns>
public async Task<DataResult<List<PaymentApplicationDetailDto>>> GetApplicationDetailsAsync(long[] ids)
{
var details = await TenantDb.Queryable<ApplicationDetail>().Where(d => ids.Contains(d.Id) && d.Category == FeeCategory.PaidApplicationSettlement)
.LeftJoin<FeeRecord>((d, f) => d.RecordId == f.Id)
.LeftJoin<BusinessFeeStatus>((d, f, b) => f.BusinessId == b.BusinessId && f.BusinessType == b.BusinessType)
.LeftJoin<PaymentApplication>((d, f, b, p) => d.ApplicationId == p.Id)
.Select((d, f, b, p) => new PaymentApplicationDetailDto
{
Id = d.Id,
ApplicationId = d.ApplicationId,
BusinessId = d.BusinessId,
BusinessType = d.BusinessType,
RecordId = d.RecordId,
FeeName = d.FeeName,
FeeType = d.FeeType, //收付
SettlementAmount = d.ApplyAmount, //结算金额
CustomerId = f.CustomerId,
CustomerName = d.CustomerName,
OriginalCurrency = d.OriginalCurrency, //原始币别
OriginalRate = f.ExchangeRate, //原始汇率
ExchangeRate = d.ExchangeRate, //折算汇率
OriginalAmount = d.OriginalAmount, //原始金额
InvoiceNO = p.InvoiceNO //发票号
}).ToListAsync();
await FulfillDetailsAsync(details);
return DataResult<List<PaymentApplicationDetailDto>>.Success(details);
}
async Task FulfillDetailsAsync(List<PaymentApplicationDetailDto> details)
{
if (details.Count == 0)
return;
var gList = details.GroupBy(x => x.BusinessType);
foreach (var g in gList)
{
var ids = g.Select(x => x.BusinessId);
switch (g.Key)
{
case BusinessType.OceanShippingExport:
var list1 = await TenantDb.Queryable<SeaExport>().Where(s => ids.Contains(s.Id))
.LeftJoin<CodeSource>((s, cs) => s.SourceId == cs.Id)
.Select((s, cs) => new
{
s.Id,
s.AccountDate,//会计期间
s.Vessel, //船名
s.Voyno, //航次
s.CustomerName,
s.MBLNO, //主提单号
s.CustomerNo, //委托编号
s.ETD, //开船日期
s.Sale, //揽货人
cs.SourceName, //业务来源
s.Note
}).ToListAsync();
foreach (var item in g)
{
var biz = list1.Find(x => x.Id == item.BusinessId);
if (biz != null)
{
item.MBLNO = biz.MBLNO;
item.CustomerNo = biz.CustomerNo;
item.ClientName = biz.CustomerName;
item.ETD = biz.ETD;
item.SourceName = biz.SourceName;
item.SaleName = biz.Sale;
item.AccountDate = biz.AccountDate;
item.Vessel = biz.Vessel;
item.Voyage = biz.Voyno;
item.Note = biz.Note;
}
}
break;
case BusinessType.OceanShippingImport:
break;
}
}
}
/// <summary>
/// 提交结算单
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async override Task<DataResult<PaymentSettlement>> SaveAsync(SettlementRequest<PaymentSettlement> request)
{
var settlement = request.Settlement;
if (settlement.SettlementDate == default)
settlement.SettlementDate = DateTime.Now;
settlement.Mode = SettlementMode.Payment;
settlement.BillType = SettlementBillType.Payment;
if (request.Details?.Count > 0)
{
var appIds = request.Details.Select(x => x.ApplicationId).Distinct();
var appList = await TenantDb.Queryable<PaymentApplication>().Where(x => appIds.Contains(x.Id))
.Select(x => new
{
x.Id,
x.Status,
x.CustomerId,
x.CustomerName,
}).ToListAsync();
if (appList.Count == 0)
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
if (appList.Exists(x => x.Status != PaymentApplicationStatus.AuditPassed && x.Status != PaymentApplicationStatus.PartialSettlement))
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSelectStatusError));
if (appList.GroupBy(x => x.CustomerId).Select(x => x.Key).Count() > 1)
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.DetailCustomerOnlyOne));
//金额禁止为0
if (request.Details.Any(x => x.Amount == 0 || x.OriginalAmount == 0))
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero));
if (settlement.Id == 0)
{
var app = appList[0];
settlement.CustomerId = app.CustomerId;
settlement.CustomerName = app.CustomerName;
}
settlement.Details = request.Details.Select(x => new ApplicationDetail
{
ApplicationId = x.ApplicationId,
DetailId = x.Id,
RecordId = x.RecordId,
BusinessId = x.BusinessId,
BusinessType = x.BusinessType,
CustomerName = x.CustomerName ?? settlement.CustomerName,
FeeId = x.FeeId,
FeeName = x.FeeName,
FeeType = x.FeeType,
Category = FeeCategory.PaidApplicationSettlement,
ApplyAmount = x.Amount,
Currency = x.Currency,
ExchangeRate = x.ExchangeRate,
OriginalAmount = x.OriginalAmount,
OriginalCurrency = x.OriginalCurrency ?? (settlement.Currency.IsNullOrEmpty() ? x.Currency : settlement.Currency),
}).ToList();
if (settlement.Details.Any(x => x.OriginalCurrency.IsNullOrEmpty()))
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull));
//获取剩余待结算金额
var ids2 = settlement.Details.Select(x => x.DetailId);
var appDetails = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids2.Contains(x.Id) && x.Category == FeeCategory.PaidApplication)
.Select(x => new
{
x.Id,
//RestAmount = x.ApplyAmount - x.ProcessedAmount,
OriginalRestAmount = x.OriginalAmount - x.OriginalProcessedAmount
}).ToListAsync();
StringBuilder sb = new();
foreach (var detail in settlement.Details)
{
var item = appDetails.Find(x => x.Id == detail.DetailId);
if (item == null)
{
sb.Append(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.EmptyData)));
break;
}
if (detail.OriginalAmount > 0 && detail.OriginalAmount > item.OriginalRestAmount)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName);
sb.Append("");
continue;
}
else if (detail.OriginalAmount < 0 && detail.OriginalAmount < item.OriginalRestAmount)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName);
sb.Append("");
continue;
}
}
if (sb.Length > 0)
return DataResult<PaymentSettlement>.Failed(sb.ToString());
settlement.Amount = settlement.Details.Sum(x => x.ApplyAmount);
}
await TenantDb.Ado.BeginTranAsync();
try
{
//关联导航属性插入
if (settlement.Id == 0)
{
//创建时需要生成申请单编号
var sequence = CommonService.Value.GetSequenceNext<PaymentSettlement>();
if (!sequence.Succeeded)
{
return DataResult<PaymentSettlement>.Failed(sequence.Message, MultiLanguageConst.SequenceSetNotExist);
}
settlement.ApplicationNO = "CP" + SnowFlakeSingle.Instance.NextId(); //申请编号
settlement.SettlementNO = sequence.Data; //结算单号
await TenantDb.InsertNav(settlement).Include(x => x.Details).ExecuteCommandAsync();
}
else
{
if (settlement.Details.Count > 0)
await TenantDb.Insertable(settlement.Details).ExecuteCommandAsync();
await TenantDb.Updateable(settlement).IgnoreColumns(x => new
{
x.ApplicationNO,
x.SettlementNO,
x.IsLocked,
x.CreateBy,
x.CreateTime,
x.Deleted,
x.DeleteBy,
x.DeleteTime
}).ExecuteCommandAsync();
}
if (request.Details?.Count > 0)
{
//更新申请明细的已处理金额
var list = request.Details.Select(x => new ApplicationDetail
{
Id = x.Id,
ProcessedAmount = x.Amount,
OriginalProcessedAmount = x.OriginalAmount
}).ToList();
await TenantDb.Updateable(list)
.PublicSetColumns(x => x.ProcessedAmount, "+")
.PublicSetColumns(x => x.OriginalProcessedAmount, "+")
.UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount })
.ExecuteCommandAsync();
//更新费用记录的已结算金额
var fees = request.Details.Select(x => new FeeRecord
{
Id = x.RecordId,
SettlementAmount = x.OriginalAmount
}).ToList();
await TenantDb.Updateable(fees)
.PublicSetColumns(x => x.SettlementAmount, "+")
.UpdateColumns(x => new { x.SettlementAmount })
.ExecuteCommandAsync();
}
await TenantDb.Ado.CommitTranAsync();
return DataResult<PaymentSettlement>.Success(settlement);
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
finally
{
if (request.Details?.Count > 0)
await WriteBackStatusAsync(settlement);
}
}
/// <summary>
/// 回写申请单的状态
/// </summary>
/// <param name="settlement">结算单</param>
/// <returns></returns>
public async Task WriteBackStatusAsync(PaymentSettlement settlement)
{
var details = await TenantDb.Queryable<ApplicationDetail>()
.InnerJoin<ApplicationDetail>((x, y) => x.DetailId == y.Id && y.ApplicationId == settlement.Id && y.Category == FeeCategory.PaidApplicationSettlement)
.Where((x, y) => x.Category == FeeCategory.PaidApplication)
.GroupBy((x, y) => x.ApplicationId).Select((x, y) => new
{
x.ApplicationId,
Count = SqlFunc.AggregateCount(x.Id),
ProcessedCount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.ApplicationId &&
y.Category == FeeCategory.PaidApplication && y.OriginalAmount - y.OriginalProcessedAmount == 0).Count()
}).ToListAsync();
List<PaymentApplication> applications = [];
foreach (var item in details)
{
if (item.Count == 0 || item.ProcessedCount == 0)
continue;
var entity = new PaymentApplication { Id = item.ApplicationId };
if (item.Count == item.ProcessedCount)
{
entity.Status = PaymentApplicationStatus.SettlementCompleted;
}
else if (item.ProcessedCount > 0)
{
entity.Status = PaymentApplicationStatus.PartialSettlement;
}
applications.Add(entity);
}
await TenantDb.Updateable(applications).UpdateColumns(x => new { x.Status }).ExecuteCommandAsync();
}
protected override DataResult PreDelete(List<PaymentSettlement> settlements)
{
if (settlements.Any(x => x.IsLocked))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked));
return DataResult.Success;
}
protected override async Task OnDeleteDetailAsync(List<PaymentSettlement> settlements)
{
await base.OnDeleteDetailAsync(settlements);
var detailList = settlements.SelectMany(x => x.Details);
//还原费用表的已结算金额
var fees = detailList.Select(x => new FeeRecord { Id = x.RecordId, SettlementAmount = x.OriginalAmount }).ToList();
await TenantDb.Updateable(fees)
.PublicSetColumns(it => it.SettlementAmount, "-")
.UpdateColumns(x => new { x.SettlementAmount })
.ExecuteCommandAsync();
}
}
}