chore: import enterprise addons 19.0 bulk snapshot

This commit is contained in:
1b-agent committed 2026-09-16 10:13:08 +00:00
commit ca4af030d3
39951 files changed
+15570005

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
# coding: utf-8
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
from . import wizard
+1
View File
@@ -0,0 +1 @@
{'name': 'Odoo Mexican XML Polizas Export', 'summary': 'XML Export of the Journal Entries for the Mexican Tax Authorities for a compulsory audit.', 'version': '0.1', 'author': 'Odoo', 'category': 'Accounting/Localizations/Reporting', 'website': 'http://www.odoo.com/', 'license': 'LGPL-3', 'depends': [], 'data': ['security/ir.model.access.csv', 'data/templates/xml_polizas.xml', 'wizard/xml_polizas_wizard_view.xml'], 'installable': True, 'auto_install': True}
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="xml_polizas"><PLZ:Polizas
xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd"
Version="1.3"
t-att-TipoSolicitud="export_type"
t-att-NumOrden="order_number"
t-att-NumTramite="process_number"
t-att-Anio="period.year"
t-att-Mes="period.month"
t-att-RFC="vat"><t t-foreach="moves" t-as="move_key">
<PLZ:Poliza
t-att-Fecha="move_key.date"
t-att-Concepto="move_key.journal_name"
t-att-NumUnIdenPol="move_key.name"><t t-foreach="moves[move_key]" t-as="line">
<PLZ:Transaccion
t-att-Concepto="line['line_label']"
t-att-DesCta="line['account_name']"
t-att-NumCta="line['account_code']"
t-att-Haber="line['credit']"
t-att-Debe="line['debit']">
<PLZ:CompNal
t-if="line.get('uuid')"
t-att-UUID_CFDI="line['uuid']"
t-att-RFC="line['partner_rfc']"
t-att-MontoTotal="line['amount_total']"
t-att-Moneda="line['currency_name']"
t-att-TipCamb="line['currency_conversion_rate']"/>
</PLZ:Transaccion>
</t>
</PLZ:Poliza></t>
</PLZ:Polizas>
</template>
</odoo>
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,664 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:contelec_td="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogosParaEsqContE" targetNamespace="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:import namespace="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogosParaEsqContE" schemaLocation="CatalogosParaEsqContE.xsd"/>
<xs:element name="Polizas">
<xs:annotation>
<xs:documentation>Estándar de pólizas del periodo que se entrega como parte de la contabilidad electrónica.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="Poliza" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo obligatorio para relacionar el detalle de cada transacción dentro de la póliza.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="Transaccion" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo obligatorio para relacionar el detalle de cada transacción dentro de la póliza</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="CompNal" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo opcional para relacionar el detalle de los comprobantes de origen nacional relacionados con la transacción. Se considera que se debe identificar, el soporte documental, tanto en la provisión, como en el pago y/o cobro de cada una de las cuentas y subcuentas que se vean afectadas. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="UUID_CFDI" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar la clave UUID del CFDI soporte de la operación. (36 caracteres)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
<xs:length value="36"/>
<xs:pattern value="[a-f0-9A-F]{8}-[a-f0-9A-F]{4}-[a-f0-9A-F]{4}-[a-f0-9A-F]{4}-[a-f0-9A-F]{12}"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="RFC" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el RFC relacionado con el movimiento o transacción. El RFC al que se hace referencia, es el distinto del contribuyente que envía los datos, es decir, el RFC del tercero vinculado.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="12"/>
<xs:maxLength value="13"/>
<xs:whiteSpace value="collapse"/>
<xs:pattern value="[A-ZÑ&amp;]{3,4}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]?[A-Z0-9]?[0-9A-Z]?"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="MontoTotal" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el monto total del CFDI que soporte la transacción. (Incluye IVA en su caso)</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Moneda" type="contelec_td:c_Moneda" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de moneda utilizado en la transacción, de acuerdo al catálogo publicado en la página de internet del SAT. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TipCamb" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de cambio utilizado de acuerdo al tipo de moneda. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:totalDigits value="19"/>
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="CompNalOtr" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo opcional para relacionar el detalle de los comprobantes de origen nacional relacionados con la transacción, diferente a CFDI, es decir, CFD y/o CBB. Se considera que se debe identificar, el soporte documental, tanto en la provisión, como en el pago y/o cobro de cada una de las cuentas y subcuentas que se vean afectadas. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="CFD_CBB_Serie" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar la serie del comprobante CFD_CBB que soporte la transacción.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="10"/>
<xs:pattern value="[A-Z]+"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="CFD_CBB_NumFol" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el número de folio del comprobante CFD_CBB que soporte la transacción.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:totalDigits value="20"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="RFC" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el RFC relacionado con el movimiento o transacción. El RFC al que se hace referencia, es el distinto del contribuyente que envía los datos, es decir, el RFC del tercero vinculado.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="12"/>
<xs:maxLength value="13"/>
<xs:whiteSpace value="collapse"/>
<xs:pattern value="[A-ZÑ&amp;]{3,4}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]?[A-Z0-9]?[0-9A-Z]?"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="MontoTotal" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el monto total del CFD y/o CBB que soporte la transacción. (Incluye IVA en su caso)</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Moneda" type="contelec_td:c_Moneda" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de moneda utilizado en la transacción, de acuerdo al catálogo publicado en la página de internet del SAT. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TipCamb" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de cambio utilizado de acuerdo al tipo de moneda. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:totalDigits value="19"/>
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="CompExt" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo opcional para relacionar el detalle de los comprobantes de origen extranjero relacionados con la transacción. Se considera que se debe identificar, el soporte documental, tanto en la provisión, como en el pago y/o cobro de cada una de las cuentas y subcuentas que se vean afectadas. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="NumFactExt" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar la clave numérico o alfanumérico del comprobante de origen extranjero que soporte la operación</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
<xs:minLength value="1"/>
<xs:maxLength value="36"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="TaxID" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional que sirve para expresar el Identificador del contribuyente extranjero. Se convierte en requerido cuando se cuente con la información </xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="30"/>
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="MontoTotal" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el monto total del comprobante de origen extranjero que soporte la operación.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Moneda" type="contelec_td:c_Moneda" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de moneda utilizado en la transacción, de acuerdo al catálogo publicado en la página de internet del SAT. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TipCamb" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de cambio utilizado de acuerdo al tipo de moneda. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:totalDigits value="19"/>
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="Cheque" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo opcional para relacionar el detalle de los cheques que integran la póliza. Se convierte en requerido cuando exista una salida o entrada de recursos, que involucre este método de pago o cobro de la obligación contraída por parte del contribuyente que envía los datos.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="Num" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el número del cheque emitido</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="20"/>
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="BanEmisNal" type="contelec_td:c_Banco" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, para expresar el Banco nacional emisor del cheque, de acuerdo al catálogo publicado en la página de internet del SAT. Se consideran banco nacional aquellos bancos de residencia nacional, indistintamente, si el tipo de moneda es nacional o extranjero.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="BanEmisExt" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el nombre completo del Banco extranjero emisor del cheque. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="150"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="CtaOri" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el número de cuenta bancaria del origen de los recursos.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50"/>
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Fecha" type="xs:date" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, es la fecha del cheque</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Benef" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, nombre del beneficiario del cheque</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="300"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="RFC" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el RFC relacionado con el movimiento. El RFC al que se hace referencia, es el distinto del contribuyente que envía los datos, es decir, el RFC del tercero vinculado.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="12"/>
<xs:maxLength value="13"/>
<xs:whiteSpace value="collapse"/>
<xs:pattern value="[A-ZÑ&amp;]{3,4}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]?[A-Z0-9]?[0-9A-Z]?"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Monto" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, es el monto del cheque emitido</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Moneda" type="contelec_td:c_Moneda" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de moneda utilizado en la transacción, de acuerdo al catálogo publicado en la página de internet del SAT. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TipCamb" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de cambio utilizado de acuerdo al tipo de moneda. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:totalDigits value="19"/>
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="Transferencia" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo opcional para relacionar el detalle de las transferencias bancarias que integran la póliza. Se convierte en requerido cuando exista una salida o entrada de recursos que involucre este método de pago o cobro por parte del contribuyente que envía los datos. Además se convierte en requerido cuando se realicen transacciones, entre las cuentas propias del contribuyente.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="CtaOri" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el número de cuenta de origen desde la cual se transfieren los recursos. Se convierte en requerido cuando se cuente con la información. </xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="50"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="BancoOriNal" type="contelec_td:c_Banco" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, para expresar el Banco de la cuenta origen de la transferencia, de acuerdo al catálogo publicado en la página de internet del SAT. Se considera banco nacional aquellos bancos de residencia nacional, indistintamente, si el tipo de moneda es nacional o extranjero.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="BancoOriExt" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el nombre completo del banco origen extranjero. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="150"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="CtaDest" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el número de cuenta destino, la cual se transfieren los recursos.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="50"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="BancoDestNal" type="contelec_td:c_Banco" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, para expresar el Banco de la cuenta destino de la transferencia, de acuerdo al catálogo publicado en la página de internet del SAT. Se considera banco nacional aquellos bancos de residencia nacional, indistintamente, si el tipo de moneda es nacional o extranjero.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="BancoDestExt" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el nombre completo del banco destino extranjero. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="150"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Fecha" type="xs:date" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, es la fecha de la transferencia</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Benef" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, nombre del beneficiario de la transferencia.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="300"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="RFC" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el RFC relacionado con el movimiento. El RFC al que se hace referencia, es el distinto del contribuyente que envía los datos, es decir, el RFC del tercero vinculado.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="12"/>
<xs:maxLength value="13"/>
<xs:whiteSpace value="collapse"/>
<xs:pattern value="[A-ZÑ&amp;]{3,4}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]?[A-Z0-9]?[0-9A-Z]?"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Monto" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, es el monto transferido</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Moneda" type="contelec_td:c_Moneda" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de moneda utilizado en la transacción, de acuerdo al catálogo publicado en la página de internet del SAT. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TipCamb" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de cambio utilizado de acuerdo al tipo de moneda. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:totalDigits value="19"/>
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="OtrMetodoPago" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Nodo opcional para relacionar otros métodos de pago o cobro de la transacción. Se convierte en requerido cuando la transacción involucra un método de pago o cobro diverso a cheque y/o transferencia.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="MetPagoPol" type="contelec_td:c_MetPagos" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el método de pago de la operación, de acuerdo al catálogo publicado en la página de internet del SAT.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Fecha" type="xs:date" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, es la fecha de la transacción de otros métodos de pago.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Benef" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido, nombre de la persona o contribuyente a la cual se realiza éstos métodos de pago.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="300"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="RFC" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el RFC relacionado con la transacción. El RFC al que se hace referencia, es el distinto del contribuyente que envía los datos, es decir, el RFC del tercero vinculado.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="12"/>
<xs:maxLength value="13"/>
<xs:whiteSpace value="collapse"/>
<xs:pattern value="[A-ZÑ&amp;]{3,4}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]?[A-Z0-9]?[0-9A-Z]?"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Monto" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el monto del método de pago soporte de la transacción.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Moneda" type="contelec_td:c_Moneda" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de moneda utilizado en la transacción, de acuerdo al catálogo publicado en la página de internet del SAT. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TipCamb" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el tipo de cambio utilizado de acuerdo al tipo de moneda. Este dato sólo se utiliza en el caso de que el tipo de moneda, sea diferente a la moneda nacional (peso). Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:totalDigits value="19"/>
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="NumCta" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar la clave con que se distingue la cuenta o subcuenta que se afecta por la transacción.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="100"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="DesCta" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el nombre de la cuenta o subcuenta que se afecta por la transacción.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="100"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Concepto" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el concepto de la transacción</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="200"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Debe" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el monto del cargo a la cuenta o subcuenta que se afecta en la transacción. En caso de no existir dato, colocar cero (0)</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Haber" type="PLZ:t_Importe" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el monto del abono a la cuenta o subcuenta que se afecta en la transacción. En caso de no existir dato, colocar cero (0)</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="NumUnIdenPol" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el número único de identificación de la póliza. El campo deberá contener la clave o nombre utilizado por el contribuyente para diferenciar, el tipo de póliza y el número correspondiente. En un mes ordinario no debe repetirse un mismo número de póliza con la clave o nombre asignado por el contribuyente.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50"/>
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Fecha" type="xs:date" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar la fecha de registro de la póliza</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Concepto" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el concepto de la operación</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="300"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Version" type="xs:string" use="required" fixed="1.3">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar la versión del formato.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="RFC" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el RFC del contribuyente que envía los datos</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="12"/>
<xs:maxLength value="13"/>
<xs:whiteSpace value="collapse"/>
<xs:pattern value="[A-ZÑ&amp;]{3,4}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z0-9]?[A-Z0-9]?[0-9A-Z]?"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Mes" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el mes al que corresponde la póliza</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="01"/>
<xs:enumeration value="02"/>
<xs:enumeration value="03"/>
<xs:enumeration value="04"/>
<xs:enumeration value="05"/>
<xs:enumeration value="06"/>
<xs:enumeration value="07"/>
<xs:enumeration value="08"/>
<xs:enumeration value="09"/>
<xs:enumeration value="10"/>
<xs:enumeration value="11"/>
<xs:enumeration value="12"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Anio" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el año al que corresponde la póliza</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="2015"/>
<xs:maxInclusive value="2099"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="TipoSolicitud" use="required">
<xs:annotation>
<xs:documentation>Atributo requerido para expresar el tipo de solicitud de la póliza ( AF - Acto de Fiscalización; FC - Fiscalización Compulsa; DE - Devolución; CO - Compensación )</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="AF|FC|DE|CO"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="NumOrden" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el número de orden asignado al acto de fiscalización al que hace referencia la solicitud de la póliza. Requerido para tipo de solicitud = AF y FC. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="13"/>
<xs:pattern value="[A-Z]{3}[0-9]{7}(/)[0-9]{2}"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="NumTramite" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el número de trámite asignado a la solicitud de devolución o compensación al que hace referencia la solicitud de la póliza. Requerido para tipo de solicitud = DE o CO. Se convierte en requerido cuando se cuente con la información.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="14"/>
<xs:pattern value="[A-Z]{2}[0-9]{12}"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Sello" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para contener el sello digital del archivo de contabilidad electrónica. El sello deberá ser expresado cómo una cadena de texto en formato Base 64</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="noCertificado" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional para expresar el número de serie del certificado de sello digital que ampara el archivo de contabilidad electrónica, de acuerdo al acuse correspondiente a 20 posiciones otorgado por el sistema del SAT.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="20"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Certificado" use="optional">
<xs:annotation>
<xs:documentation>Atributo opcional que sirve para expresar el certificado de sello digital que ampara al archivo de contabilidad electrónica como texto, en formato base 64.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:simpleType name="t_Importe">
<xs:annotation>
<xs:documentation>Tipo definido para expresar importes numéricos con fracción hasta dos decimales</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:decimal">
<xs:fractionDigits value="2"/>
<xs:whiteSpace value="collapse"/>
<xs:maxInclusive value="9999999999999999999999.99"/>
<xs:minExclusive value="-9999999999999999999999.99"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
+303
View File
@@ -0,0 +1,303 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_mx_xml_polizas
#
# "Patricia Gutiérrez (pagc)" <pagc@odoo.com>, 2026.
# "Fernanda Alvarez (mfar)" <mfar@odoo.com>, 2026.
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.1alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-02-20 19:06+0000\n"
"PO-Revision-Date: 2026-07-31 17:09+0000\n"
"Last-Translator: \"Fernanda Alvarez (mfar)\" <mfar@odoo.com>\n"
"Language-Team: Spanish (Latin America) <https://translate.odoo.com/projects/"
"odoo-19-l10n/l10n_mx_xml_polizas/es_419/>\n"
"Language: es_419\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.6.1\n"
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "AB123451234512"
msgstr "AB123451234512"
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "ABC6987654/99"
msgstr "ABC6987654/99"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__order_number
msgid ""
"Attribute to express the order number assigned to the tax audit to which the "
"Journal Entry application refers.\n"
"Required for request types 'AF' and 'FC'"
msgstr ""
"Atributo que se usa para expresar el número de orden asignada a la auditoría "
"fiscal a la que se refiere la aplicación Asiento contable.\n"
"Obligatorio para tipos de solicitud 'AF' y 'FC'"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__process_number
msgid ""
"Attribute to express the process number assigned to the request for refund "
"or compensation to which the request for the Journal Entry refers.\n"
"Required for request types 'DE' and 'CO'"
msgstr ""
"Atributo para expresar el número de proceso asignado a la solicitud de "
"reembolso o remuneración a la que se refiere el Asiento contable.\n"
"Obligatorio para tipos de solicitud 'DE' y 'CO'"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__fc
msgid "Audit certification"
msgstr "Certificación de auditoría"
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "Cancel"
msgstr "Cancel"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Company Settings"
msgstr "Ajustes de la empresa"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__co
msgid "Compensation"
msgstr "Compensación"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__create_date
msgid "Created on"
msgstr "Creado el"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_account_general_ledger_report_handler__display_name
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__display_name
msgid "Display Name"
msgstr "Nombre mostrado"
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "Export"
msgstr "Exportar"
#. module: l10n_mx_xml_polizas
#: model:ir.actions.act_window,name:l10n_mx_xml_polizas.xml_polizas_action
msgid "Export XML Polizas Wizard"
msgstr "Asistente para exportar pólizas XML"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__export_type
msgid "Export type"
msgstr "Tipo de exportación"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__report_filename
msgid "Filename"
msgstr "Nombre del archivo"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_all_entries
msgid "Filter All Entries"
msgstr "Filtrar todos los asientos"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_journals
msgid "Filter Partial Journals"
msgstr "Filtrar diarios parciales"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_month
msgid "Filter Partial Month"
msgstr "Filtrar mes parcial"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_account_general_ledger_report_handler__id
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__id
msgid "ID"
msgstr "ID"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__write_date
msgid "Last Updated on"
msgstr "Última actualización el"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__mimetype
msgid "Mimetype"
msgstr "Tipo MIME"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "No records could be exported with current selection."
msgstr "No se pudieron exportar los registros con la selección actual"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__order_number
msgid "Order Number"
msgstr "Número de orden"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Order number (%(number)s) is invalid, must be like: %(example)s"
msgstr ""
"El número de la orden (%(number)s) no es válido, debe tener el siguiente "
"formato: %(example)s"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid ""
"Order number is required for Export Type \"%(export_type_af)s\" or \"%"
"(export_type_fc)s\""
msgstr ""
"Se requiere el número de la orden para el Tipo de exportación \"%"
"(export_type_af)s\" o \"%(export_type_fc)s\""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Please define the VAT on your company."
msgstr "Defina el RFC de su empresa"
#. module: l10n_mx_xml_polizas
#: model:ir.model,name:l10n_mx_xml_polizas.model_account_general_ledger_report_handler
msgid "Polish JPK KR PD Custom Handler"
msgstr "Gestor personalizado"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__process_number
msgid "Process Number"
msgstr "Número de proceso"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Process number (%(number)s) is invalid, must be like: %(example)s"
msgstr ""
"El número de procedimiento (%(number)s) no es válido, debe tener el "
"siguiente formato: %(example)s"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid ""
"Process number is required for Export Type \"%(export_type_co)s\" or \"%"
"(export_type_de)s\""
msgstr ""
"Se requiere un número de procedimiento para el Tipo de exportación \"%"
"(export_type_co)s\" o \"%(export_type_de)s\""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__report_data
msgid "Report file"
msgstr "Reportar archivo"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__de
msgid "Return of goods"
msgstr "Devolución de bienes"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__af
msgid "Tax audit"
msgstr "Auditoría fiscal"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "The company's VAT is invalid for Mexico."
msgstr "El RFC de la empresa no es válido para México"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_journals
msgid "The filter does not include all journals"
msgstr "Este filtro no incluye todos los diarios"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_month
msgid "The filter does not only include full months"
msgstr "Este filtro no incluye los meses completos"
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_all_entries
msgid "The filter includes unposted entries"
msgstr "El filtro incluye asientos sin publicar"
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid ""
"The filter is selecting <strong>an incomplete period</strong>. The resulting "
"XML files may be incomplete."
msgstr ""
"El filtro selecciona <strong>un periodo incompleto</strong>. Los archivos "
"XML resultantes pueden estar incompletos."
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid ""
"The filter is selecting <strong>only some of the journals</strong>. The "
"resulting XML files may be incomplete."
msgstr ""
"El filtro selecciona <strong>solo algunos diarios</strong>. Los archivos XML "
"resultantes pueden estar incompletos."
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid ""
"The resulting XML will contain also <strong>unposted entries</strong>. The "
"resulting XML files may be incorrect."
msgstr ""
"El XML resultante también contendrá <strong>asientos sin registrar</strong>. "
"Es posible que los archivos XML resultantes sean erróneos."
#. module: l10n_mx_xml_polizas
#: model:ir.model,name:l10n_mx_xml_polizas.model_l10n_mx_xml_polizas_xml_polizas_wizard
msgid "Wizard for the XML Polizas export of Journal Entries"
msgstr "Asistente para la exportación de pólizas XML de los asientos contables"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/models/account_general_ledger.py:0
msgid "XML"
msgstr "XML"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/models/account_general_ledger.py:0
msgid "XML (Polizas)"
msgstr "XML (Pólizas)"
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "XML Polizas Export"
msgstr "Exportación de pólizas XML"
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/models/account_general_ledger.py:0
msgid "XML Polizas Export Options"
msgstr "Opciones de exportación de pólizas XML"
#~ msgid "FEC Report Custom Handler"
#~ msgstr "Gestor personalizado del reporte FEC"
@@ -0,0 +1,273 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_mx_xml_polizas
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 19.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-02-20 19:06+0000\n"
"PO-Revision-Date: 2026-02-20 19:06+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "AB123451234512"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "ABC6987654/99"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__order_number
msgid ""
"Attribute to express the order number assigned to the tax audit to which the Journal Entry application refers.\n"
"Required for request types 'AF' and 'FC'"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__process_number
msgid ""
"Attribute to express the process number assigned to the request for refund or compensation to which the request for the Journal Entry refers.\n"
"Required for request types 'DE' and 'CO'"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__fc
msgid "Audit certification"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "Cancel"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Company Settings"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__co
msgid "Compensation"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__create_uid
msgid "Created by"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__create_date
msgid "Created on"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_account_general_ledger_report_handler__display_name
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__display_name
msgid "Display Name"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "Export"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.actions.act_window,name:l10n_mx_xml_polizas.xml_polizas_action
msgid "Export XML Polizas Wizard"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__export_type
msgid "Export type"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__report_filename
msgid "Filename"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_all_entries
msgid "Filter All Entries"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_journals
msgid "Filter Partial Journals"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_month
msgid "Filter Partial Month"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_account_general_ledger_report_handler__id
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__id
msgid "ID"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__write_uid
msgid "Last Updated by"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__write_date
msgid "Last Updated on"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__mimetype
msgid "Mimetype"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "No records could be exported with current selection."
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__order_number
msgid "Order Number"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Order number (%(number)s) is invalid, must be like: %(example)s"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid ""
"Order number is required for Export Type \"%(export_type_af)s\" or "
"\"%(export_type_fc)s\""
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Please define the VAT on your company."
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model,name:l10n_mx_xml_polizas.model_account_general_ledger_report_handler
msgid "Polish JPK KR PD Custom Handler"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__process_number
msgid "Process Number"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "Process number (%(number)s) is invalid, must be like: %(example)s"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid ""
"Process number is required for Export Type \"%(export_type_co)s\" or "
"\"%(export_type_de)s\""
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,field_description:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__report_data
msgid "Report file"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__de
msgid "Return of goods"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields.selection,name:l10n_mx_xml_polizas.selection__l10n_mx_xml_polizas_xml_polizas_wizard__export_type__af
msgid "Tax audit"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/wizard/xml_polizas_wizard.py:0
msgid "The company's VAT is invalid for Mexico."
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_journals
msgid "The filter does not include all journals"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_partial_month
msgid "The filter does not only include full months"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model.fields,help:l10n_mx_xml_polizas.field_l10n_mx_xml_polizas_xml_polizas_wizard__filter_all_entries
msgid "The filter includes unposted entries"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid ""
"The filter is selecting <strong>an incomplete period</strong>. The resulting"
" XML files may be incomplete."
msgstr ""
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid ""
"The filter is selecting <strong>only some of the journals</strong>. The "
"resulting XML files may be incomplete."
msgstr ""
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid ""
"The resulting XML will contain also <strong>unposted entries</strong>. The "
"resulting XML files may be incorrect."
msgstr ""
#. module: l10n_mx_xml_polizas
#: model:ir.model,name:l10n_mx_xml_polizas.model_l10n_mx_xml_polizas_xml_polizas_wizard
msgid "Wizard for the XML Polizas export of Journal Entries"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/models/account_general_ledger.py:0
msgid "XML"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/models/account_general_ledger.py:0
msgid "XML (Polizas)"
msgstr ""
#. module: l10n_mx_xml_polizas
#: model_terms:ir.ui.view,arch_db:l10n_mx_xml_polizas.xml_polizas_wizard_form
msgid "XML Polizas Export"
msgstr ""
#. module: l10n_mx_xml_polizas
#. odoo-python
#: code:addons/l10n_mx_xml_polizas/models/account_general_ledger.py:0
msgid "XML Polizas Export Options"
msgstr ""
+4
View File
@@ -0,0 +1,4 @@
# coding: utf-8
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account_general_ledger
@@ -0,0 +1,39 @@
# coding: utf-8
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from odoo import _, models
_logger = logging.getLogger(__name__)
class AccountGeneralLedgerReportHandler(models.AbstractModel):
_inherit = 'account.general.ledger.report.handler'
def _custom_options_initializer(self, report, options, previous_options):
# Overridden to add export button on GL for Mexican companies
super()._custom_options_initializer(report, options, previous_options=previous_options)
if self.env.company.account_fiscal_country_id.code == 'MX':
options['buttons'].append({
'name': _('XML (Polizas)'),
'sequence': 30,
'action': 'l10n_mx_open_xml_export_wizard',
'file_export_type': _('XML')
})
def l10n_mx_open_xml_export_wizard(self, options):
""" Action to open the XML Polizas Export Options from the General Ledger button """
return {
'type': 'ir.actions.act_window',
'name': _('XML Polizas Export Options'),
'res_model': 'l10n_mx_xml_polizas.xml_polizas_wizard',
'views': [[False, 'form']],
'target': 'new',
'context': {
**self.env.context,
'l10n_mx_xml_polizas_generation_options': options,
'default_export_type': 'AF'
}
}
@@ -0,0 +1,2 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
l10n_mx_xml_polizas.access_l10n_mx_xml_polizas_xml_polizas_wizard,access_l10n_mx_xml_polizas_xml_polizas_wizard,l10n_mx_xml_polizas.model_l10n_mx_xml_polizas_xml_polizas_wizard,account.group_account_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 l10n_mx_xml_polizas.access_l10n_mx_xml_polizas_xml_polizas_wizard access_l10n_mx_xml_polizas_xml_polizas_wizard l10n_mx_xml_polizas.model_l10n_mx_xml_polizas_xml_polizas_wizard account.group_account_user 1 1 1 0
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_xml_polizas
@@ -0,0 +1,461 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date
from freezegun import freeze_time
from odoo.tests import tagged
from odoo.addons.account_reports.tests.test_general_ledger_report import TestAccountReportsCommon
from odoo.addons.l10n_mx_edi.tests.common import TestMxEdiCommon
@tagged('post_install', 'post_install_l10n', '-at_install')
class AccountXmlPolizasWizard(TestMxEdiCommon, TestAccountReportsCommon):
@classmethod
def setUpClass(cls):
""" Set up the test class for its own tests """
super().setUpClass()
# Setup the company
cls.company = cls.company_data['company']
cls.company_2 = cls.company_data_2['company']
# Enforce old default expence account
cls.company_data['default_account_expense'] = cls.env.ref(f'account.{cls.company.id}_cuenta601_84')
cls.company_data_2['default_account_expense'] = cls.env.ref(f'account.{cls.company_2.id}_cuenta601_84')
cls.company.vat = 'AAAA611013AAA'
cls.company_2.vat = 'P&G851223B24'
cls.wizard = cls.env['l10n_mx_xml_polizas.xml_polizas_wizard'].create({
"export_type": 'AF',
"order_number": "ABC6987654/99",
})
cls.tax_16.tax_exigibility = 'on_invoice'
# Create moves to check the export
cls.moves_company_1 = cls.env['account.move'].create([{
'move_type': 'entry',
'date': date(2016, 1, 1),
'journal_id': cls._get_id('journal_misc'),
'line_ids': [
(0, 0, {'debit': 100.0, 'credit': 0.0, 'name': '2016_1_1', 'account_id': cls._get_id('account_payable')}),
(0, 0, {'debit': 200.0, 'credit': 0.0, 'name': '2016_1_2', 'account_id': cls._get_id('account_expense')}),
(0, 0, {'debit': 0.0, 'credit': 300.0, 'name': '2016_1_3', 'account_id': cls._get_id('account_revenue')}),
],
}, {
'move_type': 'entry',
'date': date(2016, 6, 15),
'journal_id': cls._get_id('journal_misc'),
'line_ids': [
(0, 0, {'debit': 40.0, 'credit': 0.0, 'name': '2016_1b_1', 'account_id': cls._get_id('account_payable')}),
(0, 0, {'debit': 0.0, 'credit': 40.0, 'name': '2016_1b_1', 'account_id': cls._get_id('account_revenue')}),
],
}, {
'move_type': 'entry',
'date': date(2017, 1, 1),
'journal_id': cls._get_id('journal_misc'),
'line_ids': [
(0, 0, {'debit': 1000.0, 'credit': 0.0, 'name': '2017_1_1', 'account_id': cls._get_id('account_receivable')}),
(0, 0, {'debit': 2000.0, 'credit': 0.0, 'name': '2017_1_2', 'account_id': cls._get_id('account_revenue')}),
(0, 0, {'debit': 3000.0, 'credit': 0.0, 'name': '2017_1_3', 'account_id': cls._get_id('account_revenue')}),
(0, 0, {'debit': 4000.0, 'credit': 0.0, 'name': '2017_1_4', 'account_id': cls._get_id('account_revenue')}),
(0, 0, {'debit': 5000.0, 'credit': 0.0, 'name': '2017_1_5', 'account_id': cls._get_id('account_revenue')}),
(0, 0, {'debit': 6000.0, 'credit': 0.0, 'name': '2017_1_6', 'account_id': cls._get_id('account_revenue')}),
(0, 0, {'debit': 0.0, 'credit': 6000.0, 'name': '2017_1_7', 'account_id': cls._get_id('account_expense')}),
(0, 0, {'debit': 0.0, 'credit': 7000.0, 'name': '2017_1_8', 'account_id': cls._get_id('account_expense')}),
(0, 0, {'debit': 0.0, 'credit': 8000.0, 'name': '2017_1_9', 'account_id': cls._get_id('account_expense')}),
],
}
])
cls.moves_company_1.action_post()
cls.moves_company_2 = cls.env["account.move"].create([
{
'move_type': 'entry',
'date': date(2016, 1, 1),
'journal_id': cls._get_id('journal_misc', 2),
'line_ids': [
(0, 0, {'debit': 100.0, 'credit': 0.0, 'name': '2016_2_1', 'account_id': cls._get_id('account_payable', 2)}),
(0, 0, {'debit': 0.0, 'credit': 100.0, 'name': '2016_2_2', 'account_id': cls._get_id('account_revenue', 2)}),
],
}, {
'move_type': 'entry',
'date': date(2017, 6, 1),
'journal_id': cls._get_id('journal_bank', 2),
'line_ids': [
(0, 0, {'debit': 400.0, 'credit': 0.0, 'name': '2017_2_1', 'account_id': cls._get_id('account_expense', 2)}),
(0, 0, {'debit': 0.0, 'credit': 400.0, 'name': '2017_2_2', 'account_id': cls._get_id('account_revenue', 2)}),
],
}
])
cls.moves_company_2.action_post()
@classmethod
def _get_id(cls, name, company_no=1):
""" Syntactic sugar method to simplify access to default accounts/journals """
company_data = cls.company_data if company_no == 1 else cls.company_data_2
return company_data['default_%s' % name].id
def _get_xml_data(self, date_from, date_to, company=None):
""" Fire the export wizard and get the generated XML and metadata (year, month, filename) """
options = self._generate_options(self.env.ref('account_reports.general_ledger_report'), date_from, date_to)
wizard = self.wizard.with_context(l10n_mx_xml_polizas_generation_options=options)
if company:
wizard = wizard.with_company(company)
return wizard._get_xml_data()
def _assert_export_equal(self, year, month, filename, expected_xml, actual_data):
""" Compare that the given export output file corresponds to what is expected """
actual_xml_tree = self.get_xml_tree_from_string(actual_data['content'])
expected_xml_tree = self.get_xml_tree_from_string(expected_xml.encode())
self.assertEqual(actual_data['year'], "%04d" % year)
self.assertEqual(actual_data['month'], "%02d" % month)
self.assertEqual(actual_data['filename'], filename)
self.assertXmlTreeEqual(actual_xml_tree, expected_xml_tree)
def test_xml_polizas_simple(self):
""" Test a simple entry """
expected_xml = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo"
xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd"
Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2017" Mes="01" RFC="AAAA611013AAA">
<PLZ:Poliza Fecha="2017-01-01" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2017/01/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_1" DesCta="___ignore___" NumCta="105.01.01" Haber="0.00" Debe="1000.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_2" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="2000.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_3" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="3000.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_4" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="4000.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_5" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="5000.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_6" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="6000.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_7" DesCta="___ignore___" NumCta="601.84.01" Haber="6000.00" Debe="0.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_8" DesCta="___ignore___" NumCta="601.84.01" Haber="7000.00" Debe="0.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_9" DesCta="___ignore___" NumCta="601.84.01" Haber="8000.00" Debe="0.00"></PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>"""
exported_file = self._get_xml_data(date(2017, 1, 1), date(2017, 12, 31))[0]
self._assert_export_equal(year=2017, month=1, filename='AAAA611013AAA201701PL.XML',
expected_xml=expected_xml, actual_data=exported_file)
def test_xml_polizas_multicompany(self):
""" For the same period, different move lines are exported for different companies"""
date_from, date_to = date(2016, 1, 1), date(2016, 1, 31)
expected_xml = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo"
xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd"
Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2016" Mes="01" RFC="AAAA611013AAA">
<PLZ:Poliza Fecha="2016-01-01" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2016/01/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1_1" DesCta="___ignore___" NumCta="201.01.01" Haber="0.00" Debe="100.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1_2" DesCta="___ignore___" NumCta="601.84.01" Haber="0.00" Debe="200.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1_3" DesCta="___ignore___" NumCta="401.01.01" Haber="300.00" Debe="0.00"></PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>"""
exported_file = self._get_xml_data(date_from, date_to)[0]
self._assert_export_equal(year=2016, month=1, filename='AAAA611013AAA201601PL.XML',
expected_xml=expected_xml, actual_data=exported_file)
expected_xml = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo"
xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd"
Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2016" Mes="01" RFC="P&amp;G851223B24">
<PLZ:Poliza Fecha="2016-01-01" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2016/01/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_2_1" DesCta="___ignore___" NumCta="201.01.01" Haber="0.00" Debe="100.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_2_2" DesCta="___ignore___" NumCta="401.01.01" Haber="100.00" Debe="0.00"></PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>"""
exported_file = self._get_xml_data(date_from, date_to, company=self.company_2)[0]
self._assert_export_equal(year=2016, month=1, filename='P&G851223B24201601PL.XML',
expected_xml=expected_xml, actual_data=exported_file)
def test_xml_polizas_split_by_date(self):
""" Test that the moves are split by date into different files """
exported_files = self._get_xml_data(date(2016, 1, 1), date(2016, 12, 31))
expected_xml_jan = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo"
xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd"
Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2016" Mes="01" RFC="AAAA611013AAA">
<PLZ:Poliza Fecha="2016-01-01" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2016/01/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1_1" DesCta="___ignore___" NumCta="201.01.01" Haber="0.00" Debe="100.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1_2" DesCta="___ignore___" NumCta="601.84.01" Haber="0.00" Debe="200.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1_3" DesCta="___ignore___" NumCta="401.01.01" Haber="300.00" Debe="0.00"></PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>"""
jan_filename = 'AAAA611013AAA201601PL.XML'
exported_jan_file = next((x for x in exported_files if x['filename'] == jan_filename), None)
self.assertIsNotNone(exported_jan_file)
self._assert_export_equal(year=2016, month=1, filename=jan_filename,
expected_xml=expected_xml_jan, actual_data=exported_jan_file)
expected_xml_jun = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo"
xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd"
Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2016" Mes="06" RFC="AAAA611013AAA">
<PLZ:Poliza Fecha="2016-06-15" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2016/06/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1b_1" DesCta="___ignore___" NumCta="201.01.01" Haber="0.00" Debe="40.00"></PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2016_1b_1" DesCta="___ignore___" NumCta="401.01.01" Haber="40.00" Debe="0.00"></PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>"""
jun_filename = 'AAAA611013AAA201606PL.XML'
exported_jun_file = next((x for x in exported_files if x['filename'] == jun_filename), None)
self.assertIsNotNone(exported_jun_file)
self._assert_export_equal(year=2016, month=6, filename=jun_filename,
expected_xml=expected_xml_jun, actual_data=exported_jun_file)
def _get_xml_polizas_data(self, date_from, date_to, company=None):
""" Fire the export wizard and get the generated XML and metadata (year, month, filename) """
wizard = self.env['l10n_mx_xml_polizas.xml_polizas_wizard'].create({
"export_type": 'AF',
"order_number": "ABC6987654/99",
})
options = self._init_options(self.env['account.general.ledger'], date_from, date_to)
wizard = wizard.with_context(l10n_mx_xml_polizas_generation_options=options)
if company:
wizard = wizard.with_company(company)
return wizard._get_xml_data()
def _fake_cfdi_values(self, moves):
for move in moves:
move.write({
'l10n_mx_edi_cfdi_uuid': "AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA",
'l10n_mx_edi_cfdi_supplier_rfc': "AAAA611013AAA",
'l10n_mx_edi_cfdi_customer_rfc': "XEXX010101000",
'l10n_mx_edi_cfdi_amount': 10.0,
})
moves.flush_recordset()
def test_xml_edi_polizas_simple(self):
""" Test XML Polizas is exported with CompNal info """
invoice_a = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'invoice_date': '2017-01-01',
'date': '2017-01-01',
'currency_id': self.company_data['currency'].id,
'invoice_incoterm_id': self.env.ref('account.incoterm_FCA').id,
'invoice_line_ids': [(0, 0, {
'product_id': self.product.id,
'price_unit': 2000.0,
'quantity': 5,
'discount': 20.0,
'tax_ids': [(6, 0, (self.tax_16 + self.tax_10_ret_isr).ids)],
})],
})
with freeze_time(self.frozen_today):
invoice_a.action_post()
self._fake_cfdi_values(invoice_a)
expected_xml = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo" xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd" Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2017" Mes="01" RFC="AAAA611013AAA">
<PLZ:Poliza Fecha="2017-01-01" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2017/01/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_1" DesCta="___ignore___" NumCta="105.01.01" Haber="0.00" Debe="1000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_2" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="2000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_3" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="3000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_4" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="4000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_5" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="5000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_6" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="6000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_7" DesCta="___ignore___" NumCta="601.84.01" Haber="6000.00" Debe="0.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_8" DesCta="___ignore___" NumCta="601.84.01" Haber="7000.00" Debe="0.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_9" DesCta="___ignore___" NumCta="601.84.01" Haber="8000.00" Debe="0.00">
</PLZ:Transaccion>
</PLZ:Poliza>
<PLZ:Poliza Fecha="2017-01-01" Concepto="Sales" NumUnIdenPol="INV/2017/00001">
<PLZ:Transaccion Concepto="Sales - 10% WH L I" DesCta="___ignore___" NumCta="216.03.01" Haber="0.00" Debe="800.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="800.00"></PLZ:CompNal>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Sales - 16%" DesCta="___ignore___" NumCta="208.01.01" Haber="1280.00" Debe="0.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="-1280.00"></PLZ:CompNal>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Sales - INV/2017/00001" DesCta="___ignore___" NumCta="105.01.01" Haber="0.00" Debe="8480.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="8480.00"></PLZ:CompNal>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Sales - [product_mx] product_mx" DesCta="___ignore___" NumCta="401.01.01" Haber="8000.00" Debe="0.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="-8000.00"></PLZ:CompNal>
</PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>
"""
exported_file = self._get_xml_data(date(2017, 1, 1), date(2017, 12, 31))[0]
self._assert_export_equal(year=2017, month=1, filename='AAAA611013AAA201701PL.XML',
expected_xml=expected_xml, actual_data=exported_file)
def test_xml_edi_polizas_vendor_bill(self):
""" Test XML Polizas is exported with CompNal info """
self.partner_a.write({
'country_id': self.env.ref('base.mx').id,
'l10n_mx_type_of_operation': '85',
'vat': 'XAXX010101000'
})
self.partner_a.flush_recordset()
bill = self.env['account.move'].create({
'move_type': 'in_invoice',
'partner_id': self.partner_a.id,
'invoice_date': '2017-01-01',
'date': '2017-01-01',
'currency_id': self.company_data['currency'].id,
'invoice_line_ids': [(0, 0, {
'product_id': self.product.id,
'price_unit': 2000.0,
'quantity': 5,
'discount': 20.0,
'tax_ids': [],
'account_id': self.company_data['default_account_expense'].id,
})],
})
with freeze_time(self.frozen_today):
bill.action_post()
self._fake_cfdi_values(bill)
bill.line_ids.flush_recordset()
expected_xml = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo" xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd" Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2017" Mes="01" RFC="AAAA611013AAA">
<PLZ:Poliza Fecha="2017-01-01" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2017/01/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_1" DesCta="___ignore___" NumCta="105.01.01" Haber="0.00" Debe="1000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_2" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="2000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_3" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="3000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_4" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="4000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_5" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="5000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_6" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="6000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_7" DesCta="___ignore___" NumCta="601.84.01" Haber="6000.00" Debe="0.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_8" DesCta="___ignore___" NumCta="601.84.01" Haber="7000.00" Debe="0.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_9" DesCta="___ignore___" NumCta="601.84.01" Haber="8000.00" Debe="0.00">
</PLZ:Transaccion>
</PLZ:Poliza>
<PLZ:Poliza Fecha="2017-01-01" Concepto="Purchases" NumUnIdenPol="BILL/2017/01/0001">
<PLZ:Transaccion Concepto="Purchases" DesCta="___ignore___" NumCta="201.01.01" Haber="8000.00" Debe="0.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XAXX010101000" MontoTotal="-8000.00"></PLZ:CompNal>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Purchases - [product_mx] product_mx" DesCta="___ignore___" NumCta="601.84.01" Haber="0.00" Debe="8000.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XAXX010101000" MontoTotal="8000.00"></PLZ:CompNal>
</PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>
"""
exported_file = self._get_xml_data(date(2017, 1, 1), date(2017, 12, 31))[0]
self._assert_export_equal(year=2017, month=1, filename='AAAA611013AAA201701PL.XML',
expected_xml=expected_xml, actual_data=exported_file)
def test_xml_edi_polizas_multicurrency(self):
""" Test XML Polizas is exported with CompNal info (multicurrency data)"""
cur_eur = self.env.ref('base.EUR')
cur_eur.active = True
self.env['res.currency.rate'].create({
'name': '2017-01-01',
'rate': 0.05,
'currency_id': cur_eur.id,
'company_id': self.env.company.id,
})
self.env['res.currency.rate'].create({
'name': '2017-01-02',
'rate': 0.055,
'currency_id': cur_eur.id,
'company_id': self.env.company.id,
})
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'invoice_date': '2017-01-01',
'date': '2017-01-01',
'currency_id': cur_eur.id,
'invoice_incoterm_id': self.env.ref('account.incoterm_FCA').id,
'invoice_line_ids': [(0, 0, {
'product_id': self.product.id,
'price_unit': 1000.0,
'quantity': 5,
'tax_ids': [(6, 0, (self.tax_16 + self.tax_10_ret_isr).ids)],
})],
})
with freeze_time(self.frozen_today):
invoice.action_post()
payment = self.env['account.payment.register']\
.with_context(active_model='account.move', active_ids=invoice.ids)\
.create({
'currency_id': self.company_data['currency'].id,
'amount': 1820.0,
'payment_date': '2017-01-02',
})\
._create_payments()
self._fake_cfdi_values(invoice + payment.move_id)
expected_xml = """<?xml version='1.0' encoding='utf-8'?>
<PLZ:Polizas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:PLZ="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo" xsi:schemaLocation="http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd" Version="1.3" TipoSolicitud="AF" NumOrden="ABC6987654/99" Anio="2017" Mes="01" RFC="AAAA611013AAA">
<PLZ:Poliza Fecha="2017-01-01" Concepto="Miscellaneous Operations" NumUnIdenPol="MISC/2017/01/0001">
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_1" DesCta="___ignore___" NumCta="105.01.01" Haber="0.00" Debe="1000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_2" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="2000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_3" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="3000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_4" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="4000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_5" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="5000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_6" DesCta="___ignore___" NumCta="401.01.01" Haber="0.00" Debe="6000.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_7" DesCta="___ignore___" NumCta="601.84.01" Haber="6000.00" Debe="0.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_8" DesCta="___ignore___" NumCta="601.84.01" Haber="7000.00" Debe="0.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Miscellaneous Operations - 2017_1_9" DesCta="___ignore___" NumCta="601.84.01" Haber="8000.00" Debe="0.00">
</PLZ:Transaccion>
</PLZ:Poliza>
<PLZ:Poliza Fecha="2017-01-01" Concepto="Sales" NumUnIdenPol="INV/2017/00001">
<PLZ:Transaccion Concepto="Sales - 10% WH L I" DesCta="___ignore___" NumCta="216.03.01" Haber="0.00" Debe="10000.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="500.00" Moneda="EUR" TipCamb="20.00000"/>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Sales - 16%" DesCta="___ignore___" NumCta="208.01.01" Haber="16000.00" Debe="0.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="-800.00" Moneda="EUR" TipCamb="20.00000"/>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Sales - INV/2017/00001" DesCta="___ignore___" NumCta="105.01.01" Haber="0.00" Debe="106000.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="5300.00" Moneda="EUR" TipCamb="20.00000"/>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Sales - [product_mx] product_mx" DesCta="___ignore___" NumCta="401.01.01" Haber="100000.00" Debe="0.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="-5000.00" Moneda="EUR" TipCamb="20.00000"/>
</PLZ:Transaccion>
</PLZ:Poliza>
<PLZ:Poliza Fecha="2017-01-02" Concepto="Bank" NumUnIdenPol="PBNK1/2017/00001">
<PLZ:Transaccion Concepto="Bank - Manual Payment: INV/2017/00001" DesCta="___ignore___" NumCta="102.01.04" Haber="0.00" Debe="1820.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="1820.00"/>
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Bank - Manual Payment: INV/2017/00001" DesCta="___ignore___" NumCta="105.01.01" Haber="1820.00" Debe="0.00">
<PLZ:CompNal UUID_CFDI="AAAAAAAA-ABCD-ABCD-ABCD-AAAAAAAAAAAA" RFC="XEXX010101000" MontoTotal="-1820.00"/>
</PLZ:Transaccion>
</PLZ:Poliza>
<PLZ:Poliza Fecha="2017-01-31" Concepto="Exchange Difference" NumUnIdenPol="EXCH/2017/01/0001">
<PLZ:Transaccion Concepto="Exchange Difference - Currency exchange rate difference" DesCta="___ignore___" NumCta="105.01.01" Haber="182.00" Debe="0.00">
</PLZ:Transaccion>
<PLZ:Transaccion Concepto="Exchange Difference - Currency exchange rate difference" DesCta="___ignore___" NumCta="701.01.01" Haber="0.00" Debe="182.00">
</PLZ:Transaccion>
</PLZ:Poliza>
</PLZ:Polizas>
"""
exported_file = self._get_xml_data(date(2017, 1, 1), date(2017, 12, 31))[0]
self._assert_export_equal(year=2017, month=1, filename='AAAA611013AAA201701PL.XML',
expected_xml=expected_xml, actual_data=exported_file)
+4
View File
@@ -0,0 +1,4 @@
# coding: utf-8
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import xml_polizas_wizard
@@ -0,0 +1,425 @@
# coding: utf-8
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
import io
import logging
import re
import textwrap
import zipfile
from collections import defaultdict, namedtuple
from datetime import date, timedelta
import stdnum.mx
from werkzeug.urls import url_encode
from odoo import _, api, fields, models, tools
from odoo.exceptions import RedirectWarning, UserError, ValidationError
from odoo.tools import SQL
# Order number is constrained by this pattern, an example is given.
ORDER_NUMBER_PATTERN = re.compile('^[A-Z]{3}[0-6][0-9][0-9]{5}(/)[0-9]{2}$')
ORDER_NUMBER_EXAMPLE = 'ABC6987654/99'
# Process number is constrained by this pattern, an example is given.
PROCESS_NUMBER_PATTERN = re.compile('^[A-Z]{2}[0-9]{12}$')
PROCESS_NUMBER_EXAMPLE = 'AB123451234512'
_logger = logging.getLogger(__name__)
class MoveExportData(defaultdict):
Period = namedtuple('Period', ['year', 'month'])
Key = namedtuple('Key', ['date', 'journal_name', 'name'])
def __init__(self):
super().__init__(lambda: defaultdict(list))
def append(self, move_date, journal_name, move_name, move_data):
period = self.Period('%04d' % move_date.year, '%02d' % move_date.month)
move_key = self.Key(date.strftime(move_date, '%Y-%m-%d'), journal_name, move_name)
self[period][move_key].append(move_data)
class L10n_Mx_Xml_PolizasXml_Polizas_Wizard(models.TransientModel):
_name = 'l10n_mx_xml_polizas.xml_polizas_wizard'
_description = "Wizard for the XML Polizas export of Journal Entries"
# Report fields
report_data = fields.Binary('Report file', readonly=True, attachment=False)
report_filename = fields.Char(string='Filename', readonly=True)
mimetype = fields.Char(string='Mimetype', readonly=True)
# Extra data for the report
export_type = fields.Selection(
string='Export type',
selection=[
('AF', 'Tax audit'),
('FC', 'Audit certification'),
('DE', 'Return of goods'),
('CO', 'Compensation'),
],
required=True)
order_number = fields.Char(
string='Order Number',
help="Attribute to express the order number assigned to the tax audit to which "
"the Journal Entry application refers.\n"
"Required for request types 'AF' and 'FC'")
process_number = fields.Char(
string='Process Number',
help="Attribute to express the process number assigned to the request for refund "
"or compensation to which the request for the Journal Entry refers.\n"
"Required for request types 'DE' and 'CO'")
# Filter status booleans
filter_partial_month = fields.Boolean(
compute='_compute_filter_partial_month',
help="The filter does not only include full months")
filter_partial_journals = fields.Boolean(
compute='_compute_filter_partial_journals',
help="The filter does not include all journals")
filter_all_entries = fields.Boolean(
compute='_compute_filter_all_entries',
help="The filter includes unposted entries")
# ------------------------------
#
# Compute functions
#
# ------------------------------
@api.depends('export_type')
def _compute_filter_all_entries(self):
""" Detects if the current filter selects unposted entries """
self.filter_all_entries = self._options.get('all_entries', False)
@api.depends('export_type')
def _compute_filter_partial_journals(self):
""" Detects if the current filter only selects one journal """
journals_options = self._options.get('journals', None)
partial_journals = False
if journals_options:
selected_journals = [x.get('selected', False) for x in journals_options if 'code' in x]
partial_journals = any(selected_journals) and not all(selected_journals)
self.filter_partial_journals = partial_journals
@api.depends('export_type')
def _compute_filter_partial_month(self):
""" Detects if the current filter selects months partially """
partial_month = False
date_options = self._options.get('date', {})
if date_options.get('mode', '') == 'range':
start = fields.Date.to_date(date_options['date_from'])
end = fields.Date.to_date(date_options['date_to'])
if start.day != 1 or (end + timedelta(1)).day != 1 or end > date.today():
partial_month = True
self.filter_partial_month = partial_month
# ------------------------------
#
# Properties
#
# ------------------------------
@property
def _options(self):
""" Get the options from the context """
return self.env.context.get('l10n_mx_xml_polizas_generation_options', {})
# ------------------------------
#
# Onchange
#
# ------------------------------
@api.onchange('export_type')
def _onchange_export_type(self):
""" Blanks out unrequired fields depending on the export_type """
for record in self:
if record.export_type in ['AF', 'FC']:
record.process_number = False
elif record.export_type in ['DE', 'CO']:
record.order_number = False
# ------------------------------
#
# Constraints
#
# ------------------------------
@api.constrains('order_number')
def _check_order_number(self):
""" Checks that the order number follows the ORDER_NUMBER_PATTERN """
for record in self:
if not record.order_number:
if self.export_type in ('AF', 'FC'):
selection = dict(self._fields['export_type']._description_selection(self.env))
raise ValidationError(_(
'Order number is required for Export Type "%(export_type_af)s" or "%(export_type_fc)s"',
export_type_af=selection['AF'],
export_type_fc=selection['FC'],
))
elif not re.match(ORDER_NUMBER_PATTERN, record.order_number):
raise ValidationError(_("Order number (%(number)s) is invalid, must be like: %(example)s",
number=record.order_number, example=ORDER_NUMBER_EXAMPLE))
@api.constrains('process_number')
def _check_process_number(self):
""" Checks that the process number follows the PROCESS_NUMBER_PATTERN """
for record in self:
if not record.process_number:
if self.export_type in ('CO', 'DE'):
selection = dict(self._fields['export_type']._description_selection(self.env))
raise ValidationError(_(
'Process number is required for Export Type "%(export_type_co)s" or "%(export_type_de)s"',
export_type_co=selection['CO'],
export_type_de=selection['DE'],
))
elif not re.match(PROCESS_NUMBER_PATTERN, record.process_number):
raise ValidationError(_("Process number (%(number)s) is invalid, must be like: %(example)s",
number=record.process_number, example=PROCESS_NUMBER_EXAMPLE))
# ------------------------------
#
# Data retrieval
#
# ------------------------------
def _do_query(self, ledger, options):
""" Execute the query
"""
query = ledger._get_report_query(options, domain=False, date_scope='strict_range')
account_alias = query.join(lhs_alias='account_move_line', lhs_column='account_id', rhs_table='account_account', rhs_column='id', link='account_id')
account_code = self.env['account.account']._field_to_sql(account_alias, 'code', query)
account_name = self.env['account.account']._field_to_sql(account_alias, 'name')
journal_name = self.env['account.journal']._field_to_sql('journal', 'name')
product_name = self.env['product.template']._field_to_sql('product_template', 'name')
query = SQL(
'''
SELECT
account_move_line.id,
account_move_line.name,
account_move_line.date,
account_move_line.product_id,
account_move_line.currency_id,
account_move_line.amount_currency,
%(debit_select)s AS debit,
%(credit_select)s AS credit,
%(balance_select)s AS balance,
company.currency_id AS company_currency_id,
%(account_code)s AS account_code,
%(account_name)s AS account_name,
%(journal_name)s AS journal_name,
currency.name AS currency_name,
move.id AS move_id,
move.name AS move_name,
move.l10n_mx_edi_cfdi_uuid AS l10n_mx_edi_cfdi_uuid,
partner.vat AS partner_vat,
product.default_code AS product_default_code,
%(product_name)s AS product_name,
country.code AS country_code
FROM %(table_references)s
%(currency_table_join)s
LEFT JOIN account_move move ON move.id = account_move_line.move_id
LEFT JOIN res_company company ON company.id = account_move_line.company_id
LEFT JOIN account_journal journal ON journal.id = account_move_line.journal_id
LEFT JOIN res_currency currency ON currency.id = account_move_line.currency_id
LEFT JOIN res_partner partner ON account_move_line.partner_id = partner.id
LEFT JOIN res_country country ON partner.country_id = country.id
LEFT JOIN product_product product ON product.id = account_move_line.product_id
LEFT JOIN product_template product_template ON product_template.id = product.product_tmpl_id
WHERE %(search_condition)s
ORDER BY account_move_line.date, account_move_line.id
''',
debit_select=ledger._currency_table_apply_rate(SQL("account_move_line.debit")),
credit_select=ledger._currency_table_apply_rate(SQL("account_move_line.credit")),
balance_select=ledger._currency_table_apply_rate(SQL("account_move_line.balance")),
account_code=account_code,
account_name=account_name,
journal_name=journal_name,
product_name=product_name,
table_references=query.from_clause,
currency_table_join=ledger._currency_table_aml_join(options),
search_condition=query.where_clause,
)
self.env['account.move.line'].flush_model()
self.env.cr.execute(query)
result = self.env.cr.dictfetchall()
return result
def _get_move_export_data(self, accounts_results):
""" Parse db results in a structure feasible for xml report
"""
move_conversion_rate = {}
move_data = MoveExportData()
for line in accounts_results:
recomputed_line_name = f"[{line['product_default_code']}] {line['product_name']}" if line['product_default_code'] else line['product_name'] or ''
line['name'] = recomputed_line_name if not line['name'] else line['name']
data = {
'line_label': textwrap.shorten(
line['journal_name'] + ((' - ' + line['name']) if line['name'] else ''),
width=200),
'account_name': line['account_name'],
'account_code': line['account_code'],
'credit': '%.2f' % line['credit'],
'debit': '%.2f' % line['debit'],
}
if line.get('l10n_mx_edi_cfdi_uuid'):
foreign_currency = line['currency_id'] and line['currency_id'] != line['company_currency_id']
amount_total = line['amount_currency'] if foreign_currency else line['balance']
if line['country_code'] != 'MX':
partner_rfc = 'XEXX010101000'
elif line['partner_vat']:
partner_rfc = line['partner_vat'].strip()
elif line['country_code'] in (False, 'MX'):
partner_rfc = 'XAXX010101000'
else:
partner_rfc = 'XEXX010101000'
currency_name = False
currency_conversion_rate = False
if foreign_currency:
# calculate conversion rate just once per move so we don't see
# rounding differences between lines
currency_name = line['currency_name']
currency_conversion_rate = move_conversion_rate.get(line['move_id'])
if not currency_conversion_rate:
amount_total_signed = line['balance']
if amount_total:
currency_conversion_rate = abs(amount_total_signed) / abs(amount_total)
else:
currency_conversion_rate = 1.0
currency_conversion_rate = '%.*f' % (5, currency_conversion_rate)
move_conversion_rate[line['move_id']] = currency_conversion_rate
data.update({
'uuid': line['l10n_mx_edi_cfdi_uuid'],
'partner_rfc': partner_rfc,
'currency_name': currency_name,
'currency_conversion_rate': currency_conversion_rate,
'amount_total': '%.2f' % amount_total,
})
move_data.append(line['date'], line['journal_name'], line['move_name'], data)
return move_data
def _get_moves_data(self):
""" Retrieve the moves data to be rendered with the template """
# Retrieve the data from the ledger itself, unfolding every group
ledger = self.env.ref('account_reports.general_ledger_report')
# Options ---------------------------------
# Ensure that the date range is enforced
options = ledger.with_context(allowed_company_ids=self.env.company.ids).get_options({
**self._options,
'unfold_all': True,
'export_mode': 'file',
})
# If the filter is on a date range, exclude initial balances
if options.get('date', {}).get('mode', '') == 'range':
options['general_ledger_strict_range'] = True
# Retrieve --------------------------------
ledger._init_currency_table(options)
accounts_results = self._do_query(ledger, options)
# Group data for (year, month / move)
move_data = self._get_move_export_data(accounts_results)
# Sort the lines by name, to have a consistent order
for period, moves in move_data.items():
for move_key, lines in moves.items():
move_data[period][move_key] = sorted(lines, key=lambda x: x['line_label'])
return move_data
def _get_xml_data(self):
""" Gather the XML Polizas information and render the template.
This function is also called by tests. """
records = []
for period, moves in self._get_moves_data().items():
# Render the template
xml_content = self.env['ir.qweb']._render('l10n_mx_xml_polizas.xml_polizas', values={
'period': period,
'moves': moves,
'export_type': self.export_type,
'vat': self.env.company.vat,
'order_number': self.order_number,
'process_number': self.process_number,
})
# Validate against the XSD
with tools.file_open('l10n_mx_xml_polizas/data/xsd/1.3/PolizasPeriodo_1_3.xsd', 'rb') as xsd:
tools.xml_utils._check_with_xsd(xml_content, xsd)
records.append({
'year': period.year,
'month': period.month,
'filename': '%s%s%sPL.XML' % (self.env.company.vat, period.year, period.month),
'content': xml_content
})
return records
# ------------------------------
#
# Export
#
# ------------------------------
def export_xml(self):
""" Export the XML Polizas export for SAT, after some internal consistency check """
# Check VAT
vat = self.env.company.vat
if not vat:
action = self.env.ref('base.action_res_company_form')
raise RedirectWarning(_('Please define the VAT on your company.'),
action.id, _('Company Settings'))
elif not stdnum.mx.rfc.is_valid(vat):
raise UserError(_("The company's VAT is invalid for Mexico."))
# Retrieve the records
xml_records = self._get_xml_data()
# If there's no record, there's an error
if len(xml_records) == 0:
raise UserError(_('No records could be exported with current selection.'))
# If only one month was selected, return the XML
elif len(xml_records) == 1:
record = xml_records[0]
self.write({
'report_data': base64.b64encode(record['content'].encode()),
'report_filename': record['filename'],
'mimetype': 'application/xml',
})
# If there's more than one month, return a zipfile
else:
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
for record in xml_records:
zip_file.writestr(record['filename'], record['content'])
self.write({
'report_data': base64.b64encode(zip_buffer.getvalue()),
'report_filename': '%sPL.zip' % vat,
'mimetype': 'application/zip',
})
return {
'type': 'ir.actions.act_url',
'url': '/web/content/?' + url_encode({
'model': self._name,
'id': self.id,
'filename_field': 'report_filename',
'field': 'report_data',
'download': 'true'
}),
'target': 'new'
}
@@ -0,0 +1,39 @@
<odoo>
<record id="xml_polizas_wizard_form" model="ir.ui.view">
<field name="name">l10n_mx_xml_polizas.xml_polizas_wizard.form</field>
<field name="model">l10n_mx_xml_polizas.xml_polizas_wizard</field>
<field name="arch" type="xml">
<form string="XML Polizas Export">
<field name="filter_partial_month" invisible="1"/>
<field name="filter_partial_journals" invisible="1"/>
<field name="filter_all_entries" invisible="1"/>
<div class="alert alert-info" role="alert" invisible="not filter_partial_month">
The filter is selecting <strong>an incomplete period</strong>. The resulting XML files may be incomplete.
</div>
<div class="alert alert-info" role="alert" invisible="not filter_partial_journals">
The filter is selecting <strong>only some of the journals</strong>. The resulting XML files may be incomplete.
</div>
<div class="alert alert-info" role="alert" invisible="not filter_all_entries">
The resulting XML will contain also <strong>unposted entries</strong>. The resulting XML files may be incorrect.
</div>
<group>
<field name="export_type"/>
<field name="order_number" placeholder="ABC6987654/99" invisible="export_type not in ['AF', 'FC']" required="export_type in ['AF', 'FC']"/>
<field name="process_number" placeholder="AB123451234512" invisible="export_type not in ['DE', 'CO']" required="export_type in ['DE', 'CO']"/>
</group>
<footer>
<button name="export_xml" string="Export" type="object" class="btn-primary"/>
<button special="cancel" string="Cancel" class="btn-secondary"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="xml_polizas_action">
<field name="view_mode">form</field>
<field name="name">Export XML Polizas Wizard</field>
<field name="res_model">l10n_mx_xml_polizas.xml_polizas_wizard</field>
<field name="target">new</field>
</record>
</odoo>