consultame-sdk 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -4
- package/dist/index.js +163 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +163 -2
- package/dist/index.mjs.map +1 -1
- package/dist/shared/functions/functions.utils.d.ts +2 -1
- package/dist/shared/functions/functions.utils.d.ts.map +1 -1
- package/dist/sifen/applications/dtos/index.d.ts +1 -0
- package/dist/sifen/applications/dtos/index.d.ts.map +1 -1
- package/dist/sifen/applications/dtos/nominationInvoice.dto.d.ts +31 -0
- package/dist/sifen/applications/dtos/nominationInvoice.dto.d.ts.map +1 -0
- package/dist/sifen/applications/services/sifen.service.d.ts +3 -1
- package/dist/sifen/applications/services/sifen.service.d.ts.map +1 -1
- package/dist/sifen/domain/repository/sifen.repository.d.ts +2 -1
- package/dist/sifen/domain/repository/sifen.repository.d.ts.map +1 -1
- package/dist/sifen/domain/useCases/index.d.ts +1 -0
- package/dist/sifen/domain/useCases/index.d.ts.map +1 -1
- package/dist/sifen/domain/useCases/nominationInvoice.useCase.d.ts +8 -0
- package/dist/sifen/domain/useCases/nominationInvoice.useCase.d.ts.map +1 -0
- package/dist/sifen/infrastructure/persistence/sifen.persistence.d.ts +2 -1
- package/dist/sifen/infrastructure/persistence/sifen.persistence.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ que se necesitan para interactuar con **SIFEN** (Sistema Integrado de Facturaci
|
|
|
5
5
|
Nacional de Paraguay – SET).
|
|
6
6
|
|
|
7
7
|
La librería **no** hace las peticiones HTTP al web service de SIFEN: su responsabilidad es
|
|
8
|
-
**construir los sobres XML** (consulta de RUC, consulta de lote, consulta de documento
|
|
8
|
+
**construir los sobres XML** (consulta de RUC, consulta de lote, consulta de documento y
|
|
9
|
+
evento de nominación de un documento ya emitido),
|
|
9
10
|
**extraer el certificado y la llave privada** desde un archivo de firma digital `.p12`/`.pfx`,
|
|
10
11
|
**firmar digitalmente (XMLDSig)** el Documento Electrónico generado y **generar el código QR**
|
|
11
12
|
que se incrusta en el documento electrónico ya firmado.
|
|
@@ -25,6 +26,7 @@ Con esa salida, la aplicación consumidora envía los mensajes por su cuenta.
|
|
|
25
26
|
- [`generateQr`](#generateqrgenerationqrdto)
|
|
26
27
|
- [`generateDocument`](#generatedocumentgeneratedocumentoelectronicodto)
|
|
27
28
|
- [`signedXml`](#signedxmlxml-tag-responsedigitalsign)
|
|
29
|
+
- [`nominationInvoice`](#nominationinvoicenominationinvoicedto)
|
|
28
30
|
- [DTOs (contratos de entrada)](#dtos-contratos-de-entrada)
|
|
29
31
|
- [Funciones utilitarias internas](#funciones-utilitarias-internas)
|
|
30
32
|
- [Arquitectura del proyecto](#arquitectura-del-proyecto)
|
|
@@ -69,7 +71,7 @@ Todo el punto de entrada público es la clase **`SifenService`**. Se instancia s
|
|
|
69
71
|
argumentos y ya arma internamente sus casos de uso y dependencias.
|
|
70
72
|
|
|
71
73
|
```ts
|
|
72
|
-
import { SifenService } from "consultame-
|
|
74
|
+
import { SifenService } from "consultame-sdk";
|
|
73
75
|
|
|
74
76
|
const sifen = new SifenService();
|
|
75
77
|
|
|
@@ -170,6 +172,21 @@ const xmlConQr = await sifen.generateQr({
|
|
|
170
172
|
idCsc: "0001",
|
|
171
173
|
ambiente: "test", // "test" | "produccion"
|
|
172
174
|
});
|
|
175
|
+
|
|
176
|
+
// 8) Nominar un documento ya emitido a un receptor (evento de nominación, sin firmar)
|
|
177
|
+
const xmlNominacion = sifen.nominationInvoice({
|
|
178
|
+
id: 4,
|
|
179
|
+
cdc: "01800123456001001000000012023052212345678901",
|
|
180
|
+
motivo: "Nominación solicitada por el cliente",
|
|
181
|
+
idTipoReceptor: 1, // 1 = contribuyente
|
|
182
|
+
idTipoOperacion: 1, // 1 = B2B
|
|
183
|
+
idPais: "PRY",
|
|
184
|
+
esContribuyente: true,
|
|
185
|
+
idTipoContribuyente: 2,
|
|
186
|
+
ruc: "80099999",
|
|
187
|
+
digitoVerificado: "1",
|
|
188
|
+
razonSocial: "Cliente Ejemplo S.R.L.",
|
|
189
|
+
});
|
|
173
190
|
```
|
|
174
191
|
|
|
175
192
|
---
|
|
@@ -342,7 +359,7 @@ Toma un documento electrónico (`rDE`) **ya firmado digitalmente**, calcula el e
|
|
|
342
359
|
código QR exigido por SIFEN y devuelve el **mismo XML con el nodo `<gCamFuFD><dCarQR>`
|
|
343
360
|
incrustado**.
|
|
344
361
|
|
|
345
|
-
> ⚠️
|
|
362
|
+
> ⚠️ Método **asíncrono**: devuelve `Promise<string>`.
|
|
346
363
|
|
|
347
364
|
| Parámetro | Tipo | Descripción |
|
|
348
365
|
| ---------- | -------- | ---------------------------------------------------------------------- |
|
|
@@ -634,6 +651,131 @@ try {
|
|
|
634
651
|
|
|
635
652
|
---
|
|
636
653
|
|
|
654
|
+
### `nominationInvoice(nominationInvoiceDto)`
|
|
655
|
+
|
|
656
|
+
Genera el sobre SOAP `rEnviEventoDe` con el **evento de nominación** (`rGEveNom`): asocia los
|
|
657
|
+
datos de un receptor a un documento electrónico ya emitido, identificado por su **CDC**.
|
|
658
|
+
|
|
659
|
+
> ⚠️ El XML devuelto **no está firmado**: la aplicación consumidora debe firmar el evento y
|
|
660
|
+
> enviarlo a SIFEN por su cuenta.
|
|
661
|
+
|
|
662
|
+
Método **síncrono** que valida el DTO antes de armar el XML.
|
|
663
|
+
|
|
664
|
+
| Parámetro | Tipo | Descripción |
|
|
665
|
+
| --------------------- | ------------------- | --------------------------------------------------------------------------------------------- |
|
|
666
|
+
| `id` | `number` | Identificador de la petición (`dId`); también se usa como `Id` del evento (`rEve`). |
|
|
667
|
+
| `cdc` | `string` | CDC de 44 dígitos del documento a nominar (`Id` de `rGEveNom`). |
|
|
668
|
+
| `motivo` | `string` | Motivo del evento (`mOtEve`), de 5 a 500 caracteres. |
|
|
669
|
+
| `idTipoReceptor` | `number` | `1` = contribuyente, `2` = no contribuyente (`iNatRec`). |
|
|
670
|
+
| `idTipoOperacion` | `number` | `1` = B2B, `2` = B2C, `4` = B2F (`iTiOpe`). |
|
|
671
|
+
| `idPais` | `string` | Código de país del receptor (ej. `"PRY"`); debe existir en `PAISES`. |
|
|
672
|
+
| `esContribuyente` | `boolean` | Si el receptor es contribuyente. |
|
|
673
|
+
| `razonSocial` | `string` | Nombre o razón social del receptor (`dNomRec`), de 4 a 255 caracteres. |
|
|
674
|
+
| `idTipoContribuyente` | `number?` | `1` = persona física, `2` = persona jurídica. Obligatorio si `esContribuyente`. |
|
|
675
|
+
| `ruc` | `string?` | RUC del receptor. Obligatorio si `esContribuyente`. |
|
|
676
|
+
| `digitoVerificado` | `string \| number?` | Dígito verificador del RUC. Obligatorio si `esContribuyente`. |
|
|
677
|
+
| `idTipoDocumento` | `number?` | Tipo de documento de identidad. Obligatorio si **no** es contribuyente. |
|
|
678
|
+
| `numeroDocumento` | `string?` | Número de documento. Obligatorio si **no** es contribuyente. |
|
|
679
|
+
| `otroTipoDocumento` | `string?` | Descripción del tipo de documento cuando `idTipoDocumento = 9` (Otro). |
|
|
680
|
+
| `nombreFantasia` | `string?` | Nombre de fantasía del receptor. |
|
|
681
|
+
| `direccion` | `string?` | Dirección del receptor. Obligatoria si `idTipoOperacion = 4` (B2F). |
|
|
682
|
+
| `numeroCasa` | `string?` | Obligatorio si se informa `direccion`. |
|
|
683
|
+
| `idDepartamento`, `idDistricto`, `idCiudad` | `number?` | Ubicación del receptor. **Se ignoran en B2F.** |
|
|
684
|
+
| `telefono`, `celular`, `email`, `codigoCliente` | `string?` | Datos de contacto opcionales. |
|
|
685
|
+
|
|
686
|
+
> El campo se llama `idDistricto` (con esa grafía) en el DTO.
|
|
687
|
+
|
|
688
|
+
**Retorna:** `string` — XML SOAP normalizado (una sola línea), con `dFecFirma` tomado de la
|
|
689
|
+
fecha/hora actual y `dVerFor` = `150`.
|
|
690
|
+
|
|
691
|
+
```ts
|
|
692
|
+
const xml = sifen.nominationInvoice({
|
|
693
|
+
id: 4,
|
|
694
|
+
cdc: "01800123456001001000000012023052212345678901",
|
|
695
|
+
motivo: "Nominación solicitada por el cliente",
|
|
696
|
+
idTipoReceptor: 1,
|
|
697
|
+
idTipoOperacion: 1,
|
|
698
|
+
idPais: "PRY",
|
|
699
|
+
esContribuyente: true,
|
|
700
|
+
idTipoContribuyente: 2,
|
|
701
|
+
ruc: "80099999",
|
|
702
|
+
digitoVerificado: "1",
|
|
703
|
+
razonSocial: "Cliente Ejemplo S.R.L.",
|
|
704
|
+
});
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
<details>
|
|
708
|
+
<summary>Ejemplo de salida (formateada para lectura)</summary>
|
|
709
|
+
|
|
710
|
+
```xml
|
|
711
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
712
|
+
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
|
|
713
|
+
<env:Header/>
|
|
714
|
+
<env:Body>
|
|
715
|
+
<rEnviEventoDe xmlns="http://ekuatia.set.gov.py/sifen/xsd">
|
|
716
|
+
<dId>4</dId>
|
|
717
|
+
<dEvReg>
|
|
718
|
+
<gGroupGesEve xmlns="http://ekuatia.set.gov.py/sifen/xsd"
|
|
719
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
720
|
+
xsi:schemaLocation="http://ekuatia.set.gov.py/sifen/xsd siRecepEvento_v150.xsd">
|
|
721
|
+
<rGesEve xsi:schemaLocation="http://ekuatia.set.gov.py/sifen/xsd siRecepEvento_v150.xsd">
|
|
722
|
+
<rEve Id="4">
|
|
723
|
+
<dFecFirma>2026-10-14T16:43:03</dFecFirma>
|
|
724
|
+
<dVerFor>150</dVerFor>
|
|
725
|
+
<gGroupTiEvt>
|
|
726
|
+
<rGEveNom>
|
|
727
|
+
<Id>01800123456001001000000012023052212345678901</Id>
|
|
728
|
+
<mOtEve>Nominación solicitada por el cliente</mOtEve>
|
|
729
|
+
<iNatRec>1</iNatRec>
|
|
730
|
+
<iTiOpe>1</iTiOpe>
|
|
731
|
+
<cPaisRec>PRY</cPaisRec>
|
|
732
|
+
<dDesPaisRe>Paraguay</dDesPaisRe>
|
|
733
|
+
<iTiContRec>2</iTiContRec>
|
|
734
|
+
<dRucRec>80099999</dRucRec>
|
|
735
|
+
<dDVRec>1</dDVRec>
|
|
736
|
+
<dNomRec>Cliente Ejemplo S.R.L.</dNomRec>
|
|
737
|
+
</rGEveNom>
|
|
738
|
+
</gGroupTiEvt>
|
|
739
|
+
</rEve>
|
|
740
|
+
</rGesEve>
|
|
741
|
+
</gGroupGesEve>
|
|
742
|
+
</dEvReg>
|
|
743
|
+
</rEnviEventoDe>
|
|
744
|
+
</env:Body>
|
|
745
|
+
</env:Envelope>
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
</details>
|
|
749
|
+
|
|
750
|
+
#### Reglas de validación
|
|
751
|
+
|
|
752
|
+
Antes de armar el XML se valida el DTO y se lanza un `Error` con un mensaje descriptivo si
|
|
753
|
+
algo no cumple:
|
|
754
|
+
|
|
755
|
+
- `cdc` debe tener exactamente 44 dígitos.
|
|
756
|
+
- `motivo` de 5 a 500 caracteres y `razonSocial` de 4 a 255 (ambos sin contar espacios en los extremos).
|
|
757
|
+
- `idTipoReceptor` debe ser coherente con `esContribuyente` (`1` ⇔ contribuyente).
|
|
758
|
+
- `idTipoOperacion` debe ser `1`, `2` o `4`; B2B (`1`) exige receptor contribuyente, y B2C (`2`) /
|
|
759
|
+
B2F (`4`) exigen no contribuyente.
|
|
760
|
+
- `idPais` debe ser `"PRY"`, salvo en B2F (`4`), donde debe ser **distinto** de `"PRY"`.
|
|
761
|
+
- Contribuyente: `idTipoContribuyente`, `ruc` y `digitoVerificado` son obligatorios.
|
|
762
|
+
- No contribuyente: `idTipoDocumento` y `numeroDocumento` son obligatorios.
|
|
763
|
+
- B2F: `direccion` es obligatoria; y si se informa `direccion`, también `numeroCasa`.
|
|
764
|
+
|
|
765
|
+
También lanza error si algún código (`idPais`, `idTipoDocumento`, `idDepartamento`, `idDistricto`,
|
|
766
|
+
`idCiudad`) no existe en los catálogos de
|
|
767
|
+
[`src/shared/utils/dictionary.utils.ts`](src/shared/utils/dictionary.utils.ts).
|
|
768
|
+
|
|
769
|
+
```ts
|
|
770
|
+
try {
|
|
771
|
+
const xml = sifen.nominationInvoice({ ... });
|
|
772
|
+
} catch (error) {
|
|
773
|
+
// DTO inválido (ver reglas de validación) o código inexistente en el diccionario
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
---
|
|
778
|
+
|
|
637
779
|
## DTOs (contratos de entrada)
|
|
638
780
|
|
|
639
781
|
Todos los DTOs de consulta extienden `GenerateIdDto`, que aporta el campo `id`.
|
|
@@ -666,6 +808,18 @@ interface GenerationQrDto {
|
|
|
666
808
|
idCsc: string; // Identificador del CSC
|
|
667
809
|
ambiente: string; // "test" | "produccion"
|
|
668
810
|
}
|
|
811
|
+
|
|
812
|
+
// Campos completos y reglas en la sección `nominationInvoice`
|
|
813
|
+
interface NominationInvoiceDto extends GenerateIdDto {
|
|
814
|
+
cdc: string;
|
|
815
|
+
motivo: string;
|
|
816
|
+
idTipoReceptor: number;
|
|
817
|
+
idTipoOperacion: number;
|
|
818
|
+
idPais: string;
|
|
819
|
+
esContribuyente: boolean;
|
|
820
|
+
razonSocial: string;
|
|
821
|
+
// ...y los campos opcionales del receptor (ruc, direccion, idDistricto, email, etc.)
|
|
822
|
+
}
|
|
669
823
|
```
|
|
670
824
|
|
|
671
825
|
Enums disponibles en [`src/shared/utils/dictionary.utils.ts`](src/shared/utils/dictionary.utils.ts):
|
|
@@ -725,6 +879,8 @@ No forman parte de la API pública, pero es útil conocerlas:
|
|
|
725
879
|
| `generateConsultRucXml` | Arma el string XML de consulta de RUC. |
|
|
726
880
|
| `generateConsultDocumentXml` | Arma el string XML de consulta de documento por CDC. |
|
|
727
881
|
| `generateConsultBatchXml` | Arma el string XML de consulta de lote. |
|
|
882
|
+
| `generateNominationInvoiceXml` | Valida el `NominationInvoiceDto` y arma el sobre `rEnviEventoDe` del evento de nominación con `xml2js.Builder`, ya normalizado. |
|
|
883
|
+
| `convertToFormatDateSET` | Formatea una `Date` como fecha/hora SIFEN (usada para `dFecFirma` del evento). |
|
|
728
884
|
| `normalizeXML` | Colapsa el XML a una sola línea: elimina saltos, tabulaciones y espacios entre etiquetas. |
|
|
729
885
|
| `readDigitalSign` | Lee el `.p12` con `node-forge` y extrae certificado + llave privada en PEM, emparejando el certificado correcto por módulo RSA cuando hay varios. |
|
|
730
886
|
| `signXml` | Firma un XML (XMLDSig) con `xml-crypto`: `enveloped-signature` + `exc-c14n`, digest SHA-256, firma RSA-SHA256. _(async)_ |
|
|
@@ -787,6 +943,11 @@ mantener estado intermedio (`jsonFactura`) mientras se arma cada sección del XM
|
|
|
787
943
|
`SifenRepository` → `SifenPersistence.signedXml`), delegando en la función utilitaria `signXml`
|
|
788
944
|
(`src/shared/functions/functions.utils.ts`), que envuelve `xml-crypto`.
|
|
789
945
|
|
|
946
|
+
`nominationInvoice` también sigue el mismo flujo (`SifenService.nominationInvoice` →
|
|
947
|
+
`NominationInvoiceUseCase` → `SifenRepository` → `SifenPersistence.nominationInvoice`),
|
|
948
|
+
delegando en `generateNominationInvoiceXml`, que valida el DTO y arma el evento con
|
|
949
|
+
`xml2js.Builder` (a diferencia de las consultas simples, que son strings de plantilla).
|
|
950
|
+
|
|
790
951
|
**Por qué esta separación:**
|
|
791
952
|
|
|
792
953
|
- **`domain`** no depende de nada externo: define _qué_ se hace (casos de uso) y el
|
|
@@ -830,6 +991,7 @@ consultame-sdk/
|
|
|
830
991
|
│ │ │ ├── consultBatch.dto.ts
|
|
831
992
|
│ │ │ ├── digitalSign.dto.ts
|
|
832
993
|
│ │ │ ├── generationQr.dto.ts
|
|
994
|
+
│ │ │ ├── nominationInvoice.dto.ts
|
|
833
995
|
│ │ │ ├── cancelDocument.dto.ts
|
|
834
996
|
│ │ │ └── invalidationInvoice.dto.ts
|
|
835
997
|
│ │ └── services/
|
|
@@ -846,6 +1008,7 @@ consultame-sdk/
|
|
|
846
1008
|
│ │ ├── obtainDigitalSign.useCase.ts
|
|
847
1009
|
│ │ ├── generateQr.useCase.ts
|
|
848
1010
|
│ │ ├── generateDocument.useCase.ts
|
|
1011
|
+
│ │ ├── nominationInvoice.useCase.ts
|
|
849
1012
|
│ │ └── signedXml.useCase.ts
|
|
850
1013
|
│ │
|
|
851
1014
|
│ └── infrastructure/ # Detalles concretos (ADAPTADORES)
|
|
@@ -886,6 +1049,7 @@ Funcionalidades **implementadas**:
|
|
|
886
1049
|
- ✅ Generación del XML completo del Documento Electrónico — Factura, Autofactura, Nota de
|
|
887
1050
|
Crédito/Débito y Remisión (`generateDocument`)
|
|
888
1051
|
- ✅ Firma digital XMLDSig del Documento Electrónico (`signedXml`)
|
|
1052
|
+
- ✅ Evento de nominación de un documento emitido (`nominationInvoice`)
|
|
889
1053
|
|
|
890
1054
|
Definidas pero **pendientes de implementación** (hoy lanzan `Method not implemented`
|
|
891
1055
|
o aún no están expuestas en `SifenService`):
|
|
@@ -897,5 +1061,5 @@ o aún no están expuestas en `SifenService`):
|
|
|
897
1061
|
|
|
898
1062
|
> **Nota:** esta librería genera insumos (XML, credenciales, firma XMLDSig y el QR) para SIFEN,
|
|
899
1063
|
> pero no realiza el envío HTTP de los documentos — eso queda a cargo de la aplicación
|
|
900
|
-
> consumidora. `generateQr` **requiere** que el XML ya venga firmado (con `signedXml` o por
|
|
1064
|
+
> consumidora. El evento que devuelve `nominationInvoice` tampoco viene firmado. `generateQr` **requiere** que el XML ya venga firmado (con `signedXml` o por
|
|
901
1065
|
> cualquier otro medio), porque toma el `DigestValue` de la firma para calcular el hash del QR.
|
package/dist/index.js
CHANGED
|
@@ -120,6 +120,18 @@ var SignedXmlUseCase = class {
|
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
+
// src/sifen/domain/useCases/nominationInvoice.useCase.ts
|
|
124
|
+
var NominationInvoiceUseCase = class {
|
|
125
|
+
constructor(sifenRepository) {
|
|
126
|
+
this.sifenRepository = sifenRepository;
|
|
127
|
+
}
|
|
128
|
+
sifenRepository;
|
|
129
|
+
execute(nominationInvoiceDto) {
|
|
130
|
+
const xml = this.sifenRepository.nominationInvoice(nominationInvoiceDto);
|
|
131
|
+
return xml;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
123
135
|
// src/shared/utils/dictionary.utils.ts
|
|
124
136
|
var TIPOS_DOCUMENTOS = [
|
|
125
137
|
{
|
|
@@ -8157,6 +8169,139 @@ var generateConsultBatchXml = (consultBatchDto) => {
|
|
|
8157
8169
|
</env:Envelope>
|
|
8158
8170
|
`;
|
|
8159
8171
|
};
|
|
8172
|
+
var validateNominationInvoice = (dto) => {
|
|
8173
|
+
if (!/^\d{44}$/.test(dto.cdc)) {
|
|
8174
|
+
throw new Error("El CDC debe tener 44 d\xEDgitos");
|
|
8175
|
+
}
|
|
8176
|
+
if (dto.motivo.trim().length < 5 || dto.motivo.trim().length > 500) {
|
|
8177
|
+
throw new Error("El motivo debe tener entre 5 y 500 caracteres");
|
|
8178
|
+
}
|
|
8179
|
+
if (dto.razonSocial.trim().length < 4 || dto.razonSocial.trim().length > 255) {
|
|
8180
|
+
throw new Error("La raz\xF3n social debe tener entre 4 y 255 caracteres");
|
|
8181
|
+
}
|
|
8182
|
+
if (dto.esContribuyente !== (dto.idTipoReceptor === 1)) {
|
|
8183
|
+
throw new Error(
|
|
8184
|
+
"idTipoReceptor (1 = contribuyente, 2 = no contribuyente) no coincide con esContribuyente"
|
|
8185
|
+
);
|
|
8186
|
+
}
|
|
8187
|
+
if (![1, 2, 4].includes(dto.idTipoOperacion)) {
|
|
8188
|
+
throw new Error("idTipoOperacion debe ser 1 (B2B), 2 (B2C) o 4 (B2F)");
|
|
8189
|
+
}
|
|
8190
|
+
if (dto.esContribuyente !== (dto.idTipoOperacion === 1)) {
|
|
8191
|
+
throw new Error(
|
|
8192
|
+
"B2B exige receptor contribuyente; B2C y B2F exigen no contribuyente"
|
|
8193
|
+
);
|
|
8194
|
+
}
|
|
8195
|
+
if (dto.idTipoOperacion === 4 === (dto.idPais === "PRY")) {
|
|
8196
|
+
throw new Error(
|
|
8197
|
+
"idPais debe ser PRY, salvo en B2F donde debe ser distinto de PRY"
|
|
8198
|
+
);
|
|
8199
|
+
}
|
|
8200
|
+
if (dto.esContribuyente) {
|
|
8201
|
+
if (!dto.idTipoContribuyente || !dto.ruc || dto.digitoVerificado === void 0) {
|
|
8202
|
+
throw new Error(
|
|
8203
|
+
"Receptor contribuyente: idTipoContribuyente, ruc y digitoVerificado son obligatorios"
|
|
8204
|
+
);
|
|
8205
|
+
}
|
|
8206
|
+
} else if (!dto.idTipoDocumento || !dto.numeroDocumento) {
|
|
8207
|
+
throw new Error(
|
|
8208
|
+
"Receptor no contribuyente: idTipoDocumento y numeroDocumento son obligatorios"
|
|
8209
|
+
);
|
|
8210
|
+
}
|
|
8211
|
+
if (dto.idTipoOperacion === 4 && !dto.direccion) {
|
|
8212
|
+
throw new Error("B2F: la direcci\xF3n del receptor es obligatoria");
|
|
8213
|
+
}
|
|
8214
|
+
if (dto.direccion && !dto.numeroCasa) {
|
|
8215
|
+
throw new Error("numeroCasa es obligatorio si se informa la direcci\xF3n");
|
|
8216
|
+
}
|
|
8217
|
+
};
|
|
8218
|
+
var generateNominationInvoiceXml = (dto) => {
|
|
8219
|
+
validateNominationInvoice(dto);
|
|
8220
|
+
const pais = PAISES.find((item) => item.codigo === dto.idPais).descripcion;
|
|
8221
|
+
const rGEveNom = {
|
|
8222
|
+
Id: dto.cdc,
|
|
8223
|
+
mOtEve: dto.motivo.trim(),
|
|
8224
|
+
iNatRec: dto.idTipoReceptor,
|
|
8225
|
+
iTiOpe: dto.idTipoOperacion,
|
|
8226
|
+
cPaisRec: dto.idPais,
|
|
8227
|
+
dDesPaisRe: pais
|
|
8228
|
+
};
|
|
8229
|
+
if (dto.esContribuyente) {
|
|
8230
|
+
rGEveNom.iTiContRec = dto.idTipoContribuyente;
|
|
8231
|
+
rGEveNom.dRucRec = dto.ruc;
|
|
8232
|
+
rGEveNom.dDVRec = dto.digitoVerificado;
|
|
8233
|
+
} else {
|
|
8234
|
+
rGEveNom.iTipIDRec = dto.idTipoDocumento;
|
|
8235
|
+
rGEveNom.dDTipIDRec = dto.idTipoDocumento === 9 && dto.otroTipoDocumento ? dto.otroTipoDocumento : TIPOS_DOCUMENTOS.find((item) => item.codigo === dto.idTipoDocumento).descripcion;
|
|
8236
|
+
rGEveNom.dNumIDRec = dto.numeroDocumento.trim();
|
|
8237
|
+
}
|
|
8238
|
+
rGEveNom.dNomRec = dto.razonSocial.trim();
|
|
8239
|
+
if (dto.nombreFantasia) rGEveNom.dNomFanRec = dto.nombreFantasia.trim();
|
|
8240
|
+
if (dto.direccion) {
|
|
8241
|
+
rGEveNom.dDirRec = dto.direccion.trim();
|
|
8242
|
+
rGEveNom.dNumCasRec = dto.numeroCasa.trim();
|
|
8243
|
+
}
|
|
8244
|
+
if (dto.idTipoOperacion !== 4) {
|
|
8245
|
+
if (dto.idDepartamento) {
|
|
8246
|
+
rGEveNom.cDepRec = dto.idDepartamento;
|
|
8247
|
+
rGEveNom.dDesDepRec = DEPARTAMENTOS.find(
|
|
8248
|
+
(item) => item.codigo === dto.idDepartamento
|
|
8249
|
+
).descripcion;
|
|
8250
|
+
}
|
|
8251
|
+
if (dto.idDistricto) {
|
|
8252
|
+
rGEveNom.cDisRec = dto.idDistricto;
|
|
8253
|
+
rGEveNom.dDesDisRec = DISTRICTOS.find(
|
|
8254
|
+
(item) => item.codigo === dto.idDistricto
|
|
8255
|
+
).descripcion;
|
|
8256
|
+
}
|
|
8257
|
+
if (dto.idCiudad) {
|
|
8258
|
+
rGEveNom.cCiuRec = dto.idCiudad;
|
|
8259
|
+
rGEveNom.dDesCiuRec = CIUDADES.find(
|
|
8260
|
+
(item) => item.codigo === dto.idCiudad
|
|
8261
|
+
).descripcion;
|
|
8262
|
+
}
|
|
8263
|
+
}
|
|
8264
|
+
if (dto.telefono) rGEveNom.dTelRec = dto.telefono.trim();
|
|
8265
|
+
if (dto.celular) rGEveNom.dCelRec = dto.celular.trim();
|
|
8266
|
+
if (dto.email) rGEveNom.dEmailRec = dto.email.trim();
|
|
8267
|
+
if (dto.codigoCliente) rGEveNom.dCodCliente = dto.codigoCliente.trim();
|
|
8268
|
+
const xsd = "http://ekuatia.set.gov.py/sifen/xsd";
|
|
8269
|
+
const schemaLocation = `${xsd} siRecepEvento_v150.xsd`;
|
|
8270
|
+
const envelope = {
|
|
8271
|
+
"env:Envelope": {
|
|
8272
|
+
$: { "xmlns:env": "http://www.w3.org/2003/05/soap-envelope" },
|
|
8273
|
+
"env:Header": {},
|
|
8274
|
+
"env:Body": {
|
|
8275
|
+
rEnviEventoDe: {
|
|
8276
|
+
$: { xmlns: xsd },
|
|
8277
|
+
dId: dto.id,
|
|
8278
|
+
dEvReg: {
|
|
8279
|
+
gGroupGesEve: {
|
|
8280
|
+
$: {
|
|
8281
|
+
xmlns: xsd,
|
|
8282
|
+
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
|
|
8283
|
+
"xsi:schemaLocation": schemaLocation
|
|
8284
|
+
},
|
|
8285
|
+
rGesEve: {
|
|
8286
|
+
$: { "xsi:schemaLocation": schemaLocation },
|
|
8287
|
+
rEve: {
|
|
8288
|
+
$: { Id: dto.id },
|
|
8289
|
+
dFecFirma: convertToFormatDateSET(/* @__PURE__ */ new Date()),
|
|
8290
|
+
dVerFor: 150,
|
|
8291
|
+
gGroupTiEvt: { rGEveNom }
|
|
8292
|
+
}
|
|
8293
|
+
}
|
|
8294
|
+
}
|
|
8295
|
+
}
|
|
8296
|
+
}
|
|
8297
|
+
}
|
|
8298
|
+
}
|
|
8299
|
+
};
|
|
8300
|
+
const builder = new xml2js__namespace.Builder({
|
|
8301
|
+
xmldec: { version: "1.0", encoding: "UTF-8", standalone: false }
|
|
8302
|
+
});
|
|
8303
|
+
return normalizeXML(builder.buildObject(envelope));
|
|
8304
|
+
};
|
|
8160
8305
|
var OIDS_KEYS = [forge__default.default.pki.oids.pkcs8ShroudedKeyBag, forge__default.default.pki.oids.keyBag];
|
|
8161
8306
|
var obtainBags = (almacen) => almacen.safeContents.flatMap((contenido) => contenido.safeBags);
|
|
8162
8307
|
var readDigitalSign = (digitalSignDto) => {
|
|
@@ -8471,7 +8616,7 @@ var DetalleDocumento = class {
|
|
|
8471
8616
|
};
|
|
8472
8617
|
result.dBasGravIVA = 0;
|
|
8473
8618
|
if (datos.idIva == 1 || datos.idIva == 4) {
|
|
8474
|
-
result.dBasGravIVA = 100 *
|
|
8619
|
+
result.dBasGravIVA = 100 * totalItem * datos.ivaBase / (1e4 + datos.tasaIva * datos.ivaBase);
|
|
8475
8620
|
if (result.dBasGravIVA) {
|
|
8476
8621
|
result.dBasGravIVA = parseFloat(result.dBasGravIVA.toFixed(8));
|
|
8477
8622
|
}
|
|
@@ -9358,7 +9503,7 @@ var Documento = class {
|
|
|
9358
9503
|
if (idTipoDocumento != 4 && idTipoDocumento != 7) {
|
|
9359
9504
|
currentItem["gCamIVA"] = DetalleDocumento.generateDatosItemsOperacionIVA(
|
|
9360
9505
|
currentDetalle,
|
|
9361
|
-
|
|
9506
|
+
currentItem["gValorItem"].gValorRestaItem.dTotOpeItem
|
|
9362
9507
|
);
|
|
9363
9508
|
}
|
|
9364
9509
|
}
|
|
@@ -9976,6 +10121,14 @@ var SifenPersistence = class {
|
|
|
9976
10121
|
throw error;
|
|
9977
10122
|
}
|
|
9978
10123
|
}
|
|
10124
|
+
nominationInvoice(nominationInvoiceDto) {
|
|
10125
|
+
try {
|
|
10126
|
+
return generateNominationInvoiceXml(nominationInvoiceDto);
|
|
10127
|
+
} catch (error) {
|
|
10128
|
+
console.log(error);
|
|
10129
|
+
throw error;
|
|
10130
|
+
}
|
|
10131
|
+
}
|
|
9979
10132
|
obtainDigitalSign(digitalSignDto) {
|
|
9980
10133
|
try {
|
|
9981
10134
|
const digitalSign = readDigitalSign(digitalSignDto);
|
|
@@ -10026,6 +10179,7 @@ var SifenService = class {
|
|
|
10026
10179
|
generateQrUseCase;
|
|
10027
10180
|
generateDocumentUseCase;
|
|
10028
10181
|
signedXmlUseCase;
|
|
10182
|
+
nominationInvoiceUseCase;
|
|
10029
10183
|
sifenRepository;
|
|
10030
10184
|
constructor() {
|
|
10031
10185
|
this.sifenRepository = new SifenPersistence();
|
|
@@ -10042,6 +10196,9 @@ var SifenService = class {
|
|
|
10042
10196
|
);
|
|
10043
10197
|
this.signedXmlUseCase = new SignedXmlUseCase(this.sifenRepository);
|
|
10044
10198
|
this.generateQrUseCase = new GenerateQrUseCase(this.sifenRepository);
|
|
10199
|
+
this.nominationInvoiceUseCase = new NominationInvoiceUseCase(
|
|
10200
|
+
this.sifenRepository
|
|
10201
|
+
);
|
|
10045
10202
|
}
|
|
10046
10203
|
consultRuc(consultRucDto) {
|
|
10047
10204
|
const ruc = this.consultRucUseCase.execute(consultRucDto);
|
|
@@ -10055,6 +10212,10 @@ var SifenService = class {
|
|
|
10055
10212
|
const invoice = this.consultDocumentUseCase.execute(consultDocumentDto);
|
|
10056
10213
|
return invoice;
|
|
10057
10214
|
}
|
|
10215
|
+
nominationInvoice(nominationInvoiceDto) {
|
|
10216
|
+
const xml = this.nominationInvoiceUseCase.execute(nominationInvoiceDto);
|
|
10217
|
+
return xml;
|
|
10218
|
+
}
|
|
10058
10219
|
obtainDigitalSign(digitalSignDto) {
|
|
10059
10220
|
const digitalSign = this.obtainDigitalSignUseCase.execute(digitalSignDto);
|
|
10060
10221
|
return digitalSign;
|