xhandler 6.0.0a1__py3-none-any.whl

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.
@@ -0,0 +1,707 @@
1
+ """Code generated by xhandler-wasm/codegen.py from xhandler.schema.json. DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import date, time
6
+ from decimal import Decimal
7
+ from enum import Enum
8
+ from typing import Annotated, ClassVar, Union
9
+
10
+ from pydantic import BaseModel, ConfigDict, Field, PlainSerializer
11
+
12
+ __all__ = ['Anticipo', 'Atributo', 'Cargo', 'Chofer', 'Cliente', 'CodigoGs1', 'Contacto', 'CreditNote', 'CuotaPago', 'DOCUMENT_KINDS', 'DebitNote', 'Defaults', 'Descuento', 'DespatchAdvice', 'DespatchAdviceAtributo', 'DespatchAdviceDocumentoBaja', 'DespatchAdviceDocumentoRelacionado', 'DespatchAdviceItem', 'Destinatario', 'Detalle', 'Detraccion', 'Direccion', 'Document', 'DocumentoAdicional', 'DocumentoRelacionado', 'Envio', 'Firmante', 'FormaPago', 'Guia', 'GuiaEmbebida', 'Invoice', 'Partida', 'Percepcion', 'PercepcionRetencionComprobanteAfectado', 'PercepcionRetencionOperacion', 'Perception', 'Proveedor', 'Puerto', 'Remitente', 'Retention', 'Reversion', 'SummaryDocuments', 'SummaryDocumentsCliente', 'SummaryDocumentsComprobanteAfectado', 'SummaryDocumentsImpuestos', 'SummaryDocumentsItem', 'SummaryDocumentsItemComprobante', 'SummaryDocumentsPercepcion', 'SummaryDocumentsValorVenta', 'TipoCambio', 'TipoFormaPago', 'TotalImporteInvoice', 'TotalImporteNote', 'TotalImpuestos', 'Transportista', 'Vehiculo', 'VoidedDocuments', 'VoidedDocumentsItem']
13
+
14
+ PlainDecimal = Annotated[
15
+ Decimal, PlainSerializer(lambda d: format(d, "f"), return_type=str, when_used="json")
16
+ ]
17
+ """A Decimal sent as plain text with its scale: "118.00", never "1.18E+2"."""
18
+
19
+
20
+ class _Model(BaseModel):
21
+ model_config = ConfigDict(extra="forbid", validate_assignment=True)
22
+
23
+
24
+ class Anticipo(_Model):
25
+ """Anticipo asociado a un documento"""
26
+ tipo: str | None = None
27
+ """Catalog53. Valores válidos: "04", "05", "06\""""
28
+ comprobante_serie_numero: str
29
+ """Serie y número de comprobante del detalle, por ejemplo "F123-4\""""
30
+ comprobante_tipo: str | None = None
31
+ """Catalog12."""
32
+ monto: PlainDecimal
33
+
34
+
35
+ class Atributo(_Model):
36
+ """Atributo adicional de un detalle"""
37
+ nombre: str = ''
38
+ codigo: str = ''
39
+ valor: str | None = None
40
+ fecha_inicio: date | None = None
41
+ fecha_fin: date | None = None
42
+ duracion: int | None = None
43
+
44
+
45
+ class Cargo(_Model):
46
+ """Cargo global (AllowanceCharge con ChargeIndicator true)"""
47
+ tipo: str
48
+ """Catalog53, e.g. "49" (afecta la base imponible) or "50" (no la afecta)"""
49
+ monto: PlainDecimal
50
+ monto_base: PlainDecimal | None = None
51
+ """`monto` when missing"""
52
+ factor: PlainDecimal | None = None
53
+
54
+
55
+ class Chofer(_Model):
56
+ """Conductor del vehiculo"""
57
+ tipo: str | None = None
58
+ """Free text rendered as JobTitle, e.g. "CONDUCTOR_PRINCIPAL", "COPILOTO\""""
59
+ tipo_documento_identidad: str = ''
60
+ """Catalog6"""
61
+ numero_documento_identidad: str = ''
62
+ nombres: str | None = None
63
+ apellidos: str | None = None
64
+ licencia: str | None = None
65
+
66
+
67
+ class Direccion(_Model):
68
+ """Direccion"""
69
+ ubigeo: str | None = None
70
+ codigo_local: str | None = None
71
+ urbanizacion: str | None = None
72
+ departamento: str | None = None
73
+ provincia: str | None = None
74
+ distrito: str | None = None
75
+ direccion: str | None = None
76
+ codigo_pais: str | None = None
77
+
78
+
79
+ class Contacto(_Model):
80
+ """Contacto"""
81
+ telefono: str | None = None
82
+ email: str | None = None
83
+
84
+
85
+ class Cliente(_Model):
86
+ """Quien es el cliente de la transaccion"""
87
+ tipo_documento_identidad: str = ''
88
+ """Catalog6"""
89
+ numero_documento_identidad: str = ''
90
+ nombre: str = ''
91
+ direccion: Direccion | None = None
92
+ contacto: Contacto | None = None
93
+
94
+
95
+ class CodigoGs1(_Model):
96
+ """Código estándar GS1/GTIN para identificación de producto"""
97
+ codigo: str
98
+ """Código GS1/GTIN del producto"""
99
+ tipo: str
100
+ """Tipo de estructura GTIN: e.g. "GTIN-8", "GTIN-13", "GTIN-14\""""
101
+
102
+
103
+ class Proveedor(_Model):
104
+ """Quien provee el documento electronico. Quien genera o crea el documento."""
105
+ ruc: str = ''
106
+ razon_social: str = ''
107
+ nombre_comercial: str | None = None
108
+ direccion: Direccion | None = None
109
+ contacto: Contacto | None = None
110
+
111
+
112
+ class Firmante(_Model):
113
+ """Quien firma electronicamente el XML"""
114
+ ruc: str
115
+ razon_social: str
116
+
117
+
118
+ class Detalle(_Model):
119
+ """Detalle de las ventas en Boleta/Factura/Nota Credito/Nota Debito"""
120
+ descripcion: str = ''
121
+ cantidad: PlainDecimal = Decimal("0")
122
+ unidad_medida: str | None = None
123
+ codigo: str | None = None
124
+ """Código del producto del vendedor (SellersItemIdentification)"""
125
+ codigo_sunat: str | None = None
126
+ """Código de producto SUNAT - Catalog25 (CommodityClassification)"""
127
+ codigo_gs1: CodigoGs1 | None = None
128
+ """Código estándar GS1/GTIN (StandardItemIdentification).
129
+ Incluye el código y el tipo de estructura GTIN (e.g. "GTIN-8", "GTIN-13", "GTIN-14")."""
130
+ precio: PlainDecimal | None = None
131
+ """Precio unitario sin impuestos; se calcula de `precio_con_impuestos` si no se da"""
132
+ precio_con_impuestos: PlainDecimal | None = None
133
+ """Precio unitario con impuestos; se calcula de `precio` si no se da"""
134
+ precio_referencia: PlainDecimal | None = None
135
+ precio_referencia_tipo: str | None = None
136
+ """Catalog16"""
137
+ igv_tasa: PlainDecimal | None = None
138
+ icb_tasa: PlainDecimal | None = None
139
+ isc_tasa: PlainDecimal | None = None
140
+ igv_tipo: str | None = None
141
+ """Catalog7"""
142
+ isc_tipo: str | None = None
143
+ """Catalog8"""
144
+ icb_aplica: bool = False
145
+ icb: PlainDecimal | None = None
146
+ igv: PlainDecimal | None = None
147
+ igv_base_imponible: PlainDecimal | None = None
148
+ isc: PlainDecimal | None = None
149
+ isc_base_imponible: PlainDecimal | None = None
150
+ total_impuestos: PlainDecimal | None = None
151
+ atributos: list[Atributo] = Field(default_factory=list)
152
+
153
+
154
+ class TotalImporteNote(_Model):
155
+ importe: PlainDecimal
156
+ importe_sin_impuestos: PlainDecimal
157
+
158
+
159
+ class TotalImpuestos(_Model):
160
+ """Total impuestos"""
161
+ total: PlainDecimal
162
+ ivap_importe: PlainDecimal
163
+ ivap_base_imponible: PlainDecimal
164
+ exportacion_importe: PlainDecimal
165
+ exportacion_base_imponible: PlainDecimal
166
+ gravado_importe: PlainDecimal
167
+ gravado_base_imponible: PlainDecimal
168
+ inafecto_importe: PlainDecimal
169
+ inafecto_base_imponible: PlainDecimal
170
+ exonerado_importe: PlainDecimal
171
+ exonerado_base_imponible: PlainDecimal
172
+ gratuito_importe: PlainDecimal
173
+ gratuito_base_imponible: PlainDecimal
174
+ icb_importe: PlainDecimal
175
+ isc_importe: PlainDecimal
176
+ isc_base_imponible: PlainDecimal
177
+
178
+
179
+ class Guia(_Model):
180
+ """Guia asociada a un documento"""
181
+ tipo_comprobante: str
182
+ """Catalog1. Valores válidos: "09", "31\""""
183
+ serie_numero: str
184
+
185
+
186
+ class DocumentoRelacionado(_Model):
187
+ """Documento relacionado"""
188
+ tipo_documento: str
189
+ """Catalog12."""
190
+ serie_numero: str
191
+
192
+
193
+ class CreditNote(_Model):
194
+ """Nota de credito"""
195
+ kind: ClassVar[str] = 'CreditNote'
196
+ leyendas: dict[str, str] = Field(default_factory=dict)
197
+ serie_numero: str = ''
198
+ moneda: str | None = None
199
+ fecha_emision: date | None = None
200
+ hora_emision: time | None = None
201
+ proveedor: Proveedor = Field(default_factory=Proveedor)
202
+ cliente: Cliente = Field(default_factory=Cliente)
203
+ firmante: Firmante | None = None
204
+ icb_tasa: PlainDecimal | None = None
205
+ igv_tasa: PlainDecimal | None = None
206
+ ivap_tasa: PlainDecimal | None = None
207
+ tipo_nota: str | None = None
208
+ """Catalog9"""
209
+ comprobante_afectado_serie_numero: str = ''
210
+ comprobante_afectado_tipo: str | None = None
211
+ """Catalog1"""
212
+ descripcion_sustento: str = ''
213
+ detalles: list[Detalle] = Field(default_factory=list)
214
+ total_importe: TotalImporteNote | None = None
215
+ total_impuestos: TotalImpuestos | None = None
216
+ guias: list[Guia] = Field(default_factory=list)
217
+ documentos_relacionados: list[DocumentoRelacionado] = Field(default_factory=list)
218
+ orden_compra: str | None = None
219
+
220
+
221
+ class CuotaPago(_Model):
222
+ """Cuota de pago"""
223
+ importe: PlainDecimal
224
+ fecha_pago: date
225
+
226
+
227
+ class DebitNote(_Model):
228
+ """Nota de debito"""
229
+ kind: ClassVar[str] = 'DebitNote'
230
+ leyendas: dict[str, str] = Field(default_factory=dict)
231
+ serie_numero: str = ''
232
+ moneda: str | None = None
233
+ fecha_emision: date | None = None
234
+ hora_emision: time | None = None
235
+ proveedor: Proveedor = Field(default_factory=Proveedor)
236
+ cliente: Cliente = Field(default_factory=Cliente)
237
+ firmante: Firmante | None = None
238
+ icb_tasa: PlainDecimal | None = None
239
+ igv_tasa: PlainDecimal | None = None
240
+ ivap_tasa: PlainDecimal | None = None
241
+ tipo_nota: str | None = None
242
+ """Catalog10"""
243
+ comprobante_afectado_serie_numero: str = ''
244
+ comprobante_afectado_tipo: str | None = None
245
+ """Catalog1"""
246
+ descripcion_sustento: str = ''
247
+ detalles: list[Detalle] = Field(default_factory=list)
248
+ total_importe: TotalImporteNote | None = None
249
+ total_impuestos: TotalImpuestos | None = None
250
+ guias: list[Guia] = Field(default_factory=list)
251
+ documentos_relacionados: list[DocumentoRelacionado] = Field(default_factory=list)
252
+ orden_compra: str | None = None
253
+
254
+
255
+ class Defaults(_Model):
256
+ """Values used when the document does not set them; every field is optional."""
257
+ fecha_emision: date | None = None
258
+ """Today in Peru by default"""
259
+ icb_tasa: PlainDecimal | None = None
260
+ """The current SUNAT rate by default"""
261
+ igv_tasa: PlainDecimal | None = None
262
+ """The current SUNAT rate by default"""
263
+ ivap_tasa: PlainDecimal | None = None
264
+ """The current SUNAT rate by default"""
265
+
266
+
267
+ class Descuento(_Model):
268
+ """Descuento asociado a un documento o item"""
269
+ tipo: str | None = None
270
+ """Catalog53."""
271
+ monto: PlainDecimal
272
+ monto_base: PlainDecimal | None = None
273
+ factor: PlainDecimal | None = None
274
+
275
+
276
+ class DespatchAdviceDocumentoBaja(_Model):
277
+ """Documento de baja asociado"""
278
+ tipo_comprobante: str
279
+ """Catalog1"""
280
+ serie_numero: str
281
+
282
+
283
+ class DespatchAdviceDocumentoRelacionado(_Model):
284
+ """Documento relacionado"""
285
+ tipo_documento: str
286
+ serie_numero: str
287
+
288
+
289
+ class DocumentoAdicional(_Model):
290
+ """Documento adicional relacionado al transporte"""
291
+ tipo_documento: str = ''
292
+ """Catalog61"""
293
+ tipo_documento_descripcion: str | None = None
294
+ numero: str = ''
295
+ ruc_emisor: str | None = None
296
+
297
+
298
+ class Remitente(_Model):
299
+ """Remitente (emisor de la guia)"""
300
+ ruc: str = ''
301
+ razon_social: str = ''
302
+ numero_registro_mtc: str | None = None
303
+
304
+
305
+ class Destinatario(_Model):
306
+ """Persona identificada por su documento y nombre: el destinatario de la
307
+ mercancia, y tambien el comprador y el tercero"""
308
+ tipo_documento_identidad: str = ''
309
+ """Catalog6"""
310
+ numero_documento_identidad: str = ''
311
+ nombre: str = ''
312
+
313
+
314
+ class Transportista(_Model):
315
+ """Transportista (transporte publico)"""
316
+ tipo_documento_identidad: str = ''
317
+ """Catalog6"""
318
+ numero_documento_identidad: str = ''
319
+ nombre: str = ''
320
+ numero_registro_mtc: str | None = None
321
+
322
+
323
+ class Vehiculo(_Model):
324
+ """Vehiculo principal, o secundario dentro de `secundarios`"""
325
+ placa: str = ''
326
+ numero_circulacion: str | None = None
327
+ """Tarjeta unica de circulacion (TUC)"""
328
+ numero_autorizacion: str | None = None
329
+ codigo_emisor: str | None = None
330
+ """Entidad que emite la autorizacion"""
331
+ secundarios: list[Vehiculo] = Field(default_factory=list)
332
+
333
+
334
+ class Puerto(_Model):
335
+ """Puerto o aeropuerto"""
336
+ codigo: str = ''
337
+ nombre: str = ''
338
+
339
+
340
+ class Partida(_Model):
341
+ """Punto de partida"""
342
+ ubigeo: str = ''
343
+ direccion: str = ''
344
+ codigo_local: str | None = None
345
+ """Codigo de establecimiento anexo, del `ruc` indicado"""
346
+ ruc: str | None = None
347
+
348
+
349
+ class Envio(_Model):
350
+ """Informacion del envio"""
351
+ tipo_traslado: str = ''
352
+ """Catalog20: motivo de traslado"""
353
+ motivo_traslado: str | None = None
354
+ sustento_peso: str | None = None
355
+ peso_total: PlainDecimal = Decimal("0")
356
+ peso_total_unidad_medida: str = ''
357
+ peso_items: PlainDecimal | None = None
358
+ """Peso neto de los items, en KGM"""
359
+ numero_bultos: int | None = None
360
+ indicadores: list[str] = Field(default_factory=list)
361
+ """Indicadores especiales (SpecialInstructions)"""
362
+ tipo_modalidad_traslado: str = ''
363
+ """Catalog18: modalidad de traslado (01=publico, 02=privado)"""
364
+ fecha_traslado: date | None = None
365
+ """Fecha de inicio del traslado; obligatoria"""
366
+ transportista: Transportista | None = None
367
+ choferes: list[Chofer] = Field(default_factory=list)
368
+ vehiculo: Vehiculo | None = None
369
+ contenedores: list[str] = Field(default_factory=list)
370
+ puerto: Puerto | None = None
371
+ """Catalog63"""
372
+ aeropuerto: Puerto | None = None
373
+ """Catalog64, used when there is no puerto"""
374
+ partida: Partida | None = None
375
+ destino: Partida | None = None
376
+
377
+
378
+ class DespatchAdviceAtributo(_Model):
379
+ """Propiedad adicional de un item (AdditionalItemProperty)"""
380
+ codigo: str = ''
381
+ nombre: str = ''
382
+ valor: str | None = None
383
+
384
+
385
+ class DespatchAdviceItem(_Model):
386
+ """Item de la guia de remision"""
387
+ unidad_medida: str = ''
388
+ cantidad: PlainDecimal = Decimal("0")
389
+ descripcion: str | None = None
390
+ codigo: str = ''
391
+ codigo_sunat: str | None = None
392
+ atributos: list[DespatchAdviceAtributo] = Field(default_factory=list)
393
+
394
+
395
+ class DespatchAdvice(_Model):
396
+ """Guia de Remision (GRE)"""
397
+ kind: ClassVar[str] = 'DespatchAdvice'
398
+ serie_numero: str = ''
399
+ version: str | None = None
400
+ """UBL CustomizationID, "2.0" when missing"""
401
+ fecha_emision: date | None = None
402
+ hora_emision: time | None = None
403
+ tipo_comprobante: str | None = None
404
+ """Catalog1: auto-filled from serie prefix (T->"09", V->"31")"""
405
+ observaciones: str | None = None
406
+ documento_baja: DespatchAdviceDocumentoBaja | None = None
407
+ documento_relacionado: DespatchAdviceDocumentoRelacionado | None = None
408
+ documentos_adicionales: list[DocumentoAdicional] = Field(default_factory=list)
409
+ firmante: Firmante | None = None
410
+ remitente: Remitente = Field(default_factory=Remitente)
411
+ destinatario: Destinatario = Field(default_factory=Destinatario)
412
+ comprador: Destinatario | None = None
413
+ tercero: Destinatario | None = None
414
+ """Remitente original when a third party issues the guia (e.g. the carrier in a "31")"""
415
+ proveedor: Proveedor | None = None
416
+ """Rendered as SellerSupplierParty when there is no tercero"""
417
+ envio: Envio = Field(default_factory=Envio)
418
+ detalles: list[DespatchAdviceItem] = Field(default_factory=list)
419
+
420
+
421
+ class Detraccion(_Model):
422
+ """Detraccion"""
423
+ medio_pago: str
424
+ """Catalog59"""
425
+ cuenta_bancaria: str
426
+ tipo_bien_detraido: str
427
+ """Catalog54"""
428
+ porcentaje: PlainDecimal
429
+ monto: PlainDecimal | None = None
430
+
431
+
432
+ class TipoFormaPago(str, Enum):
433
+ """Tipo de forma de pago"""
434
+ CREDITO = 'Credito'
435
+ CONTADO = 'Contado'
436
+
437
+
438
+ class FormaPago(_Model):
439
+ """Forma de pago. A missing `tipo` is filled in by the enricher, and
440
+ payment in full ("contado") has no `cuotas`."""
441
+ tipo: TipoFormaPago | None = None
442
+ cuotas: list[CuotaPago] = Field(default_factory=list)
443
+ total: PlainDecimal | None = None
444
+
445
+
446
+ class GuiaEmbebida(_Model):
447
+ """Datos del traslado de una factura guia"""
448
+ partida: Direccion
449
+ destino: Direccion
450
+ transportista: Cliente
451
+ licencia: str
452
+ """Licencia de conducir del chofer"""
453
+ placa: str
454
+ """Placa del vehiculo"""
455
+ tipo_modalidad_traslado: str
456
+ """Catalog18: modalidad de traslado"""
457
+ peso_bruto: PlainDecimal
458
+ peso_bruto_unidad_medida: str
459
+
460
+
461
+ class Percepcion(_Model):
462
+ """Percepcion asociada a un documento"""
463
+ tipo: str
464
+ """Catalog53"""
465
+ porcentaje: PlainDecimal | None = None
466
+ monto: PlainDecimal | None = None
467
+ monto_base: PlainDecimal | None = None
468
+ monto_total: PlainDecimal | None = None
469
+
470
+
471
+ class TotalImporteInvoice(_Model):
472
+ """Total Importe Invoice"""
473
+ anticipos: PlainDecimal
474
+ descuentos: PlainDecimal
475
+ cargos: PlainDecimal = Decimal("0")
476
+ """Cargos que no afectan la base imponible (ChargeTotalAmount)"""
477
+ importe: PlainDecimal
478
+ importe_sin_impuestos: PlainDecimal
479
+ importe_con_impuestos: PlainDecimal
480
+
481
+
482
+ class Invoice(_Model):
483
+ """Boleta o Factura"""
484
+ kind: ClassVar[str] = 'Invoice'
485
+ leyendas: dict[str, str] = Field(default_factory=dict)
486
+ serie_numero: str = ''
487
+ moneda: str | None = None
488
+ fecha_emision: date | None = None
489
+ hora_emision: time | None = None
490
+ fecha_vencimiento: date | None = None
491
+ proveedor: Proveedor = Field(default_factory=Proveedor)
492
+ cliente: Cliente = Field(default_factory=Cliente)
493
+ firmante: Firmante | None = None
494
+ icb_tasa: PlainDecimal | None = None
495
+ igv_tasa: PlainDecimal | None = None
496
+ ivap_tasa: PlainDecimal | None = None
497
+ tipo_comprobante: str | None = None
498
+ """Catalog1"""
499
+ tipo_operacion: str | None = None
500
+ """Catalog51"""
501
+ detraccion: Detraccion | None = None
502
+ percepcion: Percepcion | None = None
503
+ direccion_entrega: Direccion | None = None
504
+ guia_embebida: GuiaEmbebida | None = None
505
+ """Factura guia: the invoice also works as the guia de remision"""
506
+ forma_pago: FormaPago | None = None
507
+ anticipos: list[Anticipo] = Field(default_factory=list)
508
+ descuentos: list[Descuento] = Field(default_factory=list)
509
+ cargos: list[Cargo] = Field(default_factory=list)
510
+ detalles: list[Detalle] = Field(default_factory=list)
511
+ total_importe: TotalImporteInvoice | None = None
512
+ total_impuestos: TotalImpuestos | None = None
513
+ guias: list[Guia] = Field(default_factory=list)
514
+ documentos_relacionados: list[DocumentoRelacionado] = Field(default_factory=list)
515
+ observaciones: str | None = None
516
+ orden_compra: str | None = None
517
+
518
+
519
+ class PercepcionRetencionComprobanteAfectado(_Model):
520
+ """Comprobante afectado por la percepcion o retencion"""
521
+ tipo_comprobante: str
522
+ serie_numero: str
523
+ fecha_emision: date
524
+ importe_total: PlainDecimal
525
+ moneda: str | None = None
526
+
527
+
528
+ class TipoCambio(_Model):
529
+ """Tipo de cambio"""
530
+ valor: PlainDecimal
531
+ fecha: date
532
+
533
+
534
+ class PercepcionRetencionOperacion(_Model):
535
+ """Operacion de percepcion o retencion"""
536
+ numero_operacion: int
537
+ fecha_operacion: date
538
+ importe_operacion: PlainDecimal
539
+ comprobante_afectado: PercepcionRetencionComprobanteAfectado
540
+ tipo_cambio: TipoCambio | None = None
541
+
542
+
543
+ class Perception(_Model):
544
+ """Comprobante de Percepcion"""
545
+ kind: ClassVar[str] = 'Perception'
546
+ serie: str = ''
547
+ numero: int = 0
548
+ fecha_emision: date | None = None
549
+ moneda: str | None = None
550
+ proveedor: Proveedor = Field(default_factory=Proveedor)
551
+ cliente: Cliente = Field(default_factory=Cliente)
552
+ firmante: Firmante | None = None
553
+ tipo_regimen: str = ''
554
+ """Catalog22"""
555
+ tipo_regimen_porcentaje: PlainDecimal = Decimal("0")
556
+ importe_total_percibido: PlainDecimal = Decimal("0")
557
+ importe_total_cobrado: PlainDecimal = Decimal("0")
558
+ observaciones: str | None = None
559
+ operacion: PercepcionRetencionOperacion | None = None
560
+ documento_id: str | None = None
561
+ """Computed during enrichment: "{serie}-{numero}\""""
562
+
563
+
564
+ class Retention(_Model):
565
+ """Comprobante de Retencion"""
566
+ kind: ClassVar[str] = 'Retention'
567
+ serie: str = ''
568
+ numero: int = 0
569
+ fecha_emision: date | None = None
570
+ moneda: str | None = None
571
+ proveedor: Proveedor = Field(default_factory=Proveedor)
572
+ cliente: Cliente = Field(default_factory=Cliente)
573
+ firmante: Firmante | None = None
574
+ tipo_regimen: str = ''
575
+ """Catalog23"""
576
+ tipo_regimen_porcentaje: PlainDecimal = Decimal("0")
577
+ importe_total_retenido: PlainDecimal = Decimal("0")
578
+ importe_total_pagado: PlainDecimal = Decimal("0")
579
+ observaciones: str | None = None
580
+ operacion: PercepcionRetencionOperacion | None = None
581
+ documento_id: str | None = None
582
+ """Computed during enrichment: "{serie}-{numero}\""""
583
+
584
+
585
+ class VoidedDocumentsItem(_Model):
586
+ """Detalle de un comprobante dado de baja"""
587
+ tipo_comprobante: str | None = None
588
+ """Catalog1: auto-filled from serie prefix (F->"01", B->"03", T->"09", V->"31", P->"40", R->"20")"""
589
+ serie: str = ''
590
+ numero: int = 0
591
+ descripcion_sustento: str = ''
592
+
593
+
594
+ class Reversion(_Model):
595
+ """Comunicacion de reversion: same content as a [`VoidedDocuments`] (and
596
+ rendered with its template), used to revert perception (P) and retention
597
+ (R) documents. Its ID is "RR-YYYYMMDD-{numero}"."""
598
+ kind: ClassVar[str] = 'Reversion'
599
+ numero: int = 0
600
+ fecha_emision: date | None = None
601
+ fecha_emision_comprobantes: date | None = None
602
+ proveedor: Proveedor = Field(default_factory=Proveedor)
603
+ firmante: Firmante | None = None
604
+ comprobantes: list[VoidedDocumentsItem] = Field(default_factory=list)
605
+ documento_id: str | None = None
606
+ """Computed during enrichment: "RA-YYYYMMDD-{numero}\""""
607
+
608
+
609
+ class SummaryDocumentsCliente(_Model):
610
+ """Cliente simplificado para SummaryDocuments"""
611
+ numero_documento_identidad: str = ''
612
+ tipo_documento_identidad: str = ''
613
+
614
+
615
+ class SummaryDocumentsComprobanteAfectado(_Model):
616
+ """Comprobante afectado (para NC/ND en el resumen)"""
617
+ tipo_comprobante: str
618
+ serie_numero: str
619
+
620
+
621
+ class SummaryDocumentsPercepcion(_Model):
622
+ """Percepcion aplicada a una boleta del resumen"""
623
+ tipo_regimen: str
624
+ """Catalog22: regimen de percepcion"""
625
+ porcentaje: PlainDecimal
626
+ """Porcentaje de percepcion (e.g. 2 para 2%)"""
627
+ monto_base: PlainDecimal
628
+ """Base imponible (TaxableAmount)"""
629
+ monto: PlainDecimal
630
+ """Importe percibido (TotalInvoiceAmount)"""
631
+ monto_total: PlainDecimal
632
+ """Total cobrado incluida la percepcion (SUNATTotalCashed)"""
633
+
634
+
635
+ class SummaryDocumentsValorVenta(_Model):
636
+ """Valor de venta de un comprobante en el resumen"""
637
+ importe_total: PlainDecimal = Decimal("0")
638
+ gravado: PlainDecimal | None = None
639
+ exonerado: PlainDecimal | None = None
640
+ inafecto: PlainDecimal | None = None
641
+ gratuito: PlainDecimal | None = None
642
+ otros_cargos: PlainDecimal | None = None
643
+
644
+
645
+ class SummaryDocumentsImpuestos(_Model):
646
+ """Impuestos de un comprobante en el resumen"""
647
+ igv: PlainDecimal | None = None
648
+ """Filled with 0 when missing"""
649
+ igv_tasa: PlainDecimal | None = None
650
+ """IGV rate as percentage (e.g., 18 for 18%). Required by SUNAT; filled from the defaults when missing."""
651
+ icb: PlainDecimal | None = None
652
+ isc: PlainDecimal | None = None
653
+ ivap: PlainDecimal | None = None
654
+ otros: PlainDecimal | None = None
655
+
656
+
657
+ class SummaryDocumentsItemComprobante(_Model):
658
+ """Comprobante dentro de SummaryDocumentsItem"""
659
+ tipo_comprobante: str = ''
660
+ """Catalog1: "03"=Boleta, "07"=NC, "08"=ND"""
661
+ serie_numero: str = ''
662
+ moneda: str | None = None
663
+ cliente: SummaryDocumentsCliente = Field(default_factory=SummaryDocumentsCliente)
664
+ comprobante_afectado: SummaryDocumentsComprobanteAfectado | None = None
665
+ percepcion: SummaryDocumentsPercepcion | None = None
666
+ valor_venta: SummaryDocumentsValorVenta = Field(default_factory=SummaryDocumentsValorVenta)
667
+ impuestos: SummaryDocumentsImpuestos = Field(default_factory=SummaryDocumentsImpuestos)
668
+
669
+
670
+ class SummaryDocumentsItem(_Model):
671
+ """Detalle de un comprobante en el resumen"""
672
+ tipo_operacion: str = ''
673
+ """Catalog19: "1"=Adicionar, "2"=Modificar, "3"=Anulado"""
674
+ comprobante: SummaryDocumentsItemComprobante = Field(default_factory=SummaryDocumentsItemComprobante)
675
+
676
+
677
+ class SummaryDocuments(_Model):
678
+ """Resumen diario de boletas"""
679
+ kind: ClassVar[str] = 'SummaryDocuments'
680
+ numero: int = 0
681
+ fecha_emision: date | None = None
682
+ fecha_emision_comprobantes: date | None = None
683
+ moneda: str | None = None
684
+ proveedor: Proveedor = Field(default_factory=Proveedor)
685
+ firmante: Firmante | None = None
686
+ comprobantes: list[SummaryDocumentsItem] = Field(default_factory=list)
687
+ documento_id: str | None = None
688
+ """Computed during enrichment: "RC-YYYYMMDD-{numero}\""""
689
+
690
+
691
+ class VoidedDocuments(_Model):
692
+ """Comunicacion de Baja"""
693
+ kind: ClassVar[str] = 'VoidedDocuments'
694
+ numero: int = 0
695
+ fecha_emision: date | None = None
696
+ fecha_emision_comprobantes: date | None = None
697
+ proveedor: Proveedor = Field(default_factory=Proveedor)
698
+ firmante: Firmante | None = None
699
+ comprobantes: list[VoidedDocumentsItem] = Field(default_factory=list)
700
+ documento_id: str | None = None
701
+ """Computed during enrichment: "RA-YYYYMMDD-{numero}\""""
702
+
703
+
704
+ Document = Union[Invoice, CreditNote, DebitNote, DespatchAdvice, Perception, Retention, SummaryDocuments, VoidedDocuments, Reversion]
705
+ """Any document xbuilder can enrich and render."""
706
+
707
+ DOCUMENT_KINDS = ('Invoice', 'CreditNote', 'DebitNote', 'DespatchAdvice', 'Perception', 'Retention', 'SummaryDocuments', 'VoidedDocuments', 'Reversion')