创建付费申请结算单

usertest
嵇文龙 5 months ago
parent f8015c2a54
commit 373646d302

@ -26,7 +26,7 @@ public static class MultiLanguageConst
/// 未能获取指定的数据
/// </summary>
[Description("未能获取指定的数据")]
public const string DataNotFound = "Data_NotFound";
public const string EmptyData = "Empty_Data";
/// <summary>
/// 查询成功
/// </summary>
@ -573,8 +573,8 @@ public static class MultiLanguageConst
#endregion
#region 申请相关
[Description("申请单明细的结算对象有且只能有一个")]
public const string ApplicationCustomerOnlyOne = "Application_Customer_OnlyOne";
[Description("费用明细的结算对象有且只能有一个")]
public const string DetailCustomerOnlyOne = "Application_Customer_OnlyOne";
[Description("申请单明细每次提交只能对应一条费用记录")]
public const string ApplicationRecordOnlyOne = "Application_Record_OnlyOne";
[Description("提交审批时必须包含费用明细")]
@ -608,4 +608,11 @@ public static class MultiLanguageConst
[Description("模板")]
public const string DefaultTemplateName = "Default_Template_Name";
#endregion
#region 结算相关
[Description("结算单已被锁定,禁止提交")]
public const string SettlementIsLocked = "Settlement_IsLocked";
[Description("只能选择状态为:审核通过/部分结算的申请")]
public const string ApplicationSelectStatusError = "Application_Select_StatusError";
#endregion
}

@ -55,7 +55,7 @@ public static partial class Extensions
/// <param name="page">分页设置</param>
/// <returns></returns>
public static async Task<DataResult<List<TEntity>>> ToQueryPageAsync<TEntity>(this ISugarQueryable<TEntity> source,
PageCondition page)
PageCondition? page)
{
page.NotNull(nameof(page));
var result = page.IsExport ? await source.WhereNoPageAsync(page.SortConditions) : await source.WhereAsync(page.PageIndex, page.PageSize, page.SortConditions);

@ -1,4 +1,7 @@
namespace DS.Module.Core;
using DS.Module.Core.Extensions;
using SqlSugar;
namespace DS.Module.Core;
/// <summary>
/// 查询请求实体
@ -8,15 +11,42 @@ public class PageRequest
/// <summary>
/// 查询条件
/// </summary>
public string QueryCondition { get; set; }
public string QueryCondition { get; set; } = string.Empty;
/// <summary>
/// 其他查询条件
/// </summary>
public string OtherQueryCondition { get; set; }
public string? OtherQueryCondition { get; set; }
/// <summary>
/// 分页排序条件
/// </summary>
public PageCondition PageCondition { get; set; }
public PageCondition? PageCondition { get; set; }
/// <summary>
/// 获取当前实例的查询条件
/// </summary>
/// <param name="client">SqlSugar对象</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException">当<paramref name="client"/>为null时引发</exception>
public List<IConditionalModel> GetConditionalModels(ISqlSugarClient client)
{
if (QueryCondition.IsNullOrEmpty())
return [];
ArgumentNullException.ThrowIfNull(client, nameof(client));
return client.ConfigQuery.Context.Utilities.JsonToConditionalModels(QueryCondition);
}
}
}
/// <summary>
/// 查询请求实体的泛型版本
/// </summary>
/// <typeparam name="T">查他查询条件的类型</typeparam>
public class PageRequest<T> : PageRequest
{
/// <summary>
/// 其他查询条件
/// </summary>
public new T? OtherQueryCondition { get; set; }
}

@ -13,6 +13,14 @@ namespace DS.WMS.Core.Application.Dtos
/// </summary>
public long Id { get; set; }
/// <summary>
/// 申请单ID
/// </summary>
public long ApplicationId { get; set; }
/// <summary>
/// 费用记录ID
/// </summary>
public long RecordId { get; set; }
/// <summary>

@ -43,6 +43,18 @@ namespace DS.WMS.Core.Application.Entity
[Navigate(NavigateType.OneToOne, nameof(RecordId))]
public FeeRecord? Record { get; set; }
/// <summary>
/// 引用的明细ID用于结算
/// </summary>
[SugarColumn(ColumnDescription = "引用的明细ID")]
public long? DetailId { get; set; }
/// <summary>
/// 引用的明细(用于结算)
/// </summary>
[Navigate(NavigateType.OneToOne, nameof(DetailId))]
public ApplicationDetail? RefDetail { get; set; }
/// <summary>
/// 结算对象名称
/// </summary>

@ -60,7 +60,7 @@ namespace DS.WMS.Core.Application.Method
}).ToListAsync();
if (apps.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DataNotFound));
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
if (apps.Exists(x => !x.FlowId.HasValue))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NotInFlows));
@ -148,7 +148,7 @@ namespace DS.WMS.Core.Application.Method
if (app == null)
{
await new ApplicationException($"未能获取ID={callback.BusinessId}的申请单,回调更新失败").LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DataNotFound));
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
}
DateTime dtNow = DateTime.Now;

@ -52,7 +52,7 @@ namespace DS.WMS.Core.Application.Method
x => new TEntity { Status = x.Status, Currency = x.Currency }).FirstAsync();
if (dbValue == null)
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.DataNotFound));
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
}
application.Details ??= [];
@ -67,7 +67,7 @@ namespace DS.WMS.Core.Application.Method
application.Details.RemoveAll(x => x.Id > 0);
if (application.Details.GroupBy(x => x.CustomerName).Select(x => x.Key).Count() > 1)
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.ApplicationCustomerOnlyOne));
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.DetailCustomerOnlyOne));
if (application.Details.GroupBy(x => x.RecordId).Where(g => g.Count() > 1).Select(x => x.Key).Count() > 0)
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.ApplicationRecordOnlyOne));
@ -389,7 +389,7 @@ namespace DS.WMS.Core.Application.Method
}).ToListAsync();
if (list.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DataNotFound));
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
if (list.Exists(x => x.DetailCount == 0))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationMustHaveDetail));
@ -472,7 +472,7 @@ namespace DS.WMS.Core.Application.Method
}).ToListAsync();
if (list.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DataNotFound));
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
//未在审批状态中
var list2 = list.FindAll(x => x.FlowId == null).ToList();
if (list2.Count > 0)

@ -92,7 +92,7 @@ namespace DS.WMS.Core.Application.Method
{
var dto = await GetTemplateFormAsync(id);
if (dto == null)
return DataResult<string>.FailedWithDesc(nameof(MultiLanguageConst.DataNotFound));
return DataResult<string>.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
string json = JsonConvert.SerializeObject(dto);
var jObj = JObject.Parse(json);

@ -466,7 +466,7 @@ namespace DS.WMS.Core.Fee.Method
}).ToListAsync();
if (fees.Count == 0)
return DataResult.Failed(MultiLanguageConst.DataNotFound);
return DataResult.Failed(MultiLanguageConst.EmptyData);
if (fees.Exists(x => !x.FlowId.HasValue))
return DataResult.Failed(MultiLanguageConst.NotInFlows);
@ -579,7 +579,7 @@ namespace DS.WMS.Core.Fee.Method
}).ToListAsync();
if (bizList.Count == 0)
return DataResult.Failed(MultiLanguageConst.DataNotFound);
return DataResult.Failed(MultiLanguageConst.EmptyData);
if (!bizList.Any(x => x.FlowId.HasValue))
return DataResult.Failed(MultiLanguageConst.NotInFlows);

@ -709,7 +709,7 @@ namespace DS.WMS.Core.Fee.Method
x.Name
}).FirstAsync();
if (model == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DataNotFound));
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
var list = idArray.Select(x => new FeeRecord
{

@ -1,6 +1,5 @@
using DS.WMS.Core.Application.Dtos;
using SqlSugar;
using System.Runtime.Serialization;
using System.Runtime.Serialization;
using DS.WMS.Core.Application.Dtos;
namespace DS.WMS.Core.Settlement.Dtos
{

@ -0,0 +1,20 @@
using DS.WMS.Core.Application.Dtos;
namespace DS.WMS.Core.Settlement.Dtos
{
/// <summary>
/// 结算明细DTO
/// </summary>
public class SettlementDetailDto : ApplicationDetailDto
{
/// <summary>
/// 结算金额
/// </summary>
public decimal SettlementAmount { get; set; }
/// <summary>
/// 发票号
/// </summary>
public string? InvoiceNO { get; set; }
}
}

@ -0,0 +1,20 @@
using DS.WMS.Core.Settlement.Entity;
namespace DS.WMS.Core.Settlement.Dtos
{
/// <summary>
/// 提交结算单请求参数
/// </summary>
public class SettlementRequest<TEntity> where TEntity : SettlementBase
{
/// <summary>
/// 结算单
/// </summary>
public TEntity Settlement { get; set; }
/// <summary>
/// 申请明细
/// </summary>
public List<SettlementDetailDto>? Details { get; set; }
}
}

@ -1,4 +1,5 @@
using SqlSugar;
using DS.WMS.Core.Application.Entity;
using SqlSugar;
namespace DS.WMS.Core.Settlement.Entity
{
@ -8,6 +9,12 @@ namespace DS.WMS.Core.Settlement.Entity
[SugarTable("application_payment_settlement", TableDescription = "付费结算")]
public class PaymentSettlement : SettlementBase
{
/// <summary>
/// 继承自<see cref="ApplicationBase"/>,由于付费结算不存在状态,访问此属性将始终引发<see cref="NotSupportedException"/>异常
/// </summary>
/// <exception cref="NotSupportedException">始终引发此异常</exception>
public new int Status => throw new NotSupportedException();
/// <summary>
/// 汇率
/// </summary>

@ -1,5 +1,6 @@
using DS.Module.Core;
using DS.WMS.Core.Application.Dtos;
using DS.WMS.Core.Application.Interface;
using DS.WMS.Core.Settlement.Dtos;
using DS.WMS.Core.Settlement.Entity;
@ -22,6 +23,13 @@ namespace DS.WMS.Core.Settlement.Interface
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<DataResult<List<PaymentApplicationDto>>> GetApplicationListAsync(PageRequest request);
Task<DataResult<List<PaymentApplicationDto>>> GetApplicationListAsync(PageRequest<bool> request);
/// <summary>
/// 获取付费申请的费用明细
/// </summary>
/// <param name="id">申请单ID</param>
/// <returns></returns>
Task<DataResult<List<SettlementDetailDto>>> GetDetailsAsync(long id);
}
}

@ -1,13 +1,33 @@
using DS.WMS.Core.Settlement.Entity;
using DS.Module.Core;
using DS.WMS.Core.Settlement.Entity;
namespace DS.WMS.Core.Settlement.Interface
namespace DS.WMS.Core.Application.Interface
{
/// <summary>
/// 定义结算基础服务
/// 结算基础服务定义
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public interface ISettlementService<in TEntity> where TEntity : SettlementBase, new()
/// <typeparam name="TEntity">实体的类型声明</typeparam>
public interface ISettlementService<TEntity> where TEntity : SettlementBase, new()
{
/// <summary>
/// 提交结算单
/// </summary>
/// <param name="application"></param>
/// <returns></returns>
Task<DataResult<TEntity>> SaveAsync(TEntity application);
/// <summary>
/// 删除结算明细
/// </summary>
/// <param name="ids">明细ID</param>
/// <returns></returns>
Task<DataResult> DeleteDetailAsync(params long[] ids);
/// <summary>
/// 删除结算单
/// </summary>
/// <param name="ids">结算单ID</param>
/// <returns></returns>
Task<DataResult> DeleteAsync(params long[] ids);
}
}

@ -1,9 +1,12 @@
using DS.Module.Core;
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;
@ -76,13 +79,8 @@ namespace DS.WMS.Core.Settlement.Method
//Category = x.Category, //业务类别
});
if (!request.QueryCondition.IsNullOrEmpty())
{
var whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition);
query = query.Where(whereList);
}
var result = await query.ToQueryPageAsync(request.PageCondition);
var whereList = request.GetConditionalModels(Db);
var result = await query.Where(whereList).ToQueryPageAsync(request.PageCondition);
if (result.Data.Count > 0)
{
//关联用户名称
@ -113,12 +111,10 @@ namespace DS.WMS.Core.Settlement.Method
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<PaymentApplicationDto>>> GetApplicationListAsync(PageRequest request)
public async Task<DataResult<List<PaymentApplicationDto>>> GetApplicationListAsync(PageRequest<bool> request)
{
var query = TenantDb.Queryable<PaymentApplication>().Where(x => x.Status == PaymentApplicationStatus.AuditPassed)
.InnerJoin<ApplicationDetail>((a, d) => a.Id == d.ApplicationId)
//未结算金额=(金额-已结算金额-申请金额+申请金额已结算) != 0
.InnerJoin<FeeRecord>((a, d, f) => d.RecordId == f.Id && (f.Amount - f.SettlementAmount - d.ApplyAmount + f.OrderSettlementAmount) != 0)
var query = TenantDb.Queryable<PaymentApplication>().Where(a => a.Status == PaymentApplicationStatus.AuditPassed || a.Status == PaymentApplicationStatus.PartialSettlement)
.WhereIF(request.OtherQueryCondition, a => a.Status != PaymentApplicationStatus.SettlementCompleted && SqlFunc.Subqueryable<ApplicationDetail>().Where(d => d.ApplicationId == a.Id && (d.ApplyAmount - d.ProcessedAmount) != 0).Any())
.Select(a => new PaymentApplicationDto
{
Id = a.Id,
@ -133,11 +129,11 @@ namespace DS.WMS.Core.Settlement.Method
AmountRMB = a.AmountRMB, //RMB申请金额
AmountUSD = a.AmountUSD, //USD申请金额
//RMB未结金额
UnSettlementRMB = SqlFunc.Subqueryable<ApplicationDetail>().InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id).Where(d => d.Currency == RMB_CODE)
.Select((d, f) => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - d.ApplyAmount + f.OrderSettlementAmount)),
UnSettlementRMB = SqlFunc.Subqueryable<ApplicationDetail>().Where(d => d.Currency == RMB_CODE)
.Select(d => SqlFunc.AggregateSum(d.ApplyAmount - d.ProcessedAmount)),
//USD未结金额
UnSettlementUSD = SqlFunc.Subqueryable<ApplicationDetail>().InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id).Where(d => d.Currency == USD_CODE)
.Select((d, f) => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - d.ApplyAmount + f.OrderSettlementAmount)),
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, //结算方式
@ -151,31 +147,301 @@ namespace DS.WMS.Core.Settlement.Method
Note = a.Note
});
if (!request.QueryCondition.IsNullOrEmpty())
{
var whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition);
query = query.Where(whereList);
}
var result = await query.ToQueryPageAsync(request.PageCondition);
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).Distinct().ToList();
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<SettlementDetailDto>>> GetDetailsAsync(long id)
{
var details = await TenantDb.Queryable<ApplicationDetail>().Where(d => d.ApplicationId == id && (d.ApplyAmount - d.ProcessedAmount) != 0)
.InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id)
.InnerJoin<BusinessFeeStatus>((d, f, b) => f.BusinessId == b.BusinessId && f.BusinessType == b.BusinessType)
.Select((d, f, b) => new SettlementDetailDto
{
Id = d.Id,
ApplicationId = d.ApplicationId,
RecordId = d.RecordId,
FeeName = d.FeeName,
FeeType = d.FeeType, //收付
Amount = d.ApplyAmount, //申请金额
SettlementAmount = d.ApplyAmount, //结算金额默认=申请金额
CustomerId = f.CustomerId,
CustomerName = d.CustomerName,
OriginalCurrency = d.OriginalCurrency, //原始币别
OriginalRate = f.ExchangeRate, //原始汇率
ExchangeRate = d.ExchangeRate, //折算汇率
OriginalAmount = d.OriginalAmount, //原始金额
InvoiceNO = f.InvoiceNO, //发票号
BusinessId = f.BusinessId,
BusinessType = f.BusinessType
}).ToListAsync();
if (details.Count > 0)
{
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, //业务来源
}).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;
}
}
break;
case BusinessType.OceanShippingImport:
break;
}
}
}
return DataResult<List<SettlementDetailDto>>.Success(details);
}
/// <summary>
/// 创建结算单
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<PaymentSettlement>> CreateAsync(SettlementRequest<PaymentSettlement> request)
{
var ids = request.Details.Select(x => x.ApplicationId).Distinct();
var appList = await TenantDb.Queryable<PaymentApplication>().Where(x => ids.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.AuditSubmittd && 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.SettlementAmount == 0))
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero));
StringBuilder sb = new();
var appDetails = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId))
.Select(x => new
{
x.Id,
x.ApplicationId,
x.ApplyAmount,
x.BusinessId,
x.BusinessType,
x.Currency,
x.CustomerName,
x.FeeId,
x.FeeName,
x.FeeType,
x.OriginalAmount,
x.OriginalCurrency,
x.ProcessedAmount,
x.OriginalProcessedAmount,
}).ToListAsync();
foreach (var item in request.Details)
{
var appDetail = appDetails.Find(x => x.Id == item.Id);
decimal restValue = appDetail.ApplyAmount - appDetail.ProcessedAmount;
if (item.SettlementAmount > 0 && item.SettlementAmount > restValue)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), item.FeeName);
sb.Append("");
continue;
}
else if (item.SettlementAmount < 0 && item.SettlementAmount < restValue)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), item.FeeName);
sb.Append("");
continue;
}
}
if (sb.Length > 0)
return DataResult<PaymentSettlement>.Failed(sb.ToString());
var ids2 = request.Details.Select(x => x.RecordId).Distinct().ToList();
var fees = await TenantDb.Queryable<FeeRecord>().Where(x => ids2.Contains(x.Id)).Select(x => new FeeRecord
{
Id = x.Id,
//BusinessId = x.BusinessId,
//BusinessType = x.BusinessType,
//FeeId = x.FeeId,
//FeeName = x.FeeName,
//FeeType = x.FeeType,
//CustomerId = x.CustomerId,
//CustomerName = x.CustomerName,
Amount = x.Amount,
//Currency = x.Currency,
//ExchangeRate = x.ExchangeRate,
//OrderAmount = x.OrderAmount,
OrderSettlementAmount = x.OrderSettlementAmount,
//SettlementAmount = x.SettlementAmount
}).ToListAsync();
if (fees.Count != request.Details.Count)
return DataResult<PaymentSettlement>.FailedWithDesc(nameof(MultiLanguageConst.FeeRecordNone));
var settlement = request.Settlement;
if (settlement.SettlementDate == default)
settlement.SettlementDate = DateTime.Now;
if (settlement.Id == 0)
{
var app = appList[0];
settlement.CustomerId = app.CustomerId;
settlement.CustomerName = app.CustomerName;
}
settlement.Mode = SettlementMode.ChargeAndPayment;
settlement.BillType = SettlementBillType.Payment;
settlement.Amount = request.Details.Sum(x => x.SettlementAmount);
settlement.Details = request.Details.Select(x => new ApplicationDetail
{
ApplicationId = x.ApplicationId,
DetailId = x.Id,
ApplyAmount = x.SettlementAmount,
BusinessId = x.BusinessId,
BusinessType = x.BusinessType,
Category = FeeCategory.PaidApplicationSettlement,
Currency = x.Currency,
CustomerName = x.CustomerName,
ExchangeRate = x.ExchangeRate,
FeeId = x.FeeId,
FeeName = x.FeeName,
FeeType = x.FeeType,
OriginalAmount = x.OriginalAmount,
OriginalCurrency = x.OriginalCurrency
}).ToList();
foreach (var detail in settlement.Details)
{
//var fee = fees.Find(x => x.Id == detail.RecordId);
//detail.BusinessId = fee.BusinessId;
//detail.BusinessType = fee.BusinessType;
//detail.ExchangeRate = detail.ExchangeRate ?? fee.ExchangeRate;
//detail.FeeId = fee.FeeId;
//detail.FeeName = fee.FeeName;
//detail.FeeType = fee.FeeType;
detail.CustomerName = detail.CustomerName ?? settlement.CustomerName;
//原币申请
if (settlement.Currency.IsNullOrEmpty())
{
detail.OriginalAmount = detail.ApplyAmount;
//if (detail.OriginalCurrency.IsNullOrEmpty())
// detail.OriginalCurrency = fee.Currency;
}
}
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.CreateBy,
x.CreateTime,
x.Deleted,
x.DeleteBy,
x.DeleteTime
}).ExecuteCommandAsync();
}
if (fees != null && fees.Count > 0)
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));
}
}
}
}

@ -1,6 +1,8 @@
using DS.WMS.Core.Fee.Method;
using DS.Module.Core;
using DS.WMS.Core.Application.Entity;
using DS.WMS.Core.Application.Interface;
using DS.WMS.Core.Fee.Method;
using DS.WMS.Core.Settlement.Entity;
using DS.WMS.Core.Settlement.Interface;
using DS.WMS.Core.Sys.Interface;
using Microsoft.Extensions.DependencyInjection;
@ -13,7 +15,7 @@ namespace DS.WMS.Core.Settlement.Method
public class SettlementService<TEntity> : FeeServiceBase, ISettlementService<TEntity>
where TEntity : SettlementBase, new()
{
readonly Lazy<ICommonService> commonService;
protected readonly Lazy<ICommonService> CommonService;
/// <summary>
/// 初始化
@ -21,9 +23,132 @@ namespace DS.WMS.Core.Settlement.Method
/// <param name="serviceProvider">DI容器</param>
public SettlementService(IServiceProvider serviceProvider) : base(serviceProvider)
{
commonService = new Lazy<ICommonService>(serviceProvider.GetRequiredService<ICommonService>());
CommonService = new Lazy<ICommonService>(serviceProvider.GetRequiredService<ICommonService>());
}
#region 保存
public Task<DataResult<TEntity>> SaveAsync(TEntity application)
{
throw new NotImplementedException();
}
#endregion
#region 删除
/// <summary>
/// 删除结算单明细
/// </summary>
/// <param name="ids">结算单明细ID</param>
/// <returns></returns>
public async Task<DataResult> DeleteDetailAsync(params long[] ids)
{
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.Id)).Select(
x => new ApplicationDetail
{
Id = x.Id,
ApplicationId = x.ApplicationId,
RecordId = x.RecordId,
OriginalAmount = x.OriginalAmount
}).ToListAsync();
var appIds = details.Select(x => x.ApplicationId).Distinct().ToList();
var apps = await TenantDb.Queryable<TEntity>().Where(x => appIds.Contains(x.Id)).Select(x => new TEntity
{
Id = x.Id,
Status = x.Status
}).ToListAsync();
foreach (var app in apps)
app.Details = details.FindAll(x => x.ApplicationId == app.Id);
var result = PreDelete(apps);
if (!result.Succeeded)
return result;
await TenantDb.Ado.BeginTranAsync();
try
{
await OnDeleteDetailAsync(apps);
await TenantDb.Deleteable(details).ExecuteCommandAsync();
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 删除结算单
/// </summary>
/// <param name="ids">结算单ID</param>
/// <returns></returns>
public async Task<DataResult> DeleteAsync(params long[] ids)
{
var apps = await TenantDb.Queryable<TEntity>().Where(x => ids.Contains(x.Id)).Select(x => new TEntity
{
Id = x.Id,
Status = x.Status
}).ToListAsync();
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId)).Select(
x => new ApplicationDetail
{
Id = x.Id,
RecordId = x.RecordId,
OriginalAmount = x.OriginalAmount
}).ToListAsync();
foreach (var app in apps)
app.Details = details.FindAll(x => x.ApplicationId == app.Id); await TenantDb.Ado.BeginTranAsync();
var result = PreDelete(apps);
if (!result.Succeeded)
return result;
try
{
await OnDeleteDetailAsync(apps);
await TenantDb.DeleteNav<TEntity>(x => ids.Contains(x.Id)).Include(x => x.Details).ExecuteCommandAsync();
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 在删除结算单或其明细之前调用,用于检查状态
/// </summary>
/// <param name="settlements">结算单</param>
/// <returns></returns>
protected virtual DataResult PreDelete(List<TEntity> settlements)
{
return DataResult.Success;
}
/// <summary>
/// 在执行删除结算单或其明细时调用
/// </summary>
/// <param name="settlements">结算单及其明细</param>
/// <returns></returns>
protected virtual Task OnDeleteDetailAsync(List<TEntity> settlements)
{
return Task.CompletedTask;
}
#endregion
}
}

@ -39,9 +39,20 @@ namespace DS.WMS.FeeApi.Controllers
/// <param name="request"></param>
/// <returns></returns>
[HttpPost, Route("GetApplicationList")]
public async Task<DataResult<List<PaymentApplicationDto>>> GetApplicationListAsync([FromBody] PageRequest request)
public async Task<DataResult<List<PaymentApplicationDto>>> GetApplicationListAsync([FromBody] PageRequest<bool> request)
{
return await _service.GetApplicationListAsync(request);
}
/// <summary>
/// 获取付费申请的费用明细
/// </summary>
/// <param name="id">申请单ID</param>
/// <returns></returns>
[HttpGet, Route("GetDetails")]
public async Task<DataResult<List<SettlementDetailDto>>> GetDetailsAsync(long id)
{
return await _service.GetDetailsAsync(id);
}
}
}

@ -2000,3 +2000,31 @@
2024-07-03 17:13:05.1459 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config
2024-07-03 17:13:05.1459 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile
2024-07-03 17:13:05.1607 Info Configuration initialized.
2024-07-04 10:05:30.0363 Info Registered target NLog.Targets.FileTarget(Name=allfile)
2024-07-04 10:05:30.1149 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web)
2024-07-04 10:05:30.1149 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console)
2024-07-04 10:05:30.1414 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False
2024-07-04 10:05:30.1414 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config
2024-07-04 10:05:30.1574 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile
2024-07-04 10:05:30.1574 Info Configuration initialized.
2024-07-04 10:22:24.8796 Info Registered target NLog.Targets.FileTarget(Name=allfile)
2024-07-04 10:22:24.9160 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web)
2024-07-04 10:22:24.9160 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console)
2024-07-04 10:22:24.9326 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False
2024-07-04 10:22:24.9376 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config
2024-07-04 10:22:24.9376 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile
2024-07-04 10:22:24.9376 Info Configuration initialized.
2024-07-04 10:26:34.4238 Info Registered target NLog.Targets.FileTarget(Name=allfile)
2024-07-04 10:26:34.4851 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web)
2024-07-04 10:26:34.4851 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console)
2024-07-04 10:26:34.5015 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False
2024-07-04 10:26:34.5015 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config
2024-07-04 10:26:34.5015 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile
2024-07-04 10:26:34.5198 Info Configuration initialized.
2024-07-04 13:55:50.7465 Info Registered target NLog.Targets.FileTarget(Name=allfile)
2024-07-04 13:55:50.7854 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web)
2024-07-04 13:55:50.7854 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console)
2024-07-04 13:55:50.8005 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False
2024-07-04 13:55:50.8005 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config
2024-07-04 13:55:50.8005 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile
2024-07-04 13:55:50.8005 Info Configuration initialized.

Loading…
Cancel
Save