From 97bac4a2d7dbf00e0f360d9f5b4c4ac91458871d Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Tue, 25 Sep 2018 17:24:24 -0500
Subject: [PATCH 01/11] docs(test): historia de usuario de la cancelacion con
 aprobacion

#24
---
 .../features/cancelacion_cfdi_33.feature      | 37 +++++++++++++++++++
 1 file changed, 37 insertions(+)
 create mode 100644 l10n_mx_facturae/tests/features/cancelacion_cfdi_33.feature

diff --git a/l10n_mx_facturae/tests/features/cancelacion_cfdi_33.feature b/l10n_mx_facturae/tests/features/cancelacion_cfdi_33.feature
new file mode 100644
index 0000000000..0007bec285
--- /dev/null
+++ b/l10n_mx_facturae/tests/features/cancelacion_cfdi_33.feature
@@ -0,0 +1,37 @@
+Feature: Cancelar CFDI's 3.3 que requiere aceptacion de cancelación
+    Como contador
+    A fin de cumplir con las reglas de la Resolucion Miscelanea Fiscal para 2017
+    Quiero cancelar cfdi's
+    Una factura requiere aceptación de cancelación cuando su monto excede los
+    $5000.00, o cuando su emisión tiene mas de 72 horas, segun la regla 2.7.1.39
+    de la resolución Miscelánea Fiscal para 2017
+
+Scenario: solicitar cancelacion de Factura abierta con monto mayor a $5000.00
+    Given factura en estado abierto con un monto de $5500.00 
+    When cancelo la factura
+    Then El estado de la Factura es 'Por cancelar'
+    And se notifica que la factura esta pendiente de cancelar
+
+Scenario: solicitar cancelacion de factura con mas de 72 horas abierta
+    Given una factura con mas de 72 horas abierta
+    When cancelo la factura
+    Then el estado de la factura es 'Por cancelar'
+    And se notifica que la factura esta pendiente de cancelar
+
+Scenario: contribuyente aprueba cancelacion de la factura
+    Given un factura en estado 'Por cancelar'
+    When el contribuyente aprueba la cancelacion
+    Then se cancela la factura
+    And se notifica que la factura se cancelo
+
+Scenario: contribuyente rechaza la cancelación de la factura
+    Given una factura en estado 'Por cancelar'
+    When el contribuyente rechaza la cancelación
+    Then el estado de la factura es 'abierta'
+    And se le notifica al usuario que la cancelacion fue rechazada
+
+Scenario: se aprueba cancelacion de la factura por plazo vencido
+    Given una factura en estado 'Por cancelar'
+    When se aprueba la cancelacion por plazo vencido
+    Then se cancela la factura
+    And se notifica que la factura se cancelo 
\ No newline at end of file
-- 
GitLab


From 871c26179118522a865e03092e89239d0abf2b67 Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Thu, 4 Oct 2018 13:45:00 -0500
Subject: [PATCH 02/11] refactor(account.invoice): se manda a llamar la funcion
 que verifica si se puede cancelar

---
 l10n_mx_facturae/models/account_invoice.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index 71c7a2a47c..63525db77c 100644
--- a/l10n_mx_facturae/models/account_invoice.py
+++ b/l10n_mx_facturae/models/account_invoice.py
@@ -300,17 +300,17 @@ class AccountInvoice(models.Model):
 
     @api.multi
     def action_cancel(self,):
-        res = super(AccountInvoice, self).action_cancel()
         for account_invoice in self:
             # Maybe a third test could review state, but since
             # button cancel only is displayed in open state, we decided to not
             # used third test
+            account_invoice.check_if_can_cancel()
             if (
                     account_invoice.journal_id.sign_sat and
                     account_invoice.cfdi_folio_fiscal
             ):
                 account_invoice.cfdi_id.action_cancel()
-        return res
+                super(AccountInvoice, self).action_cancel()
 
     @staticmethod
     def _sanitize(text):
-- 
GitLab


From 55fa2d11aafe505abe19f7b7f7c1fdbc05ce1b5b Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Thu, 18 Oct 2018 13:10:11 -0500
Subject: [PATCH 03/11] perf(account.invoice): integracion con base_cfdi_mixin

se usa el modelo base_cfdi_mixin para tratar lo relacionado con los CFDI
se modifica la vista, para la integracion con base_cfdi_mixin
---
 l10n_mx_facturae/models/account_invoice.py | 64 +++++++---------------
 l10n_mx_facturae/views/account_invoice.xml |  2 +-
 2 files changed, 20 insertions(+), 46 deletions(-)

diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index 63525db77c..6f214e9f80 100644
--- a/l10n_mx_facturae/models/account_invoice.py
+++ b/l10n_mx_facturae/models/account_invoice.py
@@ -23,7 +23,11 @@ _logger = logging.getLogger(__name__)
 
 
 class AccountInvoice(models.Model):
-    _inherit = 'account.invoice'
+    _name = 'account.invoice'
+    _inherit = [
+        'account.invoice',
+        'base.cfdi',
+    ]
 
     @api.model
     def _default_address_issued_id(self):
@@ -179,13 +183,6 @@ class AccountInvoice(models.Model):
         'cfdi.use', 'CFDI use',
         readonly=True, states={'draft': [('readonly', False)]},
     )
-    cfdi_id = fields.Many2one(
-        'ir.attachment.facturae.mx', 'CFDI', compute='_compute_cfdi_id',
-    )
-    cfdi_folio_fiscal = fields.Char(
-        'CFD-I Folio Fiscal', compute='_compute_cfdi_folio_fiscal',
-        help='Folio used in the electronic invoice',
-    )
     cfdi_adenda_id = fields.Many2one(
         'cfdi.adenda', 'Addendum',
         help='Select addendum node to use on invoice.',
@@ -212,25 +209,6 @@ class AccountInvoice(models.Model):
             )
             self.datetime = invoice_datetime
 
-    @api.one
-    def _compute_cfdi_id(self):
-        ir_attachment_mx_obj = self.env['ir.attachment.facturae.mx']
-        related_attachment = ir_attachment_mx_obj.search(
-            [
-                ('res_id', '=', self.id),
-                ('type_attachment', '=', 'account.invoice'),
-                ('company_id', '=', self.company_id.id),
-                ('state', 'in', ['signed', 'done']),
-            ],
-        )
-        if related_attachment:
-            self.cfdi_id = related_attachment
-
-    @api.one
-    @api.depends('state')
-    def _compute_cfdi_folio_fiscal(self):
-        self.cfdi_folio_fiscal = self.cfdi_id.uuid
-
     def onchange_partner_id(
             self, cr, uid, ids, type, partner_id,
             date_invoice=False, payment_term=False, partner_bank_id=False,
@@ -279,27 +257,17 @@ class AccountInvoice(models.Model):
     @signals.invoice_validate.connect
     def sign_invoice_sat(self, cr, uid, ids, context=None):
         context = dict(context or {})
-        ir_attach_obj = self.pool.get('ir.attachment.facturae.mx')
         for account_invoice in self.browse(cr, uid, ids, context=context):
             if account_invoice.journal_id.sign_sat:
                 # Create new CFDI object for this invoice
-                cfdi_id = ir_attach_obj.create(
-                    cr, uid,
-                    {
-                        'name': account_invoice.fname_invoice,
-                        'res_id': account_invoice.id,
-                        'type_attachment': 'account.invoice',
-                        'company_id': account_invoice.company_id.id,
-                    },
-                    context=context,
-                )
-                cfdi = ir_attach_obj.browse(
-                    cr, uid, cfdi_id, context=context,
-                )
-                cfdi.action_validate()
+                account_invoice.create_cfdi()
 
     @api.multi
-    def action_cancel(self,):
+    def action_cancel(self):
+        '''
+        Extend `AccountInvoice.action_cancel()`; Cancels the CFDI related to the
+        invoice
+         '''
         for account_invoice in self:
             # Maybe a third test could review state, but since
             # button cancel only is displayed in open state, we decided to not
@@ -309,8 +277,14 @@ class AccountInvoice(models.Model):
                     account_invoice.journal_id.sign_sat and
                     account_invoice.cfdi_folio_fiscal
             ):
-                account_invoice.cfdi_id.action_cancel()
-                super(AccountInvoice, self).action_cancel()
+                cancelacion = account_invoice.cancel_cfdi()[0]
+                if cancelacion:
+                    super(AccountInvoice, self).action_cancel()
+                    account_invoice.unlink_cfdi()
+                    return
+                account_invoice.write({
+                    'state':account_invoice.cfdi_state,
+                    })
 
     @staticmethod
     def _sanitize(text):
diff --git a/l10n_mx_facturae/views/account_invoice.xml b/l10n_mx_facturae/views/account_invoice.xml
index f3fa183d2d..45f371a548 100644
--- a/l10n_mx_facturae/views/account_invoice.xml
+++ b/l10n_mx_facturae/views/account_invoice.xml
@@ -13,7 +13,7 @@
         <field name="arch" type="xml">
             <xpath expr="//sheet[@string='Invoice']/h1" position="after">
                 <h4 collspan="2">
-                    <field string="Fiscal Number" name="cfdi_folio_fiscal"
+                    <field string="Fiscal Number" name="cfdi_id"
                            placeholder="Fiscal Number" readonly="1"/>
                 </h4>
             </xpath>
-- 
GitLab


From 5d563d7b97bff3f0fe53bda4bb65df3f690da9a3 Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Fri, 19 Oct 2018 10:24:53 -0500
Subject: [PATCH 04/11] perf(account.invoice): Integracion con base_cfdi_mixin
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Manda a llamar a la función `unlink_cfdi()` para que explicitamente se borre el cfdi relacionado
---
 l10n_mx_facturae/models/account_voucher.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/l10n_mx_facturae/models/account_voucher.py b/l10n_mx_facturae/models/account_voucher.py
index 4849c4d5b8..7e54dff529 100644
--- a/l10n_mx_facturae/models/account_voucher.py
+++ b/l10n_mx_facturae/models/account_voucher.py
@@ -36,6 +36,7 @@ class AccountVoucher(models.Model):
         """Cancel CFDI for selected vouchers"""
         res = super(AccountVoucher, self).cancel_voucher()
         self.cancel_cfdi()
+        self.unlink_cfdi()
         return res
 
     @api.multi
-- 
GitLab


From 570c87019c828c95d60ab81296e784a2516aecdd Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Mon, 29 Oct 2018 17:14:41 -0600
Subject: [PATCH 05/11] feat(account.invoice): se agrega el estado waiting

se extiende el campo state y se agrega ('waiting', 'To cancel')
---
 l10n_mx_facturae/models/account_invoice.py | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index 6f214e9f80..d35a521270 100644
--- a/l10n_mx_facturae/models/account_invoice.py
+++ b/l10n_mx_facturae/models/account_invoice.py
@@ -195,6 +195,8 @@ class AccountInvoice(models.Model):
         'cfdi.relation.type', 'CFDI Relation type',
     )
 
+    state = fields.Selection(selection_add=[('waiting', _('To cancel'))])
+
     @api.one
     @api.depends('state')
     def _compute_datetime(self):
@@ -214,7 +216,7 @@ class AccountInvoice(models.Model):
             date_invoice=False, payment_term=False, partner_bank_id=False,
             company_id=False, context=None,
     ):
-        # pylint: disable=too-many-arguments
+        # pylint: disable=too-many-arguments, redefined-builtin
         """Copy fields cfdi_use, payment_method_id and cfdi_adenda_id
         from selected partner
         """
@@ -278,13 +280,13 @@ class AccountInvoice(models.Model):
                     account_invoice.cfdi_folio_fiscal
             ):
                 cancelacion = account_invoice.cancel_cfdi()[0]
+                account_invoice.write({
+                    'state': account_invoice.cfdi_state,
+                })
                 if cancelacion:
-                    super(AccountInvoice, self).action_cancel()
+                    res = super(AccountInvoice, self).action_cancel()
                     account_invoice.unlink_cfdi()
-                    return
-                account_invoice.write({
-                    'state':account_invoice.cfdi_state,
-                    })
+                    return res
 
     @staticmethod
     def _sanitize(text):
-- 
GitLab


From f7542b478f65c39833fbefd0bee84f11bb53128e Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Wed, 31 Oct 2018 12:10:28 -0600
Subject: [PATCH 06/11] feat(migrations): se agrego post-migration en la
 version 2.8.0

---
 .../migrations/2.8.0/post-migration.py        | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100644 l10n_mx_facturae/migrations/2.8.0/post-migration.py

diff --git a/l10n_mx_facturae/migrations/2.8.0/post-migration.py b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
new file mode 100644
index 0000000000..694c4c0e5f
--- /dev/null
+++ b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+from openupgradelib import openupgrade as tools
+
+from openerp import SUPERUSER_ID
+
+
+def compute_cfdi_id(env):
+    ir_attachment_mx_obj = env['ir.attachment.facturae.mx']
+    invoices = env['account.invoice'].search(
+        [
+            ('state', 'in', ['signed', 'done'])
+        ]
+    )
+    for invoice in invoices:
+        related_attachment = ir_attachment_mx_obj.search(
+            [
+                ('res_id', '=', invoice.id),
+                ('type_attachment', '=', 'account.invoice'),
+                ('company_id', '=', invoice.company_id.id),
+                ('state', 'in', ['signed', 'done']),
+            ],
+        )
+        if related_attachment:
+            invoice.cfdi_id = related_attachment
+
+
+@tools.migrate(use_env=True, uid=SUPERUSER_ID)
+def migrate(env, installed_version):
+    compute_cfdi_id(env)
-- 
GitLab


From a691fd11ef0a78978d2a2872b68010f4a0ee8f9f Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Wed, 31 Oct 2018 19:18:36 -0600
Subject: [PATCH 07/11] feat(l10n_mx_facturae): se agrega cron job que verifica
 las facturas en esperea de cancelacion

---
 l10n_mx_facturae/__openerp__.py                   |  1 +
 l10n_mx_facturae/data/ir_cron.xml                 | 15 +++++++++++++++
 .../migrations/2.8.0/post-migration.py            | 15 ++++++++++++++-
 l10n_mx_facturae/models/account_invoice.py        | 12 ++++++++++++
 4 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 l10n_mx_facturae/data/ir_cron.xml

diff --git a/l10n_mx_facturae/__openerp__.py b/l10n_mx_facturae/__openerp__.py
index d007d74f9a..648897c065 100644
--- a/l10n_mx_facturae/__openerp__.py
+++ b/l10n_mx_facturae/__openerp__.py
@@ -26,6 +26,7 @@
         'wizard/account_invoice_refund.xml',
         'report/account_invoice.xml',
         'report/account_voucher.xml',
+        'data/ir_cron.xml',
         'data/email_template.xml',
         'data/ir_attachment_facturae_config.xml',
     ],
diff --git a/l10n_mx_facturae/data/ir_cron.xml b/l10n_mx_facturae/data/ir_cron.xml
new file mode 100644
index 0000000000..c8318da8c0
--- /dev/null
+++ b/l10n_mx_facturae/data/ir_cron.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<openerp>
+    <data noupdate="1">
+        <record model="ir.cron" id="ir_cron_invoices_pending_to_cancel">
+           <field name="name">Invoices pending to cancel</field>
+           <field name="interval_number">2</field>
+           <field name="interval_type">hours</field>
+           <field name="numbercall">-1</field>
+           <field name="model" eval="'account.invoice'"/>
+           <field name="function" eval="'cron_invoices_pending_to_cancel'"/>
+           <field name="args" eval="'(None,)'"/>
+           <field name="active" eval="False" />
+        </record>
+    </data>
+</openerp>
\ No newline at end of file
diff --git a/l10n_mx_facturae/migrations/2.8.0/post-migration.py b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
index 694c4c0e5f..dac311dcb6 100644
--- a/l10n_mx_facturae/migrations/2.8.0/post-migration.py
+++ b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
@@ -1,17 +1,25 @@
 # -*- coding: utf-8 -*-
 
+import logging
 from openupgradelib import openupgrade as tools
 
 from openerp import SUPERUSER_ID
 
 
+_logger = logging.getLogger(__name__)
+
+
 def compute_cfdi_id(env):
+    _logger.info("*****************START**********************")
+    _logger.info("***********COMPUTE_CFDI_ID**************")
+    _logger.info("*********************************************")
     ir_attachment_mx_obj = env['ir.attachment.facturae.mx']
     invoices = env['account.invoice'].search(
         [
-            ('state', 'in', ['signed', 'done'])
+            ('state', 'in', ['open', 'paid'])
         ]
     )
+    _logger.info("invoices to upgrade: " +str(len(invoices)))
     for invoice in invoices:
         related_attachment = ir_attachment_mx_obj.search(
             [
@@ -23,8 +31,13 @@ def compute_cfdi_id(env):
         )
         if related_attachment:
             invoice.cfdi_id = related_attachment
+    _logger.info("******************END**********************")
+    _logger.info("***********COMPUTE_CFDI_ID**************")
+    _logger.info("*********************************************")
 
 
 @tools.migrate(use_env=True, uid=SUPERUSER_ID)
 def migrate(env, installed_version):
+    _logger.info("INICIAMOS MIGRACION L10N_MX_FACTURAE")
     compute_cfdi_id(env)
+    _logger.info("FINALIZAMOS MIGRACION")
diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index d35a521270..516f3d58df 100644
--- a/l10n_mx_facturae/models/account_invoice.py
+++ b/l10n_mx_facturae/models/account_invoice.py
@@ -197,6 +197,18 @@ class AccountInvoice(models.Model):
 
     state = fields.Selection(selection_add=[('waiting', _('To cancel'))])
 
+    @api.multi
+    def cron_invoices_pending_to_cancel(self):
+        _logger.info('cron job')
+        # actionca_cancel()
+        invoices =self.env['account.invoice'].search(
+            [
+                ('state', 'in', ['waiting'])
+            ]
+        )
+        _logger.info(invoices)
+        for invoice in invoices:
+            invoice.action_cancel()
     @api.one
     @api.depends('state')
     def _compute_datetime(self):
-- 
GitLab


From 524924806a75f3002dc90c4c24a3a093c64cb7f1 Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Mon, 5 Nov 2018 16:22:29 -0600
Subject: [PATCH 08/11] fix(post-migration 2.8.0): se corrige la busqueda de
 facturas

los estados de las facturas que nos interesan son: `paid` y `open`
---
 .../migrations/2.8.0/post-migration.py        | 30 +++++++------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/l10n_mx_facturae/migrations/2.8.0/post-migration.py b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
index dac311dcb6..9cc5bb6935 100644
--- a/l10n_mx_facturae/migrations/2.8.0/post-migration.py
+++ b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import logging
+
 from openupgradelib import openupgrade as tools
 
 from openerp import SUPERUSER_ID
@@ -10,34 +11,23 @@ _logger = logging.getLogger(__name__)
 
 
 def compute_cfdi_id(env):
-    _logger.info("*****************START**********************")
-    _logger.info("***********COMPUTE_CFDI_ID**************")
-    _logger.info("*********************************************")
-    ir_attachment_mx_obj = env['ir.attachment.facturae.mx']
-    invoices = env['account.invoice'].search(
-        [
-            ('state', 'in', ['open', 'paid'])
-        ]
-    )
-    _logger.info("invoices to upgrade: " +str(len(invoices)))
+
+    ir_attachment_mx_obj = env["ir.attachment.facturae.mx"]
+    invoices = env["account.invoice"].search([("state", "in", ["open", "paid"])])
+    _logger.info("invoices to set cfdi_id: " + str(len(invoices)))
     for invoice in invoices:
         related_attachment = ir_attachment_mx_obj.search(
             [
-                ('res_id', '=', invoice.id),
-                ('type_attachment', '=', 'account.invoice'),
-                ('company_id', '=', invoice.company_id.id),
-                ('state', 'in', ['signed', 'done']),
-            ],
+                ("res_id", "=", invoice.id),
+                ("type_attachment", "=", "account.invoice"),
+                ("company_id", "=", invoice.company_id.id),
+                ("state", "in", ["signed", "done"]),
+            ]
         )
         if related_attachment:
             invoice.cfdi_id = related_attachment
-    _logger.info("******************END**********************")
-    _logger.info("***********COMPUTE_CFDI_ID**************")
-    _logger.info("*********************************************")
 
 
 @tools.migrate(use_env=True, uid=SUPERUSER_ID)
 def migrate(env, installed_version):
-    _logger.info("INICIAMOS MIGRACION L10N_MX_FACTURAE")
     compute_cfdi_id(env)
-    _logger.info("FINALIZAMOS MIGRACION")
-- 
GitLab


From 35f3369fb855d5ba5c90a409ed1c5b0ab1712726 Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Mon, 12 Nov 2018 10:48:40 -0600
Subject: [PATCH 09/11] =?UTF-8?q?feat(account.invoice):=20Se=20agrega=20fu?=
 =?UTF-8?q?nci=C3=B3n=20`undo=5Fwaiting=5Fstate()`?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Se usa para regresar el estado de la factura de `waiting` a `open`, cuando se niega la cancelación
de la factura por parte del contribuyente receptor
---
 l10n_mx_facturae/models/account_invoice.py | 25 +++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index 516f3d58df..bf6153841e 100644
--- a/l10n_mx_facturae/models/account_invoice.py
+++ b/l10n_mx_facturae/models/account_invoice.py
@@ -287,18 +287,33 @@ class AccountInvoice(models.Model):
             # button cancel only is displayed in open state, we decided to not
             # used third test
             account_invoice.check_if_can_cancel()
-            if (
+            res = None
+            if account_invoice.cfdi_folio_fiscal is False:
+                res = super(AccountInvoice, self).action_cancel()
+            elif (
                     account_invoice.journal_id.sign_sat and
                     account_invoice.cfdi_folio_fiscal
             ):
                 cancelacion = account_invoice.cancel_cfdi()[0]
-                account_invoice.write({
+                if cancelacion is None:
+                    account_invoice.write({
                     'state': account_invoice.cfdi_state,
-                })
-                if cancelacion:
+                    })
+                elif cancelacion is False:
+                    self.undo_waiting_state()
+                else:
                     res = super(AccountInvoice, self).action_cancel()
                     account_invoice.unlink_cfdi()
-                    return res
+            return res
+
+    @api.multi
+    def undo_waiting_state(self):
+        '''when cancel is negate, undo waiting state'''
+        self.ensure_one()
+        if self.state in ("waiting"):
+            self.write({
+                "state":"open"
+            })
 
     @staticmethod
     def _sanitize(text):
-- 
GitLab


From bb8d90d0e8c6bd2c207c7885743409942de42bca Mon Sep 17 00:00:00 2001
From: Cuauhtemoc Diaz Minor <cuauhtemoc.diaz@openpyme.mx>
Date: Mon, 12 Nov 2018 16:25:26 -0600
Subject: [PATCH 10/11] feat(account.invoice): cron task para las facturas
 pendientes de cancelar

se crea funcion `action_consult_cancellation_status()` que sirve para consultar el estatus de
cancelacion de las facturas pendientes por cancelar
---
 l10n_mx_facturae/models/account_invoice.py | 23 +++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index bf6153841e..9307d93dc3 100644
--- a/l10n_mx_facturae/models/account_invoice.py
+++ b/l10n_mx_facturae/models/account_invoice.py
@@ -197,18 +197,16 @@ class AccountInvoice(models.Model):
 
     state = fields.Selection(selection_add=[('waiting', _('To cancel'))])
 
-    @api.multi
+    @api.model
     def cron_invoices_pending_to_cancel(self):
-        _logger.info('cron job')
-        # actionca_cancel()
         invoices =self.env['account.invoice'].search(
             [
                 ('state', 'in', ['waiting'])
             ]
         )
-        _logger.info(invoices)
         for invoice in invoices:
-            invoice.action_cancel()
+            invoice.action_consult_cancellation_status()
+
     @api.one
     @api.depends('state')
     def _compute_datetime(self):
@@ -315,6 +313,21 @@ class AccountInvoice(models.Model):
                 "state":"open"
             })
 
+    @api.multi
+    def action_consult_cancellation_status(self):
+        """ """
+        for account_invoice in self:
+            res = None
+            status_cancelacion = account_invoice.consult_cfdi_cancellation_status()
+            if status_cancelacion is None:
+                pass
+            elif status_cancelacion is False:
+                self.undo_waiting_state()
+            else:
+                res = super(AccountInvoice, self).action_cancel()
+                account_invoice.unlink_cfdi()
+        return res
+
     @staticmethod
     def _sanitize(text):
         # Chars not allowed on CFDI
-- 
GitLab


From d3d2764a8ced6b7db868e2c3c8a684f817fee301 Mon Sep 17 00:00:00 2001
From: agb80 <atin81@gmail.com>
Date: Mon, 19 Nov 2018 17:23:41 -0600
Subject: [PATCH 11/11] style(flake): actualiza los estilos para cumplir con
 flake

---
 l10n_mx_facturae/data/ir_cron.xml                |  3 ++-
 .../migrations/2.8.0/post-migration.py           | 16 ++++++++--------
 l10n_mx_facturae/models/account_invoice.py       | 15 +++++++--------
 3 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/l10n_mx_facturae/data/ir_cron.xml b/l10n_mx_facturae/data/ir_cron.xml
index c8318da8c0..95322d884e 100644
--- a/l10n_mx_facturae/data/ir_cron.xml
+++ b/l10n_mx_facturae/data/ir_cron.xml
@@ -12,4 +12,5 @@
            <field name="active" eval="False" />
         </record>
     </data>
-</openerp>
\ No newline at end of file
+</openerp>
+
diff --git a/l10n_mx_facturae/migrations/2.8.0/post-migration.py b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
index 9cc5bb6935..b475eae4a3 100644
--- a/l10n_mx_facturae/migrations/2.8.0/post-migration.py
+++ b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
@@ -11,17 +11,17 @@ _logger = logging.getLogger(__name__)
 
 
 def compute_cfdi_id(env):
-
-    ir_attachment_mx_obj = env["ir.attachment.facturae.mx"]
-    invoices = env["account.invoice"].search([("state", "in", ["open", "paid"])])
-    _logger.info("invoices to set cfdi_id: " + str(len(invoices)))
+    """Update reference to `ir.attachment.facturae.mx` for invoices"""
+    ir_attachment_mx_obj = env['ir.attachment.facturae.mx']
+    invoices = env['account.invoice'].search([('state', 'in', ['open', 'paid'])])
+    _logger.info('Updating reference for cfdi on ' + str(len(invoices)) + ' invoices')
     for invoice in invoices:
         related_attachment = ir_attachment_mx_obj.search(
             [
-                ("res_id", "=", invoice.id),
-                ("type_attachment", "=", "account.invoice"),
-                ("company_id", "=", invoice.company_id.id),
-                ("state", "in", ["signed", "done"]),
+                ('res_id', '=', invoice.id),
+                ('type_attachment', '=', 'account.invoice'),
+                ('company_id', '=', invoice.company_id.id),
+                ('state', 'in', ['signed', 'done']),
             ]
         )
         if related_attachment:
diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index 9307d93dc3..962282e008 100644
--- a/l10n_mx_facturae/models/account_invoice.py
+++ b/l10n_mx_facturae/models/account_invoice.py
@@ -199,7 +199,7 @@ class AccountInvoice(models.Model):
 
     @api.model
     def cron_invoices_pending_to_cancel(self):
-        invoices =self.env['account.invoice'].search(
+        invoices = self.env['account.invoice'].search(
             [
                 ('state', 'in', ['waiting'])
             ]
@@ -294,9 +294,9 @@ class AccountInvoice(models.Model):
             ):
                 cancelacion = account_invoice.cancel_cfdi()[0]
                 if cancelacion is None:
-                    account_invoice.write({
-                    'state': account_invoice.cfdi_state,
-                    })
+                    account_invoice.write(
+                        {'state': account_invoice.cfdi_state}
+                    )
                 elif cancelacion is False:
                     self.undo_waiting_state()
                 else:
@@ -306,16 +306,15 @@ class AccountInvoice(models.Model):
 
     @api.multi
     def undo_waiting_state(self):
-        '''when cancel is negate, undo waiting state'''
+        """when cancel is negate, undo waiting state"""
         self.ensure_one()
-        if self.state in ("waiting"):
+        if self.state == 'waiting':
             self.write({
-                "state":"open"
+                'state': 'open'
             })
 
     @api.multi
     def action_consult_cancellation_status(self):
-        """ """
         for account_invoice in self:
             res = None
             status_cancelacion = account_invoice.consult_cfdi_cancellation_status()
-- 
GitLab