diff --git a/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs b/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs index aa581e2b..8f8de7e0 100644 --- a/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs +++ b/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs @@ -473,7 +473,11 @@ namespace DS.WMS.Core.Invoice.Method //invoice.InvoiceRemark = $"购买方地址电话:" + Environment.NewLine + invoice.CustomerAddressTel + Environment.NewLine // + "购买方开户行/账号:" + invoice.CustomerBankName + " " + invoice.CustomerAccount; if (!string.IsNullOrEmpty(invRemark)) + { invoice.Note += Environment.NewLine + invRemark; + invoice.InvoiceRemark += Environment.NewLine + invRemark; + } + } //筛选出新增的费用明细 diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs index 19356d05..ef02432f 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs @@ -49,14 +49,14 @@ namespace DS.WMS.Core.Settlement.Method ApplicationNO = x.ApplicationNO, SettlementNO = x.SettlementNO, SettlementTypeName = x.SettlementType.StlName, //结算方式 - - RMBAmount = SqlFunc.Subqueryable().Where(y => y.ApplicationId == x.Id && y.Currency == FeeCurrency.RMB_CODE) + + RMBAmount = SqlFunc.Subqueryable().Where(y => y.ApplicationId == x.Id && y.OriginalCurrency == FeeCurrency.RMB_CODE) .Select(y => SqlFunc.AggregateSum(y.OriginalAmount)), - USDAmount = SqlFunc.Subqueryable().Where(y => y.ApplicationId == x.Id && y.Currency == FeeCurrency.USD_CODE) + USDAmount = SqlFunc.Subqueryable().Where(y => y.ApplicationId == x.Id && y.OriginalCurrency == FeeCurrency.USD_CODE) .Select(y => SqlFunc.AggregateSum(y.OriginalAmount)), - OtherAmount = SqlFunc.Subqueryable().Where(y => y.ApplicationId == x.Id && y.Currency != FeeCurrency.RMB_CODE && y.Currency != FeeCurrency.USD_CODE) + OtherAmount = SqlFunc.Subqueryable().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 } } + /// + /// 保存申请结算 + /// + /// + /// + public override async Task> SaveAsync(SettlementRequest request) + { + var settlement = request.Settlement; + if (settlement.SettlementDate == default) + settlement.SettlementDate = DateTime.Now; + + if (settlement.BillType == 0) + return DataResult.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().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.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked)); + } + var result = EnsureSettlement(request.Settlement, dbValue); + if (!result.Succeeded) + return DataResult.Failed(result.Message, result.MultiCode); + + List? 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? 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(); + + 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() + .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.Failed("结算单据与费用明细不一致"); + + var exchange = doc.ExchangeRates?.Find(x => x.Currency == detail.OriginalCurrency); + if (exchange == null) + return DataResult.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.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.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.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.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero)); + + if (settlement.Details.Exists(x => x.OriginalCurrency.IsNullOrEmpty())) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull)); + + result = await PreSaveAsync(settlement); + if (!result.Succeeded) + return DataResult.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(); + if (!sequence.Succeeded) + { + return DataResult.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().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.Success(settlement); + } + catch (Exception ex) + { + await TenantDb.Ado.RollbackTranAsync(); + await ex.LogAsync(Db); + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); + } + } protected override async Task PreSaveAsync(ApplicationSettlement settlement) { diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs index 176c9e54..45173985 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs @@ -174,7 +174,8 @@ namespace DS.WMS.Core.Settlement.Method var cIds = inquiry.Items.Select(x => x.CustomerId).Distinct(); var list = await TenantDb.Queryable() - .Where(f => bizIds.Contains(f.BusinessId) && types.Contains(f.BusinessType) && cIds.Contains(f.CustomerId)) + .Where(f => bizIds.Contains(f.BusinessId) && types.Contains(f.BusinessType) && cIds.Contains(f.CustomerId) && + (f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) != 0) .Where(inquiry.GetConditionalModels(Db)) .Select(f => new FeeItem { @@ -369,11 +370,201 @@ namespace DS.WMS.Core.Settlement.Method return DataResult.Success(model); } - protected override async Task PreSaveAsync(ApplicationSettlement settlement) + /// + /// 保存自由结算 + /// + /// + /// + public override async Task> SaveAsync(SettlementRequest request) { - //settlement.Mode = SettlementMode.FreeSettlement; - //settlement.BillType = SettlementBillType.Payment; + var settlement = request.Settlement; + if (settlement.SettlementDate == default) + settlement.SettlementDate = DateTime.Now; + + settlement.Mode = SettlementMode.FreeSettlement; + if (settlement.BillType == 0) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.UnknownSettlementType)); + + ApplicationSettlement? dbValue = default; + if (request.Settlement.Id > 0) + { + dbValue = await TenantDb.Queryable().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.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked)); + } + var result = EnsureSettlement(request.Settlement, dbValue); + if (!result.Succeeded) + return DataResult.Failed(result.Message, result.MultiCode); + + List? details1 = null; + if (request.Details?.Count > 0) + { + if (settlement.Id == 0) + { + var first = request.Details[0]; + settlement.CustomerId = first.CustomerId; + settlement.CustomerName = first.CustomerName; + } + + details1 = request.Details.Select(x => new ApplicationDetail + { + RefId = x.ApplicationId, + DetailId = x.Id, + RecordId = x.RecordId, + CustomerName = x.CustomerName ?? settlement.CustomerName, + FeeId = x.FeeId, + FeeName = x.FeeName, + FeeType = x.FeeType, + ApplyAmount = x.RestAmount.GetValueOrDefault(), + Currency = x.Currency, + ExchangeRate = x.ExchangeRate, + OriginalAmount = x.OriginalAmount, + OriginalCurrency = x.OriginalCurrency ?? (settlement.Currency.IsNullOrEmpty() ? x.Currency : settlement.Currency), + }).ToList(); + } + + //按业务自由结算 + 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); + + + var types = request.Documents.Select(x => x.BusinessType.GetValueOrDefault()); + var custIds = request.Documents.Select(x => x.CustomerId); + details1 = await TenantDb.Queryable().Where(f => ids.Contains(f.BusinessId) && types.Contains(f.BusinessType) && custIds.Contains(f.CustomerId) && + (f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement) && (f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) != 0) + .Where(request.GetConditionalModels(Db)) + .Select(f => new ApplicationDetail + { + ApplicationId = settlement.Id, + BusinessId = f.BusinessId, + BusinessType = f.BusinessType, + RecordId = f.Id, + Category = f.FeeType == FeeType.Payable ? DetailCategory.PaidFreeSettlement : DetailCategory.ChargeFreeSettlement, + CustomerName = f.CustomerName ?? settlement.CustomerName, + FeeId = f.FeeId, + FeeName = f.FeeName, + FeeType = f.FeeType, + ApplyAmount = f.Amount - f.SettlementAmount, + Currency = f.Currency, + OriginalAmount = f.Amount - f.SettlementAmount, + OriginalCurrency = f.Currency, + ExchangeRate = f.ExchangeRate + }).ToListAsync(); + + if (!string.IsNullOrEmpty(settlement.Currency)) //指定结算币别 + { + 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.BusinessId && x.BusinessType == detail.BusinessType && x.CustomerName == x.CustomerName); + if (doc == null) + return DataResult.Failed("结算单据与费用明细不一致"); + + var exchange = doc.ExchangeRates?.Find(x => x.Currency == detail.OriginalCurrency); + if (exchange == null) + return DataResult.Failed($"未传入结算币别 {settlement.Currency} 与费用原币别 {detail.OriginalCurrency} 之间的汇率信息"); + + detail.ExchangeRate = exchange.ExchangeRate; + } + } + } + + //金额禁止为0 + if (settlement.Details.Exists(x => x.ApplyAmount == 0 || x.OriginalAmount == 0)) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero)); + + if (settlement.Details.Exists(x => x.OriginalCurrency.IsNullOrEmpty())) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull)); + + result = await PreSaveAsync(settlement); + if (!result.Succeeded) + return DataResult.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(); + if (!sequence.Succeeded) + { + return DataResult.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().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.Success(settlement); + } + catch (Exception ex) + { + await TenantDb.Ado.RollbackTranAsync(); + await ex.LogAsync(Db); + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); + } + } + + protected override async Task PreSaveAsync(ApplicationSettlement settlement) + { //获取剩余待结算金额 var ids = settlement.Details.Select(x => x.RecordId); var fees = await TenantDb.Queryable().Where(x => ids.Contains(x.Id)) diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Method/InvoiceSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Method/InvoiceSettlementService.cs index 4f611b99..050aa898 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Method/InvoiceSettlementService.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Method/InvoiceSettlementService.cs @@ -215,6 +215,178 @@ namespace DS.WMS.Core.Settlement.Method return list; } + public override async Task> SaveAsync(SettlementRequest request) + { + var settlement = request.Settlement; + if (settlement.SettlementDate == default) + settlement.SettlementDate = DateTime.Now; + + if (settlement.BillType == 0) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.UnknownSettlementType)); + + settlement.Mode = settlement.BillType == SettlementBillType.Payment ? SettlementMode.PaymentInvoiceSettlement : SettlementMode.InvoiceSettlement; + + ApplicationSettlement? dbValue = default; + if (request.Settlement.Id > 0) + { + dbValue = await TenantDb.Queryable().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.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked)); + } + var result = EnsureSettlement(request.Settlement, dbValue); + if (!result.Succeeded) + return DataResult.Failed(result.Message, result.MultiCode); + + List? details1 = null; + //按发票结算 + if (request.Documents?.Count > 0) + { + if (settlement.Id == 0) + { + var first = request.Documents[0]; + settlement.CustomerId = first.CustomerId; + settlement.CustomerName = first.CustomerName; + } + //发票结算 + Expressionable? 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(); + + 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 ids = request.Documents.Select(x => x.Id); + details1 = await TenantDb.Queryable().Where(x => ids.Contains(x.ApplicationId) && x.Category == DetailCategory.InvoiceIssuance) + .WhereIF(expr != null, expr.ToExpression()) + .Select(x => new ApplicationDetail + { + ApplicationId = settlement.Id, + RefId = x.ApplicationId, + DetailId = x.Id, + RecordId = x.RecordId, + Category = DetailCategory.InvoiceSettlement, + 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 (settlement.Currency != FeeCurrency.RMB_CODE) //发票结算非人民币需做转换 + { + 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.ApplicationId); + if (doc == null) + return DataResult.Failed("结算单据与费用明细不一致"); + + var exchange = doc.ExchangeRates?.Find(x => x.Currency == settlement.Currency); + if (exchange == null) + return DataResult.Failed($"使用发票做结算时,非 {FeeCurrency.RMB_CODE} 的费用必须指定汇率"); + + detail.ExchangeRate = exchange.ExchangeRate; + } + } + + } + + //金额禁止为0 + if (settlement.Details.Exists(x => x.ApplyAmount == 0 || x.OriginalAmount == 0)) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero)); + + if (settlement.Details.Exists(x => x.OriginalCurrency.IsNullOrEmpty())) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull)); + + result = await PreSaveAsync(settlement); + if (!result.Succeeded) + return DataResult.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(); + if (!sequence.Succeeded) + { + return DataResult.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().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.Success(settlement); + } + catch (Exception ex) + { + await TenantDb.Ado.RollbackTranAsync(); + await ex.LogAsync(Db); + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); + } + } protected override async Task PreSaveAsync(ApplicationSettlement settlement) { diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Method/SettlementService`1.cs b/ds-wms-service/DS.WMS.Core/Settlement/Method/SettlementService`1.cs index 94fb5f5a..ea23074a 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Method/SettlementService`1.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Method/SettlementService`1.cs @@ -22,7 +22,7 @@ namespace DS.WMS.Core.Settlement.Method public class SettlementService : FeeServiceBase, ISettlementService where TEntity : SettlementBase, new() { - readonly Lazy CommonService; + protected readonly Lazy SeqService; /// /// 初始化 @@ -30,7 +30,7 @@ namespace DS.WMS.Core.Settlement.Method /// DI容器 public SettlementService(IServiceProvider serviceProvider) : base(serviceProvider) { - CommonService = new Lazy(serviceProvider.GetRequiredService()); + SeqService = new Lazy(serviceProvider.GetRequiredService()); } @@ -41,7 +41,7 @@ namespace DS.WMS.Core.Settlement.Method /// /// /// - public async Task> SaveAsync(SettlementRequest request) + public virtual async Task> SaveAsync(SettlementRequest request) { var settlement = request.Settlement; if (settlement.SettlementDate == default) @@ -82,6 +82,7 @@ namespace DS.WMS.Core.Settlement.Method details1 = request.Details.Select(x => new ApplicationDetail { + Assigned = true, RefId = x.ApplicationId, DetailId = x.Id, RecordId = x.RecordId, @@ -98,7 +99,7 @@ namespace DS.WMS.Core.Settlement.Method } - if (request.Documents != 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); //按付费/发票申请/自由业务结算 @@ -175,6 +176,7 @@ namespace DS.WMS.Core.Settlement.Method .WhereIF(request.Documents.Any(x => x.SettlementOther.HasValue), x => x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE) .Select(x => new ApplicationDetail { + Assigned = true, ApplicationId = settlement.Id, RefId = x.ApplicationId, DetailId = x.Id, @@ -221,6 +223,7 @@ namespace DS.WMS.Core.Settlement.Method .Where(request.GetConditionalModels(Db)) .Select(f => new ApplicationDetail { + Assigned = true, ApplicationId = settlement.Id, BusinessId = f.BusinessId, BusinessType = f.BusinessType, @@ -310,7 +313,7 @@ namespace DS.WMS.Core.Settlement.Method if (settlement.Id == 0) { //创建时需要生成申请单编号 - var sequence = CommonService.Value.GetSequenceNext(); + var sequence = SeqService.Value.GetSequenceNext(); if (!sequence.Succeeded) { return DataResult.Failed(sequence.Message, MultiLanguageConst.SequenceSetNotExist); @@ -370,7 +373,7 @@ namespace DS.WMS.Core.Settlement.Method } } - static DataResult AssignAmount(List details, decimal stlAmount, string currency) + internal static DataResult AssignAmount(List details, decimal stlAmount, string currency) { if (details.Count == 0) return DataResult.Success;