using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.JsonPatch; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Mvc.Abstractions; using MisIngredientesVue.Core.Exceptions; using MisIngredientesVue.Core.Models; using MisIngredientesVue.Core.Extensions; using MisIngredientesVue.Core.Services; using Wkhtmltopdf.NetCore; namespace MisIngredientesVue.Controllers { [Route("api/[controller]")] [ApiController] public class InvoicingController : Controller { private readonly IAuthenticationTokenService _authenticationTokenService; private readonly IUsersService _userService; private readonly ISettingsService _settingsService; private readonly IServiceProvider _serviceProvider; private readonly IHostingEnvironment _env; private readonly IInvoicingService _invoicingService; readonly IGeneratePdf _generatePdf; public InvoicingController( IServiceProvider serviceProvider, IHostingEnvironment env, IInvoicingService invoicingService, IGeneratePdf generatePdf, IAuthenticationTokenService authenticationTokenService, IUsersService userService, ISettingsService settingsService) { _env = env; _invoicingService = invoicingService; _serviceProvider = serviceProvider; _generatePdf = generatePdf; _authenticationTokenService = authenticationTokenService; _userService = userService; _settingsService = settingsService; //_clientService = clientService; } [HttpPost("{orderId}")] public async Task GenerateOrder(int orderId, [FromBody]StampRequest request) { try { if (User.Identity.IsClient()) { return BadRequest(); } else { if (!User.Identity.IsInvoicingInfoAvailable()) throw new BadRequestException(); var cfdi = await _invoicingService.GenerateInvoice(User.Identity.GetTenantId(), User.Identity.GetCompanyRfc(), User.Identity.GetCompanyFiscalName(), User.Identity.GetCompanyFiscalReg(), User.Identity.GetUserId(), orderId, request.Rfc, request.UsoCfdi, request.PaymentForm, request.PaymentMethod, User.Identity.GetSubSubscriptionItemId(), Request.GetTimeOffset(), User.Identity.GetFreeInvoicingFolios(), User.Identity.GetSubSubscriptionId()); var showPromissoryNote = await _settingsService.GetSettingValue(User.Identity.GetTenantId(), ClientSettingType.OrdersShowPromissoryNote); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); cfdi.ShowPromissoryNote = showPromissoryNote; var view = View("Templates/InvoicePdf", cfdi); return Ok(new StampResponse() { InvoiceId = cfdi.Id, Emails = GetEmails(cfdi, false), Html = await RenderToStringAsync(view, _serviceProvider), IsDataMissing = cfdi == null }); } } catch (EInvoicingException ex) { return Ok(new StampResponse() { Html = null, Error = ex.Message, IsDataMissing = false, RanOutOfFolios = ex.RanOutOfFolios }); } catch (BadRequestException) { return BadRequest(new StampResponse() { Html = null, Error = "Datos de facturación inválidos", IsDataMissing = false }); } } [HttpPost("global")] public async Task InvoiceOrders([FromBody] StampRequest request) { try { if (User.Identity.IsClient()) { return BadRequest(); } if (!User.Identity.IsInvoicingInfoAvailable()) throw new BadRequestException(); if (request.OrderIds.Length <= 1) return BadRequest(new StampResponse() { Html = null, Error = "Especifique más de un pedido", IsDataMissing = false }); var cfdi = await _invoicingService.GenerateGlobalInvoice(User.Identity.GetTenantId(), User.Identity.GetCompanyRfc(), User.Identity.GetCompanyFiscalName(), User.Identity.GetCompanyFiscalReg(), User.Identity.GetUserId(), request.OrderIds, request.Rfc, request.UsoCfdi, request.PaymentForm, request.PaymentMethod, User.Identity.GetSubSubscriptionItemId(), Request.GetTimeOffset(), request.BreakDownOrders, request.Query, User.Identity.GetFreeInvoicingFolios(), User.Identity.GetSubSubscriptionId()); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var view = View("Templates/InvoicePdf", cfdi); return Ok(new StampResponse() { InvoiceId = cfdi.Id, Emails = GetEmails(cfdi, false), Html = await RenderToStringAsync(view, _serviceProvider), IsDataMissing = cfdi == null }); } catch (EInvoicingException ex) { return Ok(new StampResponse() { Html = null, Error = ex.Message, IsDataMissing = false, RanOutOfFolios = ex.RanOutOfFolios }); } catch (BadRequestException) { return BadRequest(new StampResponse() { Html = null, Error = "Datos de facturación inválidos", IsDataMissing = false }); } } [HttpPost("payment")] public async Task GenerateOrderPayment([FromBody] StampPaymentRequest request) { try { if (User.Identity.IsClient()) { return BadRequest(); } if (!User.Identity.IsInvoicingInfoAvailable()) throw new BadRequestException(); var cfdi = await _invoicingService.GeneratePayment(User.Identity.GetTenantId(), User.Identity.GetUserId(), request.OrderPaymentIds, request.PaymentForm, request.PaymentDate, request.PaymentTime, User.Identity.GetSubSubscriptionItemId(), Request.GetTimeOffset(), User.Identity.GetFreeInvoicingFolios(), User.Identity.GetSubSubscriptionId()); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var view = View("Templates/PaymentPdf", cfdi); return Ok(new StampResponse() { InvoiceId = cfdi.Id, Emails = await _invoicingService.GetEmailsFromOrderIds(User.Identity.GetTenantId(), request.OrderIds), Html = await RenderToStringAsync(view, _serviceProvider), IsDataMissing = cfdi == null }); } catch (EInvoicingException ex) { return Ok(new StampResponse() { Html = null, Error = ex.Message, IsDataMissing = false, RanOutOfFolios = ex.RanOutOfFolios }); } catch (BadRequestException) { return BadRequest(new StampResponse() { Html = null, Error = "Datos de facturación inválidos", IsDataMissing = false }); } } [HttpPost("preview/{orderId}")] public async Task GetPreviewInvoice(int orderId, [FromBody]StampRequest request) { var showPromissoryNote = await _settingsService.GetSettingValue(User.Identity.GetTenantId(), ClientSettingType.OrdersShowPromissoryNote); var cfdi = await _invoicingService.GetPreviewInvoice(User.Identity.GetTenantId(), User.Identity.GetCompanyRfc(), User.Identity.GetCompanyFiscalName(), User.Identity.GetCompanyFiscalReg(), orderId, request.Rfc, request.UsoCfdi, request.PaymentForm, request.PaymentMethod, Request.GetTimeOffset()); cfdi.ShowPromissoryNote = showPromissoryNote; cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var view = View("Templates/InvoicePdf", cfdi); return Ok(new { cfdi.Id, html = await RenderToStringAsync(view, _serviceProvider) }); ; } [HttpPost("globalpreview")] public async Task GetGlobalPreviewInvoice([FromBody]StampRequest request) { var showPromissoryNote = await _settingsService.GetSettingValue(User.Identity.GetTenantId(), ClientSettingType.OrdersShowPromissoryNote); var cfdi = await _invoicingService.GetGlobalPreviewInvoice(User.Identity.GetTenantId(), User.Identity.GetCompanyRfc(), User.Identity.GetCompanyFiscalName(), User.Identity.GetCompanyFiscalReg(), request.OrderIds, request.Rfc, request.UsoCfdi, request.PaymentForm, request.PaymentMethod, Request.GetTimeOffset(), request.BreakDownOrders, request.Query); cfdi.ShowPromissoryNote = showPromissoryNote; cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var view = View("Templates/InvoicePdf", cfdi); return Ok(new { cfdi.Id, html = await RenderToStringAsync(view, _serviceProvider) }); ; } [HttpPost("previewpayment")] public async Task GetPreviewPayment([FromBody]ProofOfPaymentStampRequest request) { var showPromissoryNote = await _settingsService.GetSettingValue(User.Identity.GetTenantId(), ClientSettingType.OrdersShowPromissoryNote); var cfdi = await _invoicingService.GetPreviewPayment(User.Identity.GetTenantId(), request.OrderPaymentIds, request.PaymentMethod, request.PaymentDate, request.PaymentTime, Request.GetTimeOffset()); cfdi.ShowPromissoryNote = showPromissoryNote; cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var view = View("Templates/PaymentPdf", cfdi); return Ok(new { cfdi.Id, html = await RenderToStringAsync(view, _serviceProvider) }); ; } [HttpGet("{invoiceId}")] public async Task GetInvoice(int invoiceId) //invoiceId = CFDI Id { if (User.Identity.IsClient()) { //WARNING: Revisar que este tenantId sea amigo del actual var cfdiTenantId = await _invoicingService.GetTenantIdFromInvoiceId(invoiceId); var cfdi = await _invoicingService.GetInvoice(cfdiTenantId, invoiceId); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(cfdiTenantId, false); cfdi.ShowPromissoryNote = true; var view = View("Templates/InvoicePdf", cfdi); return Ok(new { cfdi.Id, emails = GetEmails(cfdi, true), html = await RenderToStringAsync(view, _serviceProvider) }); } else { var showPromissoryNote = await _settingsService.GetSettingValue(User.Identity.GetTenantId(), ClientSettingType.OrdersShowPromissoryNote); var cfdi = await _invoicingService.GetInvoice(User.Identity.GetTenantId(), invoiceId); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); cfdi.ShowPromissoryNote = showPromissoryNote; var view = View("Templates/InvoicePdf", cfdi); return Ok(new { cfdi.Id, emails = GetEmails(cfdi, false), html = await RenderToStringAsync(view, _serviceProvider) }); } } [HttpPost("{invoiceId}/cancel")] public async Task CancelInvoice(int invoiceId, [FromBody] CancelInvoiceRequest request) { if (User.Identity.IsClient()) { return BadRequest(); } var cfdi = await _invoicingService.GetInvoice(User.Identity.GetTenantId(), invoiceId); if (cfdi == null) return NotFound(); var acuse = await _invoicingService.CancelInvoice(User.Identity.GetTenantId(), User.Identity.GetUserId(), invoiceId, User.Identity.GetSubSubscriptionItemId(), request.Motive); await _invoicingService.SendCancelledEmail(User.Identity.GetTenantId(), cfdi, WebUtility.HtmlDecode(acuse), GetEmails(cfdi, false), request.Email, User.Identity.GetSubscriptionLevel() == 0); return Ok(new { acuse }); } [HttpGet("payment/{paymentId}/{orderId}")] public async Task GetPayment(int paymentId, int orderId) //paymentId = CFDI Id { if (User.Identity.IsClient()) { return BadRequest(); } var cfdi = await _invoicingService.GetPayment(User.Identity.GetTenantId(), paymentId); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var view = View("Templates/PaymentPdf", cfdi); return Ok(new { cfdi.Id, emails = await _invoicingService.GetEmailsFromOrderId(User.Identity.GetTenantId(), orderId), html = await RenderToStringAsync(view, _serviceProvider) }); } [HttpPost("payment/{paymentId}/cancel")] public async Task CancelPayment(int paymentId, CancelPaymentRequest request) //paymentId = CFDI Id { if (User.Identity.IsClient()) { return BadRequest(); } var cfdi = await _invoicingService.GetPayment(User.Identity.GetTenantId(), paymentId); if (cfdi == null) return NotFound(); var acuse = await _invoicingService.CancelPayment(User.Identity.GetTenantId(), User.Identity.GetUserId(), paymentId, User.Identity.GetSubSubscriptionItemId(), request.Motive); var emails = await _invoicingService.GetEmailsFromOrderId(User.Identity.GetTenantId(), request.OrderId); await _invoicingService.SendCancelledEmail(User.Identity.GetTenantId(), cfdi, WebUtility.HtmlDecode(acuse), emails, null, User.Identity.GetSubscriptionLevel() == 0); return Ok(new { acuse }); } [HttpPost("{id}/xml")] public async Task GetInvoiceXml(int id) { if (User.Identity.IsClient()) { //WARNING: Revisar que este tenantId sea amigo del actual var cfdiTenantId = await _invoicingService.GetTenantIdFromInvoiceId(id); var cfdi = await _invoicingService.GetInvoice(cfdiTenantId, id); if (cfdi == null) return NotFound(); var fileResult = new FileContentResult(System.Text.UTF8Encoding.UTF8.GetBytes(cfdi.XmlAsString), "application/xml"); fileResult.FileDownloadName = $"Factura {cfdi.Serie}-{cfdi.Folio}.xml"; return fileResult; } else { var cfdi = await _invoicingService.GetInvoice(User.Identity.GetTenantId(), id); if (cfdi == null) return NotFound(); var fileResult = new FileContentResult(System.Text.UTF8Encoding.UTF8.GetBytes(cfdi.XmlAsString), "application/xml"); fileResult.FileDownloadName = $"Factura {cfdi.Serie}-{cfdi.Folio}.xml"; return fileResult; } } [HttpPost("{id}/payment/xml")] public async Task GetPaymentXml(int id) { if (User.Identity.IsClient()) { return BadRequest(); } var cfdi = await _invoicingService.GetPayment(User.Identity.GetTenantId(), id); if (cfdi == null) return NotFound(); var fileResult = new FileContentResult(System.Text.UTF8Encoding.UTF8.GetBytes(cfdi.XmlAsString), "application/xml"); fileResult.FileDownloadName = $"Complemento de Pago {cfdi.Serie}-{cfdi.Folio}.xml"; return fileResult; } [HttpGet("folios")] public async Task GetInvoicingFolios() { if (User.Identity.IsClient()) { return BadRequest(); } var now = DateTime.Now; return Ok(await _invoicingService.GetInvoicingFolios(User.Identity.GetTenantId(), User.Identity.GetCompanyRfc(), User.Identity.GetCompanyFiscalName(), User.Identity.GetCompanyFiscalReg(), "TODO", new DateTime(now.Year, now.Month, 1), new DateTime(now.Year, now.Month, DateTime.DaysInMonth(now.Year, now.Month)))); } [HttpGet("info")] public async Task GetInvoicingInfo() { if (User.Identity.IsClient()) { return BadRequest(); } return Ok(await _invoicingService.GetInvoicingInfo(User.Identity.GetTenantId())); } [HttpPost("info")] public async Task SaveInvoicingInfo([FromForm] InvoicingInfo info) { if (User.Identity.IsClient()) { return BadRequest(); } var res = await _invoicingService.SaveInvoicingInfo(User.Identity.GetTenantId(), info); await RefreshJsonToken(); return Ok(res); } [HttpPost("{id}/email")] public async Task SendEmail(int id, [FromBody]SendEmailRequest request) { if (User.Identity.IsClient()) { //WARNING: Revisar que este tenantId sea amigo del actual var cfdiTenantId = await _invoicingService.GetTenantIdFromInvoiceId(id); var cfdi = await _invoicingService.GetInvoice(cfdiTenantId, id); if (cfdi == null) return NotFound(); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(cfdiTenantId, false); var pdf = await GetCfdiPdf(cfdiTenantId, cfdi, "/Views/Templates/InvoicePdf.cshtml"); await _invoicingService.SendEmail(cfdiTenantId, cfdi, pdf, request.Recipients, request.EmailBody, User.Identity.GetSubscriptionLevel() == 0); return Ok(); } else { var cfdi = await _invoicingService.GetInvoice(User.Identity.GetTenantId(), id); if (cfdi == null) return NotFound(); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var pdf = await GetCfdiPdf(User.Identity.GetTenantId(), cfdi, "/Views/Templates/InvoicePdf.cshtml"); await _invoicingService.SendEmail(User.Identity.GetTenantId(), cfdi, pdf, request.Recipients, request.EmailBody, User.Identity.GetSubscriptionLevel() == 0); return Ok(); } } //[HttpPost("{id}/cancelledemail")] //public async Task SendCancelledEmail(int id, [FromBody] SendCancelledEmailRequest request) //{ // var cfdi = await _invoicingService.GetPayment(User.Identity.GetTenantId(), id); // if (cfdi == null) // return NotFound(); // await _invoicingService.SendCancelledEmail(User.Identity.GetTenantId(), // cfdi, // WebUtility.HtmlDecode(request.Acuse), // request.Recipients); // return Ok(); //} [HttpPost("{id}/payment/email")] public async Task SendEmailPayment(int id, [FromBody] SendEmailRequest request) { if (User.Identity.IsClient()) { return BadRequest(); } var cfdi = await _invoicingService.GetPayment(User.Identity.GetTenantId(), id); if (cfdi == null) return NotFound(); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var pdf = await GetCfdiPdf(User.Identity.GetTenantId(), cfdi, "/Views/Templates/PaymentPdf.cshtml"); await _invoicingService.SendEmail(User.Identity.GetTenantId(), cfdi, pdf, request.Recipients, request.EmailBody, User.Identity.GetSubscriptionLevel() == 0); return Ok(); } [HttpPost("{id}/pdf")] public async Task GetInvoicePdf(int id) { if(User.Identity.IsClient()) { //WARNING: Revisar que este tenantId sea amigo del actual var cfdiTenantId = await _invoicingService.GetTenantIdFromInvoiceId(id); var cfdi = await _invoicingService.GetInvoice(cfdiTenantId, id); if (cfdi == null) return NotFound(); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(cfdiTenantId, false); var pdf = await GetCfdiPdf(cfdiTenantId, cfdi, "/Views/Templates/InvoicePdf.cshtml"); var fileResult = new FileContentResult(pdf, "application/pdf"); fileResult.FileDownloadName = $"Factura {cfdi.Serie}-{cfdi.Folio}.pdf"; return fileResult; } else { var cfdi = await _invoicingService.GetInvoice(User.Identity.GetTenantId(), id); if (cfdi == null) return NotFound(); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var pdf = await GetCfdiPdf(User.Identity.GetTenantId(), cfdi, "/Views/Templates/InvoicePdf.cshtml"); var fileResult = new FileContentResult(pdf, "application/pdf"); fileResult.FileDownloadName = $"Factura {cfdi.Serie}-{cfdi.Folio}.pdf"; return fileResult; } } [HttpPost("{id}/payment/pdf")] public async Task GetPaymentPdf(int id) { if (User.Identity.IsClient()) { return BadRequest(); } var cfdi = await _invoicingService.GetPayment(User.Identity.GetTenantId(), id); if (cfdi == null) return NotFound(); cfdi.LogoBase64 = await _userService.GetCompanyImageAsBase64String(User.Identity.GetTenantId(), User.Identity.HasFreeSubscription()); var pdf = await GetCfdiPdf(User.Identity.GetTenantId(), cfdi, "/Views/Templates/PaymentPdf.cshtml"); var fileResult = new FileContentResult(pdf, "application/pdf"); fileResult.FileDownloadName = $"Complemento de Pago {cfdi.Serie}-{cfdi.Folio}.pdf"; return fileResult; } private static async Task RenderToStringAsync(ViewResult viewResult, IServiceProvider serviceProvider, object model = null) { if (viewResult == null) throw new ArgumentNullException(nameof(viewResult)); var httpContext = new DefaultHttpContext { RequestServices = serviceProvider, }; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); using (var stream = new MemoryStream()) { httpContext.Response.Body = stream; // inject a convenient memory stream await viewResult.ExecuteResultAsync(actionContext); // execute view result on that stream httpContext.Response.Body.Position = 0; return new StreamReader(httpContext.Response.Body).ReadToEnd(); // collect the content of the stream } } private async Task GetCfdiPdf(string tenantId, Cfdi cfdi, string template) { var showPromissoryNote = await _settingsService.GetSettingValue(tenantId, ClientSettingType.OrdersShowPromissoryNote); var view = View(template, cfdi); cfdi.ShowPromissoryNote = showPromissoryNote; var htmlString = await RenderToStringAsync(view, _serviceProvider); //var converter = new HtmlToPdf(); //converter.Options.PdfPageSize = PdfPageSize.Letter; //converter.Options.PdfPageOrientation = PdfPageOrientation.Portrait; //converter.Options.MarginLeft = 15; //converter.Options.MarginRight = 15; //converter.Options.MarginTop = 15; //converter.Options.MarginBottom = 15; _generatePdf.SetConvertOptions(new ConvertOptions() { PageSize = Wkhtmltopdf.NetCore.Options.Size.Letter, PageOrientation = Wkhtmltopdf.NetCore.Options.Orientation.Portrait, PageMargins = new Wkhtmltopdf.NetCore.Options.Margins(5,5,5,5) }); string baseUrl = _env.WebRootPath; //var doc = converter.ConvertHtmlString(htmlString, baseUrl); //var pdf = doc.Save(); //doc.Close(); var pdf = _generatePdf.GetPDF(htmlString); return pdf; } private async Task RefreshJsonToken() { var user = await _userService.GetUser(User.Identity.GetTenantId(), User.Identity.GetUserId(), User.Identity.IsClient()); var invoicingInfo = await _invoicingService.GetInvoicingInfo(User.Identity.GetTenantId()); var newToken = await _authenticationTokenService.GetTokenForUser(user.TenantId, user, invoicingInfo); Response.Headers.Add("x-refresh-token", newToken.Token); } private string[] GetEmails(Cfdi cfdi, bool isClient) { var list = new List(); if (cfdi?.Orders == null) return list.ToArray(); foreach (var order in cfdi.Orders) { list.Add((order.Branch?.SendInvoice ?? false) ? order.Branch.ManagerEmail : null); list.Add((order.Branch?.ClientBrand?.SendInvoice ?? false) ? order.Branch.ClientBrand.ContactEmail : null); list.Add((order.Branch?.TaxPayer?.SendInvoice ?? false) ? (isClient ? order.Branch.TaxPayer.BillingManagerEmail : order.Branch.TaxPayer.Email) : null); } return list.Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().ToArray(); } } public class CancelInvoiceRequest { public string Email { get; set; } public string Motive { get; set; } } public class CancelPaymentRequest { public int OrderId { get; set; } public string Motive { get; set; } } public class GetTenantInfoRequest { public string TenantId { get; set; } } public class StampResponse { public string[] Emails { get; set; } public int InvoiceId { get; set; } public string Html { get; set; } public bool IsDataMissing { get; set; } public string Error { get; set; } public bool RanOutOfFolios { get; set; } } public class SendEmailRequest { public string[] Recipients { get; set; } public string EmailBody { get; set; } } public class SendCancelledEmailRequest { public string Acuse { get; set; } public string[] Recipients { get; set; } } public class StampRequest { public int[] OrderIds { get; set; } public string Rfc { get; set; } public string UsoCfdi { get; set; } public string PaymentForm { get; set; } public string PaymentMethod { get; set; } public string Comments { get; set; } public bool BreakDownOrders { get; set; } public OrdersFilterQuery Query { get; set; } } public class StampPaymentRequest { public int[] OrderIds { get; set; } public int[] OrderPaymentIds { get; set; } public string PaymentForm { get; set; } public string PaymentDate { get; set; } public string PaymentTime { get; set; } } public class ProofOfPaymentStampRequest { public int[] OrderPaymentIds { get; set; } public string PaymentMethod { get; set; } public string PaymentDate { get; set; } public string PaymentTime { get; set; } } public class SaveDataAndStampRequest { public string TenantId { get; set; } public string OrderId { get; set; } public string Rfc { get; set; } public string UsoCfdi { get; set; } public string TotalAmount { get; set; } public string Street { get; set; } public string LegalName { get; set; } public string NumExt { get; set; } public string NumInt { get; set; } public string Col { get; set; } public string Mun { get; set; } public string Email { get; set; } public string Phone { get; set; } public string Zip { get; set; } public string State { get; set; } } }