1
|
|
|
"""dvz http://www.diverza.com/ns/addenda/diverza/1""" |
2
|
1 |
|
from decimal import Decimal |
3
|
1 |
|
from datetime import datetime, date, time |
4
|
1 |
|
from collections.abc import Sequence |
5
|
1 |
|
from ...cfdi import CFDI |
6
|
1 |
|
from ...xelement import XElement |
7
|
1 |
|
from ...utils import ScalarMap |
8
|
|
|
|
9
|
|
|
|
10
|
1 |
|
class Extra(ScalarMap): |
11
|
|
|
""" |
12
|
|
|
Tipo definido para determinar cualquier información útil que se requiera expresar en la versión impresa del Comprobante. |
13
|
|
|
|
14
|
|
|
:param indicador: Atributo opcional para señalar un valor que sea útil para identificar el atributo extra |
15
|
|
|
:param atributo: Atributo opcional para especificar el nombre de un atributo adicional que se desee incluir en la Addenda |
16
|
|
|
:param valor: Dato opcional que especifica el valor del atributo determinado en el elemento extra |
17
|
|
|
:param prefijo: Valor opcional que puede incorporarse como prefijo para una mejor identificación del elemento extra |
18
|
|
|
:param sufijo: Valor opcional que puede incorporarse como sufijo para una mejor identificación del elemento extra |
19
|
|
|
""" |
20
|
|
|
|
21
|
1 |
|
def __init__( |
22
|
|
|
self, |
23
|
|
|
indicador: str = None, |
24
|
|
|
atributo: str = None, |
25
|
|
|
valor: str = None, |
26
|
|
|
prefijo: str = None, |
27
|
|
|
sufijo: str = None, |
28
|
|
|
): |
29
|
|
|
super().__init__({ |
30
|
|
|
'Indicador': indicador, |
31
|
|
|
'Atributo': atributo, |
32
|
|
|
'Valor': valor, |
33
|
|
|
'Prefijo': prefijo, |
34
|
|
|
'Sufijo': sufijo, |
35
|
|
|
}) |
36
|
|
|
|
37
|
|
|
|
38
|
1 |
|
class DatosContacto(ScalarMap): |
39
|
|
|
""" |
40
|
|
|
Tipo de dato para determinar información de datos de contacto como teléfono, email y otros. |
41
|
|
|
|
42
|
|
|
:param telefono: Atributo opcional para especificar el teléfono de contacto. |
43
|
|
|
:param email_comercial: Atributo opcional para especificar el email comerical que se quiera publicar a los clientes. |
44
|
|
|
:param email_contacto: Atributo opcional para especificar el email de contacto para notificaciones privadas. |
45
|
|
|
:param web: Atributo opcional para especificar la URL del sitio Web. |
46
|
|
|
""" |
47
|
|
|
|
48
|
1 |
|
def __init__( |
49
|
|
|
self, |
50
|
|
|
telefono: str = None, |
51
|
|
|
email_comercial: str = None, |
52
|
|
|
email_contacto: str = None, |
53
|
|
|
web: str = None, |
54
|
|
|
): |
55
|
|
|
super().__init__({ |
56
|
|
|
'Telefono': telefono, |
57
|
|
|
'EmailComercial': email_comercial, |
58
|
|
|
'EmailContacto': email_contacto, |
59
|
|
|
'Web': web, |
60
|
|
|
}) |
61
|
|
|
|
62
|
|
|
|
63
|
1 |
|
class Ubicacion(ScalarMap): |
64
|
|
|
""" |
65
|
|
|
Tipo definido para expresar domicilios o direcciones |
66
|
|
|
|
67
|
|
|
:param tax_id: Atributo opcional para colocar la clave de identificación fiscal del receptor. |
68
|
|
|
:param codigo_sitio: Elemento opcional para especificar el código de sitio del domicilio. |
69
|
|
|
:param calle: Este atributo opcional sirve para precisar la avenida, calle, camino o carretera donde se da la ubicación. |
70
|
|
|
:param numero: Este atributo opcional sirve para expresar el número particular en donde se da la ubicación sobre una calle dada. |
71
|
|
|
:param colonia: Este atributo opcional sirve para precisar la colonia en donde se da la ubicación cuando se desea ser más específico en casos de ubicaciones urbanas. |
72
|
|
|
:param ciudad: Atributo opcional que sirve para precisar la ciudad o población donde se da la ubicación. |
73
|
|
|
:param municipio: Atributo opcional que sirve para precisar el municipio o delegación (en el caso del Distrito Federal) en donde se da la ubicación. |
74
|
|
|
:param estado: Atributo opcional que sirve para precisar el estado o entidad federativa donde se da la ubicación. |
75
|
|
|
:param pais: Atributo opcional que sirve para precisar el país donde se da la ubicación. |
76
|
|
|
:param codigo_postal: Atributo opcional que sirve para asentar el código postal en donde se da la ubicación. |
77
|
|
|
""" |
78
|
|
|
|
79
|
1 |
|
def __init__( |
80
|
|
|
self, |
81
|
|
|
tax_id: str = None, |
82
|
|
|
codigo_sitio: str = None, |
83
|
|
|
calle: str = None, |
84
|
|
|
numero: str = None, |
85
|
|
|
colonia: str = None, |
86
|
|
|
ciudad: str = None, |
87
|
|
|
municipio: str = None, |
88
|
|
|
estado: str = None, |
89
|
|
|
pais: str = None, |
90
|
|
|
codigo_postal: str = None, |
91
|
|
|
): |
92
|
|
|
super().__init__({ |
93
|
|
|
'TaxID': tax_id, |
94
|
|
|
'CodigoSitio': codigo_sitio, |
95
|
|
|
'Calle': calle, |
96
|
|
|
'Numero': numero, |
97
|
|
|
'Colonia': colonia, |
98
|
|
|
'Ciudad': ciudad, |
99
|
|
|
'Municipio': municipio, |
100
|
|
|
'Estado': estado, |
101
|
|
|
'Pais': pais, |
102
|
|
|
'CodigoPostal': codigo_postal, |
103
|
|
|
}) |
104
|
|
|
|
105
|
|
|
|
106
|
1 |
|
class Concepto(ScalarMap): |
107
|
|
|
""" |
108
|
|
|
Nodo de información para especificar información adicional a un concepto del Comprobante |
109
|
|
|
|
110
|
|
|
:param indicador: Atributo opcional para definir un identificador básico que relacione la información de la Addenda con los nodos Concepto del Comprobante |
111
|
|
|
:param identificador1: Atributo opcional para especificar un identificador especial útil al Concepto |
112
|
|
|
:param identificador2: Atributo opcional para especificar otro identificador especial útil al Concepto |
113
|
|
|
:param descripcion_extranjera: Valor opcional si se requeire agregar información descripriva del Concepto en un idioma diferente al español |
114
|
|
|
:param valor_unitario_moneda_extranjera: Atributo opcional para determinar el Valor Unitario en alguna moneada extranjera |
115
|
|
|
:param importe_moneda_extranjera: Atributo opcional para determinar el importe total del concepto en una moneda extranjera |
116
|
|
|
:param mensaje: Atributo opcional para especificar cualquier mensaje de tipo comercial relacionado al Concepto |
117
|
|
|
:param unidad_medida: Atributo opcional para determinar alguna unidad de medida adicional que se desee especificar en el Concepto |
118
|
|
|
:param codigo_ean: Atributo opcional para especificar si se desea el código de barras EAN (European Article Number) |
119
|
|
|
:param sku: Atributo opcional para especificar el 'Stock-keeping unit' o SKU registrado internamente por el negocio |
120
|
|
|
:param nombre_transportista_c: Atributo opcional para proporcionar el nombre o clave del servicio de transporte usado para el traslado del atrículo definido en el Concepto |
121
|
|
|
:param numero_entrega_c: Atributo opcional para determinar el número de registro originado en el momento de entrega del producto relacionado al Concepto facturado |
122
|
|
|
:param fecha_entrega_c: Atributo opcional para indicar la fecha de entrega del producto relacionado al concepto facturado |
123
|
|
|
:param datos_extra_c: Elemento para determinar datos adicionales que no están contemplados en el esquema pero que se desean especificar en el Comprobante |
124
|
|
|
""" |
125
|
|
|
|
126
|
1 |
|
def __init__( |
127
|
|
|
self, |
128
|
|
|
indicador: str = None, |
129
|
|
|
identificador1: str = None, |
130
|
|
|
identificador2: str = None, |
131
|
|
|
descripcion_extranjera: str = None, |
132
|
|
|
valor_unitario_moneda_extranjera: Decimal | int = None, |
133
|
|
|
importe_moneda_extranjera: Decimal | int = None, |
134
|
|
|
mensaje: str = None, |
135
|
|
|
unidad_medida: str = None, |
136
|
|
|
codigo_ean: str = None, |
137
|
|
|
sku: str = None, |
138
|
|
|
nombre_transportista_c: str = None, |
139
|
|
|
numero_entrega_c: str = None, |
140
|
|
|
fecha_entrega_c: date = None, |
141
|
|
|
datos_extra_c: Extra | dict | Sequence[Extra | dict] = None, |
142
|
|
|
): |
143
|
|
|
super().__init__({ |
144
|
|
|
'Indicador': indicador, |
145
|
|
|
'Identificador1': identificador1, |
146
|
|
|
'Identificador2': identificador2, |
147
|
|
|
'DescripcionExtranjera': descripcion_extranjera, |
148
|
|
|
'ValorUnitarioMonedaExtranjera': valor_unitario_moneda_extranjera, |
149
|
|
|
'ImporteMonedaExtranjera': importe_moneda_extranjera, |
150
|
|
|
'Mensaje': mensaje, |
151
|
|
|
'UnidadMedida': unidad_medida, |
152
|
|
|
'CodigoEAN': codigo_ean, |
153
|
|
|
'Sku': sku, |
154
|
|
|
'NombreTransportistaC': nombre_transportista_c, |
155
|
|
|
'NumeroEntregaC': numero_entrega_c, |
156
|
|
|
'FechaEntregaC': fecha_entrega_c, |
157
|
|
|
'DatosExtraC': datos_extra_c, |
158
|
|
|
}) |
159
|
|
|
|
160
|
|
|
|
161
|
1 |
|
class Conceptos(ScalarMap): |
162
|
|
|
""" |
163
|
|
|
|
164
|
|
|
:param concepto: Nodo de información para especificar información adicional a un concepto del Comprobante |
165
|
|
|
:param numero_conceptos: Atributo opcional definido para especificar el número de líneas de concepto presentes en el documento. |
166
|
|
|
""" |
167
|
|
|
|
168
|
1 |
|
def __init__( |
169
|
|
|
self, |
170
|
|
|
concepto: Concepto | dict | Sequence[Concepto | dict], |
171
|
|
|
numero_conceptos: int = None, |
172
|
|
|
): |
173
|
|
|
super().__init__({ |
174
|
|
|
'Concepto': concepto, |
175
|
|
|
'NumeroConceptos': numero_conceptos, |
176
|
|
|
}) |
177
|
|
|
|
178
|
|
|
|
179
|
1 |
|
class Receptor(ScalarMap): |
180
|
|
|
""" |
181
|
|
|
Nodo opcional para agregar información relacionada al receptor del documento. |
182
|
|
|
|
183
|
|
|
:param comprador: Atributo opcional para colocar la clave ó código del comprador. |
184
|
|
|
:param num_cliente: Atributo opcional para colocar la clave o número de cliente asignado al receptor por parte del emisor del documento. |
185
|
|
|
:param datos_contacto_r: Elemento opcional para agregar datos de contacto del receptor. |
186
|
|
|
:param domicilio_fiscal_r: Elemento opcional para especificar la información del domicilio del receptor. |
187
|
|
|
:param destino: |
188
|
|
|
""" |
189
|
|
|
|
190
|
1 |
|
def __init__( |
191
|
|
|
self, |
192
|
|
|
comprador: str = None, |
193
|
|
|
num_cliente: str = None, |
194
|
|
|
datos_contacto_r: DatosContacto | dict = None, |
195
|
|
|
domicilio_fiscal_r: Ubicacion | dict = None, |
196
|
|
|
destino: Ubicacion | dict | Sequence[Ubicacion | dict] = None, |
197
|
|
|
): |
198
|
|
|
super().__init__({ |
199
|
|
|
'Comprador': comprador, |
200
|
|
|
'NumCliente': num_cliente, |
201
|
|
|
'DatosContactoR': datos_contacto_r, |
202
|
|
|
'DomicilioFiscalR': domicilio_fiscal_r, |
203
|
|
|
'Destino': destino, |
204
|
|
|
}) |
205
|
|
|
|
206
|
|
|
|
207
|
1 |
|
class SucursalE(ScalarMap): |
208
|
|
|
""" |
209
|
|
|
Nodo opcional para agregar información de la sucursal en la que fue expedido el documento |
210
|
|
|
|
211
|
|
|
:param alias: Atributo opcional para especificar el nombre o clave de la sucursal en la que fue expedido el documento |
212
|
|
|
:param domicilio_sucursal: Elemento opcional para especificar la información del domicilio de la sucursal en la que fue expedido el documento |
213
|
|
|
:param datos_contacto: Elemento opcional para especificar datos de contacto de la sucursal en la que fue expedido el documento |
214
|
|
|
""" |
215
|
|
|
|
216
|
1 |
|
def __init__( |
217
|
|
|
self, |
218
|
|
|
alias: str = None, |
219
|
|
|
domicilio_sucursal: Ubicacion | dict = None, |
220
|
|
|
datos_contacto: DatosContacto | dict = None, |
221
|
|
|
): |
222
|
|
|
super().__init__({ |
223
|
|
|
'Alias': alias, |
224
|
|
|
'DomicilioSucursal': domicilio_sucursal, |
225
|
|
|
'DatosContacto': datos_contacto, |
226
|
|
|
}) |
227
|
|
|
|
228
|
|
|
|
229
|
1 |
|
class Emisor(ScalarMap): |
230
|
|
|
""" |
231
|
|
|
Nodo opcional para proporcionar información adicional relacionada al emisor. |
232
|
|
|
|
233
|
|
|
:param vendedor: Atributo opcional para indicar el nombre o clave del Agente de Ventas relacionado con el documento |
234
|
|
|
:param numero_proveedor: Atributo opcional para colocar la clave o número de proveedor que el emisor tiene asignado por su cliente. |
235
|
|
|
:param tipo_proveedor: Atributo opcional para colocar el tipo de proveedor que el emisor tiene asignado por su cliente. |
236
|
|
|
:param gln: Atributo opcional para colocar el número GLN del proveedor. |
237
|
|
|
:param datos_contacto_e: Nodo opcional para agregar información de contacto del emisor |
238
|
|
|
:param domicilio_fiscal_e: Nodo opcional para agregar información del domicilo fiscal del emisor |
239
|
|
|
:param domicilio_origen_e: Elemento opcional para especificar la información del domicilio de origen de envío de la mercancía. |
240
|
|
|
:param sucursal_e: Nodo opcional para agregar información de la sucursal en la que fue expedido el documento |
241
|
|
|
""" |
242
|
|
|
|
243
|
1 |
|
def __init__( |
244
|
|
|
self, |
245
|
|
|
vendedor: str = None, |
246
|
|
|
numero_proveedor: str = None, |
247
|
|
|
tipo_proveedor: str = None, |
248
|
|
|
gln: str = None, |
249
|
|
|
datos_contacto_e: DatosContacto | dict = None, |
250
|
|
|
domicilio_fiscal_e: Ubicacion | dict = None, |
251
|
|
|
domicilio_origen_e: Ubicacion | dict = None, |
252
|
|
|
sucursal_e: SucursalE | dict = None, |
253
|
|
|
): |
254
|
|
|
super().__init__({ |
255
|
|
|
'Vendedor': vendedor, |
256
|
|
|
'NumeroProveedor': numero_proveedor, |
257
|
|
|
'TipoProveedor': tipo_proveedor, |
258
|
|
|
'Gln': gln, |
259
|
|
|
'DatosContactoE': datos_contacto_e, |
260
|
|
|
'DomicilioFiscalE': domicilio_fiscal_e, |
261
|
|
|
'DomicilioOrigenE': domicilio_origen_e, |
262
|
|
|
'SucursalE': sucursal_e, |
263
|
|
|
}) |
264
|
|
|
|
265
|
|
|
|
266
|
1 |
|
class ClavesDescripcion(ScalarMap): |
267
|
|
|
""" |
268
|
|
|
Nodo opcional para expresar las descripciones de los valores del Comprobante que tienen un catálogo oficial SAT relacionado. |
269
|
|
|
|
270
|
|
|
:param c_forma_pago: Atributo opcional para expresar la descripción de la clave del atributo FormaPago del Comprobante conforme al catálogo c_FormaPago. |
271
|
|
|
:param c_moneda: Atributo opcional para expresar la descripción de la clave del atributo Moneda del Comprobante conforme al catálogo c_Moneda. |
272
|
|
|
:param c_tipo_de_comprobante: Atributo opcional para expresar la descripción de la clave del atributo TipoDeComprobante del Comprobante conforme al catálogo c_TipoDeComprobante. |
273
|
|
|
:param c_metodo_pago: Atributo opcional para expresar la descripción de la clave del atributo MetodoPago del Comprobante conforme al catálogo c_MetodoPago. |
274
|
|
|
:param c_lugar_expedicion: Atributo opcional para expresar la Ciudad y Estado al que corresponda el Código Postal señalado en el atributo LugarExpedicion del Comprobante conforme al catálogo c_CodigoPostal. |
275
|
|
|
:param c_tipo_relacion: Atributo opcional para expresar la descripción que corresponda a la clave del Tipo de Relación entre CFDIs señalado en el atributo TipoRelacion del nodo CfdiRelacionados del Comprobante conforme al catálogo c_TipoRelacion. |
276
|
|
|
:param c_regimen_fiscal: Atributo opcional para expresar la descripción que corresponda a la clave del Régimen Fiscal del nodo Emisor del Comprobante conforme al catálogo c_RegimenFiscal. |
277
|
|
|
:param c_residencia_fiscal: Atributo opcional para expresar la descripción que corresponda a la clave del País del atributo ResidenciaFiscal del nodo Receptor del Comprobante cuando este sea extranjero y conforme al catálogo c_Pais. |
278
|
|
|
:param c_uso_cfdi: Atributo opcional para expresar la descripción que corresponda a la clave del Uso del CFDI del atributo UsoCFDI del nodo Receptor del Comprobante conforme al catálogo c_UsoCFDI. |
279
|
|
|
""" |
280
|
|
|
|
281
|
1 |
|
def __init__( |
282
|
|
|
self, |
283
|
|
|
c_forma_pago: str = None, |
284
|
|
|
c_moneda: str = None, |
285
|
|
|
c_tipo_de_comprobante: str = None, |
286
|
|
|
c_metodo_pago: str = None, |
287
|
|
|
c_lugar_expedicion: str = None, |
288
|
|
|
c_tipo_relacion: str = None, |
289
|
|
|
c_regimen_fiscal: str = None, |
290
|
|
|
c_residencia_fiscal: str = None, |
291
|
|
|
c_uso_cfdi: str = None, |
292
|
|
|
): |
293
|
|
|
super().__init__({ |
294
|
|
|
'CFormaPago': c_forma_pago, |
295
|
|
|
'CMoneda': c_moneda, |
296
|
|
|
'CTipoDeComprobante': c_tipo_de_comprobante, |
297
|
|
|
'CMetodoPago': c_metodo_pago, |
298
|
|
|
'CLugarExpedicion': c_lugar_expedicion, |
299
|
|
|
'CTipoRelacion': c_tipo_relacion, |
300
|
|
|
'CRegimenFiscal': c_regimen_fiscal, |
301
|
|
|
'CResidenciaFiscal': c_residencia_fiscal, |
302
|
|
|
'CUsoCFDI': c_uso_cfdi, |
303
|
|
|
}) |
304
|
|
|
|
305
|
|
|
|
306
|
1 |
|
class Generales(ScalarMap): |
307
|
|
|
""" |
308
|
|
|
Nodo opcional para proporcionar información general que aplique al documento. |
309
|
|
|
|
310
|
|
|
:param tipo_documento: Atributo opcional para indicar el nombre comercial del CFDI descrito en letra. Por ejemplo: Factura, Nota de Crédito, Recibo de Arrendamiento, etc. |
311
|
|
|
:param total_con_letra: Atributo opcional para indicar el importe total del CFDI descrito en letra. |
312
|
|
|
:param observaciones: Atributo opcional para agregar cualquier información de texto que sea útil para el CFDI |
313
|
|
|
:param numero_orden: Atributo opcional para identificar el número de orden comercial relacionado con el documento |
314
|
|
|
:param nombre_transportista: Atributo opcional para especificar el nombre o identificador del servico de transporte de la mercancía que ampara el documento.. |
315
|
|
|
:param embarque: Atributo opcional para especificar el dato o código de embarque. |
316
|
|
|
:param numero_entrega: Atributo opcional para identificar el número de la orden de entrega de la mercancía que ampara el documento. |
317
|
|
|
:param terminos_pago: Atributo opcional para identificar los terminos de Pago del documento. |
318
|
|
|
:param fecha_entrega: Atributo opcional para identificar la fecha de entrega de la mercancía que ampara el documento. |
319
|
|
|
:param fecha_tipo_cambio: Atributo opcional para identificar la fecha del tipo de cambio aplicado en el atributo TipoCambio del nodo Comprobante del CFDI cuando la Moneda corresponda a un valor diferente a Pesos Mexicanos. |
320
|
|
|
""" |
321
|
|
|
|
322
|
1 |
|
def __init__( |
323
|
|
|
self, |
324
|
|
|
tipo_documento: str = None, |
325
|
|
|
total_con_letra: str = None, |
326
|
|
|
observaciones: str = None, |
327
|
|
|
numero_orden: str = None, |
328
|
|
|
nombre_transportista: str = None, |
329
|
|
|
embarque: str = None, |
330
|
|
|
numero_entrega: str = None, |
331
|
|
|
terminos_pago: str = None, |
332
|
|
|
fecha_entrega: date = None, |
333
|
|
|
fecha_tipo_cambio: date = None, |
334
|
|
|
): |
335
|
1 |
|
super().__init__({ |
336
|
|
|
'TipoDocumento': tipo_documento, |
337
|
|
|
'TotalConLetra': total_con_letra, |
338
|
|
|
'Observaciones': observaciones, |
339
|
|
|
'NumeroOrden': numero_orden, |
340
|
|
|
'NombreTransportista': nombre_transportista, |
341
|
|
|
'Embarque': embarque, |
342
|
|
|
'NumeroEntrega': numero_entrega, |
343
|
|
|
'TerminosPago': terminos_pago, |
344
|
|
|
'FechaEntrega': fecha_entrega, |
345
|
|
|
'FechaTipoCambio': fecha_tipo_cambio, |
346
|
|
|
}) |
347
|
|
|
|
348
|
|
|
|
349
|
1 |
|
class Diverza(CFDI): |
350
|
|
|
""" |
351
|
|
|
|
352
|
|
|
:param generales: Nodo opcional para proporcionar información general que aplique al documento. |
353
|
|
|
:param claves_descripcion: Nodo opcional para expresar las descripciones de los valores del Comprobante que tienen un catálogo oficial SAT relacionado. |
354
|
|
|
:param emisor: Nodo opcional para proporcionar información adicional relacionada al emisor. |
355
|
|
|
:param receptor: Nodo opcional para agregar información relacionada al receptor del documento. |
356
|
|
|
:param conceptos: |
357
|
|
|
:param complemento: |
358
|
|
|
""" |
359
|
|
|
|
360
|
1 |
|
tag = '{http://www.diverza.com/ns/addenda/diverza/1}diverza' |
361
|
1 |
|
version = '1.1' |
362
|
|
|
|
363
|
1 |
|
def __init__( |
364
|
|
|
self, |
365
|
|
|
generales: Generales | dict = None, |
366
|
|
|
claves_descripcion: ClavesDescripcion | dict = None, |
367
|
|
|
emisor: Emisor | dict = None, |
368
|
|
|
receptor: Receptor | dict = None, |
369
|
|
|
conceptos: Conceptos | dict = None, |
370
|
|
|
complemento: Extra | dict | Sequence[Extra | dict] = None, |
371
|
|
|
): |
372
|
1 |
|
super().__init__({ |
373
|
|
|
'Version': self.version, |
374
|
|
|
'Generales': generales, |
375
|
|
|
'ClavesDescripcion': claves_descripcion, |
376
|
|
|
'Emisor': emisor, |
377
|
|
|
'Receptor': receptor, |
378
|
|
|
'Conceptos': conceptos, |
379
|
|
|
'Complemento': complemento, |
380
|
|
|
}) |
381
|
|
|
|
382
|
|
|
|
383
|
|
|
|