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.

400 lines
19 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.Invoice.Dtos;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Settlement.Dtos;
using DS.WMS.Core.Settlement.Entity;
using DS.WMS.Core.Settlement.Interface;
using DS.WMS.Core.Sys.Entity;
using Mapster;
using SqlSugar;
namespace DS.WMS.Core.Settlement.Method
{
/// <summary>
/// 自由结算
/// </summary>
public class FreeSettlementService : SettlementService<ApplicationSettlement>, IFreeSettlementService
{
/// <summary>
/// 初始化
/// </summary>
/// <param name="provider"></param>
public FreeSettlementService(IServiceProvider provider) : base(provider)
{
}
/// <summary>
/// 获取待结算业务分页列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
/// <remarks>查询条件请参考<see cref="FeeDto"/>中定义的字段</remarks>
public async Task<DataResult<List<SettlementBiz>>> GetBizListAsync(PageRequest request)
{
var whereList = request.GetConditionalModels(Db);
var result = await CreateBizQuery().Where(whereList).GroupBy(x => new { x.BusinessId, x.BusinessType, x.CustomerId })
.Select<SettlementBiz>().ToQueryPageAsync(request.PageCondition);
if (result.Data.Count > 0)
{
//获取统计信息
var ids = result.Data.Select(x => x.BusinessId);
var types = result.Data.Select(x => x.BusinessType).Distinct();
var fees = await TenantDb.Queryable<FeeRecord>().Where(x => ids.Contains(x.BusinessId) && types.Contains(x.BusinessType))
.Select(x => new
{
x.BusinessId,
x.BusinessType,
x.Currency,
x.FeeType,
//x.Amount,
//x.OrderAmount,
//x.SettlementAmount,
//x.OrderSettlementAmount,
x.InvoiceAmount,
UnSettledAmount = x.Amount - x.SettlementAmount - x.OrderAmount + x.OrderSettlementAmount //剩余待结算
}).ToListAsync();
//关联用户名称
var userIds = result.Data.Select(x => x.CreateBy)
.Union(result.Data.Select(x => x.OperatorId))
.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();
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.UnpaidRMB = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.RMB_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettledAmount);
item.UnpaidUSD = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.USD_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettledAmount);
item.UnpaidOther = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettledAmount);
item.UnchargedRMB = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.RMB_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettledAmount);
item.UnchargedUSD = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.USD_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettledAmount);
item.UnchargedOther = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettledAmount);
item.UnpaidInvoiceRMB = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.RMB_CODE && x.FeeType == FeeType.Payable && x.UnSettledAmount == 0).Sum(x => x.InvoiceAmount);
item.UnpaidInvoiceUSD = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.USD_CODE && x.FeeType == FeeType.Payable && x.UnSettledAmount == 0).Sum(x => x.InvoiceAmount);
item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName;
item.Operator = users.Find(x => x.Id == item.OperatorId)?.UserName;
item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
}
}
return result;
}
//创建各项费用数据的查询并集
internal ISugarQueryable<FeeDto> CreateBizQuery()
{
var query1 = TenantDb.Queryable<FeeRecord, SeaExport>((f, s) => new JoinQueryInfos(
JoinType.Inner, s.Id == f.BusinessId && f.BusinessType == BusinessType.OceanShippingExport && (f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement) &&
(f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) != 0))
.Select((f, s) => new FeeDto
{
Id = f.Id,
FeeId = f.FeeId,
FeeCode = f.FeeCode,
FeeName = f.FeeName,
FeeType = f.FeeType,
CustomerId = f.CustomerId,
CustomerName = f.CustomerName,
BusinessId = f.BusinessId,
BusinessType = BusinessType.OceanShippingExport,
Currency = f.Currency,
DebitNo = f.DebitNo,
SaleOrgId = f.SaleOrgId,
SaleOrg = f.SaleOrg,
CreateBy = f.CreateBy,
AccountDate = s.AccountDate,
BusinessDate = s.CreateTime,//业务日期
ClientName = s.CustomerName,//委托单位
CustomerNo = s.CustomerNo,
CustomNo = s.CustomNo,
DischargePort = s.DischargePort,
ETD = s.ETD,
HBLNO = s.HBLNO,
LoadPort = s.LoadPort,
MBLNO = s.MBLNO,
OperatorId = s.OperatorId,
SaleDeptId = s.SaleDeptId,
Sale = s.Sale,//揽货人
Vessel = s.Vessel,//船名
Voyage = s.Voyno,//航次
BookingNo = s.BookingNo,
Enterprise = s.Enterprise,
});
//海运进口
return TenantDb.UnionAll(new List<ISugarQueryable<FeeDto>> { query1 });
}
/// <summary>
/// 根据业务编号及类型获取关联费用记录
/// </summary>
/// <param name="items">业务ID与业务类型</param>
/// <returns></returns>
public async Task<DataResult<FeeForm>> GetFeesAsync(params FeeClient[] items)
{
var bizIds = items.Select(x => x.Id).Distinct();
var types = items.Select(x => x.BusinessType).Distinct();
var cIds = items.Select(x => x.CustomerId).Distinct();
var list = await TenantDb.Queryable<FeeRecord>()
.Where(f => bizIds.Contains(f.BusinessId) && types.Contains(f.BusinessType) && cIds.Contains(f.CustomerId) &&
(f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement) && (f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) != 0)
.Select(f => new FeeItem
{
RecordId = f.Id,
BusinessId = f.BusinessId,
BusinessType = f.BusinessType,
CustomerId = f.CustomerId,
CustomerName = f.CustomerName,
FeeId = f.FeeId,
FeeName = f.FeeName,
FeeType = f.FeeType,
TotalAmount = f.Amount,
Currency = f.Currency,
OriginalRate = f.ExchangeRate,
RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount,
InvoiceAmount = f.InvoiceAmount,
AccTaxRate = f.AccTaxRate,
Remark = f.Remark
}).ToListAsync();
foreach (var item in list)
{
//本次结算金额默认等于剩余金额
item.Amount = item.RestAmount;
item.OriginalAmount = item.RestAmount;
}
return DataResult<FeeForm>.Success(new FeeForm(list));
}
/// <summary>
/// 根据业务编号及类型获取该票业务的币别
/// </summary>
/// <param name="items">业务ID与业务类型</param>
/// <returns></returns>
public async Task<DataResult<List<FeeClient>>> GetCurrenciesAsync(List<FeeClient> items)
{
var bizIds = items.Select(x => x.Id).Distinct();
var types = items.Select(x => x.BusinessType).Distinct();
var cIds = items.Select(x => x.CustomerId).Distinct();
var list = await TenantDb.Queryable<FeeRecord>()
.Where(f => bizIds.Contains(f.BusinessId) && types.Contains(f.BusinessType) && cIds.Contains(f.CustomerId)
&& (f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement))
.Select(f => new
{
f.BusinessId,
f.BusinessType,
f.CustomerId,
f.Currency,
f.ExchangeRate
}).ToListAsync();
foreach (var item in items)
{
item.ExchangeRates = list.Where(x => x.BusinessId == item.Id && x.BusinessType == item.BusinessType && x.CustomerId == item.CustomerId)
.GroupBy(x => x.Currency).Select(x => new CurrencyExchangeRate
{
Currency = x.Key,
ExchangeRate = x.First().ExchangeRate
}).ToList();
}
return DataResult<List<FeeClient>>.Success(items);
}
/// <summary>
/// 获取付费自由结算单
/// </summary>
/// <param name="id">结算单ID</param>
/// <returns></returns>
public async Task<DataResult<FreeSettlementDto>> GetAsync(long id)
{
var model = await TenantDb.Queryable<ApplicationSettlement>().Select(x => new FreeSettlementDto
{
SettlementTypeName = x.SettlementType.StlName, //结算方式
CustomerBankName = x.CustomerBank.BankName,
CustomerAccount = x.CustomerBank.Account
}, true).FirstAsync(x => x.Id == id && x.Mode == SettlementMode.FreeSettlement);
if (model != null)
{
if (model.SaleDeptId.HasValue)
model.SaleDeptName = await Db.Queryable<SysOrg>().Where(x => x.Id == model.SaleDeptId.Value)
.Select(x => x.OrgName).FirstAsync();
if (model.OrgBankId.HasValue)
model.OrgBankName = await TenantDb.Queryable<SysBank>().Where(x => x.Id == model.OrgBankId.Value)
.Select(x => x.BankName + " " + x.BankAccountNo).FirstAsync();
model.SettlementDetails = await CreateApplicationDetailQuery((d, f, s) => d.ApplicationId == id)
.Select(x => new SettlementDetailDto
{
}, true).ToListAsync();
}
return DataResult<FreeSettlementDto>.Success(model);
}
/// <summary>
/// 获取付费自由结算明细
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<FreeSettlementDto>> GetDetailsAsync(PageRequest<long> request)
{
var model = new FreeSettlementDto();
model.SettlementDetails = await TenantDb.Queryable<ApplicationDetail>().Where(x => x.ApplicationId == request.OtherQueryCondition && x.Category == DetailCategory.PaidFreeSettlement)
.InnerJoin<FeeRecord>((d, f) => d.RecordId == f.Id)
.Select((d, f) => new SettlementDetailDto
{
Id = d.Id,
RecordId = f.Id,
BusinessId = f.BusinessId,
BusinessType = f.BusinessType,
CustomerName = d.CustomerName,
FeeName = d.FeeName,
FeeType = d.FeeType,
ExchangeRate = d.ExchangeRate,
OriginalAmount = d.OriginalAmount,
OriginalCurrency = d.OriginalCurrency,
OriginalRate = f.ExchangeRate,
ApplyAmount = d.ApplyAmount,
Currency = d.Currency
}).ToListAsync();
var gList = model.SettlementDetails.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(x => ids.Contains(x.Id))
.LeftJoin<CodeSource>((s, cs) => s.SourceId == cs.Id)
.Select((s, cs) => new
{
s.Id,
s.MBLNO,
s.HBLNO,
s.CustomerNo,
ClientName = s.CustomerName,
s.ETD,
cs.SourceName,
s.Sale,
s.AccountDate,
s.Vessel,
Voyage = s.Voyno,
s.Carrier,
s.Enterprise,
s.CustomNo
}).ToListAsync();
foreach (var item in g)
{
var biz = list1.Find(x => x.Id == item.BusinessId);
if (biz != null)
{
item.MBLNO = biz.MBLNO;
item.HBLNO = biz.HBLNO;
item.CustomerNo = biz.CustomerNo;
item.ClientName = biz.ClientName;
item.ETD = biz.ETD;
item.SourceName = biz.SourceName;
item.SaleName = biz.Sale;
item.AccountDate = biz.AccountDate;
item.Vessel = biz.Vessel;
item.Voyage = biz.Voyage;
item.Carrier = biz.Carrier;
item.Enterprise = biz.Enterprise;
item.CustomNo = biz.CustomNo;
}
}
break;
case BusinessType.OceanShippingImport:
break;
}
}
model.SummaryItems = model.SettlementDetails.GroupBy(x => new { x.FeeType, x.Currency }).Select(x => new SummaryItem
{
FeeType = x.Key.FeeType,
Currency = x.Key.Currency,
Amount = x.Sum(y => y.ApplyAmount)
}).ToList();
return DataResult<FreeSettlementDto>.Success(model);
}
protected override async Task<DataResult> PreSaveAsync(ApplicationSettlement settlement)
{
//settlement.Mode = SettlementMode.FreeSettlement;
//settlement.BillType = SettlementBillType.Payment;
//获取剩余待结算金额
var ids = settlement.Details.Select(x => x.RecordId);
var fees = await TenantDb.Queryable<FeeRecord>().Where(x => ids.Contains(x.Id) && x.FeeStatus == FeeStatus.AuditPassed)
.Select(x => new
{
x.Id,
OriginalRestAmount = x.Amount - x.SettlementAmount - x.OrderAmount + x.OrderSettlementAmount
}).ToListAsync();
StringBuilder sb = new();
foreach (var detail in settlement.Details)
{
var item = fees.Find(x => x.Id == detail.RecordId);
if (item == null)
{
sb.Append(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.EmptyData)));
break;
}
if (detail.OriginalAmount > 0 && detail.OriginalAmount > item.OriginalRestAmount)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName);
sb.Append("");
continue;
}
else if (detail.OriginalAmount < 0 && detail.OriginalAmount < item.OriginalRestAmount)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName);
sb.Append("");
continue;
}
detail.Category = DetailCategory.PaidApplicationSettlement;
}
return sb.Length > 0 ? DataResult.Failed(sb.ToString()) : DataResult.Success;
}
protected override DataResult PreDelete(List<ApplicationSettlement> settlements)
{
if (settlements.Any(x => x.IsLocked))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked));
return DataResult.Success;
}
}
}