From 32aa5defc9d722e2e0af027700b43f851dfc26a3 Mon Sep 17 00:00:00 2001 From: Jose Antonio Medina Date: Wed, 11 Feb 2026 02:07:35 -0600 Subject: [PATCH 1/4] Updated package.json --- package-lock.json | 416 ++-------------------------------------------- package.json | 2 +- 2 files changed, 12 insertions(+), 406 deletions(-) diff --git a/package-lock.json b/package-lock.json index e77a8f9..cae2270 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "dotenv": "^16.4.7", - "fiscalapi": "^4.0.141", + "fiscalapi": "^4.0.360", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "swagger-ui-express": "^5.0.1" @@ -1842,246 +1842,6 @@ "@napi-rs/nice-win32-x64-msvc": "1.0.1" } }, - "node_modules/@napi-rs/nice-android-arm-eabi": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.0.1.tgz", - "integrity": "sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-android-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.0.1.tgz", - "integrity": "sha512-GqvXL0P8fZ+mQqG1g0o4AO9hJjQaeYG84FRfZaYjyJtZZZcMjXW5TwkL8Y8UApheJgyE13TQ4YNUssQaTgTyvA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.0.1.tgz", - "integrity": "sha512-91k3HEqUl2fsrz/sKkuEkscj6EAj3/eZNCLqzD2AA0TtVbkQi8nqxZCZDMkfklULmxLkMxuUdKe7RvG/T6s2AA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.0.1.tgz", - "integrity": "sha512-jXnMleYSIR/+TAN/p5u+NkCA7yidgswx5ftqzXdD5wgy/hNR92oerTXHc0jrlBisbd7DpzoaGY4cFD7Sm5GlgQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-freebsd-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.0.1.tgz", - "integrity": "sha512-j+iJ/ezONXRQsVIB/FJfwjeQXX7A2tf3gEXs4WUGFrJjpe/z2KB7sOv6zpkm08PofF36C9S7wTNuzHZ/Iiccfw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.0.1.tgz", - "integrity": "sha512-G8RgJ8FYXYkkSGQwywAUh84m946UTn6l03/vmEXBYNJxQJcD+I3B3k5jmjFG/OPiU8DfvxutOP8bi+F89MCV7Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.0.1.tgz", - "integrity": "sha512-IMDak59/W5JSab1oZvmNbrms3mHqcreaCeClUjwlwDr0m3BoR09ZiN8cKFBzuSlXgRdZ4PNqCYNeGQv7YMTjuA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.0.1.tgz", - "integrity": "sha512-wG8fa2VKuWM4CfjOjjRX9YLIbysSVV1S3Kgm2Fnc67ap/soHBeYZa6AGMeR5BJAylYRjnoVOzV19Cmkco3QEPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-ppc64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.0.1.tgz", - "integrity": "sha512-lxQ9WrBf0IlNTCA9oS2jg/iAjQyTI6JHzABV664LLrLA/SIdD+I1i3Mjf7TsnoUbgopBcCuDztVLfJ0q9ubf6Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-riscv64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.0.1.tgz", - "integrity": "sha512-3xs69dO8WSWBb13KBVex+yvxmUeEsdWexxibqskzoKaWx9AIqkMbWmE2npkazJoopPKX2ULKd8Fm9veEn0g4Ig==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-s390x-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.0.1.tgz", - "integrity": "sha512-lMFI3i9rlW7hgToyAzTaEybQYGbQHDrpRkg+1gJWEpH0PLAQoZ8jiY0IzakLfNWnVda1eTYYlxxFYzW8Rqczkg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.0.1.tgz", - "integrity": "sha512-XQAJs7DRN2GpLN6Fb+ZdGFeYZDdGl2Fn3TmFlqEL5JorgWKrQGRUrpGKbgZ25UeZPILuTKJ+OowG2avN8mThBA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.0.1.tgz", - "integrity": "sha512-/rodHpRSgiI9o1faq9SZOp/o2QkKQg7T+DK0R5AkbnI/YxvAIEHf2cngjYzLMQSQgUhxym+LFr+UGZx4vK4QdQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-arm64-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.0.1.tgz", - "integrity": "sha512-rEcz9vZymaCB3OqEXoHnp9YViLct8ugF+6uO5McifTedjq4QMQs3DHz35xBEGhH3gJWEsXMUbzazkz5KNM5YUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-ia32-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.0.1.tgz", - "integrity": "sha512-t7eBAyPUrWL8su3gDxw9xxxqNwZzAqKo0Szv3IjVQd1GpXXVkb6vBBQUuxfIYaXMzZLwlxRQ7uzM2vdUE9ULGw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@napi-rs/nice-win32-x64-msvc": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.0.1.tgz", @@ -2629,150 +2389,6 @@ } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.16.tgz", - "integrity": "sha512-l6uWMU+MUdfLHCl3dJgtVEdsUHPskoA4BSu0L1hh9SGBwPZ8xeOz8iLIqZM27lTuXxL4KsYH6GQR/OdQ/vhLtg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.16.tgz", - "integrity": "sha512-TH0IW8Ao1WZ4ARFHIh29dAQHYBEl4YnP74n++rjppmlCjY+8v3s5nXMA7IqxO3b5LVHyggWtU4+46DXTyMJM7g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.16.tgz", - "integrity": "sha512-2IxD9t09oNZrbv37p4cJ9cTHMUAK6qNiShi9s2FJ9LcqSnZSN4iS4hvaaX6KZuG54d58vWnMU7yycjkdOTQcMg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.16.tgz", - "integrity": "sha512-AYkN23DOiPh1bf3XBf/xzZQDKSsgZTxlbyTyUIhprLJpAAAT0ZCGAUcS5mHqydk0nWQ13ABUymodvHoroutNzw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.16.tgz", - "integrity": "sha512-n/nWXDRCIhM51dDGELfBcTMNnCiFatE7LDvsbYxb7DJt1HGjaCNvHHCKURb/apJTh/YNtWfgFap9dbsTgw8yPA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.16.tgz", - "integrity": "sha512-xr182YQrF47n7Awxj+/ruI21bYw+xO/B26KFVnb+i3ezF9NOhqoqTX+33RL1ZLA/uFTq8ksPZO/y+ZVS/odtQA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.16.tgz", - "integrity": "sha512-k2JBfiwWfXCIKrBRjFO9/vEdLSYq0QLJ+iNSLdfrejZ/aENNkbEg8O7O2GKUSb30RBacn6k8HMfJrcPLFiEyCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.16.tgz", - "integrity": "sha512-taOb5U+abyEhQgex+hr6cI48BoqSvSdfmdirWcxprIEUBHCxa1dSriVwnJRAJOFI9T+5BEz88by6rgbB9MjbHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.16.tgz", - "integrity": "sha512-b7yYggM9LBDiMY+XUt5kYWvs5sn0U3PXSOGvF3CbLufD/N/YQiDcYON2N3lrWHYL8aYnwbuZl45ojmQHSQPcdA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core-win32-x64-msvc": { "version": "1.11.16", "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.16.tgz", @@ -5770,11 +5386,13 @@ } }, "node_modules/fiscalapi": { - "version": "4.0.141", - "resolved": "https://registry.npmjs.org/fiscalapi/-/fiscalapi-4.0.141.tgz", - "integrity": "sha512-EruakXeMel+0lBiVQoR8fOtU0W8A7HdOGvb+wSTZuBV6fLhW2r9RszTpFITv9rkVC7qJh6JKU9RLz9C0nKLhyQ==", + "version": "4.0.360", + "resolved": "https://registry.npmjs.org/fiscalapi/-/fiscalapi-4.0.360.tgz", + "integrity": "sha512-Wb1OwIqHa+hb31z2rE3j7/DY7iI5ye0fAGcBMlc9dLK1eSSf1EUZVRghheSaEZ2rSWGcH19SjudQGJRw/MjAmA==", + "license": "MPL-2.0", "dependencies": { "axios": "^1.8.4", + "form-data": "^4.0.4", "luxon": "^3.6.0" }, "engines": { @@ -5924,13 +5542,15 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -6021,20 +5641,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", diff --git a/package.json b/package.json index 0614dc5..a3c30d0 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "dotenv": "^16.4.7", - "fiscalapi": "^4.0.141", + "fiscalapi": "^4.0.360", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "swagger-ui-express": "^5.0.1" From 41123f770b1a555eb3853379289683839173dbe8 Mon Sep 17 00:00:00 2001 From: Jose Antonio Medina Date: Wed, 11 Feb 2026 02:08:12 -0600 Subject: [PATCH 2/4] Added examples for payroll and local taxes complement --- src/facturas/invoices.controller.ts | 514 +++++++++++++++++++++++++++- 1 file changed, 513 insertions(+), 1 deletion(-) diff --git a/src/facturas/invoices.controller.ts b/src/facturas/invoices.controller.ts index b377100..2ec5206 100644 --- a/src/facturas/invoices.controller.ts +++ b/src/facturas/invoices.controller.ts @@ -820,6 +820,519 @@ export class InvoicesController { } } + @Post('complemento-nomina-por-valores') + @ApiOperation({ summary: 'Crear factura con complemento de nómina por valores' }) + @ApiResponse({ status: 200, description: 'Factura con complemento de nómina creada correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de nómina' }) + async crearComplementoNominaPorValores() { + try { + const payrollInvoice: Invoice = { + versionCode: "4.0", + series: "F", + date: this.currentDate, + paymentMethodCode: "PUE", + currencyCode: "MXN", + typeCode: "N", + expeditionZipCode: "20000", + exportCode: "01", + issuer: { + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + taxRegimeCode: "621", + employerData: { + employerRegistration: "B5510768108", + curp: "XEXX010101MNEXXXA8" + }, + taxCredentials: [ + { + base64File: this.base64Cert, + fileType: 0, + password: this.password + }, + { + base64File: this.base64Key, + fileType: 1, + password: this.password + } + ] + }, + recipient: { + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + zipCode: "01160", + taxRegimeCode: "605", + cfdiUseCode: "CN01", + employeeData: { + curp: "XEXX010101MNEXXXA8", + socialSecurityNumber: "04078873454", + laborRelationStartDate: "2024-08-18", + seniority: "P54W", + satContractTypeId: "01", + satTaxRegimeTypeId: "02", + employeeNumber: "123456789", + department: "GenAI", + position: "Sr Software Engineer", + satJobRiskId: "1", + satPaymentPeriodicityId: "05", + satBankId: "012", + baseSalaryForContributions: 2828.50, + integratedDailySalary: 0.00, + satPayrollStateId: "JAL" + } + }, + complement: { + payroll: { + version: "1.2", + payrollTypeCode: "O", + paymentDate: "2025-08-30", + initialPaymentDate: "2025-07-31", + finalPaymentDate: "2025-08-30", + daysPaid: 30, + earnings: { + earnings: [ + { + earningTypeCode: "001", + code: "1003", + concept: "Sueldo Nominal", + taxedAmount: 95030.00, + exemptAmount: 0.00 + }, + { + earningTypeCode: "005", + code: "5913", + concept: "Fondo de Ahorro Aportación Patrón", + taxedAmount: 0.00, + exemptAmount: 4412.46 + }, + { + earningTypeCode: "038", + code: "1885", + concept: "Bono Ingles", + taxedAmount: 14254.50, + exemptAmount: 0.00 + }, + { + earningTypeCode: "029", + code: "1941", + concept: "Vales Despensa", + taxedAmount: 0.00, + exemptAmount: 3439.00 + }, + { + earningTypeCode: "038", + code: "1824", + concept: "Herramientas Teletrabajo (telecom y prop. electri)", + taxedAmount: 273.00, + exemptAmount: 0.00 + } + ], + otherPayments: [ + { + otherPaymentTypeCode: "002", + code: "5050", + concept: "Exceso de subsidio al empleo", + amount: 0.00, + subsidyCaused: 0.00 + } + ] + }, + deductions: [ + { + deductionTypeCode: "002", + code: "5003", + concept: "ISR Causado", + amount: 27645.52 + }, + { + deductionTypeCode: "004", + code: "5910", + concept: "Fondo de ahorro Empleado Inversión", + amount: 4412.46 + }, + { + deductionTypeCode: "004", + code: "5914", + concept: "Fondo de Ahorro Patrón Inversión", + amount: 4412.46 + }, + { + deductionTypeCode: "004", + code: "1966", + concept: "Contribución póliza exceso GMM", + amount: 519.91 + }, + { + deductionTypeCode: "004", + code: "1934", + concept: "Descuento Vales Despensa", + amount: 1.00 + }, + { + deductionTypeCode: "004", + code: "1942", + concept: "Vales Despensa Electrónico", + amount: 3439.00 + }, + { + deductionTypeCode: "001", + code: "1895", + concept: "IMSS", + amount: 2391.13 + } + ] + } + } + }; + + const apiResponse = await this.fiscalApi.invoices.create(payrollInvoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); + } + } catch (error) { + throw new BadRequestException(error.message); + } + } + + @Post('complemento-impuestos-locales-por-valores') + @ApiOperation({ summary: 'Crear factura con complemento de impuestos locales por valores' }) + @ApiResponse({ status: 200, description: 'Factura con complemento de impuestos locales creada correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de impuestos locales' }) + async crearComplementoImpuestosLocalesPorValores() { + try { + const localTaxesInvoice: Invoice = { + versionCode: "4.0", + series: "F", + date: this.currentDate, + paymentFormCode: "01", + currencyCode: "MXN", + typeCode: "I", + expeditionZipCode: "42501", + paymentMethodCode: "PUE", + exchangeRate: 1, + exportCode: "01", + issuer: { + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + taxRegimeCode: "621", + taxCredentials: [ + { + base64File: this.base64Cert, + fileType: 0, + password: this.password + }, + { + base64File: this.base64Key, + fileType: 1, + password: this.password + } + ] + }, + recipient: { + tin: "EKU9003173C9", + legalName: "ESCUELA KEMPER URGATE", + zipCode: "42501", + taxRegimeCode: "601", + cfdiUseCode: "G01", + email: "someone@somewhere.com" + }, + items: [ + { + itemCode: "01010101", + quantity: 9.5, + unitOfMeasurementCode: "E48", + description: "Invoicing software as a service", + unitPrice: 3587.75, + taxObjectCode: "02", + itemSku: "7506022301697", + discount: 255.85, + itemTaxes: [ + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.160000", + taxFlagCode: "T" + } + ] + }, + { + itemCode: "01010101", + quantity: 8, + unitOfMeasurementCode: "E48", + description: "Software Consultant", + unitPrice: 250.85, + taxObjectCode: "02", + itemSku: "7506022301698", + discount: 255.85, + itemTaxes: [ + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.160000", + taxFlagCode: "T" + } + ] + }, + { + itemCode: "01010101", + quantity: 6, + unitOfMeasurementCode: "E48", + description: "Computer software", + unitPrice: 1250.75, + taxObjectCode: "02", + itemSku: "7506022301699", + itemTaxes: [ + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.160000", + taxFlagCode: "T" + }, + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.106666", + taxFlagCode: "R" + } + ] + } + ], + complement: { + localTaxes: { + taxes: [ + { + taxName: "CEDULAR", + taxRate: "3.00", + taxAmount: "6.00", + taxFlagCode: "R" + }, + { + taxName: "ISH", + taxRate: "8.00", + taxAmount: "16.00", + taxFlagCode: "R" + } + ] + } + } + }; + + const apiResponse = await this.fiscalApi.invoices.create(localTaxesInvoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); + } + } catch (error) { + throw new BadRequestException(error.message); + } + } + + @Post('complemento-nomina-referencias') + @ApiOperation({ summary: 'Crear complemento de nómina por referencias' }) + @ApiResponse({ status: 200, description: 'Complemento de nómina creado correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear el complemento de nómina' }) + @Post('complemento-nomina-por-referencias') + @ApiOperation({ summary: 'Crear factura con complemento de nómina por referencias' }) + @ApiResponse({ status: 200, description: 'Factura con complemento de nómina creada correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de nómina' }) + async crearComplementoNominaPorReferencias() { + try { + const payrollInvoice: Invoice = { + versionCode: "4.0", + series: "F", + date: this.currentDate, + paymentMethodCode: "PUE", + currencyCode: "MXN", + typeCode: "N", + expeditionZipCode: "20000", + exportCode: "01", + issuer: { + id: "0e82a655-5f0c-4e07-abab-8f322e4123ef" + }, + recipient: { + id: "da71df0c-f328-45ee-9bd9-3096ed02c164" + }, + complement: { + payroll: { + version: "1.2", + payrollTypeCode: "O", + paymentDate: "2025-08-30", + initialPaymentDate: "2025-07-31", + finalPaymentDate: "2025-08-30", + daysPaid: 30, + earnings: { + earnings: [ + { + earningTypeCode: "001", + code: "1003", + concept: "Sueldo Nominal", + taxedAmount: 95030.00, + exemptAmount: 0.00 + }, + { + earningTypeCode: "005", + code: "5913", + concept: "Fondo de Ahorro Aportación Patrón", + taxedAmount: 0.00, + exemptAmount: 4412.46 + }, + { + earningTypeCode: "038", + code: "1885", + concept: "Bono Ingles", + taxedAmount: 14254.50, + exemptAmount: 0.00 + }, + { + earningTypeCode: "029", + code: "1941", + concept: "Vales Despensa", + taxedAmount: 0.00, + exemptAmount: 3439.00 + }, + { + earningTypeCode: "038", + code: "1824", + concept: "Herramientas Teletrabajo (telecom y prop. electri)", + taxedAmount: 273.00, + exemptAmount: 0.00 + } + ], + otherPayments: [ + { + otherPaymentTypeCode: "002", + code: "5050", + concept: "Exceso de subsidio al empleo", + amount: 0.00, + subsidyCaused: 0.00 + } + ] + }, + deductions: [ + { + deductionTypeCode: "002", + code: "5003", + concept: "ISR Causado", + amount: 27645.52 + }, + { + deductionTypeCode: "004", + code: "5910", + concept: "Fondo de ahorro Empleado Inversión", + amount: 4412.46 + }, + { + deductionTypeCode: "004", + code: "5914", + concept: "Fondo de Ahorro Patrón Inversión", + amount: 4412.46 + }, + { + deductionTypeCode: "004", + code: "1966", + concept: "Contribución póliza exceso GMM", + amount: 519.91 + }, + { + deductionTypeCode: "004", + code: "1934", + concept: "Descuento Vales Despensa", + amount: 1.00 + }, + { + deductionTypeCode: "004", + code: "1942", + concept: "Vales Despensa Electrónico", + amount: 3439.00 + }, + { + deductionTypeCode: "001", + code: "1895", + concept: "IMSS", + amount: 2391.13 + } + ] + } + } + }; + + const apiResponse = await this.fiscalApi.invoices.create(payrollInvoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); + } + } catch (error) { + throw new BadRequestException(error.message); + } + } + + @Post('complemento-impuestos-locales-por-referencias') + @ApiOperation({ summary: 'Crear factura con complemento de impuestos locales por referencias' }) + @ApiResponse({ status: 200, description: 'Factura con complemento de impuestos locales creada correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de impuestos locales' }) + async crearComplementoImpuestosLocalesPorReferencias() { + try { + const localTaxesInvoice: Invoice = { + versionCode: "4.0", + series: "F", + date: this.currentDate, + paymentFormCode: "01", + currencyCode: "MXN", + typeCode: "I", + expeditionZipCode: "42501", + paymentMethodCode: "PUE", + exchangeRate: 1, + exportCode: "01", + issuer: { + id: "0e82a655-5f0c-4e07-abab-8f322e4123ef" + }, + recipient: { + id: "bd199ed8-02ef-47c0-919c-9479dd8ecae7" + }, + items: [ + { + id: "7f1c66f0-5d9b-4adc-821d-649d79abcbb5", + quantity: 1 + } + ], + complement: { + localTaxes: { + taxes: [ + { + taxName: "CEDULAR", + taxRate: "3.00", + taxAmount: "6.00", + taxFlagCode: "R" + }, + { + taxName: "ISH", + taxRate: "8.00", + taxAmount: "16.00", + taxFlagCode: "R" + } + ] + } + } + }; + + const apiResponse = await this.fiscalApi.invoices.create(localTaxesInvoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); + } + } catch (error) { + throw new BadRequestException(error.message); + } + } + @Post('complemento-pago-usd-mxn') @ApiOperation({ summary: 'Crear complemento de pago en USD para facturas en MXN' }) @ApiResponse({ status: 200, description: 'Complemento de pago creado correctamente' }) @@ -1402,5 +1915,4 @@ export class InvoicesController { throw new BadRequestException(error.message); } } - } \ No newline at end of file From 6c7c25024b4f8d1d61a8459e0f55a00f6d3385f6 Mon Sep 17 00:00:00 2001 From: Jose Antonio Medina Date: Wed, 11 Feb 2026 02:21:49 -0600 Subject: [PATCH 3/4] Fixed duplicated decoration --- src/facturas/invoices.controller.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/facturas/invoices.controller.ts b/src/facturas/invoices.controller.ts index 2ec5206..e107f66 100644 --- a/src/facturas/invoices.controller.ts +++ b/src/facturas/invoices.controller.ts @@ -1131,10 +1131,6 @@ export class InvoicesController { } } - @Post('complemento-nomina-referencias') - @ApiOperation({ summary: 'Crear complemento de nómina por referencias' }) - @ApiResponse({ status: 200, description: 'Complemento de nómina creado correctamente' }) - @ApiResponse({ status: 400, description: 'Error al crear el complemento de nómina' }) @Post('complemento-nomina-por-referencias') @ApiOperation({ summary: 'Crear factura con complemento de nómina por referencias' }) @ApiResponse({ status: 200, description: 'Factura con complemento de nómina creada correctamente' }) From 653222a6c5b5dac24fe238e9f61f8925f0f4a50b Mon Sep 17 00:00:00 2001 From: Jose Antonio Medina Date: Mon, 16 Feb 2026 17:46:28 -0600 Subject: [PATCH 4/4] Fixed broken payment complement examples and reorganized code to keep consistency in the frontend --- src/facturas/invoices.controller.ts | 1288 +++++++++++++-------------- 1 file changed, 644 insertions(+), 644 deletions(-) diff --git a/src/facturas/invoices.controller.ts b/src/facturas/invoices.controller.ts index e107f66..a58a0c2 100644 --- a/src/facturas/invoices.controller.ts +++ b/src/facturas/invoices.controller.ts @@ -696,8 +696,8 @@ export class InvoicesController { } ], // Sección de pagos - específica para complementos de pago - payments: [ - { + complement: { + payment: { paymentDate: "2025-03-31T14:44:56", // Fecha del pago (actualiza esta fecha) paymentFormCode: "28", // 28 - Tarjeta de débito currencyCode: "MXN", @@ -730,7 +730,7 @@ export class InvoicesController { } ] } - ] + } }; const apiResponse = await this.fiscalApi.invoices.create(invoice); @@ -771,8 +771,8 @@ export class InvoicesController { // ya que el sistema generará automáticamente el concepto requerido // Sección de pagos - específica para complementos de pago - payments: [ - { + complement: { + payment: { paymentDate: "2025-03-31T14:44:56", // Actualizado a una fecha más reciente paymentFormCode: "28", // 28 - Tarjeta de débito currencyCode: "MXN", @@ -805,7 +805,7 @@ export class InvoicesController { } ] } - ] + } }; const apiResponse = await this.fiscalApi.invoices.create(invoice); @@ -820,326 +820,360 @@ export class InvoicesController { } } - @Post('complemento-nomina-por-valores') - @ApiOperation({ summary: 'Crear factura con complemento de nómina por valores' }) - @ApiResponse({ status: 200, description: 'Factura con complemento de nómina creada correctamente' }) - @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de nómina' }) - async crearComplementoNominaPorValores() { - try { - const payrollInvoice: Invoice = { - versionCode: "4.0", + @Post('complemento-pago-usd-mxn') + @ApiOperation({ summary: 'Crear complemento de pago en USD para facturas en MXN' }) + @ApiResponse({ status: 200, description: 'Complemento de pago creado correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear el complemento de pago' }) + async crearComplementoPagoUsdMxn() { + try { + // Complemento de pago en USD para facturas en MXN + const invoice: Invoice = { + versionCode: "4.0", + series: "usd-mxn", // Serie descriptiva para pagos en USD de facturas MXN + date: this.currentDate, + currencyCode: "XXX", // Para complementos de pago siempre es XXX + typeCode: "P", // Tipo P para complementos de pago + expeditionZipCode: "01160", + exchangeRate: 1, // Para complementos de pago siempre es 1 + exportCode: "01", + issuer: { + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + taxRegimeCode: "621", + taxCredentials: [ + { + base64File: this.base64Cert, + fileType: 0, + password: this.password + }, + { + base64File: this.base64Key, + fileType: 1, + password: this.password + } + ] + }, + recipient: { + tin: "EKU9003173C9", + legalName: "ESCUELA KEMPER URGATE", + zipCode: "42501", + taxRegimeCode: "601", + cfdiUseCode: "CP01", // Uso específico para complementos de pago + email: "someone@somewhere.com" + }, + // El concepto es fijo para complementos de pago + items: [ + { + itemCode: "84111506", // Código específico para pagos + quantity: 1, + unitOfMeasurementCode: "ACT", + description: "Pago", + unitPrice: 0, + taxObjectCode: "01" + } + ], + // Sección de pagos - específica para complementos de pago + complement: { + payment: { + paymentDate: "2025-03-31T14:44:56", // Actualizado a una fecha más reciente + paymentFormCode: "28", // 28 - Tarjeta de débito + currencyCode: "USD", // El pago se realizó en dólares + exchangeRate: 20.64, // Tipo de cambio USD/MXN + amount: 5.62, // Monto del pago en USD + sourceBankTin: "BSM970519DU8", + sourceBankAccount: "1234567891012131", + targetBankTin: "BBA830831LJ2", + targetBankAccount: "1234567890", + paidInvoices: [ + { + uuid: "4a5d025b-813a-4acf-9f32-8fb61f4918ac", // UUID de la factura que se está pagando series: "F", - date: this.currentDate, - paymentMethodCode: "PUE", - currencyCode: "MXN", - typeCode: "N", - expeditionZipCode: "20000", - exportCode: "01", - issuer: { - tin: "FUNK671228PH6", - legalName: "KARLA FUENTE NOLASCO", - taxRegimeCode: "621", - employerData: { - employerRegistration: "B5510768108", - curp: "XEXX010101MNEXXXA8" + number: "2", + currencyCode: "MXN", // La factura original está en pesos + equivalence: 20.64, // El mismo tipo de cambio para conversión + partialityNumber: 1, // Número de parcialidad (1 si es pago único) + subTotal: 100.00, // Subtotal original de la factura + previousBalance: 116.00, // Saldo anterior en MXN + paymentAmount: 116.00, // Cantidad pagada (5.62 USD x 20.64 = 116.00 MXN) + remainingBalance: 0, // Saldo restante después del pago + taxObjectCode: "02", + paidInvoiceTaxes: [ + { + taxCode: "002", // IVA + taxTypeCode: "Tasa", + taxRate: "0.160000", // Como string para mantener precisión + taxFlagCode: "T" // Trasladado }, - taxCredentials: [ - { - base64File: this.base64Cert, - fileType: 0, - password: this.password - }, - { - base64File: this.base64Key, - fileType: 1, - password: this.password - } - ] - }, - recipient: { - tin: "FUNK671228PH6", - legalName: "KARLA FUENTE NOLASCO", - zipCode: "01160", - taxRegimeCode: "605", - cfdiUseCode: "CN01", - employeeData: { - curp: "XEXX010101MNEXXXA8", - socialSecurityNumber: "04078873454", - laborRelationStartDate: "2024-08-18", - seniority: "P54W", - satContractTypeId: "01", - satTaxRegimeTypeId: "02", - employeeNumber: "123456789", - department: "GenAI", - position: "Sr Software Engineer", - satJobRiskId: "1", - satPaymentPeriodicityId: "05", - satBankId: "012", - baseSalaryForContributions: 2828.50, - integratedDailySalary: 0.00, - satPayrollStateId: "JAL" - } - }, - complement: { - payroll: { - version: "1.2", - payrollTypeCode: "O", - paymentDate: "2025-08-30", - initialPaymentDate: "2025-07-31", - finalPaymentDate: "2025-08-30", - daysPaid: 30, - earnings: { - earnings: [ - { - earningTypeCode: "001", - code: "1003", - concept: "Sueldo Nominal", - taxedAmount: 95030.00, - exemptAmount: 0.00 - }, - { - earningTypeCode: "005", - code: "5913", - concept: "Fondo de Ahorro Aportación Patrón", - taxedAmount: 0.00, - exemptAmount: 4412.46 - }, - { - earningTypeCode: "038", - code: "1885", - concept: "Bono Ingles", - taxedAmount: 14254.50, - exemptAmount: 0.00 - }, - { - earningTypeCode: "029", - code: "1941", - concept: "Vales Despensa", - taxedAmount: 0.00, - exemptAmount: 3439.00 - }, - { - earningTypeCode: "038", - code: "1824", - concept: "Herramientas Teletrabajo (telecom y prop. electri)", - taxedAmount: 273.00, - exemptAmount: 0.00 - } - ], - otherPayments: [ - { - otherPaymentTypeCode: "002", - code: "5050", - concept: "Exceso de subsidio al empleo", - amount: 0.00, - subsidyCaused: 0.00 - } - ] - }, - deductions: [ - { - deductionTypeCode: "002", - code: "5003", - concept: "ISR Causado", - amount: 27645.52 - }, - { - deductionTypeCode: "004", - code: "5910", - concept: "Fondo de ahorro Empleado Inversión", - amount: 4412.46 - }, - { - deductionTypeCode: "004", - code: "5914", - concept: "Fondo de Ahorro Patrón Inversión", - amount: 4412.46 - }, - { - deductionTypeCode: "004", - code: "1966", - concept: "Contribución póliza exceso GMM", - amount: 519.91 - }, - { - deductionTypeCode: "004", - code: "1934", - concept: "Descuento Vales Despensa", - amount: 1.00 - }, - { - deductionTypeCode: "004", - code: "1942", - concept: "Vales Despensa Electrónico", - amount: 3439.00 - }, - { - deductionTypeCode: "001", - code: "1895", - concept: "IMSS", - amount: 2391.13 - } - ] + { + taxCode: "002", // IVA + taxTypeCode: "Tasa", + taxRate: "0.106667", + taxFlagCode: "R" // Retenido + }, + { + taxCode: "001", // ISR + taxTypeCode: "Tasa", + taxRate: "0.100000", + taxFlagCode: "R" // Retenido } + ] } - }; - - const apiResponse = await this.fiscalApi.invoices.create(payrollInvoice); - - if (apiResponse.succeeded) { - return apiResponse; - } else { - throw new BadRequestException(apiResponse); + ] } - } catch (error) { - throw new BadRequestException(error.message); } + }; + + const apiResponse = await this.fiscalApi.invoices.create(invoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); + } + } catch (error) { + throw new BadRequestException(error.message); + } } - @Post('complemento-impuestos-locales-por-valores') - @ApiOperation({ summary: 'Crear factura con complemento de impuestos locales por valores' }) - @ApiResponse({ status: 200, description: 'Factura con complemento de impuestos locales creada correctamente' }) - @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de impuestos locales' }) - async crearComplementoImpuestosLocalesPorValores() { - try { - const localTaxesInvoice: Invoice = { - versionCode: "4.0", + @Post('complemento-pago-mxn-usd') + @ApiOperation({ summary: 'Crear complemento de pago en MXN para facturas en USD' }) + @ApiResponse({ status: 200, description: 'Complemento de pago creado correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear el complemento de pago' }) + async crearComplementoPagoMxnUsd() { + try { + // Complemento de pago en MXN para facturas en USD + const invoice: Invoice = { + versionCode: "4.0", + series: "MXN-USD", // Serie descriptiva para pagos en MXN de facturas USD + date: this.currentDate, + currencyCode: "XXX", // Para complementos de pago siempre es XXX + typeCode: "P", // Tipo P para complementos de pago + expeditionZipCode: "01160", + exchangeRate: 1, // Para complementos de pago siempre es 1 + exportCode: "01", + issuer: { + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + taxRegimeCode: "621", + taxCredentials: [ + { + base64File: this.base64Cert, + fileType: 0, + password: this.password + }, + { + base64File: this.base64Key, + fileType: 1, + password: this.password + } + ] + }, + recipient: { + tin: "EKU9003173C9", + legalName: "ESCUELA KEMPER URGATE", + zipCode: "42501", + taxRegimeCode: "601", + cfdiUseCode: "CP01", // Uso específico para complementos de pago + email: "someone@somewhere.com" + }, + // El concepto es fijo para complementos de pago + items: [ + { + itemCode: "84111506", // Código específico para pagos + quantity: 1, + unitOfMeasurementCode: "ACT", + description: "Pago", + unitPrice: 0, + taxObjectCode: "01" + } + ], + // Sección de pagos - específica para complementos de pago + complement: { + payment: { + paymentDate: "2025-03-31T14:44:56", // Actualizado a una fecha más reciente + paymentFormCode: "28", // 28 - Tarjeta de débito + currencyCode: "MXN", // El pago se realizó en pesos mexicanos + exchangeRate: 1, // Tipo de cambio para MXN es 1 + amount: 921.23, // Monto del pago en MXN + sourceBankTin: "BSM970519DU8", + sourceBankAccount: "1234567891012131", + targetBankTin: "BBA830831LJ2", + targetBankAccount: "1234567890", + paidInvoices: [ + { + uuid: "4a5d025b-813a-4acf-9f32-8fb61f4918ac", // UUID de la factura que se está pagando series: "F", - date: this.currentDate, - paymentFormCode: "01", - currencyCode: "MXN", - typeCode: "I", - expeditionZipCode: "42501", - paymentMethodCode: "PUE", - exchangeRate: 1, - exportCode: "01", - issuer: { - tin: "FUNK671228PH6", - legalName: "KARLA FUENTE NOLASCO", - taxRegimeCode: "621", - taxCredentials: [ - { - base64File: this.base64Cert, - fileType: 0, - password: this.password - }, - { - base64File: this.base64Key, - fileType: 1, - password: this.password - } - ] - }, - recipient: { - tin: "EKU9003173C9", - legalName: "ESCUELA KEMPER URGATE", - zipCode: "42501", - taxRegimeCode: "601", - cfdiUseCode: "G01", - email: "someone@somewhere.com" - }, - items: [ + number: "2", + currencyCode: "USD", // La factura original está en dólares + equivalence: 0.045331, // Tipo de cambio inverso (MXN/USD) aprox. 1/22.06 + partialityNumber: 1, // Número de parcialidad (1 si es pago único) + subTotal: 36.00, // Subtotal original de la factura en USD + previousBalance: 41.76, // Saldo anterior en USD + paymentAmount: 41.76, // Cantidad pagada en USD (921.23 MXN ÷ 22.06 = 41.76 USD) + remainingBalance: 0, // Saldo restante después del pago + taxObjectCode: "02", + paidInvoiceTaxes: [ { - itemCode: "01010101", - quantity: 9.5, - unitOfMeasurementCode: "E48", - description: "Invoicing software as a service", - unitPrice: 3587.75, - taxObjectCode: "02", - itemSku: "7506022301697", - discount: 255.85, - itemTaxes: [ - { - taxCode: "002", - taxTypeCode: "Tasa", - taxRate: "0.160000", - taxFlagCode: "T" - } - ] + taxCode: "002", // IVA + taxTypeCode: "Tasa", + taxRate: "0.160000", // Como string para mantener precisión + taxFlagCode: "T" // Trasladado }, { - itemCode: "01010101", - quantity: 8, - unitOfMeasurementCode: "E48", - description: "Software Consultant", - unitPrice: 250.85, - taxObjectCode: "02", - itemSku: "7506022301698", - discount: 255.85, - itemTaxes: [ - { - taxCode: "002", - taxTypeCode: "Tasa", - taxRate: "0.160000", - taxFlagCode: "T" - } - ] + taxCode: "002", // IVA + taxTypeCode: "Tasa", + taxRate: "0.106667", + taxFlagCode: "R" // Retenido }, { - itemCode: "01010101", - quantity: 6, - unitOfMeasurementCode: "E48", - description: "Computer software", - unitPrice: 1250.75, - taxObjectCode: "02", - itemSku: "7506022301699", - itemTaxes: [ - { - taxCode: "002", - taxTypeCode: "Tasa", - taxRate: "0.160000", - taxFlagCode: "T" - }, - { - taxCode: "002", - taxTypeCode: "Tasa", - taxRate: "0.106666", - taxFlagCode: "R" - } - ] - } - ], - complement: { - localTaxes: { - taxes: [ - { - taxName: "CEDULAR", - taxRate: "3.00", - taxAmount: "6.00", - taxFlagCode: "R" - }, - { - taxName: "ISH", - taxRate: "8.00", - taxAmount: "16.00", - taxFlagCode: "R" - } - ] + taxCode: "001", // ISR + taxTypeCode: "Tasa", + taxRate: "0.100000", + taxFlagCode: "R" // Retenido } + ] } - }; - - const apiResponse = await this.fiscalApi.invoices.create(localTaxesInvoice); - - if (apiResponse.succeeded) { - return apiResponse; - } else { - throw new BadRequestException(apiResponse); + ] } - } catch (error) { - throw new BadRequestException(error.message); } + }; + + const apiResponse = await this.fiscalApi.invoices.create(invoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); + } + } catch (error) { + throw new BadRequestException(error.message); + } } - @Post('complemento-nomina-por-referencias') - @ApiOperation({ summary: 'Crear factura con complemento de nómina por referencias' }) - @ApiResponse({ status: 200, description: 'Factura con complemento de nómina creada correctamente' }) - @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de nómina' }) - async crearComplementoNominaPorReferencias() { - try { - const payrollInvoice: Invoice = { - versionCode: "4.0", - series: "F", + @Post('complemento-pago-eur-usd') + @ApiOperation({ summary: 'Crear complemento de pago en EUR para facturas en USD' }) + @ApiResponse({ status: 200, description: 'Complemento de pago creado correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear el complemento de pago' }) + async crearComplementoPagoEurUsd() { + try { + // Complemento de pago en EUR para facturas en USD + const invoice: Invoice = { + versionCode: "4.0", + series: "EUR-USD", // Serie descriptiva para pagos en EUR de facturas USD + date: this.currentDate, + currencyCode: "XXX", // Para complementos de pago siempre es XXX + typeCode: "P", // Tipo P para complementos de pago + expeditionZipCode: "01160", + exchangeRate: 1, // Para complementos de pago siempre es 1 + exportCode: "01", + issuer: { + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + taxRegimeCode: "621", + taxCredentials: [ + { + base64File: this.base64Cert, + fileType: 0, + password: this.password + }, + { + base64File: this.base64Key, + fileType: 1, + password: this.password + } + ] + }, + recipient: { + tin: "EKU9003173C9", + legalName: "ESCUELA KEMPER URGATE", + zipCode: "42501", + taxRegimeCode: "601", + cfdiUseCode: "CP01", // Uso específico para complementos de pago + email: "someone@somewhere.com" + }, + // El concepto es fijo para complementos de pago + items: [ + { + itemCode: "84111506", // Código específico para pagos + quantity: 1, + unitOfMeasurementCode: "ACT", + description: "Pago", + unitPrice: 0, + taxObjectCode: "01" + } + ], + // Sección de pagos - específica para complementos de pago + complement: { + payment: { + paymentDate: "2024-06-03T14:44:56", // Fecha del pago + paymentFormCode: "28", // 28 - Tarjeta de débito + currencyCode: "EUR", // El pago se realizó en euros + exchangeRate: 25.00, // Tipo de cambio EUR a MXN + amount: 100.00, // Monto del pago en EUR + sourceBankTin: "BSM970519DU8", + sourceBankAccount: "1234567891012131", + targetBankTin: "BBA830831LJ2", + targetBankAccount: "1234567890", + paidInvoices: [ + { + uuid: "4a5d025b-813a-4acf-9f32-8fb61f4918ac", // UUID de la factura que se está pagando + series: "F", + number: "2", + currencyCode: "USD", // La factura original está en dólares + equivalence: 1.160, // Tipo de cambio EUR/USD + partialityNumber: 1, // Número de parcialidad (1 si es pago único) + subTotal: 100.00, // Subtotal original de la factura en USD + previousBalance: 116.00, // Saldo anterior en USD + paymentAmount: 116.00, // Cantidad pagada en USD (100 EUR × 1.16 = 116 USD) + remainingBalance: 0, // Saldo restante después del pago + taxObjectCode: "02", + paidInvoiceTaxes: [ + { + taxCode: "002", // IVA + taxTypeCode: "Tasa", + taxRate: "0.160000", // Tasa de IVA trasladado + taxFlagCode: "T" // Trasladado + }, + { + taxCode: "002", // IVA + taxTypeCode: "Tasa", + taxRate: "0.106667", // Tasa de IVA retenido + taxFlagCode: "R" // Retenido + }, + { + taxCode: "001", // ISR + taxTypeCode: "Tasa", + taxRate: "0.100000", // Tasa de ISR retenido + taxFlagCode: "R" // Retenido + } + ] + } + ] + } + } + }; + + const apiResponse = await this.fiscalApi.invoices.create(invoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); + } + } catch (error) { + throw new BadRequestException(error.message); + } + } + + @Post('complemento-nomina-por-valores') + @ApiOperation({ summary: 'Crear factura con complemento de nómina por valores' }) + @ApiResponse({ status: 200, description: 'Factura con complemento de nómina creada correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de nómina' }) + async crearComplementoNominaPorValores() { + try { + const payrollInvoice: Invoice = { + versionCode: "4.0", + series: "F", date: this.currentDate, paymentMethodCode: "PUE", currencyCode: "MXN", @@ -1147,10 +1181,49 @@ export class InvoicesController { expeditionZipCode: "20000", exportCode: "01", issuer: { - id: "0e82a655-5f0c-4e07-abab-8f322e4123ef" + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + taxRegimeCode: "621", + employerData: { + employerRegistration: "B5510768108", + curp: "XEXX010101MNEXXXA8" + }, + taxCredentials: [ + { + base64File: this.base64Cert, + fileType: 0, + password: this.password + }, + { + base64File: this.base64Key, + fileType: 1, + password: this.password + } + ] }, recipient: { - id: "da71df0c-f328-45ee-9bd9-3096ed02c164" + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + zipCode: "01160", + taxRegimeCode: "605", + cfdiUseCode: "CN01", + employeeData: { + curp: "XEXX010101MNEXXXA8", + socialSecurityNumber: "04078873454", + laborRelationStartDate: "2024-08-18", + seniority: "P54W", + satContractTypeId: "01", + satTaxRegimeTypeId: "02", + employeeNumber: "123456789", + department: "GenAI", + position: "Sr Software Engineer", + satJobRiskId: "1", + satPaymentPeriodicityId: "05", + satBankId: "012", + baseSalaryForContributions: 2828.50, + integratedDailySalary: 0.00, + satPayrollStateId: "JAL" + } }, complement: { payroll: { @@ -1268,11 +1341,11 @@ export class InvoicesController { } } - @Post('complemento-impuestos-locales-por-referencias') - @ApiOperation({ summary: 'Crear factura con complemento de impuestos locales por referencias' }) + @Post('complemento-impuestos-locales-por-valores') + @ApiOperation({ summary: 'Crear factura con complemento de impuestos locales por valores' }) @ApiResponse({ status: 200, description: 'Factura con complemento de impuestos locales creada correctamente' }) @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de impuestos locales' }) - async crearComplementoImpuestosLocalesPorReferencias() { + async crearComplementoImpuestosLocalesPorValores() { try { const localTaxesInvoice: Invoice = { versionCode: "4.0", @@ -1286,15 +1359,89 @@ export class InvoicesController { exchangeRate: 1, exportCode: "01", issuer: { - id: "0e82a655-5f0c-4e07-abab-8f322e4123ef" + tin: "FUNK671228PH6", + legalName: "KARLA FUENTE NOLASCO", + taxRegimeCode: "621", + taxCredentials: [ + { + base64File: this.base64Cert, + fileType: 0, + password: this.password + }, + { + base64File: this.base64Key, + fileType: 1, + password: this.password + } + ] }, recipient: { - id: "bd199ed8-02ef-47c0-919c-9479dd8ecae7" + tin: "EKU9003173C9", + legalName: "ESCUELA KEMPER URGATE", + zipCode: "42501", + taxRegimeCode: "601", + cfdiUseCode: "G01", + email: "someone@somewhere.com" }, items: [ { - id: "7f1c66f0-5d9b-4adc-821d-649d79abcbb5", - quantity: 1 + itemCode: "01010101", + quantity: 9.5, + unitOfMeasurementCode: "E48", + description: "Invoicing software as a service", + unitPrice: 3587.75, + taxObjectCode: "02", + itemSku: "7506022301697", + discount: 255.85, + itemTaxes: [ + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.160000", + taxFlagCode: "T" + } + ] + }, + { + itemCode: "01010101", + quantity: 8, + unitOfMeasurementCode: "E48", + description: "Software Consultant", + unitPrice: 250.85, + taxObjectCode: "02", + itemSku: "7506022301698", + discount: 255.85, + itemTaxes: [ + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.160000", + taxFlagCode: "T" + } + ] + }, + { + itemCode: "01010101", + quantity: 6, + unitOfMeasurementCode: "E48", + description: "Computer software", + unitPrice: 1250.75, + taxObjectCode: "02", + itemSku: "7506022301699", + itemTaxes: [ + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.160000", + taxFlagCode: "T" + }, + { + taxCode: "002", + taxTypeCode: "Tasa", + taxRate: "0.106666", + taxFlagCode: "R" + } + ] } ], complement: { @@ -1329,349 +1476,202 @@ export class InvoicesController { } } - @Post('complemento-pago-usd-mxn') - @ApiOperation({ summary: 'Crear complemento de pago en USD para facturas en MXN' }) - @ApiResponse({ status: 200, description: 'Complemento de pago creado correctamente' }) - @ApiResponse({ status: 400, description: 'Error al crear el complemento de pago' }) - async crearComplementoPagoUsdMxn() { - try { - // Complemento de pago en USD para facturas en MXN - const invoice: Invoice = { - versionCode: "4.0", - series: "usd-mxn", // Serie descriptiva para pagos en USD de facturas MXN - date: this.currentDate, - currencyCode: "XXX", // Para complementos de pago siempre es XXX - typeCode: "P", // Tipo P para complementos de pago - expeditionZipCode: "01160", - exchangeRate: 1, // Para complementos de pago siempre es 1 - exportCode: "01", - issuer: { - tin: "FUNK671228PH6", - legalName: "KARLA FUENTE NOLASCO", - taxRegimeCode: "621", - taxCredentials: [ - { - base64File: this.base64Cert, - fileType: 0, - password: this.password - }, - { - base64File: this.base64Key, - fileType: 1, - password: this.password - } - ] - }, - recipient: { - tin: "EKU9003173C9", - legalName: "ESCUELA KEMPER URGATE", - zipCode: "42501", - taxRegimeCode: "601", - cfdiUseCode: "CP01", // Uso específico para complementos de pago - email: "someone@somewhere.com" - }, - // El concepto es fijo para complementos de pago - items: [ - { - itemCode: "84111506", // Código específico para pagos - quantity: 1, - unitOfMeasurementCode: "ACT", - description: "Pago", - unitPrice: 0, - taxObjectCode: "01" - } - ], - // Sección de pagos - específica para complementos de pago - payments: [ - { - paymentDate: "2025-03-31T14:44:56", // Actualizado a una fecha más reciente - paymentFormCode: "28", // 28 - Tarjeta de débito - currencyCode: "USD", // El pago se realizó en dólares - exchangeRate: 20.64, // Tipo de cambio USD/MXN - amount: 5.62, // Monto del pago en USD - sourceBankTin: "BSM970519DU8", - sourceBankAccount: "1234567891012131", - targetBankTin: "BBA830831LJ2", - targetBankAccount: "1234567890", - paidInvoices: [ - { - uuid: "4a5d025b-813a-4acf-9f32-8fb61f4918ac", // UUID de la factura que se está pagando + @Post('complemento-nomina-por-referencias') + @ApiOperation({ summary: 'Crear factura con complemento de nómina por referencias' }) + @ApiResponse({ status: 200, description: 'Factura con complemento de nómina creada correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de nómina' }) + async crearComplementoNominaPorReferencias() { + try { + const payrollInvoice: Invoice = { + versionCode: "4.0", series: "F", - number: "2", - currencyCode: "MXN", // La factura original está en pesos - equivalence: 20.64, // El mismo tipo de cambio para conversión - partialityNumber: 1, // Número de parcialidad (1 si es pago único) - subTotal: 100.00, // Subtotal original de la factura - previousBalance: 116.00, // Saldo anterior en MXN - paymentAmount: 116.00, // Cantidad pagada (5.62 USD x 20.64 = 116.00 MXN) - remainingBalance: 0, // Saldo restante después del pago - taxObjectCode: "02", - paidInvoiceTaxes: [ - { - taxCode: "002", // IVA - taxTypeCode: "Tasa", - taxRate: "0.160000", // Como string para mantener precisión - taxFlagCode: "T" // Trasladado - }, - { - taxCode: "002", // IVA - taxTypeCode: "Tasa", - taxRate: "0.106667", - taxFlagCode: "R" // Retenido - }, - { - taxCode: "001", // ISR - taxTypeCode: "Tasa", - taxRate: "0.100000", - taxFlagCode: "R" // Retenido + date: this.currentDate, + paymentMethodCode: "PUE", + currencyCode: "MXN", + typeCode: "N", + expeditionZipCode: "20000", + exportCode: "01", + issuer: { + id: "0e82a655-5f0c-4e07-abab-8f322e4123ef" + }, + recipient: { + id: "da71df0c-f328-45ee-9bd9-3096ed02c164" + }, + complement: { + payroll: { + version: "1.2", + payrollTypeCode: "O", + paymentDate: "2025-08-30", + initialPaymentDate: "2025-07-31", + finalPaymentDate: "2025-08-30", + daysPaid: 30, + earnings: { + earnings: [ + { + earningTypeCode: "001", + code: "1003", + concept: "Sueldo Nominal", + taxedAmount: 95030.00, + exemptAmount: 0.00 + }, + { + earningTypeCode: "005", + code: "5913", + concept: "Fondo de Ahorro Aportación Patrón", + taxedAmount: 0.00, + exemptAmount: 4412.46 + }, + { + earningTypeCode: "038", + code: "1885", + concept: "Bono Ingles", + taxedAmount: 14254.50, + exemptAmount: 0.00 + }, + { + earningTypeCode: "029", + code: "1941", + concept: "Vales Despensa", + taxedAmount: 0.00, + exemptAmount: 3439.00 + }, + { + earningTypeCode: "038", + code: "1824", + concept: "Herramientas Teletrabajo (telecom y prop. electri)", + taxedAmount: 273.00, + exemptAmount: 0.00 + } + ], + otherPayments: [ + { + otherPaymentTypeCode: "002", + code: "5050", + concept: "Exceso de subsidio al empleo", + amount: 0.00, + subsidyCaused: 0.00 + } + ] + }, + deductions: [ + { + deductionTypeCode: "002", + code: "5003", + concept: "ISR Causado", + amount: 27645.52 + }, + { + deductionTypeCode: "004", + code: "5910", + concept: "Fondo de ahorro Empleado Inversión", + amount: 4412.46 + }, + { + deductionTypeCode: "004", + code: "5914", + concept: "Fondo de Ahorro Patrón Inversión", + amount: 4412.46 + }, + { + deductionTypeCode: "004", + code: "1966", + concept: "Contribución póliza exceso GMM", + amount: 519.91 + }, + { + deductionTypeCode: "004", + code: "1934", + concept: "Descuento Vales Despensa", + amount: 1.00 + }, + { + deductionTypeCode: "004", + code: "1942", + concept: "Vales Despensa Electrónico", + amount: 3439.00 + }, + { + deductionTypeCode: "001", + code: "1895", + concept: "IMSS", + amount: 2391.13 + } + ] } - ] } - ] - } - ] - }; - - const apiResponse = await this.fiscalApi.invoices.create(invoice); - - if (apiResponse.succeeded) { - return apiResponse; - } else { - throw new BadRequestException(apiResponse); - } - } catch (error) { - throw new BadRequestException(error.message); - } - } + }; - @Post('complemento-pago-mxn-usd') - @ApiOperation({ summary: 'Crear complemento de pago en MXN para facturas en USD' }) - @ApiResponse({ status: 200, description: 'Complemento de pago creado correctamente' }) - @ApiResponse({ status: 400, description: 'Error al crear el complemento de pago' }) - async crearComplementoPagoMxnUsd() { - try { - // Complemento de pago en MXN para facturas en USD - const invoice: Invoice = { - versionCode: "4.0", - series: "MXN-USD", // Serie descriptiva para pagos en MXN de facturas USD - date: this.currentDate, - currencyCode: "XXX", // Para complementos de pago siempre es XXX - typeCode: "P", // Tipo P para complementos de pago - expeditionZipCode: "01160", - exchangeRate: 1, // Para complementos de pago siempre es 1 - exportCode: "01", - issuer: { - tin: "FUNK671228PH6", - legalName: "KARLA FUENTE NOLASCO", - taxRegimeCode: "621", - taxCredentials: [ - { - base64File: this.base64Cert, - fileType: 0, - password: this.password - }, - { - base64File: this.base64Key, - fileType: 1, - password: this.password - } - ] - }, - recipient: { - tin: "EKU9003173C9", - legalName: "ESCUELA KEMPER URGATE", - zipCode: "42501", - taxRegimeCode: "601", - cfdiUseCode: "CP01", // Uso específico para complementos de pago - email: "someone@somewhere.com" - }, - // El concepto es fijo para complementos de pago - items: [ - { - itemCode: "84111506", // Código específico para pagos - quantity: 1, - unitOfMeasurementCode: "ACT", - description: "Pago", - unitPrice: 0, - taxObjectCode: "01" - } - ], - // Sección de pagos - específica para complementos de pago - payments: [ - { - paymentDate: "2025-03-31T14:44:56", // Actualizado a una fecha más reciente - paymentFormCode: "28", // 28 - Tarjeta de débito - currencyCode: "MXN", // El pago se realizó en pesos mexicanos - exchangeRate: 1, // Tipo de cambio para MXN es 1 - amount: 921.23, // Monto del pago en MXN - sourceBankTin: "BSM970519DU8", - sourceBankAccount: "1234567891012131", - targetBankTin: "BBA830831LJ2", - targetBankAccount: "1234567890", - paidInvoices: [ - { - uuid: "4a5d025b-813a-4acf-9f32-8fb61f4918ac", // UUID de la factura que se está pagando - series: "F", - number: "2", - currencyCode: "USD", // La factura original está en dólares - equivalence: 0.045331, // Tipo de cambio inverso (MXN/USD) aprox. 1/22.06 - partialityNumber: 1, // Número de parcialidad (1 si es pago único) - subTotal: 36.00, // Subtotal original de la factura en USD - previousBalance: 41.76, // Saldo anterior en USD - paymentAmount: 41.76, // Cantidad pagada en USD (921.23 MXN ÷ 22.06 = 41.76 USD) - remainingBalance: 0, // Saldo restante después del pago - taxObjectCode: "02", - paidInvoiceTaxes: [ - { - taxCode: "002", // IVA - taxTypeCode: "Tasa", - taxRate: "0.160000", // Como string para mantener precisión - taxFlagCode: "T" // Trasladado - }, - { - taxCode: "002", // IVA - taxTypeCode: "Tasa", - taxRate: "0.106667", - taxFlagCode: "R" // Retenido - }, - { - taxCode: "001", // ISR - taxTypeCode: "Tasa", - taxRate: "0.100000", - taxFlagCode: "R" // Retenido - } - ] - } - ] + const apiResponse = await this.fiscalApi.invoices.create(payrollInvoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); } - ] - }; - - const apiResponse = await this.fiscalApi.invoices.create(invoice); - - if (apiResponse.succeeded) { - return apiResponse; - } else { - throw new BadRequestException(apiResponse); + } catch (error) { + throw new BadRequestException(error.message); } - } catch (error) { - throw new BadRequestException(error.message); - } } - @Post('complemento-pago-eur-usd') - @ApiOperation({ summary: 'Crear complemento de pago en EUR para facturas en USD' }) - @ApiResponse({ status: 200, description: 'Complemento de pago creado correctamente' }) - @ApiResponse({ status: 400, description: 'Error al crear el complemento de pago' }) - async crearComplementoPagoEurUsd() { - try { - // Complemento de pago en EUR para facturas en USD - const invoice: Invoice = { - versionCode: "4.0", - series: "EUR-USD", // Serie descriptiva para pagos en EUR de facturas USD - date: this.currentDate, - currencyCode: "XXX", // Para complementos de pago siempre es XXX - typeCode: "P", // Tipo P para complementos de pago - expeditionZipCode: "01160", - exchangeRate: 1, // Para complementos de pago siempre es 1 - exportCode: "01", - issuer: { - tin: "FUNK671228PH6", - legalName: "KARLA FUENTE NOLASCO", - taxRegimeCode: "621", - taxCredentials: [ - { - base64File: this.base64Cert, - fileType: 0, - password: this.password - }, - { - base64File: this.base64Key, - fileType: 1, - password: this.password - } - ] - }, - recipient: { - tin: "EKU9003173C9", - legalName: "ESCUELA KEMPER URGATE", - zipCode: "42501", - taxRegimeCode: "601", - cfdiUseCode: "CP01", // Uso específico para complementos de pago - email: "someone@somewhere.com" - }, - // El concepto es fijo para complementos de pago - items: [ - { - itemCode: "84111506", // Código específico para pagos - quantity: 1, - unitOfMeasurementCode: "ACT", - description: "Pago", - unitPrice: 0, - taxObjectCode: "01" - } - ], - // Sección de pagos - específica para complementos de pago - payments: [ - { - paymentDate: "2024-06-03T14:44:56", // Fecha del pago - paymentFormCode: "28", // 28 - Tarjeta de débito - currencyCode: "EUR", // El pago se realizó en euros - exchangeRate: 25.00, // Tipo de cambio EUR a MXN - amount: 100.00, // Monto del pago en EUR - sourceBankTin: "BSM970519DU8", - sourceBankAccount: "1234567891012131", - targetBankTin: "BBA830831LJ2", - targetBankAccount: "1234567890", - paidInvoices: [ - { - uuid: "4a5d025b-813a-4acf-9f32-8fb61f4918ac", // UUID de la factura que se está pagando + @Post('complemento-impuestos-locales-por-referencias') + @ApiOperation({ summary: 'Crear factura con complemento de impuestos locales por referencias' }) + @ApiResponse({ status: 200, description: 'Factura con complemento de impuestos locales creada correctamente' }) + @ApiResponse({ status: 400, description: 'Error al crear la factura con complemento de impuestos locales' }) + async crearComplementoImpuestosLocalesPorReferencias() { + try { + const localTaxesInvoice: Invoice = { + versionCode: "4.0", series: "F", - number: "2", - currencyCode: "USD", // La factura original está en dólares - equivalence: 1.160, // Tipo de cambio EUR/USD - partialityNumber: 1, // Número de parcialidad (1 si es pago único) - subTotal: 100.00, // Subtotal original de la factura en USD - previousBalance: 116.00, // Saldo anterior en USD - paymentAmount: 116.00, // Cantidad pagada en USD (100 EUR × 1.16 = 116 USD) - remainingBalance: 0, // Saldo restante después del pago - taxObjectCode: "02", - paidInvoiceTaxes: [ - { - taxCode: "002", // IVA - taxTypeCode: "Tasa", - taxRate: "0.160000", // Tasa de IVA trasladado - taxFlagCode: "T" // Trasladado - }, - { - taxCode: "002", // IVA - taxTypeCode: "Tasa", - taxRate: "0.106667", // Tasa de IVA retenido - taxFlagCode: "R" // Retenido - }, + date: this.currentDate, + paymentFormCode: "01", + currencyCode: "MXN", + typeCode: "I", + expeditionZipCode: "42501", + paymentMethodCode: "PUE", + exchangeRate: 1, + exportCode: "01", + issuer: { + id: "0e82a655-5f0c-4e07-abab-8f322e4123ef" + }, + recipient: { + id: "bd199ed8-02ef-47c0-919c-9479dd8ecae7" + }, + items: [ { - taxCode: "001", // ISR - taxTypeCode: "Tasa", - taxRate: "0.100000", // Tasa de ISR retenido - taxFlagCode: "R" // Retenido + id: "7f1c66f0-5d9b-4adc-821d-649d79abcbb5", + quantity: 1 + } + ], + complement: { + localTaxes: { + taxes: [ + { + taxName: "CEDULAR", + taxRate: "3.00", + taxAmount: "6.00", + taxFlagCode: "R" + }, + { + taxName: "ISH", + taxRate: "8.00", + taxAmount: "16.00", + taxFlagCode: "R" + } + ] } - ] } - ] + }; + + const apiResponse = await this.fiscalApi.invoices.create(localTaxesInvoice); + + if (apiResponse.succeeded) { + return apiResponse; + } else { + throw new BadRequestException(apiResponse); } - ] - }; - - const apiResponse = await this.fiscalApi.invoices.create(invoice); - - if (apiResponse.succeeded) { - return apiResponse; - } else { - throw new BadRequestException(apiResponse); + } catch (error) { + throw new BadRequestException(error.message); } - } catch (error) { - throw new BadRequestException(error.message); - } } @Post('cancelar')