Beispiel #1
0
    def _l10n_mx_edi_post_cancel_process(self, cfdi_values, order_ids, attach):
        """Post process the results of the cancel service.
        :param cfdi_values: info of xml signed
        :type cfdi_values: dict
        :param order_ids: orders use to generate cfdi
        :type order_ids: pos.order
        :param attach: file attachment in invoice
        :type attach: ir.attachment
        """

        self.ensure_one()
        cancelled = cfdi_values.get('cancelled', '')
        code = cfdi_values.get('code', '')
        msg = cfdi_values.get('msg', '')
        filename = cfdi_values.get('filename', '')
        if cancelled:
            body_msg = _('The cancel service has been called with success '
                         'to %s') % filename
            order_ids.write({'xml_generated': False})
            attach.name = 'cancelled_%s' % '_'.join(filename.split('_')[-2:])
        else:
            body_msg = _(
                'The cancel service requested failed to %s') % filename
        post_msg = []
        if code:
            post_msg.extend([_('Code: ') + str(code)])
        if msg:
            post_msg.extend([_('Message: ') + msg])
        self.message_post(body=body_msg + create_list_html(post_msg),
                          subtype='account.mt_invoice_validated')
Beispiel #2
0
    def _l10n_mx_edi_create_cfdi(self):
        if not self.l10n_mx_edi_external_trade:
            return super(AccountInvoice, self)._l10n_mx_edi_create_cfdi()

        # Call the onchange to obtain the values of l10n_mx_edi_qty_umt
        # and l10n_mx_edi_price_unit_umt, this is necessary when the
        # invoice is created from the sales order or from the picking
        self.invoice_line_ids.onchange_quantity()
        self.invoice_line_ids._set_price_unit_umt()

        bad_line = self.invoice_line_ids.filtered(
            lambda l: not l.l10n_mx_edi_qty_umt or not l.
            l10n_mx_edi_umt_aduana_id or
            (l.l10n_mx_edi_umt_aduana_id.l10n_mx_edi_code_aduana != '99' and
             not l.l10n_mx_edi_tariff_fraction_id))
        if bad_line:
            line_name = bad_line.mapped('product_id.name')
            return {
                'error':
                _('Please verify that Qty UMT has a value in the line, '
                  'and that the product has set a value in Tariff Fraction and '
                  'in UMT Aduana.<br/><br/>This for the products:') +
                create_list_html(line_name)
            }
        return super(AccountInvoice, self)._l10n_mx_edi_create_cfdi()
Beispiel #3
0
    def _l10n_mx_edi_create_cfdi(self):
        """Creates and returns a dictionnary containing 'cfdi' if the cfdi is
        well created, 'error' otherwise."""
        if not self:
            return {}
        qweb = self.env['ir.qweb']
        invoice_obj = self.env['account.invoice']
        company_id = self.mapped('company_id')
        error_log = []
        pac_name = company_id.l10n_mx_edi_pac

        values = self._l10n_mx_edi_create_cfdi_values()

        # -Check certificate
        certificate_ids = company_id.l10n_mx_edi_certificate_ids
        certificate_id = certificate_ids.sudo().get_valid_certificate()
        if not certificate_id:
            error_log.append(_('No valid certificate found'))

        # -Check PAC
        if pac_name:
            pac_test_env = company_id.l10n_mx_edi_pac_test_env
            pac_password = company_id.l10n_mx_edi_pac_password
            if not pac_test_env and not pac_password:
                error_log.append(_('No PAC credentials specified.'))
        else:
            error_log.append(_('No PAC specified.'))

        if error_log:
            return {
                'error':
                _('Please check your configuration: ') +
                create_list_html(error_log)
            }

        values['certificate_number'] = certificate_id.serial_number
        values['certificate'] = certificate_id.sudo().get_data()[0]
        values['date'] = (certificate_id.sudo().get_mx_current_datetime().
                          strftime('%Y-%m-%dT%H:%M:%S'))

        cfdi = qweb.render(CFDI_TEMPLATE_33, values=values)
        attachment = self.env.ref('l10n_mx_edi.xsd_cached_cfdv33_xsd', False)
        xsd_datas = base64.b64decode(attachment.datas) if attachment else b''
        # -Compute cadena
        tree = objectify.fromstring(cfdi)
        cadena = invoice_obj.l10n_mx_edi_generate_cadena(
            CFDI_XSLT_CADENA, tree)
        tree.attrib['Sello'] = certificate_id.sudo().get_encrypted_cadena(
            cadena)

        # Check with xsd
        if xsd_datas:
            try:
                with BytesIO(xsd_datas) as xsd:
                    _check_with_xsd(tree, xsd)
            except (IOError, ValueError):
                _logger.info(
                    _('The xsd file to validate the XML structure '
                      'was not found'))
            except BaseException as e:
                return {
                    'error': (_('The cfdi generated is not valid') +
                              create_list_html(str(e).split('\\n')))
                }

        return {
            'cfdi':
            etree.tostring(tree,
                           pretty_print=True,
                           xml_declaration=True,
                           encoding='UTF-8')
        }
Beispiel #4
0
 def _l10n_mx_edi_post_sign_process(self, cfdi_values, order_ids):
     """Post process the results of the sign service.
     :param cfdi_values: info of xml signed
     :type cfdi_values: dict
     :param order_ids: orders use to generate cfdi
     :type order_ids: pos.order
     """
     self.ensure_one()
     post_msg = []
     attach = []
     invoice_obj = self.env['account.invoice']
     xml_signed = cfdi_values.get('cfdi', '')
     code = cfdi_values.get('code', '')
     msg = cfdi_values.get('error', '')
     filename = order_ids.get_file_name()
     if xml_signed:
         body_msg = _('The sign service has been called with '
                      'success to %s') % filename
         # attach cfdi
         ctx = self.env.context.copy()
         ctx.pop('default_type', False)
         attachment_id = self.l10n_mx_edi_retrieve_last_attachment(
             '%s.xml' % filename)
         attachment_id.write({
             'datas': xml_signed,
             'datas_fname': '%s.xml' % filename,
             'description': 'Mexican invoice',
         })
         attach.extend([attachment_id.id])
         # Generate and attach pdf
         report = self.env.ref('l10n_mx_edi_pos.l10n_mx_edi_report_session')
         xml = objectify.fromstring(base64.b64decode(xml_signed))
         data = {'cfdi': xml}
         # The generation of report does not work in test environment
         # because of this issue https://github.com/odoo/odoo/issues/18841
         if not config['test_enable']:
             pdf, ext = report.render_qweb_pdf(self.ids, data)
             attachment_id = self.env['ir.attachment'].with_context(
                 ctx).create({
                     'name':
                     '%s.%s' % (filename, ext),
                     'res_id':
                     self.id,
                     'res_model':
                     self._name,
                     'datas':
                     base64.b64encode(pdf),
                     'datas_fname':
                     '%s.pdf' % filename,
                     'description':
                     'Printed representation of the CFDI',
                 })
             attach.extend([attachment_id.id])
         uuid = invoice_obj.l10n_mx_edi_get_tfd_etree(xml).get('UUID', '')
         order_ids.write({'xml_generated': True, 'l10n_mx_edi_uuid': uuid})
     else:
         body_msg = _('The sign service requested failed to %s') % filename
     if code:
         post_msg.extend([_('Code: ') + str(code)])
     if msg:
         post_msg.extend([_('Message: ') + msg])
     self.message_post(body=body_msg + create_list_html(post_msg),
                       attachment_ids=attach,
                       subtype='account.mt_invoice_validated')