| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- # -*- coding: utf-8 -*-
- from odoo import models, api, fields, _
- from odoo.exceptions import ValidationError, UserError
- import base64
- import time
- import logging
- from datetime import date, datetime
- from dateutil.relativedelta import relativedelta
- from .account_esignature_certificate import convert_key_cer_to_pem
- from .portal_sat import PortalSAT
- _logger = logging.getLogger(__name__)
- TRY_COUNT = 3 # INTENTOS DE CONEXION
- class ResCompany(models.Model):
- _inherit = 'res.company'
- x_esignature_ids = fields.Many2many(comodel_name='account.esignature.certificate', string='Certificado FIEL')
- x_last_cfdi_fetch_date = fields.Datetime("Última sincronización")
- x_only_supplier_cfdi = fields.Boolean("Solo documentos de proveedor")
- @api.model
- def auto_import_cfdi_invoices(self):
- for company in self.search([('x_esignature_ids', '!=', False)]):
- company.with_company(company.id).download_cfdi_invoices_sat()
- return True
- # =================================================PORTAL SAT===========================================================
- # DESCARGAR LOS XML DESDE EL SAT
- def download_cfdi_invoices_sat(self, start_date=False, end_Date=False, document_type=False):
- esignature_ids = self.x_esignature_ids
- esignature = esignature_ids.with_user(self.env.user).get_valid_certificate()
- if not esignature:
- raise ValidationError("No se encontraron certificados validos, favor de revisar.")
- if not esignature.content or not esignature.key or not esignature.password:
- raise ValidationError("Seleccine los archivos FIEL .cer o FIEL .pem.")
- fiel_cert_data = base64.b64decode(esignature.content)
- fiel_pem_data = convert_key_cer_to_pem(esignature.key, esignature.password)
- opt = {'credenciales': None, 'rfc': None, 'uuid': None, 'ano': None, 'mes': None, 'dia': 0,
- 'intervalo_dias': None, 'fecha_inicial': None, 'fecha_final': None, 'tipo': 't',
- 'tipo_complemento': '-1', 'rfc_emisor': None, 'rfc_receptor': None, 'sin_descargar': False,
- 'base_datos': False, 'directorio_fiel': '', 'archivo_uuids': '', 'estatus': False}
- today = datetime.utcnow()
- if start_date and end_Date:
- opt['fecha_inicial'] = datetime.combine(start_date, datetime.min.time())
- opt['fecha_final'] = datetime.combine(end_Date, datetime.max.time())
- elif self.x_last_cfdi_fetch_date:
- last_import_date = self.x_last_cfdi_fetch_date
- last_import_date - relativedelta(days=2)
- fecha_inicial = last_import_date - relativedelta(days=2)
- fecha_final = today + relativedelta(days=2)
- opt['fecha_inicial'] = fecha_inicial
- opt['fecha_final'] = fecha_final
- else:
- year = today.year
- month = today.month
- opt['ano'] = year
- opt['mes'] = month
- sat = False
- for i in range(TRY_COUNT):
- sat = PortalSAT(opt['rfc'], 'cfdi-descarga', False)
- if sat.login_fiel(fiel_cert_data, fiel_pem_data, esignature, self.env.company):
- time.sleep(1)
- break
- invoice_content_receptor, invoice_content_emisor = {}, {}
- if sat and sat.is_connect:
- if document_type == "supplier":
- invoice_content_receptor, invoice_content_emisor = sat.search(opt, 'supplier')
- elif document_type == "customer":
- invoice_content_receptor, invoice_content_emisor = sat.search(opt, 'customer')
- else:
- invoice_content_receptor, invoice_content_emisor = sat.search(opt)
- sat.logout()
- elif sat:
- sat.logout()
- attachment_data = []
- if invoice_content_receptor:
- attachment_data += self.get_cfdi_data(invoice_content_receptor, attachment_data)
- if invoice_content_emisor:
- attachment_data += self.get_cfdi_data(invoice_content_emisor, attachment_data)
- if attachment_data:
- cfdi_ids = self.env['account.cfdi'].create_cfdis(attachment_data=attachment_data)
- if cfdi_ids:
- self.write({'x_last_cfdi_fetch_date': date.today()})
- return {
- "name": _("CFDIs importados"),
- "view_mode": "list,form",
- "res_model": "account.cfdi",
- "type": "ir.actions.act_window",
- "target": "current",
- "domain": [("id", "in", cfdi_ids.ids)]
- }
- else:
- return {
- 'type': 'ir.actions.client',
- 'tag': 'display_notification',
- 'params': {
- 'title': _(
- "No se cargaron nuevos CFDIs al sistema ya que estos ya existen o no se encontraron, favor de validar."),
- 'type': 'warning',
- 'sticky': True,
- },
- }
- else:
- return {
- 'type': 'ir.actions.client',
- 'tag': 'display_notification',
- 'params': {
- 'title': _(
- "No se encontraron CFDIs que coincidan con las fechas o estos ya se encuentran en el sistema, favor de validar."),
- 'type': 'warning',
- 'sticky': True,
- },
- }
- # ======================================================================================================================
- def get_cfdi_data(self, content_sat, attachment_data):
- uuids = list(content_sat.keys())
- cfdi_ids = self.env["account.cfdi"].sudo().search([('uuid', 'in', uuids)])
- exist_uuids = cfdi_ids.mapped('uuid')
- for uuid, data in content_sat.items():
- if uuid in exist_uuids:
- continue
- xml_content = data[1]
- pdf_content = data[2]
- filename = uuid + ".xml"
- filepdf = uuid + ".pdf"
- data = dict(
- name=filename,
- store_fname=filename,
- type='binary',
- datas=base64.b64encode(xml_content),
- company_id=self.id,
- mimetype='application/xml'
- )
- data_pdf = dict(
- name=filepdf,
- store_fname=filepdf,
- type='binary',
- datas=base64.b64encode(pdf_content) if pdf_content else False,
- company_id=self.id,
- mimetype='application/pdf'
- )
- data_uuid = {
- "xml": data,
- "pdf": data_pdf
- }
- attachment_data.append(data_uuid)
- return attachment_data
|