|
|
@ -24,7 +24,7 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
/// 结算基础实现
|
|
|
|
/// 结算基础实现
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TEntity">实体的类型声明</typeparam>
|
|
|
|
/// <typeparam name="TEntity">实体的类型声明</typeparam>
|
|
|
|
public abstract class SettlementService<TEntity> : FeeServiceBase, ISettlementService<TEntity>
|
|
|
|
public class SettlementService<TEntity> : FeeServiceBase, ISettlementService<TEntity>
|
|
|
|
where TEntity : SettlementBase, new()
|
|
|
|
where TEntity : SettlementBase, new()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
readonly Lazy<ICommonService> CommonService;
|
|
|
|
readonly Lazy<ICommonService> CommonService;
|
|
|
@ -125,7 +125,7 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
if (!result.Succeeded)
|
|
|
|
if (!result.Succeeded)
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
|
|
|
|
|
|
|
List<ApplicationDetail>? details = null;
|
|
|
|
List<ApplicationDetail>? details1 = null;
|
|
|
|
//自由结算
|
|
|
|
//自由结算
|
|
|
|
if (settlement.Mode == SettlementMode.FreeSettlement && request.Details?.Count > 0)
|
|
|
|
if (settlement.Mode == SettlementMode.FreeSettlement && request.Details?.Count > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -220,7 +220,7 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
if (settlement.Mode == SettlementMode.Payment || settlement.Mode == SettlementMode.Charge)
|
|
|
|
if (settlement.Mode == SettlementMode.Payment || settlement.Mode == SettlementMode.Charge)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var detailCategory = settlement.Mode == SettlementMode.Payment ? DetailCategory.PaidApplication : DetailCategory.ChargeApplication;
|
|
|
|
var detailCategory = settlement.Mode == SettlementMode.Payment ? DetailCategory.PaidApplication : DetailCategory.ChargeApplication;
|
|
|
|
details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId) && x.Category == detailCategory)
|
|
|
|
details1 = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId) && x.Category == detailCategory)
|
|
|
|
.Select(x => new ApplicationDetail
|
|
|
|
.Select(x => new ApplicationDetail
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ApplicationId = settlement.Id,
|
|
|
|
ApplicationId = settlement.Id,
|
|
|
@ -242,7 +242,7 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(settlement.Currency)) //指定结算币别
|
|
|
|
if (!string.IsNullOrEmpty(settlement.Currency)) //指定结算币别
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var details2 = details.FindAll(x => x.OriginalCurrency != settlement.Currency);
|
|
|
|
var details2 = details1.FindAll(x => x.OriginalCurrency != settlement.Currency);
|
|
|
|
foreach (var detail in details2)
|
|
|
|
foreach (var detail in details2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
detail.Currency = settlement.Currency;
|
|
|
|
detail.Currency = settlement.Currency;
|
|
|
@ -259,111 +259,33 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
detail.ApplyAmount = Math.Round(exchange.ExchangeRate.GetValueOrDefault() * detail.OriginalAmount, 2, MidpointRounding.AwayFromZero);
|
|
|
|
detail.ApplyAmount = Math.Round(exchange.ExchangeRate.GetValueOrDefault() * detail.OriginalAmount, 2, MidpointRounding.AwayFromZero);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//执行结算费用分配
|
|
|
|
|
|
|
|
foreach (var doc in request.Documents)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var details2 = details.Where(x => x.RefId == doc.Id).OrderBy(x => x.ApplyAmount).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var rmbDetails = details2.FindAll(x => x.Currency == FeeCurrency.RMB_CODE);
|
|
|
|
|
|
|
|
if (rmbDetails.Count > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var totalRMB = rmbDetails.Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
doc.SettlementRMB ??= totalRMB;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementRMB > totalRMB)
|
|
|
|
|
|
|
|
return DataResult<TEntity>.Failed("人民币结算金额不能大于剩余人民币金额");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (totalRMB != doc.SettlementRMB)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var rest = totalRMB - doc.SettlementRMB.GetValueOrDefault();
|
|
|
|
|
|
|
|
foreach (var detail in rmbDetails)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
rest = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var usdDetails = details2.FindAll(x => x.Currency == FeeCurrency.USD_CODE);
|
|
|
|
|
|
|
|
if (usdDetails.Count > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var totalUSD = usdDetails.Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
doc.SettlementUSD ??= totalUSD;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementUSD > totalUSD)
|
|
|
|
|
|
|
|
return DataResult<TEntity>.Failed("美元结算金额不能大于剩余美元金额");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (totalUSD != doc.SettlementUSD)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var rest = totalUSD - doc.SettlementUSD.GetValueOrDefault();
|
|
|
|
|
|
|
|
foreach (var detail in usdDetails)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
rest = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var otherDetails = details2.FindAll(x => x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE);
|
|
|
|
|
|
|
|
if (otherDetails.Count > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var total = rmbDetails.Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
doc.SettlementOther ??= total;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementOther > total)
|
|
|
|
|
|
|
|
return DataResult<TEntity>.Failed("其他结算金额不能大于剩余其他金额");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (total != doc.SettlementOther)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var rest = total - doc.SettlementOther.GetValueOrDefault();
|
|
|
|
|
|
|
|
foreach (var detail in otherDetails)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
rest = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//发票结算
|
|
|
|
//发票结算
|
|
|
|
else if (settlement.Mode == SettlementMode.InvoiceSettlement || settlement.Mode == SettlementMode.PaymentInvoiceSettlement)
|
|
|
|
else if (settlement.Mode == SettlementMode.InvoiceSettlement || settlement.Mode == SettlementMode.PaymentInvoiceSettlement)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
details = await TenantDb.Queryable<ApplicationDetail>()
|
|
|
|
details1 = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId) && x.Category == DetailCategory.InvoiceIssuance)
|
|
|
|
.InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id)
|
|
|
|
.Select(x => new ApplicationDetail
|
|
|
|
.Where((d, f) => ids.Contains(d.ApplicationId) && d.Category == DetailCategory.InvoiceIssuance)
|
|
|
|
|
|
|
|
.Select((d, f) => new ApplicationDetail
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ApplicationId = settlement.Id,
|
|
|
|
ApplicationId = settlement.Id,
|
|
|
|
RefId = d.ApplicationId,
|
|
|
|
RefId = x.ApplicationId,
|
|
|
|
DetailId = d.Id,
|
|
|
|
DetailId = x.Id,
|
|
|
|
RecordId = d.RecordId,
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
Category = DetailCategory.InvoiceSettlement,
|
|
|
|
Category = DetailCategory.InvoiceSettlement,
|
|
|
|
CustomerName = d.CustomerName ?? settlement.CustomerName,
|
|
|
|
CustomerName = x.CustomerName ?? settlement.CustomerName,
|
|
|
|
FeeId = d.FeeId,
|
|
|
|
FeeId = x.FeeId,
|
|
|
|
FeeName = d.FeeName,
|
|
|
|
FeeName = x.FeeName,
|
|
|
|
FeeType = d.FeeType,
|
|
|
|
FeeType = x.FeeType,
|
|
|
|
|
|
|
|
|
|
|
|
ApplyAmount = d.ApplyAmount - d.ProcessedAmount,
|
|
|
|
ApplyAmount = x.ApplyAmount - x.ProcessedAmount,
|
|
|
|
Currency = d.Currency,
|
|
|
|
Currency = x.Currency,
|
|
|
|
OriginalAmount = d.OriginalAmount - d.OriginalProcessedAmount,
|
|
|
|
OriginalAmount = x.OriginalAmount - x.OriginalProcessedAmount,
|
|
|
|
OriginalCurrency = d.OriginalCurrency,
|
|
|
|
OriginalCurrency = x.OriginalCurrency,
|
|
|
|
ExchangeRate = d.ExchangeRate
|
|
|
|
ExchangeRate = x.ExchangeRate
|
|
|
|
}).ToListAsync();
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
|
|
if (settlement.Currency != FeeCurrency.RMB_CODE) //发票结算非人民币需做转换
|
|
|
|
if (settlement.Currency != FeeCurrency.RMB_CODE) //发票结算非人民币需做转换
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var details2 = details.FindAll(x => x.OriginalCurrency != settlement.Currency);
|
|
|
|
var details2 = details1.FindAll(x => x.OriginalCurrency != settlement.Currency);
|
|
|
|
foreach (var detail in details2)
|
|
|
|
foreach (var detail in details2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
detail.Currency = settlement.Currency;
|
|
|
|
detail.Currency = settlement.Currency;
|
|
|
@ -381,12 +303,78 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//执行结算费用分配
|
|
|
|
|
|
|
|
foreach (var doc in request.Documents)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var details2 = details1.Where(x => x.RefId == doc.Id).OrderBy(x => x.ApplyAmount).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var rmbDetails = details2.FindAll(x => x.Currency == FeeCurrency.RMB_CODE);
|
|
|
|
|
|
|
|
var totalRMB = rmbDetails.Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
doc.SettlementRMB ??= totalRMB;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementRMB > totalRMB)
|
|
|
|
|
|
|
|
return DataResult<TEntity>.Failed("人民币结算金额不能大于剩余人民币金额");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (totalRMB < doc.SettlementRMB)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var rest = totalRMB - doc.SettlementRMB.GetValueOrDefault();
|
|
|
|
|
|
|
|
foreach (var detail in rmbDetails)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
rest = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var usdDetails = details2.FindAll(x => x.Currency == FeeCurrency.USD_CODE);
|
|
|
|
|
|
|
|
var totalUSD = usdDetails.Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
doc.SettlementUSD ??= totalUSD;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementUSD > totalUSD)
|
|
|
|
|
|
|
|
return DataResult<TEntity>.Failed("美元结算金额不能大于剩余美元金额");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (totalUSD < doc.SettlementUSD)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var rest = totalUSD - doc.SettlementUSD.GetValueOrDefault();
|
|
|
|
|
|
|
|
foreach (var detail in usdDetails)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
rest = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var otherDetails = details2.FindAll(x => x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE);
|
|
|
|
|
|
|
|
var total = rmbDetails.Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
doc.SettlementOther ??= total;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementOther > total)
|
|
|
|
|
|
|
|
return DataResult<TEntity>.Failed("其他结算金额不能大于剩余其他金额");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (total < doc.SettlementOther)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var rest = total - doc.SettlementOther.GetValueOrDefault();
|
|
|
|
|
|
|
|
foreach (var detail in otherDetails)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
rest = detail.ApplyAmount - rest;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (details?.Count > 0)
|
|
|
|
|
|
|
|
settlement.Details.AddRange(details);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//仅保留新增费用明细
|
|
|
|
|
|
|
|
settlement.Details = settlement.Details.FindAll(x => x.Id == 0);
|
|
|
|
if (details1?.Count > 0)
|
|
|
|
|
|
|
|
settlement.Details.AddRange(details1);
|
|
|
|
|
|
|
|
|
|
|
|
//金额禁止为0
|
|
|
|
//金额禁止为0
|
|
|
|
if (settlement.Details.Exists(x => x.ApplyAmount == 0 || x.OriginalAmount == 0))
|
|
|
|
if (settlement.Details.Exists(x => x.ApplyAmount == 0 || x.OriginalAmount == 0))
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero));
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero));
|
|
|
@ -394,22 +382,18 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
if (settlement.Details.Exists(x => x.OriginalCurrency.IsNullOrEmpty()))
|
|
|
|
if (settlement.Details.Exists(x => x.OriginalCurrency.IsNullOrEmpty()))
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull));
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull));
|
|
|
|
|
|
|
|
|
|
|
|
if (settlement.Details.Count > 0)
|
|
|
|
settlement.Amount = settlement.Details.Sum(x => x.ApplyAmount);
|
|
|
|
{
|
|
|
|
result = await PreSaveAsync(settlement);
|
|
|
|
result = await PreSaveAsync(settlement);
|
|
|
|
if (!result.Succeeded)
|
|
|
|
if (!result.Succeeded)
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var details = settlement.Details.FindAll(x => x.Id == 0);
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
try
|
|
|
|
try
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//关联导航属性插入
|
|
|
|
//关联导航属性插入
|
|
|
|
if (settlement.Id == 0)
|
|
|
|
if (settlement.Id == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!string.IsNullOrEmpty(settlement.Currency))
|
|
|
|
|
|
|
|
settlement.Amount = settlement.Details.Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//创建时需要生成申请单编号
|
|
|
|
//创建时需要生成申请单编号
|
|
|
|
var sequence = CommonService.Value. GetSequenceNext<TEntity>();
|
|
|
|
var sequence = CommonService.Value. GetSequenceNext<TEntity>();
|
|
|
|
if (!sequence.Succeeded)
|
|
|
|
if (!sequence.Succeeded)
|
|
|
@ -423,12 +407,8 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (settlement.Details.Count > 0)
|
|
|
|
if (details.Count > 0)
|
|
|
|
await TenantDb.Insertable(settlement.Details).ExecuteCommandAsync();
|
|
|
|
await TenantDb.Insertable(details).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(settlement.Currency))
|
|
|
|
|
|
|
|
settlement.Amount = await TenantDb.Queryable<ApplicationDetail>()
|
|
|
|
|
|
|
|
.Where(x => x.ApplicationId == settlement.Id).SumAsync(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await TenantDb.Updateable(settlement).IgnoreColumns(x => new
|
|
|
|
await TenantDb.Updateable(settlement).IgnoreColumns(x => new
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -445,10 +425,10 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
|
|
|
|
|
|
|
await OnSaveAsync(settlement);
|
|
|
|
await OnSaveAsync(settlement);
|
|
|
|
|
|
|
|
|
|
|
|
if (settlement.Details.Count > 0)
|
|
|
|
if (details.Count > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//更新费用记录的已结算金额
|
|
|
|
//更新费用记录的已结算金额
|
|
|
|
var fees = settlement.Details.Select(x => new FeeRecord
|
|
|
|
var fees = details.Select(x => new FeeRecord
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Id = x.RecordId,
|
|
|
|
Id = x.RecordId,
|
|
|
|
SettlementAmount = x.OriginalAmount
|
|
|
|
SettlementAmount = x.OriginalAmount
|
|
|
|