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.

258 lines
11 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.Data;
using DS.Module.Core.Enums;
using DS.Module.Core.Extensions;
using DS.WMS.Core.Application.Dtos;
using DS.WMS.Core.Fee.Dtos;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Invoice.Dtos;
using DS.WMS.Core.Invoice.Interface;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
using SqlSugar;
namespace DS.WMS.Core.Invoice.Method
{
/// <summary>
/// 自由开票实现
/// </summary>
public class FreeInvoiceService : InvoiceService<Entity.Invoice>, IFreeInvoiceService
{
/// <summary>
/// 允许的费用状态值
/// </summary>
internal readonly FeeStatus[] AllowedStatus = [FeeStatus.AuditPassed, FeeStatus.PartialSettlement, FeeStatus.SettlementCompleted];
/// <summary>
/// 初始化
/// </summary>
/// <param name="provider"></param>
public FreeInvoiceService(IServiceProvider provider) : base(provider)
{
}
/// <summary>
/// 获取待开票的业务列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<BizInvoiceApplication>>> GetBizListAsync(PageRequest<FeeRange?> request)
{
var expr = Expressionable.Create<SeaExport, FeeRecord>().And((s, f) => AllowedStatus.Contains(f.FeeStatus) &&
(f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount + f.OrderInvSettlementAmount) != 0);
if (request.OtherQueryCondition.HasValue)
{
switch (request.OtherQueryCondition.Value)
{
case FeeRange.Unsettled:
expr = expr.And((s, f) => f.SettlementAmount == 0);
break;
case FeeRange.Settled:
expr = expr.And((s, f) => f.SettlementAmount > 0);
break;
}
}
var query = CreateFeeQuery(expr.ToExpression());
if (!request.QueryCondition.IsNullOrEmpty())
{
var whereList = request.GetConditionalModels(Db);
query = query.Where(whereList);
}
var result = await query.GroupBy(x => x.BusinessId).Select(x => new BizInvoiceApplication
{
Id = x.BusinessId,
BusinessType = x.BusinessType,
AccountDate = x.AccountDate,
CntrTotal = x.CntrTotal,
CreateBy = x.CreateBy,
CustomerNo = x.CustomerNo,
ClientName = x.ClientName,
CustomerId = x.CustomerId,
CustomerName = x.CustomerName,
DischargePort = x.DischargePort,
ETD = x.ETD,
HBLNO = x.HBLNO,
LoadPort = x.LoadPort,
MBLNO = x.MBLNO,
OperatorId = x.OperatorId,
SaleDeptId = x.SaleDeptId,
SaleId = x.SaleId,
SaleName = x.Sale,
Vessel = x.Vessel,
Voyage = x.Voyage,
BookingNo = x.BookingNo,
//未开票金额=金额-已开票金额-申请开票金额+申请开票金额已开票
UnBilledRMB = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == x.BusinessId && f.FeeStatus == FeeStatus.AuditPassed
&& f.Currency == FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.InvoiceAmount)),
UnBilledUSD = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == x.BusinessId && f.FeeStatus == FeeStatus.AuditPassed
&& f.Currency == FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.InvoiceAmount)),
UnBilledOther = SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == x.BusinessId && f.FeeStatus == FeeStatus.AuditPassed
&& f.Currency != FeeCurrency.RMB_CODE && f.Currency != FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.InvoiceAmount)),
}).ToQueryPageAsync(request.PageCondition);
if (result.Data.Count > 0)
{
//关联用户名称
var userIds = result.Data.Where(x => x.OperatorId.HasValue).Select(x => x.OperatorId.Value)
.Union(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();
var orgs = await Db.Queryable<SysOrg>().Where(x => userIds.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;
if (item.OperatorId.HasValue)
item.Operator = users.Find(x => x.Id == item.OperatorId.Value)?.UserName;
item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
}
}
return result;
}
/// <summary>
/// 根据业务编号及类型获取费用记录
/// </summary>
/// <param name="inquiry">业务ID与业务类型</param>
/// <returns></returns>
public override async Task<DataResult<InvoiceApplicaitonBiz>> GetFeesAsync(DetailInquiry inquiry)
{
var bizIds = inquiry.Items.Select(x => x.Id).Distinct();
var types = inquiry.Items.Select(x => x.BusinessType).Distinct();
var cIds = inquiry.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) &&
AllowedStatus.Contains(f.FeeStatus) && f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount + f.OrderInvSettlementAmount != 0)
.Where(inquiry.GetConditionalModels(Db))
.Select(f => new FeeInvoiceDto
{
RecordId = f.Id,
BusinessId = f.BusinessId,
BusinessType = f.BusinessType,
CustomerId = f.CustomerId,
CustomerName = f.CustomerName,
FeeId = f.FeeId,
FeeName = f.FeeName,
FeeType = f.FeeType,
Amount = f.Amount,
TaxRate = f.TaxRate,
Currency = f.Currency,
OriginalCurrency = f.Currency,
OriginalRate = f.ExchangeRate,
RestAmount = f.Amount - f.InvoiceAmount,
ExchangeRate = f.ExchangeRate,
Remark = f.Remark,
}).ToListAsync();
foreach (var item in list)
item.ApplyAmount = item.OriginalAmount = item.RestAmount;
return DataResult<InvoiceApplicaitonBiz>.Success(new InvoiceApplicaitonBiz(list));
}
/// <summary>
/// 根据业务编号及类型获取该票业务的币别
/// </summary>
/// <param name="inquiry">业务ID与业务类型</param>
/// <returns></returns>
public async Task<DataResult<List<FeeClient>>> GetCurrenciesAsync(DetailInquiry inquiry)
{
var bizIds = inquiry.Items.Select(x => x.Id).Distinct();
var types = inquiry.Items.Select(x => x.BusinessType).Distinct();
var cIds = inquiry.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) &&
AllowedStatus.Contains(f.FeeStatus))
.Select(f => new
{
f.BusinessId,
f.BusinessType,
f.CustomerId,
f.Currency
}).ToListAsync();
var currencies = list.GroupBy(x => new { x.BusinessId, x.BusinessType, x.CustomerId }).Select(x => new FeeClient
{
Id = x.Key.BusinessId,
BusinessType = x.Key.BusinessType,
CustomerId = x.Key.CustomerId,
ExchangeRates = x.GroupBy(y => y.Currency).Select(y => new CurrencyExchangeRate
{
Currency = y.Key
}).ToList()
}).ToList();
return DataResult<List<FeeClient>>.Success(currencies);
}
protected override async Task<DataResult> PreSaveAsync(Entity.Invoice invoice)
{
invoice.Mode = InvoiceMode.Free;
//获取剩余待开票金额
var ids = invoice.Details.Select(x => x.RecordId);
var fees = await TenantDb.Queryable<FeeRecord>().Where(x => ids.Contains(x.Id) && AllowedStatus.Contains(x.FeeStatus))
.Select(x => new
{
x.Id,
OriginalRestAmount = x.Amount - x.InvoiceAmount - x.OrderInvoiceAmount + x.OrderInvSettlementAmount
}).ToListAsync();
StringBuilder sb = new();
foreach (var detail in invoice.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;
}
}
return sb.Length > 0 ? DataResult.Failed(sb.ToString()) : DataResult.Success;
}
//protected override async Task OnDeleteDetailAsync(List<Entity.Invoice> invoices, DeleteOption deleteOption)
//{
// var list = invoices.SelectMany(x => x.Details).Where(x => x.DetailId.HasValue).Select(x => new ApplicationDetail
// {
// Id = x.DetailId.GetValueOrDefault(),
// ProcessedAmount = x.ApplyAmount,
// OriginalProcessedAmount = x.OriginalAmount
// }).ToList();
// //恢复发票申请明细的已处理金额
// await TenantDb.Updateable(list)
// .PublicSetColumns(x => x.ProcessedAmount, "-").PublicSetColumns(x => x.OriginalProcessedAmount, "-")
// .UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount })
// .ExecuteCommandAsync();
// await base.OnDeleteDetailAsync(invoices, deleteOption);
//}
}
}