using DS.Module.Core; using DS.Module.Core.Enums; using DS.WMS.Core.Application.Entity; using DS.WMS.Core.Application.Method; using DS.WMS.Core.Code.Entity; using DS.WMS.Core.Invoice.Dtos; using DS.WMS.Core.Invoice.Interface; using DS.WMS.Core.Sys.Entity; using Masuit.Tools; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Linq; using SqlSugar; namespace DS.WMS.Core.Invoice.Method { /// /// 发票开具服务 /// public sealed class InvoiceIssuanceService : ApplicationServiceBase, IInvoiceIssuanceService { readonly InvoiceApiFox api; /// /// 初始化并加载配置 /// /// public InvoiceIssuanceService(IServiceProvider provider) : base(provider) { var config = provider.GetRequiredService(); api = new InvoiceApiFox(config); } /// /// 发起开票请求 /// /// 发票ID /// public async Task InitiateAsync(params long[] ids) { ArgumentNullException.ThrowIfNull(ids, nameof(ids)); long userId = long.Parse(User.UserId); var userInfo = await Db.Queryable().Where(x => x.Id == userId).Select(x => new { x.UserName, x.IdCardNo }).FirstAsync(); if (string.IsNullOrEmpty(userInfo.IdCardNo)) return DataResult.FailedWithDesc(MultiLanguageConst.DrawerIDNumberIsNull); //请求参数设置 InvoiceIssuanceRequest request = new() { order = await TenantDb.Queryable().Where(x => ids.Contains(x.Id)).Select(x => new InvoiceInfo { invoiceType = x.Type == null ? "1" : ((int)x.Type).ToString(), orderNo = x.BillNO, email = x.Email, buyerTaxNum = x.TaxID, buyerName = x.InvoiceHeader, buyerAddress = x.CustomerAddressTel, buyerTel = "", gmfkhh = x.CustomerBankName, gmfzh = x.CustomerAccount, skyhmc = x.BankName, skyhzh = x.Account, checker = x.Checker, payee = x.Payee, invoiceLine = x.CategoryCode, //---------金额项--------- hjse = x.InvoiceAmount * x.TaxRate, hjje = x.InvoiceAmount - x.InvoiceAmount * x.TaxRate, jshj = x.InvoiceAmount, clerk = userInfo.UserName, //开票人 kprzjhm = userInfo.IdCardNo, //证件号 kprzjlx = "201", //身份证, //---------发票明细--------- invoiceDetail = SqlFunc.Subqueryable().Where(y => y.ApplicationId == x.Id) .LeftJoin((y, z) => y.CodeId == z.Id).ToList((y, z) => new InvoiceDetailInfo { mxxh = SqlFunc.RowNumber(y.Id), //x.InvoiceDetails.IndexOf(y) + 1, xmmc = y.Name, spfwjc = string.Empty, specType = y.Specification, unit = y.Unit, num = y.Quantity.ToString(), taxExcludedAmount = y.UnitPrice, taxRate = y.TaxRate.ToString(), tax = y.TaxAmount, taxIncludedAmount = y.TaxUnitPrice, goodsCode = z.Code, //商品和服务税收分类合并编码 invoiceLineProperty = "00", favouredPolicyFlag = z.PreferentialPolicyDescription }) }).ToListAsync() }; if (request.order.Count == 0 || request.order.Any(x => x.invoiceDetail.Count == 0)) return DataResult.FailedWithDesc(MultiLanguageConst.InvoiceIncomplete); var result = await api.PostAsync>("/api/Invoice/services", request); if (!result.Succeeded) return DataResult.Failed(result.Message, result.MultiCode); var invResult = result.Data; if (invResult.Success) { string sn = invResult.Data; //开票成功返回流水号 var invoices = ids.Select(x => new Entity.Invoice { Id = x, SN = sn, ApiType = InvoiceApiType.Default }).ToList(); await TenantDb.Updateable(invoices).UpdateColumns(x => new { x.SN, x.ApiType }).ExecuteCommandAsync(); UpdateInvoiceNumberAsync(sn); return DataResult.Success; } else { if (invResult.Code == 1) return await InitiateAsync(ids); return DataResult.Failed(invResult.Message); } } /// /// 更新发票号码 /// /// 开票流水号 /// public async Task UpdateInvoiceNumberAsync(string sn) { //调用查询API获取发票号 var result = await api.PostAsync>("/api/Invoice/GetInvoiceState", new { guid = sn }); if (!result.Succeeded) return DataResult.Failed(result.Message, result.MultiCode); var queryResult = result.Data; if (queryResult == null || !queryResult.Success) return DataResult.Failed(queryResult?.Message); if (queryResult.Data.Order?.Count > 0) { List invoices = []; foreach (var item in queryResult.Data.Order) { var inv = new Entity.Invoice { SN = sn, BillNO = item.orderNo, InvoiceNO = item.fphm, ApiCode = item.State.ToString(), ApiStatus = item.UpMessage, PDFUrl = item.FileUrl }; invoices.Add(inv); if (string.IsNullOrEmpty(inv.ApiStatus)) { switch (item.State) { case 1: inv.ApiStatus = "已提交待上传"; break; case 2: inv.ApiStatus = "已上传待开票"; break; case 3: inv.ApiStatus = "开票成功"; break; } } } await TenantDb.Updateable(invoices).WhereColumns(x => x.BillNO) .UpdateColumns(x => new { x.InvoiceNO, x.ApiCode, x.ApiStatus, x.PDFUrl }).ExecuteCommandAsync(); } return DataResult.Success; } /// /// 发票冲红 /// /// /// public async Task ReverseAsync(InvoiceReversalRequest request) { var invoice = await TenantDb.Queryable() .WhereIF(request.InvoiceId.HasValue, x => x.Id == request.InvoiceId) .WhereIF(!request.orderNo.IsNullOrEmpty(), x => x.BillNO == request.orderNo) .FirstAsync(); if (invoice == null) return DataResult.FailedWithDesc(MultiLanguageConst.EmptyData); var req = new InvoiceReversalRequest { orderNo = invoice.BillNO }; var result = await api.PostAsync>("/api/Invoice/RedInvoicing", req); if (!result.Succeeded) return DataResult.Failed(result.Message, result.MultiCode); var invResult = result.Data; JObject? jObj = JObject.Parse(invResult.Data); if (invResult.Success) return DataResult.Failed(invResult.Message); invoice.IsSetRed = true; invoice.RedReason = request.Reason; await TenantDb.Updateable(invoice).UpdateColumns(x => new { x.IsSetRed, x.RedReason }).ExecuteCommandAsync(); return DataResult.Success; } /// /// 添加租户信息 /// /// 租户信息 /// /// 为null时引发。 public async Task AddTenantAsync(Tenant tenant) { ArgumentNullException.ThrowIfNull(tenant, nameof(tenant)); var result = await api.PostAsync("/api/Login/AddTenant", tenant); return result.Data; } } }