Skip to content

Commit

Permalink
[ADD] l10n_uy_edi: se crea factura y cliente si corresponde
Browse files Browse the repository at this point in the history
  • Loading branch information
pablohmontenegro committed Oct 2, 2023
1 parent 6ef1281 commit 5404457
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 43 deletions.
3 changes: 3 additions & 0 deletions l10n_uy_account/data/l10n_latam.document.type.csv
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ dc_nota_de_crédito_de_e_factura_venta_por_cuenta_ajena_contingencia,242,Nota de
dc_nota_de_débito_de_e_factura_venta_por_cuenta_ajena_contingencia,243,Nota de Débito de e-Factura Venta por Cuenta Ajena Contingencia,debit_note,ND e-Fac.Cta.Aj.Cotg,base.uy
dc_ e_remito_contingencia,281, e-Remito Contingencia,stock_picking,e-Rem.Cotg,base.uy
dc_ e_resguardo_contingencia,282, e-Resguardo Contingencia,,E-Resguardo.Cotg,base.uy
dc_e_boleta_de_entrada,151,e-Boleta de entrada,invoice,e-Boleta-entrada,base.uy
dc_cn_e_boleta_de_entrada,152,Nota de crédito de e-Boleta de entrada,credit_note,NC e-Boleta-entrada,base.uy
dc_dn_e_boleta_de_entrada,153,Nota de débito de e-Boleta de entrada,debit_note,ND e-Boleta-entrada,base.uy
172 changes: 131 additions & 41 deletions l10n_uy_edi/models/l10n_uy_cfe.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import base64
import stdnum.uy
import re

import xml.etree.ElementTree as ET
from odoo import _, fields, models, api
from odoo.exceptions import UserError
from odoo.tools.safe_eval import safe_eval
Expand Down Expand Up @@ -578,59 +578,144 @@ def _l10n_uy_get_cfe_serie(self):
})
return res

def xml_to_dict(self, xml_string):
root = ET.fromstring(xml_string)
return self.element_to_dict(root)

def element_to_dict(self, element):
if len(element) == 0:
return element.text

result = {}
for child in element:
child_data = self.element_to_dict(child)
key = child.tag.replace('{http://cfe.dgi.gub.uy}', '')
if key in result:
if type(result[key]) is list:
result[key].append(child_data)
else:
result[key] = [result[key], child_data]
else:
result[key] = child_data

return result

@api.model
def l10n_uy_get_ucfe_notif(self):
# TODO test it

# 600 - Consulta de Notificacion Disponible
response = self.env.company._l10n_uy_ucfe_inbox_operation('600')
# import pdb; pdb.set_trace()
# If there is notifications
if response.Resp.CodRta == '00':
# response.Resp.TipoNotificacion

# 610 - Solicitud de datos de Notificacion
response2 = self.env.company._l10n_uy_ucfe_inbox_operation('610', {'IdReq': response.Resp.IdReq})
print("-------------response 2---------")
print("----------------------")
print("----------------------")
import pprint
pprint.pprint(response2)

import xml.etree.ElementTree as ET
xml_string = response2.Resp.XmlCfeFirmado
data_dict = self.xml_to_dict(xml_string)
print("----------------------")
print("----------data_dict--------------")
print("----------------------")
import pprint
pprint.pprint(data_dict)
invoice_line_ids = []
for key, value in data_dict.items():
if isinstance(value, dict):
if value.get('Encabezado'):
l10n_latam_document_type_id = value['Encabezado']['IdDoc']['TipoCFE']
invoice_date = datetime.strptime(value['Encabezado']['IdDoc']['FchEmis'], '%Y-%m-%d').date()
l10n_latam_document_number = value['Encabezado']['IdDoc']['Nro']
currency_id = value['Encabezado']['Totales']['TpoMoneda']
l10n_uy_cfe_uuid = value['CAEData']['CAE_ID']
partner_vat_RUC = value['Encabezado']['Emisor']['RUCEmisor']
partner_id = self.env['res.partner'].search([('commercial_partner_id.vat', '=', partner_vat_RUC)], limit=1)
# Si no existe el partner lo creamos
if not partner_id:
partner_name = value['Encabezado']['Emisor']['RznSoc']
partner_city = value['Encabezado']['Emisor']['Ciudad']
partner_state_id = value['Encabezado']['Emisor']['Departamento']
partner_street = value['Encabezado']['Emisor']['DomFiscal']
state_id = self.env['res.country.state'].search([('name', 'ilike', partner_state_id)], limit=1)
country_id = state_id.country_id
ruc = self.env.ref('l10n_uy_account.it_rut').id
#
partner_id = self.env['res.partner'].create({'name': partner_name, 'vat': partner_vat_RUC, 'city': partner_city, 'street': partner_street, 'state_id': state_id.id, 'country_id': country_id.id, 'l10n_latam_identification_type_id': ruc, 'is_company': True})

invoice_line_ids.append(value['Detalle']['Item'])
line_ids = []
for value in invoice_line_ids:
line_ids.append((0, 0,{'move_type': 'in_invoice', 'name': value['NomItem'], 'quantity': float(value['Cantidad']), 'price_unit': float(value['PrecioUnitario'])}))

#line_ids = [(0, 0,{'name': item['Item']['NomItem'], 'quantity': float(item['Item']['Cantidad']), 'price_unit': float(item['Item']['PrecioUnitario'])}) for item in invoice_line_ids]

if not self.env['account.move'].search([('l10n_uy_cfe_uuid', '=', l10n_uy_cfe_uuid)]):
# Facturas
if l10n_latam_document_type_id in ['101', '111', '181', '182', '121', '124', '131', '141', '151']:
move_type = 'in_invoice'
# Notas de crédito
if l10n_latam_document_type_id in ['102', '112', '122', '132', '142', '152']:
move_type = 'in_refund'
if l10n_latam_document_type_id in ['103', '113', '123', '133', '143', '153']:
move_type = 'in_refund'
document_type = self.env['l10n_latam.document.type'].search([('code', '=', l10n_latam_document_type_id)], limit=1).id
self.env['account.move'].create({'move_type': move_type, 'partner_id': partner_id.id, 'invoice_date': invoice_date, 'l10n_latam_document_type_id': document_type, 'l10n_latam_document_number': l10n_latam_document_number,'l10n_uy_cfe_uuid': l10n_uy_cfe_uuid, 'line_ids': line_ids}).action_post()

#response_parsed = etree.fromstring(response2.Resp.XmlCfeFirmado)
xml_response = response2.Resp.XmlCfeFirmado
root = ET.fromstring(xml_response)
print(xml_response)
print("Tipo de CFE:", root.find(".//{http://cfe.dgi.gub.uy}IdDoc"))
#xml_response = response2.Resp.XmlCfeFirmado
#root = ET.fromstring(xml_response)
#print(xml_response)
#print("Tipo de CFE:", root.find(".//{http://cfe.dgi.gub.uy}IdDoc"))
# Es necesario indicar el namespace de la etiqueta
factura = {'TipoCfe': 'l10n_latam_document_type_id'}
partner = {'RUCEmisor': 'partner_id.vat'}
res = {}
for key, value in factura.items():
res.update({value: root.find(".//{http://cfe.dgi.gub.uy}"+key).text})
#factura = {'TipoCFE': 'l10n_latam_document_type_id',
# 'FchEmis': 'invoice_date',
# 'Nro': 'l10n_latam_document_number',
# 'TpoMoneda': 'currency_id',
# }
#partner = {'RUCEmisor': 'partner_id.vat',
# 'RznSoc': 'partner_id.name',
# 'DomFiscal': 'partner_id.street',
# 'Ciudad': 'partner_id.city',}
#item = {'NomItem':'name',
# 'Cantidad': 'quantity',
# 'PrecioUnitario': 'price_unit',
# }
#res = {}
#for key, value in factura.items():
# res.update({value: root.find(".//{http://cfe.dgi.gub.uy}"+key+"/*").text})

# revisar si el ruc emisor existe en odoo
for key, value in partner.items():
res.update({value: root.find(".//{http://cfe.dgi.gub.uy}"+key).text})

root.find(".//{http://cfe.dgi.gub.uy}TmstFirma").text
factura["TmstFirma"] = root.find(".//{http://cfe.dgi.gub.uy}TmstFirma").text
factura["Encabezado"] = {}
factura["Encabezado"]["IdDoc"] = {}
factura["Encabezado"]["Emisor"] = {}
factura["Encabezado"]["Totales"] = {}
factura["Detalle"] = {}
factura["Detalle"]["Item"] = {}
factura["CAEData"] = {}
for child in root.findall('.//{http://cfe.dgi.gub.uy}Item/*'):
factura["Detalle"]["Item"][child.tag.split('}')[1]] = child.text
for child in root.findall('.//{http://cfe.dgi.gub.uy}CAEData/*'):
factura["CAEData"][child.tag.split('}')[1]] = child.text
for child in root.findall('.//{http://cfe.dgi.gub.uy}IdDoc/*'):
factura["Encabezado"]["IdDoc"][child.tag.split('}')[1]] = child.text
for child in root.findall('.//{http://cfe.dgi.gub.uy}Emisor/*'):
factura["Encabezado"]["Emisor"][child.tag.split('}')[1]] = child.text
for child in root.findall('.//{http://cfe.dgi.gub.uy}Totales/*'):
factura["Encabezado"]["Totales"][child.tag.split('}')[1]] = child.text
import pdb
pdb.set_trace()
partner = factura['Encabezado']['Emisor']['RUCEmisor']
self.env['res.partner'].search([('vat','=',partner)],limit=1)
#for key, value in partner.items():
# res.update({value: root.find(".//{http://cfe.dgi.gub.uy}"+key).text})

#root.find(".//{http://cfe.dgi.gub.uy}TmstFirma").text
#factura["TmstFirma"] = root.find(".//{http://cfe.dgi.gub.uy}TmstFirma").text
#factura["Encabezado"] = {}
#factura["Encabezado"]["IdDoc"] = {}
#factura["Encabezado"]["Emisor"] = {}
#factura["Encabezado"]["Totales"] = {}
#factura["Detalle"] = {}
#factura["Detalle"]["Item"] = {}
#factura["CAEData"] = {}
#for child in root.findall('.//{http://cfe.dgi.gub.uy}Item/*'):
# factura["Detalle"]["Item"][child.tag.split('}')[1]] = child.text
#for child in root.findall('.//{http://cfe.dgi.gub.uy}CAEData/*'):
# factura["CAEData"][child.tag.split('}')[1]] = child.text
#for child in root.findall('.//{http://cfe.dgi.gub.uy}IdDoc/*'):
# factura["Encabezado"]["IdDoc"][child.tag.split('}')[1]] = child.text
#for child in root.findall('.//{http://cfe.dgi.gub.uy}Emisor/*'):
# factura["Encabezado"]["Emisor"][child.tag.split('}')[1]] = child.text
#for child in root.findall('.//{http://cfe.dgi.gub.uy}Totales/*'):
# factura["Encabezado"]["Totales"][child.tag.split('}')[1]] = child.text
#partner = factura['Encabezado']['Emisor']['RUCEmisor']
#self.env['res.partner'].search([('vat','=',partner)],limit=1)
# env['account.move'].create({'partner_id': partner_id, 'invoice_date':date, 'line_ids': [(0,0,{'product_id':31}),(0,0,{'product_id':24}),(0,0,{'product_id':231}),(0,0,{'product_id':234})]})._cr.commit()

# ('5', 'Aviso de CFE emitido rechazado por DGI'), or
Expand Down Expand Up @@ -716,10 +801,15 @@ def l10n_uy_get_ucfe_notif(self):
raise UserError(_('ERROR: esto es lo que recibimos %s') % response)

# TODO 620 - Descartar Notificacion
# response3 = self.company_id._l10n_uy_ucfe_inbox_operation('620', {
# 'idReq': response.Resp.idReq, 'TipoNotificacion': response.Resp.TipoNotificacion})
# if response3.Resp.CodRta != '00':
# raise UserError(_('ERROR: la notificacion no pudo descartarse %s') % response)
response3 = self.env.company._l10n_uy_ucfe_inbox_operation('620', {
'IdReq': response.Resp.IdReq, 'TipoNotificacion': response.Resp.TipoNotificacion})
print("-------------response 3---------")
print("----------------------")
print("----------------------")
import pprint
pprint.pprint(response3)
if response3.Resp.CodRta != '00':
raise UserError(_('ERROR: la notificacion no pudo descartarse %s') % response)

def action_cfe_inform_commercial_status(self, rejection=False):
# TODO only applies for vendor bills
Expand Down
5 changes: 3 additions & 2 deletions l10n_uy_edi/models/res_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def _l10n_uy_ucfe_inbox_operation(self, msg_type, extra_req={}, return_transport
""" Call Operation get in msg_type for UCFE inbox webservice """
self.ensure_one()
# TODO consumir secuencia creada en Odoo
id_req = 1
id_req = extra_req.get('IdReq') or 1
now = datetime.utcnow()
company = self.sudo()
data = {'Req': {'TipoMensaje': msg_type, 'CodComercio': company.l10n_uy_ucfe_commerce_code,
Expand All @@ -129,7 +129,8 @@ def _l10n_uy_ucfe_inbox_operation(self, msg_type, extra_req={}, return_transport
'Tout': '30000'}
if extra_req:
data.get('Req').update(extra_req)

import pprint
pprint.pprint(data)
res = company._uy_get_client(company.l10n_uy_ucfe_inbox_url, return_transport=return_transport)
client = res[0] if isinstance(res, tuple) else res
transport = res[1] if isinstance(res, tuple) else False
Expand Down

0 comments on commit 5404457

Please sign in to comment.