...
 
Commits (35)
<a name="2.7.0"></a>
## 2.7.0 (2018-10-22)
#### Features
* **account.voucher:**
* agrega la plantilla de correo electrónico ([376acc16](376acc16))
* agrega la posibilidad de cancelar los recibos de pago electrónicos ([f0d769f0](f0d769f0))
* valida la cuenta bancaria seleccionada antes de ponerla en el XML ([6a351e87](6a351e87), closes [#23](23))
* agrega al complemento de pagos los campos adicionales de las cuentas bancaria ([29900d53](29900d53))
* **version:** set version 2.7.0 ([8e5138a4](8e5138a4))
#### Bug Fixes
* **account.invoice:**
* envía la moneda de la factura al calcular los impuestos ([55920b9d](55920b9d))
* envía la moneda de la factura al calcular los impuestos ([b8d51d94](b8d51d94))
* **account.voucher:**
* evita los errores de validación del XML: CRP214 y CRP215 ([62ec9b2e](62ec9b2e))
* mejora la validación para mostrar el campo CtaBeneficiario en el XML ([5b6a8a5f](5b6a8a5f))
* **es_MX:** actualiza traducción ([e0fe9656](e0fe9656))
* **templates:** se agrega if para saber si contamos con NomBancoOrdExt ([30a3d8a3](30a3d8a3))
<a name="2.6.7"></a>
## 2.6.7 (2018-10-08)
#### Bug Fixes
* **account.voucher:**
* se corrige la hora de pago,en voucher T ([851cae38](851cae38))
* se corrige error al momento de pagar una factura con un saldo mayor al monto ([32beb78b](32beb78b))
<a name="2.6.6"></a>
## 2.6.6 (2018-09-27)
#### Bug Fixes
* **account.voucher:**
* obtiene el tipo de cambio a utilizar en el voucher ([76f84092](76f84092))
* mejora el calculo del importe pagado en transacciones multimoneda ([200051df](200051df))
<a name="2.6.5"></a>
## 2.6.5 (2018-09-26)
#### Bug Fixes
* **account.voucher:** corrige el RFC cuando el cliente es extranjero ([e15c127c](e15c127c))
<a name="2.6.4"></a>
## 2.6.4 (2018-09-25)
#### Bug Fixes
* **account.voucher:** corrije la llamada a la función que genera el código QR ([aecc9f22](aecc9f22))
<a name="2.6.3"></a>
## 2.6.3 (2018-09-24)
#### Features
* **account.invoice:** Nota de credito ([cd99f344](cd99f344))
* **report:** se agrega parser para imprimir account.voucher ([a9b4b2ee](a9b4b2ee))
#### Performance
* **template:** se modifica la funcion que imprime codigo qr ([16fb09aa](16fb09aa))
#### Bug Fixes
* **account.voucher:**
* agrega la referencia la parser del objeto account.voucher ([8b3c92c9](8b3c92c9))
* se modifica la definicion del reporte pdf del account voucher ([86a6e1e1](86a6e1e1))
* **es_MX:** corrige la traducción del campo `Método de pago` ([e361f836](e361f836))
<a name="2.6.2"></a>
## 2.6.2 (2018-09-07)
......
......@@ -2,7 +2,7 @@
{
'name': 'Factura Electronica CFDI',
'version': '2.6.2',
'version': '2.8.0',
'author': 'OpenPyme',
'category': 'Localization/Mexico',
'website': 'http://www.openpyme.mx/',
......@@ -26,6 +26,7 @@
'wizard/account_invoice_refund.xml',
'report/account_invoice.xml',
'report/account_voucher.xml',
'data/email_template.xml',
'data/ir_attachment_facturae_config.xml',
],
'installable': True,
......
<?xml version="1.0" ?>
<openerp>
<!-- Mail template are declared in a NOUPDATE block
so users can freely customize/delete them -->
<data noupdate="1">
<!--Email template -->
<record id="account_voucher_cfdi_email_template" model="email.template">
<field name="name">Electronic Payment Receipt</field>
<field name="subject">${object.company_id.name|safe} Payment (Ref ${object.number or 'n/a'})</field>
<field name="partner_to">${object.partner_id.id}</field>
<field name="model_id" ref="account_voucher.model_account_voucher"/>
<field name="auto_delete" eval="True"/>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; ">
<p>Hello ${object.partner_id.name},</p>
<p>A new payment receipt is available for you: </p>
<p style="border-left: 1px solid #8e0000; margin-left: 30px;">
&nbsp;&nbsp;<strong>REFERENCES</strong><br />
&nbsp;&nbsp;Internal reference: <strong>${object.number}</strong><br />
&nbsp;&nbsp;Total amount: <strong>${object.amount_total} ${object.currency_id.name}</strong><br />
&nbsp;&nbsp;Payment date: ${object.date}<br />
</p>
<br/>
<p>If you have any question, do not hesitate to contact us.</p>
<p>Thank you for choosing ${object.company_id.name or 'us'}!</p>
<br/>
<br/>
<div style="width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;">
<h3 style="margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;">
<strong style="text-transform:uppercase;">${object.company_id.name}</strong></h3>
</div>
<div style="width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;">
<span style="color: #222; margin-bottom: 5px; display: block; ">
% if object.company_id.street:
${object.company_id.street}<br/>
% endif
% if object.company_id.street2:
${object.company_id.street2}<br/>
% endif
% if object.company_id.city or object.company_id.zip:
${object.company_id.zip} ${object.company_id.city}<br/>
% endif
% if object.company_id.country_id:
${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
% endif
</span>
% if object.company_id.phone:
<div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">
Phone:&nbsp; ${object.company_id.phone}
</div>
% endif
% if object.company_id.website:
<div>
Web :&nbsp;<a href="${object.company_id.website}">${object.company_id.website}</a>
</div>
%endif
<p></p>
</div>
</div>
]]></field>
</record>
</data>
</openerp>
......@@ -28,6 +28,7 @@
<field name="template_xml_cancel">Aun.no.hay.uno</field>
<field name="template_pdf_sign">account.voucher.cfdi.pdf</field>
<field name="template_pdf_cancel">account.voucher.cfdi.pdf</field>
<field name="email_template_id" ref="account_voucher_cfdi_email_template"/>
</record>
</data>
......
......@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0rc3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-22 06:23+0000\n"
"PO-Revision-Date: 2018-08-22 01:28-0500\n"
"POT-Creation-Date: 2018-09-21 21:05+0000\n"
"PO-Revision-Date: 2018-09-21 16:19-0500\n"
"Last-Translator: Agustín Cruz <agustin.cruz@openpyme.mx>\n"
"Language-Team: \n"
"Language: es_MX\n"
......@@ -139,6 +139,16 @@ msgstr "Adendas"
msgid "Adendas"
msgstr "Adendas"
#. module: l10n_mx_facturae
#: field:account.invoice,cfdi_folio_fiscal:0
msgid "CFD-I Folio Fiscal"
msgstr "Folio Fiscal"
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid "Are you sure to cancel this voucher?"
msgstr "¿Está seguro de que quiere cancelar este recibo?"
#. module: l10n_mx_facturae
#: field:account.invoice,cfdi_id:0 field:account.voucher,cfdi_id:0
msgid "CFDI"
......@@ -157,6 +167,7 @@ msgstr "Detalles"
#. module: l10n_mx_facturae
#: field:account.invoice,cfdi_relation_type:0
#: field:account.invoice.refund,cfdi_relation_type:0
#: field:account.voucher,cfdi_relation_type:0
msgid "CFDI Relation type"
msgstr "Tipo de relación de CFDI"
......@@ -170,6 +181,11 @@ msgstr "CFDI relacionado al documento seleccionado."
msgid "CFDI use"
msgstr "Uso del CFDI"
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid "Cancel"
msgstr "Cancelar"
#. module: l10n_mx_facturae
#: help:res.partner,cfdi_use:0
msgid ""
......@@ -188,7 +204,7 @@ msgstr "Código"
#. module: l10n_mx_facturae
#: view:res.partner:l10n_mx_facturae.res_partner_view_form
msgid "Configuraciones"
msgstr ""
msgstr "Configuraciones"
#. module: l10n_mx_facturae
#: field:account.invoice,date_invoice_cancel:0
......@@ -230,6 +246,11 @@ msgstr ""
msgid "Fiscal Number"
msgstr "Número fiscal"
#. module: l10n_mx_facturae
#: help:account.invoice,cfdi_folio_fiscal:0
msgid "Folio used in the electronic invoice"
msgstr "Folio usado en la factura electrónica"
#. module: l10n_mx_facturae
#: help:account.invoice,cfdi_adenda_code:0 help:res.partner,cfdi_adenda_code:0
msgid "Helper field to improve view management"
......@@ -241,7 +262,7 @@ msgid "If the invoice is cancelled, save the date when was cancel"
msgstr "Si la facura es cancelada, se guarda la fecha en que se cancela"
#. module: l10n_mx_facturae
#: code:addons/l10n_mx_facturae/models/account_invoice.py:454
#: code:addons/l10n_mx_facturae/models/account_invoice.py:456
#, python-format
msgid ""
"Incorrect tax sequence configuration, check this data in Account >> Tax >> "
......@@ -270,6 +291,11 @@ msgstr "Línea de factura"
msgid "Invoice Refund"
msgstr "Nota de crédito"
#. module: l10n_mx_facturae
#: model:ir.actions.report.xml,name:l10n_mx_facturae.l10n_mx_facturae_report_aeroo
msgid "Invoice Report aero"
msgstr "Reporte de Factura"
#. module: l10n_mx_facturae
#: model:ir.actions.report.xml,name:l10n_mx_facturae.l10n_mx_facturae_report_aeroo_xml
msgid "Invoice XML Report aero"
......@@ -286,11 +312,6 @@ msgstr "Facturación"
msgid "Missing SAT code for product: {product}"
msgstr "Falta el código SAT para el producto: {product}"
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_search
msgid "Not Signed Vouchers"
msgstr "Comprobantes sin firmar"
#. module: l10n_mx_facturae
#: help:res.partner,supplier_number:0
msgid "Number or reference that the Client assigned to our company."
......@@ -310,6 +331,11 @@ msgstr ""
"empresa,\n"
"productos, servicios, facturas o notas de entrega"
#. module: l10n_mx_facturae
#: help:account.voucher,related_cfdi_ids:0
msgid "Original CFDI to which this CFDI is referred to"
msgstr "CFDI relacionado con el CFDI actual"
#. module: l10n_mx_facturae
#: model:ir.model,name:l10n_mx_facturae.model_res_partner
msgid "Partner"
......@@ -319,14 +345,14 @@ msgstr "Empresa"
#: field:account.invoice,payment_method_id:0
#: field:res.partner,payment_method_id:0
msgid "Payment Method"
msgstr "Forma de pago"
msgstr "Método de pago"
#. module: l10n_mx_facturae
#: help:res.partner,payment_method_id:0
msgid ""
"Payment method associated with this partner accordingto CFDI 3.3 catalog."
msgstr ""
"Forma de pago asociado con esta empresa de acuerdo al catálogo del CFDI 3.3."
"Método de pago asociado con esta empresa de acuerdo al catálogo del CFDI 3.3."
#. module: l10n_mx_facturae
#: help:account.invoice,payment_method_id:0
......@@ -341,11 +367,21 @@ msgid "Posted"
msgstr "Posteda"
#. module: l10n_mx_facturae
#: code:addons/l10n_mx_facturae/models/account_invoice.py:437
#: code:addons/l10n_mx_facturae/models/account_invoice.py:439
#, python-format
msgid "Product {p} must have at least one tax selected."
msgstr "El producto {p} debe tener al menos un impuesto."
#. module: l10n_mx_facturae
#: field:account.voucher,related_cfdi_ids:0
msgid "Refund invoices"
msgstr "Notas de crédito"
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid "Replace"
msgstr "Substituir"
#. module: l10n_mx_facturae
#: help:account.invoice,cfdi_adenda_id:0
msgid "Select addendum node to use on invoice."
......@@ -417,6 +453,12 @@ msgstr ""
msgid "{'always_reload': True,'no_quick_create': True}"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid ""
"{'invisible': ['|', ('cfdi_state', '!=', False), ('state', '!=', 'cancel')]}"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.invoice:l10n_mx_facturae.account_invoice_view_form_customer
msgid ""
......
......@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0rc14\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-22 06:23+0000\n"
"PO-Revision-Date: 2018-08-22 06:23+0000\n"
"POT-Creation-Date: 2018-09-21 21:05+0000\n"
"PO-Revision-Date: 2018-09-21 21:05+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
......@@ -118,6 +118,16 @@ msgstr ""
msgid "Adendas"
msgstr ""
#. module: l10n_mx_facturae
#: field:account.invoice,cfdi_folio_fiscal:0
msgid "CFD-I Folio Fiscal"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid "Are you sure to cancel this voucher?"
msgstr ""
#. module: l10n_mx_facturae
#: field:account.invoice,cfdi_id:0
#: field:account.voucher,cfdi_id:0
......@@ -137,6 +147,7 @@ msgstr ""
#. module: l10n_mx_facturae
#: field:account.invoice,cfdi_relation_type:0
#: field:account.invoice.refund,cfdi_relation_type:0
#: field:account.voucher,cfdi_relation_type:0
msgid "CFDI Relation type"
msgstr ""
......@@ -151,6 +162,11 @@ msgstr ""
msgid "CFDI use"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid "Cancel"
msgstr ""
#. module: l10n_mx_facturae
#: help:res.partner,cfdi_use:0
msgid "Cfdi usage that will be used by default on this customer invoices and credit notes"
......@@ -218,7 +234,7 @@ msgid "If the invoice is cancelled, save the date when was cancel"
msgstr ""
#. module: l10n_mx_facturae
#: code:addons/l10n_mx_facturae/models/account_invoice.py:454
#: code:addons/l10n_mx_facturae/models/account_invoice.py:456
#, python-format
msgid "Incorrect tax sequence configuration, check this data in Account >> Tax >> Sequence"
msgstr ""
......@@ -243,6 +259,11 @@ msgstr ""
msgid "Invoice Refund"
msgstr ""
#. module: l10n_mx_facturae
#: model:ir.actions.report.xml,name:l10n_mx_facturae.l10n_mx_facturae_report_aeroo
msgid "Invoice Report aero"
msgstr ""
#. module: l10n_mx_facturae
#: model:ir.actions.report.xml,name:l10n_mx_facturae.l10n_mx_facturae_report_aeroo_xml
msgid "Invoice XML Report aero"
......@@ -276,6 +297,11 @@ msgid "Once you have selected the addendum, you must add the necessary informati
" products, services, invoices or delivery notes"
msgstr ""
#. module: l10n_mx_facturae
#: help:account.voucher,related_cfdi_ids:0
msgid "Original CFDI to which this CFDI is referred to"
msgstr ""
#. module: l10n_mx_facturae
#: model:ir.model,name:l10n_mx_facturae.model_res_partner
msgid "Partner"
......@@ -303,11 +329,21 @@ msgid "Posted"
msgstr ""
#. module: l10n_mx_facturae
#: code:addons/l10n_mx_facturae/models/account_invoice.py:437
#: code:addons/l10n_mx_facturae/models/account_invoice.py:439
#, python-format
msgid "Product {p} must have at least one tax selected."
msgstr ""
#. module: l10n_mx_facturae
#: field:account.voucher,related_cfdi_ids:0
msgid "Refund invoices"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid "Replace"
msgstr ""
#. module: l10n_mx_facturae
#: help:account.invoice,cfdi_adenda_id:0
msgid "Select addendum node to use on invoice."
......@@ -364,11 +400,6 @@ msgstr ""
msgid "UUID"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_search
msgid "Unsigned"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.invoice:l10n_mx_facturae.account_invoice_view_form_customer
msgid "[('customer', '=', True), ('is_company', '=', True)]"
......@@ -379,6 +410,11 @@ msgstr ""
msgid "{'always_reload': True,'no_quick_create': True}"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.voucher:l10n_mx_facturae.account_voucher_view_form
msgid "{'invisible': ['|', ('cfdi_state', '!=', False), ('state', '!=', 'cancel')]}"
msgstr ""
#. module: l10n_mx_facturae
#: view:account.invoice:l10n_mx_facturae.account_invoice_view_form_customer
msgid "{'search_default_customer':1, 'show_address': 1, 'default_is_company': 1}"
......
# -*- coding: utf-8 -*-
from openupgradelib import openupgrade as tools
from openerp import SUPERUSER_ID
def set_signed_status_vouchers(env):
"""Set all signed vouchers to the new signed status"""
tools.logged_query(
env.cr,
"""
UPDATE
account_voucher
SET
state = 'signed'
WHERE
cfdi_id IS NOT NULL AND
type = 'receipt' AND
state not in ('draft', 'cancel')
""",
)
@tools.migrate(use_env=True, uid=SUPERUSER_ID)
def migrate(env, installed_version):
set_signed_status_vouchers(env)
......@@ -268,6 +268,11 @@ class AccountInvoice(models.Model):
usocfdi = self.env.ref('l10n_mx.cfdi_use_G02')
values['cfdi_use'] = usocfdi.id
values['cfdi_relation_type'] = self._context.get('cfdi_relation_type')
payment_type = self.env.ref('l10n_mx.pay_method_condonacion')
values['payment_type_ids'] = [(4, payment_type.id, None)]
payment_method = self.env.ref('l10n_mx.cfdi_payment_method_1')
values['payment_method_id'] = payment_method.id
return values
@signals.invoice_validate.connect
......
# -*- coding: utf-8 -*-
from openerp import api, models
from openerp import api, fields, models
from openerp.tools import float_round
......@@ -11,13 +11,60 @@ class AccountVoucher(models.Model):
'base.cfdi',
]
state = fields.Selection(
[
('draft', 'Draft'),
('cancel', 'Cancelled'),
('proforma', 'Pro-forma'),
('posted', 'Posted'),
('signed', 'Signed'),
],
)
@api.multi
def sign_voucher(self):
"""Create CFDI for selected vouchers"""
# Only vouchers to sign are the receipts
receipts = self.filtered(lambda r: r.type == 'receipt')
# Get only receipts that doesn't have a CFDI yet and create it
receipts.filtered(lambda r: not r.cfdi_id.exists()).create_cfdi()
for receipt in receipts.filtered(lambda r: not r.cfdi_id.exists()):
receipt.create_cfdi()
receipt.state = 'signed'
@api.multi
def cancel_voucher(self):
"""Cancel CFDI for selected vouchers"""
res = super(AccountVoucher, self).cancel_voucher()
self.cancel_cfdi()
return res
@api.multi
def _cancel_voucher(self):
"""General steps needed for cancel a voucher"""
self.ensure_one()
# Before cancel original voucher set relation to current related CFDI
self.write({
'cfdi_relation_type': self.env.ref('l10n_mx.cfdi_relation_type_04').id,
'related_cfdi_ids': [(6, None, [self.cfdi_id.id])],
})
# We also remove relation for attachments to avoid confusing situations
self.cfdi_id.file_xml_sign.res_id = None
self.cfdi_id.file_pdf.res_id = None
self.cancel_voucher()
@api.multi
def substitute_voucher(self):
"""Create new voucher for substitute this one"""
self._cancel_voucher()
# After cancel voucher we must re open it
self.action_cancel_draft()
@api.multi
def replace_cfdi(self):
"""Cancel voucher cfdi by replacing with 1 MXN voucher"""
self._cancel_voucher()
# Create a new cfdi to replace the one we cancelled
self.create_cfdi()
@api.multi
def currency_rate(self):
......@@ -103,10 +150,12 @@ class AccountVoucher(models.Model):
payments = invoice.mapped('payment_ids') & self.move_ids
for payment in payments:
# If amount_currency exists it means we are dealing with a multi
# If currency_id exists it means we are dealing with a multi
# currency payment, and thus we need to sum amount_currency to
# amount_paid instead of normal debit - credit
if payment.amount_currency:
# TODO: Relay on currency_id could result in wrong results when
# transactions done in three different currencies or more
if payment.currency_id:
amount_paid += payment.amount_currency * -1
else:
amount_paid += (payment.debit - payment.credit) * -1
......
......@@ -30,11 +30,12 @@ class EmailTemplate(models.Model):
ir_model_data = self.pool.get('ir.model.data')
reference_ids = []
states = ['printable', 'sent_customer', 'done']
states = ['done']
data = {
'account': 'email_template_edi_invoice',
'portal_sale': 'email_template_edi_invoice',
'l10n_mx_ir_attachment_facturae': 'email_template_template_facturae_mx', # noqa
'l10n_mx_ir_attachment_facturae': 'email_template_template_facturae_mx',
'l10n_mx_facturae': 'account_voucher_cfdi_email_template',
}
# Look for possible templates for invoice and override
......@@ -52,15 +53,16 @@ class EmailTemplate(models.Model):
if template_id in reference_ids:
for res_id in res_ids:
model = values[res_id]['model']
iatt_ids = att_obj.search(
cr, uid,
[
('res_id', '=', res_id),
('type_attachment', '=', 'account.invoice'),
('type_attachment', '=', model),
],
context=context,
)
for iattach in att_obj.browse(cr, uid, iatt_ids, context=context): # noqa
for iattach in att_obj.browse(cr, uid, iatt_ids, context=context):
attachments = []
if iattach.state in states:
# Attach XML file to mesage
......
No preview for this file type
# -*- coding: utf-8 -*-
from openerp.report import report_sxw
class Parser(report_sxw.rml_parse):
"""Parser para generar etiquetas con codigo qr"""
def __init__(self, cr, uid, name, context):
super(self.__class__, self).__init__(cr, uid, name, context)
self.localcontext.update({'datosqr': self._datosqr})
def _datosqr(self, o):
"""Genera el string con info para la elaboración del codigo qr"""
def xstr(s):
if s:
return str(s)
return str('N/A')
msg = 'https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx'
if o.cfdi_id.sello:
msg = msg + '?id=' + xstr(o.cfdi_id.uuid)
msg = msg + '&re=' + xstr(o.company_id.partner_id.vat_split)
msg = msg + '&rr=' + xstr(o.partner_id.vat_split)
msg = msg + '&tt=' + xstr(str(o.amount))
msg = msg + '&fe=' + xstr(o.cfdi_id.sello[-8: len(o.cfdi_id.sello)])
return msg
......@@ -5,7 +5,6 @@
<record id="report_templates_aeroo_account_voucher_cfdi_33" model="report.templates.aeroo">
<field name="name">Account Invoice XML CFDI 3.3</field>
<field name="model">account.voucher</field>
<field name="report_name">account.voucher.cfdi.33</field>
<field name="report_rml">l10n_mx_facturae/templates/account_voucher_33.txt</field>
</record>
<record id="ir_actions_report_xml_account_voucher_cfdi_33" model="ir.actions.report.xml">
......@@ -20,17 +19,14 @@
eval="[(6, 0, [report_templates_aeroo_account_voucher_cfdi_33])]" />
<field name="parser_state">default</field>
</record>
</data>
<data noupdate="1">
<!-- PDF invoice report definition -->
<record id="report_templates_aeroo_account_voucher_cfdi_33" model="report.templates.aeroo">
<record id="report_templates_aeroo_account_voucher_pdf_cfdi_33" model="report.templates.aeroo">
<field name="name">Default Voucher PDF</field>
<field name="model">account.voucher</field>
<field name="report_name">account.voucher.cfdi.33.pdf</field>
<field name="report_rml">l10n_mx_facturae/report/account_voucher.odt</field>
</record>
<record id="ir_actions_report_xml_account_voucher_cfdi_33" model="ir.actions.report.xml">
<record id="ir_actions_report_pdf_account_voucher_cfdi_33" model="ir.actions.report.xml">
<field name="name">Account Voucher CFDI PDF</field>
<field name="type">ir.actions.report.xml</field>
<field name="model">account.voucher</field>
......@@ -39,7 +35,8 @@
<field name="in_format">oo-odt</field>
<field name="out_format" ref="report_aeroo.report_mimetypes_pdf_odt" />
<field name="aeroo_templates_ids" eval="[(6, 0, [report_templates_aeroo_account_voucher_cfdi_33])]" />
<field name="tml_source">file</field>
</record>
<field name="parser_loc">l10n_mx_facturae/report/account_voucher.py</field>
<field name="parser_state">loc</field>
</record>
</data>
</openerp>
......@@ -19,6 +19,13 @@
Total="0"
TipoDeComprobante="P"
LugarExpedicion="${ o.company_id.zip }" >
{% if o.related_cfdi_ids %}
<cfdi:CfdiRelacionados TipoRelacion="${ o.cfdi_relation_type.code }">
{% for cfdi in o.related_cfdi_ids %}
<cfdi:CfdiRelacionado UUID="${ cfdi.uuid }"/>
{% end %}
</cfdi:CfdiRelacionados>
{% end %}
<cfdi:Emisor
{% choose o.company_id.partner_id.vat_split %}
{% when False %}${ validationerror(_('Missing VAT number for company')) }{% end %}
......@@ -27,16 +34,22 @@
Nombre="${ html_escape(o.company_id.name) }"
RegimenFiscal="$o.company_id.account_position_id.code"/>
<cfdi:Receptor
{% choose o.partner_id.vat_split %}
{% when False %}${ validationerror(_('Missing VAT number for receiver')) }{% end %}
{% otherwise %}Rfc="${ html_escape(o.partner_id.vat_split) }"{% end %}
{% end %}
{% if o.partner_id.vat_split not in ('XAXX010101000', 'XEXX010101000') %}
Nombre="${ html_escape(o.partner_id.name) }"
{% end %}
{% if o.partner_id.country_id and o.partner_id.country_id.code != 'MX' %}
ResidenciaFiscal="$o.partner_id.country_id.code3"
NumRegIdTrib="${ html_escape(o.partner_id.vat) }"
{% choose o.partner_id.country_id and o.partner_id.country_id.code_alpha3 %}
{% when 'MEX' %}
{% choose o.partner_id.vat_split %}
{% when '' %}${ validationerror(_('Missing VAT number for receiver')) }{% end %}
{% otherwise %}Rfc="${ html_escape(o.partner_id.vat_split) }"{% end %}
{% end %}
{% end %}
{% otherwise %}
Rfc="XEXX010101000"
ResidenciaFiscal="$o.partner_id.country_id.code_alpha3"
{% choose o.partner_id.vat_split %}
{% when '' %}${ validationerror(_('Missing Tax Identification Number for receiver')) }{% end %}
{% otherwise %}NumRegIdTrib="${ html_escape(o.partner_id.vat_split) }"{% end %}
{% end %}
{% end %}
{% end %}
UsoCFDI="P01" />
<cfdi:Conceptos>
......@@ -51,72 +64,79 @@
<cfdi:Complemento>
<pago10:Pagos Version="1.0">
<pago10:Pago
FechaPago="${ format_date(o.date, '%Y-%m-%dT%H:%M:%S') }"
FechaPago="${ format_date(o.date, '%Y-%m-%dT12:%M:%S') }"
{% choose o.payment_type_id.code %}
{% when False %}${ validationerror(_('Missing payment method for voucher')) }{% end %}
{% when '99' %}${ validationerror(_('Payment method must be different than 99.')) }{% end %}
{% otherwise %}FormaDePagoP="${ o.payment_type_id.code }"{% end %}
{% end %}
MonedaP="${ o.currency_id.name }"
{% if o.currency_id.name != 'MXN' %}
TipoCambioP="${ o.currency_rate() }"
{% end %}
Monto="${ '{0:.2f}'.format(o.currency_id.cfdi_round(o.amount)) }"
NumOperacion="${ o.reference or o.number }"
{% if o.partner_bank_id and o.partner_bank_id.is_valid_for_payment_form(o.payment_type_id.regex) %}
CtaOrdenante="$o.partner_bank_id.acc_number"
{% if o.partner_bank_id.bank.exists() %}
{% choose o.partner_bank_id.bank.full_name %}
{% when False %}{% end %}
{% otherwise %}NomBancoOrdExt="$o.partner_bank_id.bank.full_name"{% end %}
{% end %}
{% choose o.partner_bank_id.bank.vat_number %}
{% when False %}{% end %}
{% otherwise %}RfcEmisorCtaOrd="$o.partner_bank_id.bank.vat_number"{% end %}
{% end %}
{% choose o.state %}
{% when 'cancel' %}
MonedaP="MXN"
Monto="1.00"
>
{% end %}
{% end %}
{% if o.payment_type_id.code in ["02", "03", "04", "05", "28" "29"]%}
{% choose o.journal_id.res_partner_bank_id.acc_number %}
{% when None %}{% end %}
{% when False %}{% end %}
{% otherwise %}
CtaBeneficiario="$o.journal_id.res_partner_bank_id.acc_number"
{% if o.journal_id.res_partner_bank_id.bank.vat_number %}
RfcEmisorCtaBen="$o.journal_id.res_partner_bank_id.bank.vat_number"
{% otherwise %}
MonedaP="${ o.currency_id.name }"
{% if o.currency_id.name != 'MXN' %}
TipoCambioP="${ o.currency_rate() }"
{% end %}
Monto="${ '{0:.2f}'.format(o.currency_id.cfdi_round(o.amount)) }"
NumOperacion="${ o.reference or o.number }"
{% if o.partner_bank_id and o.partner_bank_id.is_valid_for_payment_form(o.payment_type_id.regex) %}
CtaOrdenante="$o.partner_bank_id.acc_number"
{% if o.partner_bank_id.bank.exists() %}
{% choose o.partner_bank_id.bank.full_name %}
{% when False %}{% end %}
{% otherwise %}NomBancoOrdExt="$o.partner_bank_id.bank.full_name"{% end %}
{% end %}
{% choose o.partner_bank_id.bank.vat_number %}
{% when False %}{% end %}
{% otherwise %}RfcEmisorCtaOrd="$o.partner_bank_id.bank.vat_number"{% end %}
{% end %}
{% end %}
{% end %}
{% end %}
{% end %}
>
{% for invoice in o.doctos_relacionados %}
<pago10:DoctoRelacionado
{% if invoice.journal_id.sequence_id.prefix %}
Serie="$invoice.serie"
{% end %}
Folio="$invoice.folio"
IdDocumento="${ invoice.cfdi_folio_fiscal }"
MonedaDR="${ invoice.currency_id.name }"
{% if invoice.currency_id != o.currency_id %}
{% choose invoice.currency_id.name %}
{% when 'MXN' %}TipoCambioDR="1"{% end %}
{% otherwise %}TipoCambioDR="${ o.tipocambiodr(invoice) }"{% end %}
{% if o.payment_type_id.code in ["02", "03", "04", "05", "28" "29"]%}
{% choose o.journal_id.res_partner_bank_id.acc_number %}
{% when None %}{% end %}
{% when False %}{% end %}
{% otherwise %}
CtaBeneficiario="$o.journal_id.res_partner_bank_id.acc_number"
{% if o.journal_id.res_partner_bank_id.bank.vat_number %}
RfcEmisorCtaBen="$o.journal_id.res_partner_bank_id.bank.vat_number"
{% end %}
{% end %}
{% end %}
{% end %}
{% end %}
{% choose invoice.payment_method_id.code %}
{% when False %}MetodoDePagoDR="PUE"{% end %}
{% otherwise %}
MetodoDePagoDR="$invoice.payment_method_id.code"
{% if invoice.payment_method_id.code == 'PPD' %}
NumParcialidad="${ o.numparcialidad(invoice) }"
ImpSaldoAnt="${ '{0:.2f}'.format(o.impsaldoant(invoice)) }"
ImpSaldoInsoluto="${ '{0:.2f}'.format(o.impsaldoant(invoice) - o.imppagado(invoice)) }"
>
{% for invoice in o.doctos_relacionados %}
<pago10:DoctoRelacionado
{% if invoice.journal_id.sequence_id.prefix %}
Serie="$invoice.serie"
{% end %}
Folio="$invoice.folio"
IdDocumento="${ invoice.cfdi_folio_fiscal }"
MonedaDR="${ invoice.currency_id.name }"
{% if invoice.currency_id != o.currency_id %}
{% choose invoice.currency_id.name %}
{% when 'MXN' %}TipoCambioDR="1"{% end %}
{% otherwise %}TipoCambioDR="${ o.tipocambiodr(invoice) }"{% end %}
{% end %}
{% end %}
{% choose invoice.payment_method_id.code %}
{% when False %}MetodoDePagoDR="PUE"{% end %}
{% otherwise %}
MetodoDePagoDR="$invoice.payment_method_id.code"
{% if invoice.payment_method_id.code == 'PPD' %}
NumParcialidad="${ o.numparcialidad(invoice) }"
ImpSaldoAnt="${ '{0:.2f}'.format(o.impsaldoant(invoice)) }"
ImpSaldoInsoluto="${ '{0:.2f}'.format(o.impsaldoant(invoice) - o.imppagado(invoice)) }"
{% end %}
{% end %}
{% end %}
ImpPagado="${ '{0:.2f}'.format(o.imppagado(invoice)) }" />
{% end %}
{% end %}
{% if invoice.currency_id != o.currency_id or len(o.doctos_relacionados) > 1 %}
ImpPagado="${ '{0:.2f}'.format(o.imppagado(invoice)) }"
{% end %} />
{% end %}
</pago10:Pago>
</pago10:Pagos>
......
......@@ -19,6 +19,32 @@ Característica: Generación de archivos XML para la emisión de recibos de pago
| País | México |
Y que el usuario Facturas y Pagos está logeado
Escenario: Recibo de pago con monto mayor al de la factura
Dado una Factura en MXN por los siguientes conceptos
| Concepto | Precio Unitario | Cantidad | Impuesto |
| ProductoA | 100.0 | 1.0 | IVA 16% |
Y la Factura está en estado Abierto
Y un pago por 116.01 MXN
Y selecciono conciliar saldo del pago
Cuando genero el Recibo electrónico de pagos
Entonces deben existir 1 nodos DoctoRelacionado
Y el ImpSaldoAnt para el nodo 1 debe ser 116.00
Y el ImportePagado debe ser 116.00
Y el ImpoSaldoInsoluto debe ser 0.00
Escenario: Recibo de pago con monto menor al de la factura
Dado una Factura en MXN por los siguientes conceptos
| Concepto | Precio Unitario | Cantidad | Impuesto |
| ProductoA | 100.0 | 1.0 | IVA 16% |
Y la Factura está en estado Abierto
Y un pago por 115.99 MXN
Y selecciono conciliar saldo del pago
Cuando genero el Recibo electrónico de pagos
Entonces deben existir 1 nodos DoctoRelacionado
Y el ImpSaldoAnt para el nodo 1 debe ser 116.00
Y el ImportePagado debe ser 116.00
Y el ImpoSaldoInsoluto debe ser 0.01
@Multimoneda
Escenario: Emisión de recibo de pagos en moneda extranjera
Dado una Factura en USD por los siguientes conceptos
......
......@@ -26,7 +26,9 @@
<field name="inherit_id" ref="account_voucher.view_vendor_receipt_form"/>
<field name="arch" type="xml">
<button name="proforma_voucher" position="after">
<button name="sign_voucher" type="object" string="Sign" class="oe_highlight" attrs="{'invisible':['|',('state','!=','posted'),('cfdi_state','!=',False)]}"/>
<button name="sign_voucher" type="object" string="Sign" class="oe_highlight" states="posted"/>
<button name="substitute_voucher" type="object" string="Replace" states="signed"/>
<button name="replace_cfdi" type="object" string="Cancel" states="signed" confirm="Are you sure to cancel this voucher?"/>
</button>
<xpath expr="//sheet/h1" position="after">
<h4 attrs="{'invisible': [('number','=',False)]}" collspan="2">
......@@ -34,6 +36,11 @@
<field name="cfdi_state" invisible="1"/>
</h4>
</xpath>
<!-- Hide cancel to draft button when voucher have a related CFDI -->
<xpath expr="//button[@name='action_cancel_draft']" position="attributes">
<attribute name="states"></attribute>
<attribute name="attrs">{'invisible': ['|', ('cfdi_state', '!=', False), ('state', '!=', 'cancel')]}</attribute>
</xpath>
</field>
</record>
......@@ -46,9 +53,7 @@
<field name="cfdi_id" string="UUID" />
</field>
<filter string="Posted" position="after">
<separator/>
<filter string="Unsigned" domain="[('cfdi_id','=',False)]" help="Not Signed Vouchers"/>
<filter string="Signed" domain="[('cfdi_id','!=',False)]" help="Signed Vouchers"/>
<filter string="Signed" domain="[('state', '=', 'signed')]" help="Signed Vouchers"/>
</filter>
</field>
</record>
......