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')
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()
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') }
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')