|
|
|
@ -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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|