|
|
|
@ -49,14 +49,14 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
ApplicationNO = x.ApplicationNO,
|
|
|
|
|
SettlementNO = x.SettlementNO,
|
|
|
|
|
SettlementTypeName = x.SettlementType.StlName, //结算方式
|
|
|
|
|
|
|
|
|
|
RMBAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.Currency == FeeCurrency.RMB_CODE)
|
|
|
|
|
|
|
|
|
|
RMBAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.OriginalCurrency == FeeCurrency.RMB_CODE)
|
|
|
|
|
.Select(y => SqlFunc.AggregateSum(y.OriginalAmount)),
|
|
|
|
|
|
|
|
|
|
USDAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.Currency == FeeCurrency.USD_CODE)
|
|
|
|
|
USDAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.OriginalCurrency == FeeCurrency.USD_CODE)
|
|
|
|
|
.Select(y => SqlFunc.AggregateSum(y.OriginalAmount)),
|
|
|
|
|
|
|
|
|
|
OtherAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.Currency != FeeCurrency.RMB_CODE && y.Currency != FeeCurrency.USD_CODE)
|
|
|
|
|
OtherAmount = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => y.ApplicationId == x.Id && y.OriginalCurrency != FeeCurrency.RMB_CODE && y.OriginalCurrency != FeeCurrency.USD_CODE)
|
|
|
|
|
.Select(y => SqlFunc.AggregateSum(y.OriginalAmount)),
|
|
|
|
|
|
|
|
|
|
CustomerAccount = x.CustomerBank.AccountName + "/" + x.CustomerBank.Currency,
|
|
|
|
@ -189,16 +189,16 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
|
|
|
|
|
//申请金额
|
|
|
|
|
var details = appDetails.Where(x => x.ApplicationId == item.Id);
|
|
|
|
|
item.RMBApplyAmount = details.Where(x => x.OriginalCurrency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount);
|
|
|
|
|
item.USDApplyAmount = details.Where(x => x.OriginalCurrency == FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount);
|
|
|
|
|
item.RMBApplyAmount = details.Where(x => x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount);
|
|
|
|
|
item.USDApplyAmount = details.Where(x => x.Currency == FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount);
|
|
|
|
|
|
|
|
|
|
//本次结算金额
|
|
|
|
|
item.RMBStlAmount = details.Where(x => appIds.Contains(x.Id) && x.OriginalCurrency == FeeCurrency.RMB_CODE).Sum(x => x.ProcessedAmount);
|
|
|
|
|
item.USDStlAmount = details.Where(x => appIds.Contains(x.Id) && x.OriginalCurrency == FeeCurrency.USD_CODE).Sum(x => x.ProcessedAmount);
|
|
|
|
|
item.RMBStlAmount = details.Where(x => appIds.Contains(x.Id) && x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.ProcessedAmount);
|
|
|
|
|
item.USDStlAmount = details.Where(x => appIds.Contains(x.Id) && x.Currency == FeeCurrency.USD_CODE).Sum(x => x.ProcessedAmount);
|
|
|
|
|
|
|
|
|
|
//剩余结算金额
|
|
|
|
|
item.RMBStlRestAmount = (item.RMBApplyAmount - item.RMBStlAmount).GetValueOrDefault();
|
|
|
|
|
item.RMBStlRestAmount = (item.USDApplyAmount - item.USDStlAmount).GetValueOrDefault();
|
|
|
|
|
//剩余未结金额
|
|
|
|
|
item.RMBStlRestAmount = details.Where(x => appIds.Contains(x.Id) && x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount - x.ProcessedAmount);
|
|
|
|
|
item.RMBStlRestAmount = details.Where(x => appIds.Contains(x.Id) && x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount - x.ProcessedAmount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
@ -443,6 +443,217 @@ namespace DS.WMS.Core.Settlement.Method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 保存申请结算
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="request"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public override async Task<DataResult<ApplicationSettlement>> SaveAsync(SettlementRequest<ApplicationSettlement> request)
|
|
|
|
|
{
|
|
|
|
|
var settlement = request.Settlement;
|
|
|
|
|
if (settlement.SettlementDate == default)
|
|
|
|
|
settlement.SettlementDate = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
if (settlement.BillType == 0)
|
|
|
|
|
return DataResult<ApplicationSettlement>.FailedWithDesc(nameof(MultiLanguageConst.UnknownSettlementType));
|
|
|
|
|
|
|
|
|
|
settlement.Mode = settlement.BillType == SettlementBillType.Payment ? SettlementMode.Payment : SettlementMode.Charge;
|
|
|
|
|
|
|
|
|
|
ApplicationSettlement? dbValue = default;
|
|
|
|
|
if (request.Settlement.Id > 0)
|
|
|
|
|
{
|
|
|
|
|
dbValue = await TenantDb.Queryable<ApplicationSettlement>().Select(x => new ApplicationSettlement
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
IsLocked = x.IsLocked,
|
|
|
|
|
Mode = x.Mode
|
|
|
|
|
}).FirstAsync(x => x.Id == request.Settlement.Id);
|
|
|
|
|
|
|
|
|
|
if (dbValue != null && dbValue.IsLocked)
|
|
|
|
|
return DataResult<ApplicationSettlement>.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked));
|
|
|
|
|
}
|
|
|
|
|
var result = EnsureSettlement(request.Settlement, dbValue);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<ApplicationSettlement>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
|
|
|
|
|
List<ApplicationDetail>? details1 = null;
|
|
|
|
|
if (request.Documents != null && (settlement.Mode == SettlementMode.Payment || settlement.Mode == SettlementMode.Charge))
|
|
|
|
|
request.Documents = request.Documents.FindAll(x => x.SettlementUSD.HasValue || x.SettlementRMB.HasValue || x.SettlementOther.HasValue);
|
|
|
|
|
|
|
|
|
|
//按申请结算
|
|
|
|
|
if (request.Documents?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
if (settlement.Id == 0)
|
|
|
|
|
{
|
|
|
|
|
var first = request.Documents[0];
|
|
|
|
|
settlement.CustomerId = first.CustomerId;
|
|
|
|
|
settlement.CustomerName = first.CustomerName;
|
|
|
|
|
}
|
|
|
|
|
var ids = request.Documents.Select(x => x.Id);
|
|
|
|
|
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.Or(x => x.Currency == FeeCurrency.RMB_CODE);
|
|
|
|
|
|
|
|
|
|
if (request.Documents.Any(x => x.SettlementUSD.GetValueOrDefault() != 0))
|
|
|
|
|
expr = expr.Or(x => x.Currency == FeeCurrency.USD_CODE);
|
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
|
RefId = x.ApplicationId,
|
|
|
|
|
DetailId = x.Id,
|
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
|
Category = settlement.Mode == SettlementMode.Payment ? DetailCategory.PaidApplicationSettlement : DetailCategory.ChargeApplicationSettlement,
|
|
|
|
|
CustomerName = x.CustomerName ?? settlement.CustomerName,
|
|
|
|
|
FeeId = x.FeeId,
|
|
|
|
|
FeeName = x.FeeName,
|
|
|
|
|
FeeType = x.FeeType,
|
|
|
|
|
|
|
|
|
|
ApplyAmount = x.ApplyAmount - x.ProcessedAmount,
|
|
|
|
|
Currency = x.Currency,
|
|
|
|
|
OriginalAmount = x.OriginalAmount - x.OriginalProcessedAmount,
|
|
|
|
|
OriginalCurrency = x.OriginalCurrency,
|
|
|
|
|
ExchangeRate = x.ExchangeRate
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(settlement.Currency)) //指定结算币别
|
|
|
|
|
{
|
|
|
|
|
var details2 = details1.FindAll(x => x.OriginalCurrency != settlement.Currency);
|
|
|
|
|
foreach (var detail in details2)
|
|
|
|
|
{
|
|
|
|
|
var doc = request.Documents.Find(x => x.Id == detail.RefId);
|
|
|
|
|
if (doc == null)
|
|
|
|
|
return DataResult<ApplicationSettlement>.Failed("结算单据与费用明细不一致");
|
|
|
|
|
|
|
|
|
|
var exchange = doc.ExchangeRates?.Find(x => x.Currency == detail.OriginalCurrency);
|
|
|
|
|
if (exchange == null)
|
|
|
|
|
return DataResult<ApplicationSettlement>.Failed($"未传入结算币别 {settlement.Currency} 与费用原币别 {detail.OriginalCurrency} 之间的汇率信息");
|
|
|
|
|
|
|
|
|
|
detail.ExchangeRate = exchange.ExchangeRate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//执行结算费用分配
|
|
|
|
|
foreach (var doc in request.Documents)
|
|
|
|
|
{
|
|
|
|
|
var details2 = settlement.Mode != SettlementMode.FreeSettlement ?
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
if (doc.SettlementRMB.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var rmbDetails = details2.Where(x => x.OriginalCurrency == FeeCurrency.RMB_CODE).ToList();
|
|
|
|
|
result = AssignAmount(rmbDetails, doc.SettlementRMB.Value, settlement.Currency);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<ApplicationSettlement>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
}
|
|
|
|
|
if (doc.SettlementUSD.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var usdDetails = details2.Where(x => x.OriginalCurrency == FeeCurrency.USD_CODE).ToList();
|
|
|
|
|
result = AssignAmount(usdDetails, doc.SettlementUSD.Value, settlement.Currency);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<ApplicationSettlement>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
}
|
|
|
|
|
if (doc.SettlementOther.HasValue)
|
|
|
|
|
{
|
|
|
|
|
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<ApplicationSettlement>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (details1?.Count > 0)
|
|
|
|
|
settlement.Details.AddRange(details1.FindAll(x => x.Assigned));
|
|
|
|
|
|
|
|
|
|
//金额禁止为0
|
|
|
|
|
if (settlement.Details.Exists(x => x.ApplyAmount == 0 || x.OriginalAmount == 0))
|
|
|
|
|
return DataResult<ApplicationSettlement>.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero));
|
|
|
|
|
|
|
|
|
|
if (settlement.Details.Exists(x => x.OriginalCurrency.IsNullOrEmpty()))
|
|
|
|
|
return DataResult<ApplicationSettlement>.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull));
|
|
|
|
|
|
|
|
|
|
result = await PreSaveAsync(settlement);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<ApplicationSettlement>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
|
|
|
|
|
var details = settlement.Details.FindAll(x => x.Id == 0);
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//关联导航属性插入
|
|
|
|
|
if (settlement.Id == 0)
|
|
|
|
|
{
|
|
|
|
|
//创建时需要生成申请单编号
|
|
|
|
|
var sequence = SeqService.Value.GetSequenceNext<ApplicationSettlement>();
|
|
|
|
|
if (!sequence.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
return DataResult<ApplicationSettlement>.Failed(sequence.Message, MultiLanguageConst.SequenceSetNotExist);
|
|
|
|
|
}
|
|
|
|
|
settlement.ApplicationNO = "ST" + SnowFlakeSingle.Instance.NextId(); //申请编号
|
|
|
|
|
settlement.SettlementNO = sequence.Data; //结算单号
|
|
|
|
|
|
|
|
|
|
await TenantDb.InsertNav(settlement).Include(x => x.Details).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (details.Count > 0)
|
|
|
|
|
await TenantDb.Insertable(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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await OnSaveAsync(settlement);
|
|
|
|
|
|
|
|
|
|
if (details.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
//更新费用记录的已结算金额
|
|
|
|
|
var fees = 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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//计算结算总金额
|
|
|
|
|
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();
|
|
|
|
|
await PostSaveAsync(settlement);
|
|
|
|
|
return DataResult<ApplicationSettlement>.Success(settlement);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
await TenantDb.Ado.RollbackTranAsync();
|
|
|
|
|
await ex.LogAsync(Db);
|
|
|
|
|
return DataResult<ApplicationSettlement>.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override async Task<DataResult> PreSaveAsync(ApplicationSettlement settlement)
|
|
|
|
|
{
|
|
|
|
|