@devlas/dte-sii 2.19.0 → 2.19.1

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.
Files changed (2) hide show
  1. package/dte-sii.d.ts +79 -12
  2. package/package.json +1 -1
package/dte-sii.d.ts CHANGED
@@ -626,14 +626,73 @@ export interface FolioTope {
626
626
  bloqueado?: boolean;
627
627
  }
628
628
 
629
- export interface ReobtenerCafResult {
630
- /** Rutas de los CAF recuperados. El SII entrega los folios de a uno, así que pueden ser varios. */
631
- paths: string[];
632
- /** Cantidad total de folios recuperados entre todos los rangos. */
633
- folios: number;
634
- /** Rangos que se descartaron por estar anulados en el SII. */
635
- descartados: Array<{ desde: number; hasta: number; motivo: string }>;
636
- }
629
+ /** Un rango ya autorizado que el portal ofrece para reobtener. */
630
+ export interface RangoReobtenible {
631
+ /** Campos ocultos del formulario del portal. Hay que devolverlos tal cual para bajar el CAF. */
632
+ campos: Record<string, string>;
633
+ folioDesde: number;
634
+ folioHasta: number;
635
+ /** Folios que cubre el rango. */
636
+ cantidad: number;
637
+ /**
638
+ * true si el SII anuló el rango. Los documentos emitidos con esos folios se
639
+ * rechazan, así que hay que saltarlo.
640
+ *
641
+ * Ojo: el portal marca los ANULADOS y nada más. Un folio ya emitido aparece
642
+ * como reobtenible igual, y por eso `FolioService.reobtenerCaf` recibe
643
+ * `yaEmitido`: ese dato el SII no lo publica.
644
+ */
645
+ anulado: boolean;
646
+ }
647
+
648
+ /** Resultado de `CafSolicitor.reobtenerCaf`, para un solo rango. */
649
+ export type ReobtenerRangoResult =
650
+ | {
651
+ success: true;
652
+ /** Ruta donde quedó el CAF descargado. */
653
+ cafPath: string;
654
+ /** El XML del CAF tal como lo entregó el portal. */
655
+ xml: string;
656
+ reobtenido: true;
657
+ folioDesde: number;
658
+ folioHasta: number;
659
+ otorgados: number;
660
+ }
661
+ | {
662
+ success: false;
663
+ errorCode:
664
+ | 'RANGO_ANULADO'
665
+ | 'REOBTENCION_SIN_FORMULARIO'
666
+ | 'REOBTENCION_SIN_DESCARGA'
667
+ | 'REOBTENCION_SIN_CAF';
668
+ [extra: string]: unknown;
669
+ };
670
+
671
+ /**
672
+ * Resultado de `FolioService.reobtenerCaf`.
673
+ *
674
+ * Union discriminada por `ok` a propósito: obliga a comprobarlo antes de leer
675
+ * las rutas. El método **nunca devuelve null**, ni siquiera al fallar, así que
676
+ * `if (!resultado)` no detecta nada.
677
+ */
678
+ export type ReobtenerCafResult =
679
+ | {
680
+ ok: true;
681
+ /** Rutas de los CAF recuperados. El SII entrega los rangos de a uno, así que pueden ser varios. */
682
+ cafPaths: string[];
683
+ /** Atajo al primero de `cafPaths`. */
684
+ cafPath: string;
685
+ }
686
+ | {
687
+ ok: false;
688
+ /** Qué impidió completar la reobtención, en texto legible. */
689
+ motivo: string;
690
+ /**
691
+ * Folios que sí se alcanzaron a cubrir, cuando el fallo es por cantidad.
692
+ * Ausente si el fallo fue antes de mirar los rangos.
693
+ */
694
+ disponibles?: number;
695
+ };
637
696
 
638
697
  export class FolioService {
639
698
  constructor(config?: FolioServiceConfig);
@@ -661,7 +720,7 @@ export class FolioService {
661
720
  * cada documento vuelve rechazado con `DTE-3-101`.
662
721
  */
663
722
  yaEmitido?: (rango: { folioDesde: number; folioHasta: number }) => boolean;
664
- }): Promise<ReobtenerCafResult | null>;
723
+ }): Promise<ReobtenerCafResult>;
665
724
  /** El CAF más reciente de un tipo para este RUT y ambiente, o null. */
666
725
  findLatestCaf(tipoDte: number): string | null;
667
726
  /**
@@ -771,9 +830,17 @@ export class CafSolicitor {
771
830
  * ⚠️ El listado incluye rangos ANULADOS sin distinguirlos: solo al abrir cada uno el
772
831
  * portal lo avisa. Por eso `reobtenerCaf` hace un request por rango.
773
832
  */
774
- listarReobtenibles(tipoDte: number): Promise<Array<{ desde: number; hasta: number; raw?: string }>>;
775
- /** Descarga el CAF de un rango ya autorizado. Devuelve null si el rango está anulado. */
776
- reobtenerCaf(tipoDte: number, rango: { desde: number; hasta: number }): Promise<string | null>;
833
+ listarReobtenibles(tipoDte: number): Promise<RangoReobtenible[]>;
834
+ /**
835
+ * Descarga el CAF de un rango ya autorizado.
836
+ *
837
+ * `rango` es un elemento tal cual sale de `listarReobtenibles`: lleva los
838
+ * campos ocultos del formulario del portal en `campos`, que el portal exige de
839
+ * vuelta. No se puede construir a mano con solo los folios.
840
+ *
841
+ * **No devuelve el XML ni null**, devuelve un objeto con `success`.
842
+ */
843
+ reobtenerCaf(tipoDte: number, rango: RangoReobtenible): Promise<ReobtenerRangoResult>;
777
844
  }
778
845
 
779
846
  // ============================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devlas/dte-sii",
3
- "version": "2.19.0",
3
+ "version": "2.19.1",
4
4
  "description": "Facturación y boletas electrónicas para el SII de Chile. Genera, timbra, firma y envía DTEs, libros electrónicos y automatiza la certificación.",
5
5
  "main": "index.js",
6
6
  "types": "dte-sii.d.ts",