|
|
|
@ -98,6 +98,9 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (request.Documents != null)
|
|
|
|
|
request.Documents = request.Documents.FindAll(x => x.SettlementUSD.HasValue || x.SettlementRMB.HasValue || x.SettlementOther.HasValue);
|
|
|
|
|
|
|
|
|
|
//按付费/发票申请/自由业务结算
|
|
|
|
|
if (request.Documents?.Count > 0)
|
|
|
|
|
{
|
|
|
|
@ -107,25 +110,26 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
settlement.CustomerId = first.CustomerId;
|
|
|
|
|
settlement.CustomerName = first.CustomerName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ids = request.Documents.Select(x => x.Id);
|
|
|
|
|
//收/付费申请结算
|
|
|
|
|
if (settlement.Mode == SettlementMode.Payment || settlement.Mode == SettlementMode.Charge)
|
|
|
|
|
{
|
|
|
|
|
var detailCategory = settlement.Mode == SettlementMode.Payment ? DetailCategory.PaidApplication : DetailCategory.ChargeApplication;
|
|
|
|
|
var expr = Expressionable.Create<ApplicationDetail>().And(x => ids.Contains(x.ApplicationId) && x.Category == detailCategory);
|
|
|
|
|
|
|
|
|
|
Expressionable<ApplicationDetail>? expr = null;
|
|
|
|
|
if (request.Documents.Any(x => x.SettlementRMB.GetValueOrDefault() == 0) || request.Documents.Any(x => x.SettlementUSD.GetValueOrDefault() == 0) ||
|
|
|
|
|
request.Documents.Any(x => x.SettlementOther.GetValueOrDefault() == 0)) //按币别结算
|
|
|
|
|
{
|
|
|
|
|
expr = Expressionable.Create<ApplicationDetail>();
|
|
|
|
|
|
|
|
|
|
if (request.Documents.Any(x => x.SettlementRMB.GetValueOrDefault() != 0))
|
|
|
|
|
expr = expr.And(x => x.Currency == FeeCurrency.RMB_CODE);
|
|
|
|
|
expr = expr.Or(x => x.Currency == FeeCurrency.RMB_CODE);
|
|
|
|
|
|
|
|
|
|
if (request.Documents.Any(x => x.SettlementUSD.GetValueOrDefault() != 0))
|
|
|
|
|
expr = expr.And(x => x.Currency == FeeCurrency.USD_CODE);
|
|
|
|
|
expr = expr.Or(x => x.Currency == FeeCurrency.USD_CODE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
details1 = await TenantDb.Queryable<ApplicationDetail>().Where(expr.ToExpression())
|
|
|
|
|
var detailCategory = settlement.Mode == SettlementMode.Payment ? DetailCategory.PaidApplication : DetailCategory.ChargeApplication;
|
|
|
|
|
details1 = await TenantDb.Queryable<ApplicationDetail>()
|
|
|
|
|
.Where(x => ids.Contains(x.ApplicationId) && x.Category == detailCategory)
|
|
|
|
|
.WhereIF(expr != null, expr.ToExpression())
|
|
|
|
|
.Select(x => new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
|
ApplicationId = settlement.Id,
|
|
|
|
@ -150,8 +154,6 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
var details2 = details1.FindAll(x => x.OriginalCurrency != settlement.Currency);
|
|
|
|
|
foreach (var detail in details2)
|
|
|
|
|
{
|
|
|
|
|
detail.Currency = settlement.Currency;
|
|
|
|
|
|
|
|
|
|
var doc = request.Documents.Find(x => x.Id == detail.RefId);
|
|
|
|
|
if (doc == null)
|
|
|
|
|
return DataResult<TEntity>.Failed("结算单据与费用明细不一致");
|
|
|
|
@ -161,7 +163,6 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
return DataResult<TEntity>.Failed($"未传入结算币别 {settlement.Currency} 与费用原币别 {detail.OriginalCurrency} 之间的汇率信息");
|
|
|
|
|
|
|
|
|
|
detail.ExchangeRate = exchange.ExchangeRate;
|
|
|
|
|
//detail.ApplyAmount = Math.Round(exchange.ExchangeRate.GetValueOrDefault() * detail.OriginalAmount, 2, MidpointRounding.AwayFromZero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -207,7 +208,6 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
return DataResult<TEntity>.Failed($"使用发票做结算时,非 {FeeCurrency.RMB_CODE} 的费用必须指定汇率");
|
|
|
|
|
|
|
|
|
|
detail.ExchangeRate = exchange.ExchangeRate;
|
|
|
|
|
detail.ApplyAmount = Math.Round(exchange.ExchangeRate.GetValueOrDefault() * detail.OriginalAmount, 2, MidpointRounding.AwayFromZero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -253,7 +253,6 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
return DataResult<TEntity>.Failed($"未传入结算币别 {settlement.Currency} 与费用原币别 {detail.OriginalCurrency} 之间的汇率信息");
|
|
|
|
|
|
|
|
|
|
detail.ExchangeRate = exchange.ExchangeRate;
|
|
|
|
|
detail.ApplyAmount = Math.Round(exchange.ExchangeRate.GetValueOrDefault() * detail.OriginalAmount, 2, MidpointRounding.AwayFromZero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -265,99 +264,32 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
details1.Where(x => x.RefId == doc.Id).OrderBy(x => x.ApplyAmount) :
|
|
|
|
|
details1.Where(x => x.BusinessId == doc.Id && x.BusinessType == doc.BusinessType && x.CustomerName == doc.CustomerName).OrderBy(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
|
|
var rmbDetails = details2.Where(x => x.OriginalCurrency == FeeCurrency.RMB_CODE);
|
|
|
|
|
var totalRMB = rmbDetails.Sum(x => x.OriginalAmount);
|
|
|
|
|
doc.SettlementRMB ??= totalRMB;
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementRMB > totalRMB)
|
|
|
|
|
return DataResult<TEntity>.Failed("人民币结算金额不能大于剩余人民币金额");
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementRMB < totalRMB)
|
|
|
|
|
{
|
|
|
|
|
var rest = totalRMB - doc.SettlementRMB.GetValueOrDefault();
|
|
|
|
|
foreach (var detail in rmbDetails)
|
|
|
|
|
{
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
detail.OriginalAmount = detail.OriginalAmount - rest;
|
|
|
|
|
if (detail.OriginalCurrency == settlement.Currency)
|
|
|
|
|
{
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var er = doc.ExchangeRates.Find(x => x.Currency == detail.OriginalCurrency);
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount * er?.ExchangeRate ?? 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rest = detail.OriginalAmount - rest;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var usdDetails = details2.Where(x => x.OriginalCurrency == FeeCurrency.USD_CODE);
|
|
|
|
|
var totalUSD = usdDetails.Sum(x => x.OriginalAmount);
|
|
|
|
|
doc.SettlementUSD ??= totalUSD;
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementUSD > totalUSD)
|
|
|
|
|
return DataResult<TEntity>.Failed("美元结算金额不能大于剩余美元金额");
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementUSD < totalUSD)
|
|
|
|
|
{
|
|
|
|
|
var rest = totalUSD - doc.SettlementUSD.GetValueOrDefault();
|
|
|
|
|
foreach (var detail in usdDetails)
|
|
|
|
|
{
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
detail.OriginalAmount = detail.OriginalAmount - rest;
|
|
|
|
|
if (detail.OriginalCurrency == settlement.Currency)
|
|
|
|
|
{
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if (doc.SettlementRMB.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var er = doc.ExchangeRates.Find(x => x.Currency == detail.OriginalCurrency);
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount * er?.ExchangeRate ?? 1;
|
|
|
|
|
}
|
|
|
|
|
rest = detail.OriginalAmount - rest;
|
|
|
|
|
}
|
|
|
|
|
var rmbDetails = details2.Where(x => x.OriginalCurrency == FeeCurrency.RMB_CODE).ToList();
|
|
|
|
|
result = AssignAmount(rmbDetails, doc.SettlementRMB.Value, settlement.Currency);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var otherDetails = details2.Where(x => x.OriginalCurrency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE);
|
|
|
|
|
var total = otherDetails.Sum(x => x.OriginalAmount);
|
|
|
|
|
doc.SettlementOther ??= total;
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementOther > total)
|
|
|
|
|
return DataResult<TEntity>.Failed("其他结算金额不能大于剩余其他金额");
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementOther < total)
|
|
|
|
|
if (doc.SettlementUSD.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var rest = total - doc.SettlementOther.GetValueOrDefault();
|
|
|
|
|
foreach (var detail in otherDetails)
|
|
|
|
|
{
|
|
|
|
|
if (rest == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
detail.OriginalAmount = detail.OriginalAmount - rest;
|
|
|
|
|
if (detail.OriginalCurrency == settlement.Currency)
|
|
|
|
|
{
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount;
|
|
|
|
|
var usdDetails = details2.Where(x => x.OriginalCurrency == FeeCurrency.USD_CODE).ToList();
|
|
|
|
|
result = AssignAmount(usdDetails, doc.SettlementUSD.Value, settlement.Currency);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if (doc.SettlementOther.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var er = doc.ExchangeRates.Find(x => x.Currency == detail.OriginalCurrency);
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount * er?.ExchangeRate ?? 1;
|
|
|
|
|
}
|
|
|
|
|
rest = detail.OriginalAmount - rest;
|
|
|
|
|
}
|
|
|
|
|
var otherDetails = details2.Where(x => x.OriginalCurrency != FeeCurrency.RMB_CODE && x.OriginalCurrency != FeeCurrency.USD_CODE).ToList();
|
|
|
|
|
result = AssignAmount(otherDetails, doc.SettlementOther.Value, settlement.Currency);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (details1?.Count > 0)
|
|
|
|
|
settlement.Details.AddRange(details1);
|
|
|
|
|
settlement.Details.AddRange(details1.FindAll(x => x.Assigned));
|
|
|
|
|
|
|
|
|
|
//金额禁止为0
|
|
|
|
|
if (settlement.Details.Exists(x => x.ApplyAmount == 0 || x.OriginalAmount == 0))
|
|
|
|
@ -422,9 +354,8 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
.ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//重新计算结算总金额
|
|
|
|
|
settlement.Amount = await TenantDb.Queryable<ApplicationDetail>().Where(x => x.ApplicationId == settlement.Id)
|
|
|
|
|
.SumAsync(x => x.ApplyAmount);
|
|
|
|
|
//计算结算总金额
|
|
|
|
|
settlement.Amount = await TenantDb.Queryable<ApplicationDetail>().Where(x => x.ApplicationId == settlement.Id).SumAsync(x => x.ApplyAmount);
|
|
|
|
|
await TenantDb.Updateable(settlement).UpdateColumns(x => x.Amount).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
await TenantDb.Ado.CommitTranAsync();
|
|
|
|
@ -439,6 +370,67 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DataResult AssignAmount(List<ApplicationDetail> details, decimal stlAmount, string currency)
|
|
|
|
|
{
|
|
|
|
|
if (details.Count == 0)
|
|
|
|
|
return DataResult.Success;
|
|
|
|
|
|
|
|
|
|
if (stlAmount == 0)
|
|
|
|
|
return DataResult.Failed("结算金额不能为零");
|
|
|
|
|
|
|
|
|
|
var totalAmount = details.Exists(x => x.Currency != currency) ?
|
|
|
|
|
details.Sum(x => x.OriginalAmount) : details.Sum(x => x.ApplyAmount);
|
|
|
|
|
if (Math.Abs(stlAmount) > totalAmount)
|
|
|
|
|
return DataResult.Failed("申请结算金额不能大于剩余结算金额");
|
|
|
|
|
|
|
|
|
|
if (totalAmount != stlAmount) //非全额结算
|
|
|
|
|
{
|
|
|
|
|
decimal rest = stlAmount;
|
|
|
|
|
foreach (var detail in details)
|
|
|
|
|
{
|
|
|
|
|
if (rest <= 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (rest >= detail.OriginalAmount)
|
|
|
|
|
{
|
|
|
|
|
rest = rest - detail.OriginalAmount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
detail.OriginalAmount = rest;
|
|
|
|
|
rest = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (detail.Currency == currency)
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
detail.Currency = currency;
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount * detail.ExchangeRate.GetValueOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
detail.Assigned = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
foreach (var detail in details)
|
|
|
|
|
{
|
|
|
|
|
if (detail.Currency == currency)
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
detail.Currency = currency;
|
|
|
|
|
detail.ApplyAmount = detail.OriginalAmount * detail.ExchangeRate.GetValueOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
detail.Assigned = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DataResult.Success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 用于结算单的状态检查
|
|
|
|
|
/// </summary>
|
|
|
|
@ -510,7 +502,9 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
ApplyAmount = x.ApplyAmount,
|
|
|
|
|
OriginalAmount = x.OriginalAmount,
|
|
|
|
|
ProcessedAmount = x.ProcessedAmount,
|
|
|
|
|
OriginalProcessedAmount = x.OriginalProcessedAmount
|
|
|
|
|
OriginalProcessedAmount = x.OriginalProcessedAmount,
|
|
|
|
|
Currency = x.Currency,
|
|
|
|
|
OriginalCurrency = x.OriginalCurrency
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
if (details.Count == 0)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
|
|
|
|
@ -579,7 +573,9 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
|
DetailId = x.DetailId,
|
|
|
|
|
ApplyAmount = x.ApplyAmount,
|
|
|
|
|
OriginalAmount = x.OriginalAmount
|
|
|
|
|
OriginalAmount = x.OriginalAmount,
|
|
|
|
|
Currency = x.Currency,
|
|
|
|
|
OriginalCurrency = x.OriginalCurrency
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
foreach (var app in apps)
|
|
|
|
|