You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
15 KiB
C#

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.Application.Interface;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Info.Entity;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
using SqlSugar;
namespace DS.WMS.Core.Application.Method
{
/// <summary>
/// 付费申请审核服务
/// </summary>
public class PaymentApplicationAuditService : ApplicationAuditService<PaymentApplication>, IPaymentApplicationAuditService
{
internal static readonly FeeStatus[] FeeStatusArray = [FeeStatus.AuditPassed, FeeStatus.PartialSettlement, FeeStatus.SettlementCompleted];
public override TaskBaseTypeEnum AuditType => TaskBaseTypeEnum.APPLICATION_PAYMENT_AUDIT;
/// <summary>
/// 初始化
/// </summary>
/// <param name="serviceProvider"></param>
public PaymentApplicationAuditService(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
/// <summary>
/// 获取分页列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<PaymentApplicationDto>>> GetListAsync(PageRequest<AuditStatusForQuery> request)
{
var query = CreateListQuery();
if (!request.QueryCondition.IsNullOrEmpty())
{
var whereList = request.GetConditionalModels(Db);
query = query.Where(whereList);
}
switch (request.OtherQueryCondition)
{
case AuditStatusForQuery.Pending:
query = query.Where(x => x.Status == PaymentApplicationStatus.AuditSubmittd);
break;
case AuditStatusForQuery.Audited:
query = query.Where(x => x.Status == PaymentApplicationStatus.AuditPassed || x.Status == PaymentApplicationStatus.AuditRejected);
break;
case AuditStatusForQuery.MarkerOnly:
var ids = await GetCurrentFlowsQuery([AuditType]).Select(x => x.BusinessId).ToListAsync();
if (ids.Count == 0)
ids.Add(0L);
query = query.Where(x => x.Status == PaymentApplicationStatus.AuditSubmittd && ids.Contains(x.Id));
break;
}
var result = await query.GroupBy(x => x.Id).ToQueryPageAsync(request.PageCondition);
if (result.Data.Count > 0)
{
var orgIds = result.Data.Select(x => x.SaleDeptId).Distinct();
var orgs = await Db.Queryable<SysOrg>().Where(x => orgIds.Contains(x.Id)).Select(x => new { x.Id, x.OrgName }).ToListAsync();
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();
foreach (var item in result.Data)
{
item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
item.SaleDeptName = users.Find(x => x.Id == item.CreateBy)?.UserName;
}
}
return result;
}
internal ISugarQueryable<PaymentApplicationDto> CreateListQuery()
{
var query1 = TenantDb.Queryable<PaymentApplication>()
.LeftJoin<ApplicationDetail>((a, d) => a.Id == d.ApplicationId)
.InnerJoin<FeeRecord>((a, d, f) => d.RecordId == f.Id)
.LeftJoin<SeaExport>((a, d, f, s) => f.BusinessId == s.Id)
.LeftJoin<InfoClientBank>((a, d, f, s, b) => a.CustomerBankId == b.Id)
.Select((a, d, f, s, b) => new PaymentApplicationDto
{
InvoiceNO = a.InvoiceNO,
SettlementTypeName = a.SettlementType.StlName,
BillNO = s.CustomerNo, //业务编号=委托编号
CustomerBankName = b.BankName,
CustomerAccount = b.Account
}, true);
return TenantDb.UnionAll(new List<ISugarQueryable<PaymentApplicationDto>> { query1 });
}
/// <summary>
/// 获取申请单明细
/// </summary>
/// <param name="id">申请单ID</param>
/// <returns></returns>
public async Task<DataResult<ApplicationSummary>> GetDetailsAsync(long id)
{
var details = await TenantDb.Queryable<ApplicationDetail>()
.InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id)
.LeftJoin<BusinessFeeStatus>((d, f, b) => f.BusinessId == b.BusinessId && f.BusinessType == b.BusinessType)
.Where(d => d.ApplicationId == id)
.Select((d, f, b) => new PaymentApplicationDetailDto
{
AccTaxRate = f.AccTaxRate,
Amount = d.ApplyAmount,
CustomerId = f.CustomerId,
FeeName = d.FeeName,
FeeType = f.FeeType,
ClientName = f.CustomerName,
OriginalCurrency = d.OriginalCurrency,
OriginalRate = f.ExchangeRate,
ExchangeRate = d.ExchangeRate,
OriginalAmount = d.OriginalAmount,
BusinessId = b.BusinessId,
BusinessType = b.BusinessType,
IsBusinessLocking = b.IsBusinessLocking,
IsFeeLocking = b.IsFeeLocking
}).ToListAsync();
if (details.Count > 0)
{
var gList = details.GroupBy(x => x.BusinessType).ToList();
foreach (var g in gList)
{
var ids = g.Select(x => x.BusinessId).ToList();
switch (g.Key)
{
case BusinessType.OceanShippingExport:
var list1 = await TenantDb.Queryable<SeaExport>().Where(x => ids.Contains(x.Id)).Select(x => new
{
x.Id,
x.MBLNO,
x.CustomerNo,
x.CustomerName,
x.ETD,
x.CntrTotal,
x.AccountDate,
x.OperatorCode,
x.Vessel,
x.Voyno,
x.Carrier,
x.Forwarder,
x.BookingNo
}).ToListAsync();
foreach (var item in g)
{
var biz = list1.Find(x => x.Id == item.BusinessId);
if (biz != null)
{
item.MBLNO = biz.MBLNO;
item.CustomerName = biz.CustomerName;
item.CustomerNo = biz.CustomerNo;
item.ETD = biz.ETD;
item.CntrTotal = biz.CntrTotal;
item.AccountDate = biz.AccountDate;
item.Operator = biz.OperatorCode;
item.Vessel = biz.Vessel;
item.Voyage = biz.Voyno;
item.Carrier = biz.Carrier;
item.Forwarder = biz.Forwarder;
item.BookingNo = biz.BookingNo;
}
}
break;
case BusinessType.OceanShippingImport:
break;
}
}
}
var model = new ApplicationSummary(details);
var customerId = details.GroupBy(x => x.CustomerId).Select(x => x.Key).FirstOrDefault();
return DataResult<ApplicationSummary>.Success(model);
}
/// <summary>
/// 获取申请单统计信息
/// </summary>
/// <param name="id">申请单ID</param>
/// <returns></returns>
public async Task<DataResult<FeeBiz>> GetApplicationStatAsync(long id)
{
var fees = await TenantDb.Queryable<FeeRecord>().InnerJoin<ApplicationDetail>((f, d) => f.Id == d.RecordId)
.Where((f, d) => d.ApplicationId == id)
.Select((f, d) => new
{
f.CustomerId,
f.Currency,
f.FeeType,
f.Amount,
RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount
}).ToListAsync();
FeeBiz model = new()
{
PayableCNY = fees.Where(x => x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.Amount),
PayableUSD = fees.Where(x => x.Currency == FeeCurrency.USD_CODE).Sum(x => x.Amount),
TotalItems = fees.GroupBy(x => x.Currency).Select(x => new TotalItem
{
Currency = x.Key,
PayableAmount = x.Where(y => y.FeeType == FeeType.Payable && y.Currency == x.Key).Sum(y => y.Amount),
ReceivableAmount = x.Where(y => y.FeeType == FeeType.Receivable && y.Currency == x.Key).Sum(y => y.Amount),
RestAmount = x.Where(y => y.Currency == x.Key).Sum(y => y.RestAmount)
}).ToList()
};
if (fees.Count > 0)
{
var customerId = fees[0].CustomerId;
model.RecvByCustomer = await TenantDb.Queryable<FeeRecord>().Where(x => x.CustomerId == customerId)
.SumAsync(x => x.Amount * (x.ExchangeRate == null ? 1 : x.ExchangeRate.Value));
}
return DataResult<FeeBiz>.Success(model);
}
/// <summary>
/// 获取按票统计
/// </summary>
/// <param name="id">申请单ID</param>
/// <returns></returns>
public async Task<DataResult<List<BizFeeStat>>> GetBizStatAsync(long id)
{
var query1 = TenantDb.Queryable<ApplicationDetail>()
.InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id && f.BusinessType == BusinessType.OceanShippingExport)
.InnerJoin<SeaExport>((d, f, s) => f.BusinessId == s.Id)
.LeftJoin<BusinessFeeStatus>((d, f, s, b) => s.Id == b.BusinessId && b.BusinessType == BusinessType.OceanShippingExport)
.Where((d, f, s, b) => d.ApplicationId == id)
.GroupBy((d, f, s, b) => s.Id)
.Select((d, f, s, b) => new BizFeeStat
{
BusinessId = s.Id,
BusinessType = BusinessType.OceanShippingExport,
IsBusinessLocking = b.IsBusinessLocking,
IsFeeLocking = b.IsFeeLocking
}, true);
var list = await TenantDb.UnionAll(query1).ToListAsync();
if (list.Count == 0)
return DataResult<List<BizFeeStat>>.Success(list);
var ids = list.Select(x => x.BusinessId).Distinct();
var types = list.Select(x => x.BusinessType).Distinct();
var feeList = await TenantDb.Queryable<FeeRecord>().Where(f =>
ids.Contains(f.BusinessId) && types.Contains(f.BusinessType) && FeeStatusArray.Contains(f.FeeStatus))
.Select(x => new
{
x.BusinessId,
x.BusinessType,
x.FeeType,
x.Currency,
x.Amount
}).ToListAsync();
var usersId = list.Where(x => x.OperatorId.HasValue).Select(x => x.OperatorId.Value).Distinct();
var users = await Db.Queryable<SysUser>().Where(x => usersId.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync();
foreach (var stat in list)
{
var fees = feeList.FindAll(x => x.BusinessId == stat.BusinessId && x.BusinessType == stat.BusinessType);
stat.ReceivableTotal = fees.FindAll(x => x.FeeType == FeeType.Receivable).Sum(x => x.Amount);
stat.ReceivableCNY = fees.FindAll(x => x.FeeType == FeeType.Receivable && x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.Amount);
stat.ReceivableUSD = fees.FindAll(x => x.FeeType == FeeType.Receivable && x.Currency == FeeCurrency.USD_CODE).Sum(x => x.Amount);
stat.ReceivableOther = fees.FindAll(x => x.FeeType == FeeType.Receivable && x.Currency != FeeCurrency.USD_CODE && x.Currency != FeeCurrency.RMB_CODE).Sum(x => x.Amount);
stat.PayableTotal = fees.FindAll(x => x.FeeType == FeeType.Payable).Sum(x => x.Amount);
stat.PayableCNY = fees.FindAll(x => x.FeeType == FeeType.Payable && x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.Amount);
stat.PayableUSD = fees.FindAll(x => x.FeeType == FeeType.Payable && x.Currency == FeeCurrency.USD_CODE).Sum(x => x.Amount);
stat.PayableOther = fees.FindAll(x => x.FeeType == FeeType.Payable && x.Currency != FeeCurrency.USD_CODE && x.Currency != FeeCurrency.RMB_CODE).Sum(x => x.Amount);
stat.Operator = stat.OperatorId.HasValue ? users.Find(x => x.Id == stat.OperatorId.Value)?.UserName : string.Empty;
}
return DataResult<List<BizFeeStat>>.Success(list);
}
protected override DataResult PreAudit(List<PaymentApplication> applications)
{
if (applications.Exists(x => x.Status != PaymentApplicationStatus.AuditSubmittd))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationIsNotAuditing));
return DataResult.Success;
}
protected override async Task OnUpdateStatusAsync(FlowCallback callback, PaymentApplication application)
{
var auditType = callback.AuditType;
if (auditType != TaskBaseTypeEnum.APPLICATION_PAYMENT_AUDIT)
return;
if (callback.FlowStatus == FlowStatusEnum.Approve)
{
application.Status = PaymentApplicationStatus.AuditPassed;
application.Reason = string.Empty;
}
else if (callback.FlowStatus == FlowStatusEnum.Reject)
application.Status = PaymentApplicationStatus.AuditRejected;
await base.OnUpdateStatusAsync(callback, application);
}
}
}