diff --git a/l10n_mx_facturae/__openerp__.py b/l10n_mx_facturae/__openerp__.py
index d007d74f9a4c632a43d98bcb3e9dfee0415a5eb4..648897c065809d7028805d9a197b43136d68aaad 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 0000000000000000000000000000000000000000..95322d884e17c7c2eba5343c5c3b3e454e39bd2f
--- /dev/null
+++ b/l10n_mx_facturae/data/ir_cron.xml
@@ -0,0 +1,16 @@
+<?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>
+
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 0000000000000000000000000000000000000000..b475eae4a37e5c1d01417628f41bc9be5f4ae9e4
--- /dev/null
+++ b/l10n_mx_facturae/migrations/2.8.0/post-migration.py
@@ -0,0 +1,33 @@
+# -*- 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):
+    """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']),
+            ]
+        )
+        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)
diff --git a/l10n_mx_facturae/models/account_invoice.py b/l10n_mx_facturae/models/account_invoice.py
index 71c7a2a47c95422796c87b66ddcd4b79a7049fab..962282e008bc14051bb345ace3ca4b85a44288fb 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.',
@@ -198,6 +195,18 @@ class AccountInvoice(models.Model):
         'cfdi.relation.type', 'CFDI Relation type',
     )
 
+    state = fields.Selection(selection_add=[('waiting', _('To cancel'))])
+
+    @api.model
+    def cron_invoices_pending_to_cancel(self):
+        invoices = self.env['account.invoice'].search(
+            [
+                ('state', 'in', ['waiting'])
+            ]
+        )
+        for invoice in invoices:
+            invoice.action_consult_cancellation_status()
+
     @api.one
     @api.depends('state')
     def _compute_datetime(self):
@@ -212,31 +221,12 @@ 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,
             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
         """
@@ -279,37 +269,62 @@ 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,):
-        res = super(AccountInvoice, self).action_cancel()
+    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
             # used third test
-            if (
+            account_invoice.check_if_can_cancel()
+            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
             ):
-                account_invoice.cfdi_id.action_cancel()
+                cancelacion = account_invoice.cancel_cfdi()[0]
+                if cancelacion is None:
+                    account_invoice.write(
+                        {'state': account_invoice.cfdi_state}
+                    )
+                elif cancelacion is False:
+                    self.undo_waiting_state()
+                else:
+                    res = super(AccountInvoice, self).action_cancel()
+                    account_invoice.unlink_cfdi()
+            return res
+
+    @api.multi
+    def undo_waiting_state(self):
+        """when cancel is negate, undo waiting state"""
+        self.ensure_one()
+        if self.state == 'waiting':
+            self.write({
+                '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
diff --git a/l10n_mx_facturae/models/account_voucher.py b/l10n_mx_facturae/models/account_voucher.py
index 4849c4d5b81c80686e55ee766a6b9fd56878f11c..7e54dff529ff010708000a235e64998fef30e050 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
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 0000000000000000000000000000000000000000..0007bec28591fcc349c20a21f62402efefb2acab
--- /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
diff --git a/l10n_mx_facturae/views/account_invoice.xml b/l10n_mx_facturae/views/account_invoice.xml
index f3fa183d2de956103070952792d148e455674dc2..45f371a5482bf21546f83afd525ab7d18e218bc4 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>