using DS.Module.Core; using DS.Module.Core.Enums; using DS.Module.Core.Extensions; using DS.WMS.Core.Application.Entity; using DS.WMS.Core.Fee.Entity; using DS.WMS.Core.Fee.Method; using DS.WMS.Core.Invoice.Dto; using DS.WMS.Core.Invoice.Dtos; using DS.WMS.Core.Invoice.Interface; using DS.WMS.Core.Sys.Entity; using DS.WMS.Core.Sys.Interface; using Microsoft.Extensions.DependencyInjection; using SqlSugar; namespace DS.WMS.Core.Invoice.Method { /// /// 发票服务基类 /// /// public class InvoiceService : FeeServiceBase, IInvoiceService where TEntity : Entity.Invoice, new() { protected readonly Lazy CommonService; /// /// 初始化 /// /// public InvoiceService(IServiceProvider provider) : base(provider) { CommonService = new Lazy(provider.GetRequiredService()); } /// /// 获取分页列表 /// /// /// public async Task>> GetListAsync(PageRequest request) { var query = TenantDb.Queryable() .Select(i => new InvoiceDto { Id = i.Id, InvoiceNO = i.InvoiceNO, BillNO = i.BillNO, InvoiceDate = i.InvoiceDate, CustomerId = i.CustomerId, CustomerName = i.CustomerName, Type = i.Type, Category = i.Category, InvoiceHeader = i.InvoiceHeader, TaxID = i.TaxID, CustomerAddTel = i.CustomerAddTel, CustomerBank = i.CustomerBank, AutualCustomerName = i.AutualCustomerName, Currency = i.Currency, ReceiptCurrency = i.ReceiptCurrency, ApplyAmount = i.ApplyAmount, InvoiceAmount = i.InvoiceAmount, OperatorId = i.OperatorId, IsLocked = i.IsLocked, LockUserId = i.LockUserId, LockTime = i.LockTime, TaxRate = i.TaxRate, OrgId = i.OrgId, SaleDeptId = i.SaleDeptId, IsCancelled = i.IsCancelled, CancelUserId = i.CancelUserId, CancelTime = i.CancelTime, CreateTime = i.CreateTime, CreateBy = i.CreateBy, InvoiceApplicationList = SqlFunc.Subqueryable().InnerJoin((d, a) => d.ApplicationId == i.Id && d.Category == DetailCategory.InvoiceIssuance && d.RefId == a.Id) .GroupBy((d, a) => a.ApplicationNO).ToList((d, a) => a.ApplicationNO) }); if (!request.OtherQueryCondition.IsNullOrEmpty()) { query = query.Where(i => i.InvoiceApplicationList.Contains(request.OtherQueryCondition)); } 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) .Union(result.Data.Where(x => x.LockUserId.HasValue).Select(x => x.LockUserId.Value)) .Union(result.Data.Where(x => x.OperatorId.HasValue).Select(x => x.OperatorId.Value)) .Distinct(); var users = await Db.Queryable().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync(); var orgIds = result.Data.Where(x => x.SaleDeptId.HasValue).Select(x => x.SaleDeptId.Value) .Union(result.Data.Where(x => x.OrgId.HasValue).Select(x => x.OrgId.Value)) .Distinct(); var orgs = await Db.Queryable().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.LockUserName = users.Find(x => x.Id == item.LockUserId)?.UserName; item.OperatorName = users.Find(x => x.Id == item.OperatorId)?.UserName; item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName; item.OrgName = orgs.Find(x => x.Id == item.OrgId)?.OrgName; } } return result; } /// /// 提交发票开票 /// /// 请求参数 /// public async Task> SaveAsync(InvoiceRequest request) { var invoice = request.Invoice; if (invoice.InvoiceDate == default) invoice.InvoiceDate = DateTime.Now; TEntity? dbValue = default; if (request.Invoice.Id > 0) { dbValue = await TenantDb.Queryable().Select(x => new TEntity { Id = x.Id, IsLocked = x.IsLocked, Type = x.Type, }).FirstAsync(x => x.Id == request.Invoice.Id); if (dbValue != null && dbValue.IsLocked) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsLocked)); } var result = EnsureSettlement(request.Invoice, dbValue); if (!result.Succeeded) return DataResult.Failed(result.Message, result.MultiCode); if (request.Details?.Count > 0) { if (invoice.Id == 0 && invoice.CustomerId == 0) { var first = request.Details[0]; invoice.CustomerId = first.CustomerId.GetValueOrDefault(); invoice.CustomerName = first.CustomerName; } invoice.Details = request.Details.Select(x => new ApplicationDetail { ApplicationId = x.ApplicationId, DetailId = x.Id == 0 ? null : x.Id, RecordId = x.RecordId, CustomerName = x.CustomerName ?? invoice.CustomerName, FeeId = x.FeeId, FeeName = x.FeeName, FeeType = x.FeeType, ApplyAmount = x.Amount, Currency = x.Currency, ExchangeRate = x.ExchangeRate, OriginalAmount = x.OriginalAmount, OriginalCurrency = x.OriginalCurrency ?? (invoice.Currency.IsNullOrEmpty() ? x.Currency : invoice.Currency), }).ToList(); //金额禁止为0 if (invoice.Details.Any(x => x.ApplyAmount == 0 || x.OriginalAmount == 0)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero)); if (invoice.Details.Any(x => x.OriginalCurrency.IsNullOrEmpty())) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull)); if (invoice.Details.Any(x => x.Currency != invoice.Currency && x.ExchangeRate == null)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NeedExchangeRate)); result = await PreSaveAsync(invoice); if (!result.Succeeded) return DataResult.Failed(result.Message, result.MultiCode); invoice.InvoiceAmount = invoice.Details.Sum(x => x.ApplyAmount); } await TenantDb.Ado.BeginTranAsync(); try { //关联导航属性插入 if (invoice.Id == 0) { //创建时需要生成申请单编号 var sequence = CommonService.Value.GetSequenceNext(); if (!sequence.Succeeded) { return DataResult.Failed(sequence.Message, MultiLanguageConst.SequenceSetNotExist); } invoice.BillNO = sequence.Data; await TenantDb.InsertNav(invoice).Include(x => x.Details).ExecuteCommandAsync(); } else { if (invoice.Details.Count > 0) await TenantDb.Insertable(invoice.Details).ExecuteCommandAsync(); await TenantDb.Updateable(invoice).IgnoreColumns(x => new { x.BillNO, x.IsLocked, x.CreateBy, x.CreateTime, x.Deleted, x.DeleteBy, x.DeleteTime }).ExecuteCommandAsync(); } await OnSaveAsync(invoice); if (invoice.Details?.Count > 0) { //更新费用记录的已结算金额 var fees = invoice.Details.Select(x => new FeeRecord { Id = x.RecordId, InvoiceAmount = x.OriginalAmount }).ToList(); await TenantDb.Updateable(fees) .PublicSetColumns(x => x.InvoiceAmount, "+") .UpdateColumns(x => new { x.InvoiceAmount }) .ExecuteCommandAsync(); } await TenantDb.Ado.CommitTranAsync(); return DataResult.Success(await PostSaveAsync(invoice)); } catch (Exception ex) { await TenantDb.Ado.RollbackTranAsync(); await ex.LogAsync(Db); return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } } /// /// 用于发票的状态检查 /// /// 提交的发票 /// 数据库值,新增时为null /// protected virtual DataResult EnsureSettlement(TEntity invoice, TEntity? dbValue) { return DataResult.Success; } /// /// 在保存前调用 /// /// 发票 /// protected virtual Task PreSaveAsync(TEntity invoice) { return Task.FromResult(DataResult.Success); } /// /// 在保存时调用 /// /// 要保存的发票 /// protected virtual Task OnSaveAsync(TEntity invoice) { return Task.CompletedTask; } /// /// 在保存完成后调用 /// /// 发票 protected virtual Task PostSaveAsync(TEntity invoice) { return Task.FromResult(invoice); } public Task DeleteAsync(params long[] ids) { throw new NotImplementedException(); } public Task DeleteDetailAsync(params long[] ids) { throw new NotImplementedException(); } public Task SetLockAsync(bool isLocked, params long[] ids) { throw new NotImplementedException(); } } }