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.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 { /// /// 自由开票实现 /// public class FreeInvoiceService : InvoiceService, IFreeInvoiceService { /// /// 允许的费用状态值 /// internal readonly FeeStatus[] AllowedStatus = [FeeStatus.AuditPassed, FeeStatus.PartialSettlement, FeeStatus.SettlementCompleted]; /// /// 初始化 /// /// public FreeInvoiceService(IServiceProvider provider) : base(provider) { } /// /// 获取待开票的业务列表 /// /// /// public async Task>> GetBizListAsync(PageRequest request) { var expr = Expressionable.Create().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().Where(f => f.BusinessId == x.BusinessId && f.FeeStatus == FeeStatus.AuditPassed && f.Currency == FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount + f.OrderInvSettlementAmount)), UnBilledUSD = SqlFunc.Subqueryable().Where(f => f.BusinessId == x.BusinessId && f.FeeStatus == FeeStatus.AuditPassed && f.Currency == FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount + f.OrderInvSettlementAmount)), UnBilledOther = SqlFunc.Subqueryable().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 - f.OrderInvoiceAmount + f.OrderInvSettlementAmount)), }).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().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().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; } /// /// 根据业务编号及类型获取费用记录 /// /// 业务ID与业务类型 /// public override async Task> 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() .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) .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 - f.OrderInvoiceAmount + f.OrderInvSettlementAmount, ExchangeRate = f.ExchangeRate, Remark = f.Remark, }).ToListAsync(); foreach (var item in list) item.ApplyAmount = item.OriginalAmount = item.RestAmount; return DataResult.Success(new InvoiceApplicaitonBiz(list)); } /// /// 根据业务编号及类型获取该票业务的币别 /// /// 业务ID与业务类型 /// public async Task>> GetCurrenciesAsync(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() .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>.Success(currencies); } protected override async Task PreSaveAsync(Entity.Invoice invoice) { invoice.Mode = InvoiceMode.Free; //获取剩余待开票金额 var ids = invoice.Details.Select(x => x.RecordId); var fees = await TenantDb.Queryable().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; } } }