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.
352 lines
16 KiB
C#
352 lines
16 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.Code.Entity;
|
|
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
|
|
{
|
|
/// <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 = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition);
|
|
|
|
switch (request.OtherQueryCondition)
|
|
{
|
|
case AuditStatusForQuery.Pending:
|
|
query = query.Where(x => x.AuditerId == null);
|
|
break;
|
|
|
|
case AuditStatusForQuery.Audited:
|
|
query = query.Where(x => x.AuditerId != null);
|
|
break;
|
|
|
|
case AuditStatusForQuery.MarkerOnly:
|
|
var ids = await GetCurrentFlowsQuery(AuditTypes).Select(x => x.BusinessId).ToListAsync();
|
|
if (ids.Count == 0)
|
|
ids.Add(0L);
|
|
query = query.Where(x => ids.Contains(x.Id));
|
|
break;
|
|
}
|
|
|
|
query = query.Where(whereList);
|
|
}
|
|
|
|
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().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.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal ISugarQueryable<PaymentApplicationDto> CreateListQuery()
|
|
{
|
|
var query1 = TenantDb.Queryable<PaymentApplication>().Where(x => x.Status == PaymentApplicationStatus.AuditSubmittd)
|
|
.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
|
|
{
|
|
Id = a.Id,
|
|
ApplicationNO = a.ApplicationNO,
|
|
CustomerId = a.CustomerId,
|
|
CustomerName = a.CustomerName,
|
|
AmountOther = a.AmountOther,
|
|
AmountRMB = a.AmountRMB,
|
|
AmountUSD = a.AmountUSD,
|
|
SaleDeptId = a.SaleDeptId,
|
|
CreateBy = a.CreateBy,
|
|
CreateTime = a.CreateTime,//付费申请日期
|
|
Currency = a.Currency,
|
|
Reason = a.Reason,
|
|
Status = a.Status,
|
|
AuditerId = a.AuditerId,
|
|
AuditerName = a.AuditerName,
|
|
AuditTime = a.AuditTime,
|
|
IsInvoiceReceived = a.IsInvoiceReceived,
|
|
ClientName = s.CustomerName,
|
|
IsPrinted = a.IsPrinted,
|
|
PrintTimes = a.PrintTimes,
|
|
InvoiceAmount = a.InvoiceAmount,
|
|
InvoiceDate = a.InvoiceDate,
|
|
InvoiceNO = a.InvoiceNO,
|
|
SettlementTypeName = a.SettlementType.StlName,
|
|
PaymentDate = a.PaymentDate,
|
|
Note = a.Note,
|
|
BillNO = s.CustomerNo, //业务编号=委托编号
|
|
CustomerBankId = a.CustomerBankId,
|
|
CustomerBankName = b.BankName,
|
|
CustomerAccount = b.Account
|
|
});
|
|
|
|
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>
|
|
/// <param name="businessType">业务类型</param>
|
|
/// <param name="customerId">结算对象ID</param>
|
|
/// <returns></returns>
|
|
public async Task<DataResult<FeeBiz>> GetFeeBizAsync(long id, BusinessType businessType, long customerId)
|
|
{
|
|
FeeBiz model = new()
|
|
{
|
|
ReceivableTotal = (await TenantDb.Queryable<FeeRecord>().Where(x => x.CustomerId == customerId
|
|
&& x.FeeType == FeeType.Receivable && x.FeeStatus == FeeStatus.AuditPassed).SumAsync(x => x.Amount))
|
|
};
|
|
|
|
var fees = await TenantDb.Queryable<FeeRecord>().Where(x =>
|
|
x.BusinessId == id && x.BusinessType == businessType && x.FeeStatus == FeeStatus.AuditPassed)
|
|
.Select(x => new
|
|
{
|
|
x.Currency,
|
|
x.FeeType,
|
|
x.Amount,
|
|
}).ToListAsync();
|
|
model.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 = 0 //todo:未收
|
|
}).ToList();
|
|
|
|
return DataResult<FeeBiz>.Success(model);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取按票统计
|
|
/// </summary>
|
|
/// <param name="id">业务ID</param>
|
|
/// <param name="businessType">业务类型</param>
|
|
/// <returns></returns>
|
|
public async Task<DataResult<BizFeeStat>> GetStatAsync(long id, BusinessType businessType)
|
|
{
|
|
BizFeeStat? stat = null;
|
|
switch (businessType)
|
|
{
|
|
case BusinessType.OceanShippingExport:
|
|
stat = await TenantDb.Queryable<BusinessFeeStatus>()
|
|
.InnerJoin<SeaExport>((b, s) => b.BusinessId == s.Id)
|
|
.LeftJoin<CodeSource>((b, s, cs) => s.SourceId == cs.Id)
|
|
.LeftJoin<CodeSourceDetail>((b, s, cs, csd) => s.SourceDetailId == csd.Id)
|
|
.Select((b, s, cs, csd) => new BizFeeStat
|
|
{
|
|
IsBusinessLocking = b.IsBusinessLocking,
|
|
IsFeeLocking = b.IsFeeLocking,
|
|
HBLNO = s.HBLNO,
|
|
MBLNO = s.MBLNO,
|
|
CustomerNo = s.CustomerNo,
|
|
CustomerName = s.CustomerName,
|
|
ETD = s.ETD,
|
|
ETA = s.ETA,
|
|
CntrTotal = s.CntrTotal,
|
|
AccountDate = s.AccountDate,
|
|
OperatorId = s.OperatorId,
|
|
Vessel = s.Vessel,
|
|
Voyage = s.Voyno,
|
|
Carrier = s.Carrier,
|
|
Forwarder = s.Forwarder,
|
|
BookingNo = s.BookingNo,
|
|
CustomsDate = s.CustomDate,
|
|
LoadPort = s.LoadPort,
|
|
DischargePort = s.DischargePort,
|
|
Destination = s.Destination,
|
|
Yard = s.Yard,
|
|
Agent = s.Agent,
|
|
TEU = s.TEU,
|
|
GoodsName = s.GoodsName,
|
|
IssueType = s.IssueType,
|
|
SourceName = cs.SourceName,
|
|
SourceDetailName = csd.DetailName
|
|
}).FirstAsync();
|
|
break;
|
|
case BusinessType.OceanShippingImport:
|
|
break;
|
|
}
|
|
|
|
if (stat == null)
|
|
return DataResult<BizFeeStat>.Success(stat);
|
|
|
|
var fees = await TenantDb.Queryable<FeeRecord>().Where(f =>
|
|
f.BusinessId == id && f.BusinessType == businessType && f.FeeStatus == FeeStatus.AuditPassed)
|
|
.Select(x => new
|
|
{
|
|
x.FeeType,
|
|
x.Currency,
|
|
x.Amount
|
|
}).ToListAsync();
|
|
|
|
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);
|
|
|
|
long?[] usersId = [stat.OperatorId];
|
|
if (Array.Exists(usersId, x => x.HasValue))
|
|
{
|
|
var users = await Db.Queryable<SysUser>().Where(x => usersId.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync();
|
|
stat.Operator = users.Find(x => x.Id == stat.OperatorId)?.UserName;
|
|
}
|
|
|
|
return DataResult<BizFeeStat>.Success(stat);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|