Commit ec040661 authored by Jorge Sanabria's avatar Jorge Sanabria
Browse files

Correccion de bugs y mejoras varias.

parent 86727336
......@@ -37,9 +37,9 @@
'account',
'snailmail_account',
'l10n_co',
# 'web_notify',
#'web_notify',
'update_from_csv',
# 'account_debitnote',
#'account_debitnote',
],
'data': [
'security/security.xml',
......@@ -48,6 +48,7 @@
'views/config/res_company.xml',
'views/config/res_config_settings_views.xml',
'views/config/resolution_views.xml',
'views/config/ir_sequence.xml',
'views/config/account_product_view.xml',
'views/config/account_taxes_view.xml',
'views/account_invoice_view.xml',
......
......@@ -50,6 +50,10 @@ class AccountInvoice(models.Model):
ei_legal_monetary_totals = fields.Text(string="legal_monetary_totals json")
ei_invoice_lines = fields.Text(string="invoice_lines json")
# Permiten almacenar modo sincrono y de produccion usados al facturar
ei_sync = fields.Boolean(string="Sync", default=False)
ei_is_not_test = fields.Boolean(string="En producción", default=False)
# API Response:
ei_is_valid = fields.Boolean(string="Valido")
ei_uuid = fields.Char(string="UUID")
......@@ -341,7 +345,14 @@ class AccountInvoice(models.Model):
@api.multi
def get_ei_sync(self):
return self.env.user.company_id.is_not_test
for rec in self:
rec.ei_sync = rec.ei_is_not_test
return rec.ei_sync
@api.multi
def get_ei_is_not_test(self):
for rec in self:
return rec.ei_is_not_test
@api.multi
def get_json_request(self):
......@@ -469,8 +480,8 @@ class AccountInvoice(models.Model):
def validate_dian(self):
_logger.debug("Request Validación DIAN: %s", json.dumps(self.get_json_request(), indent=2, sort_keys=False))
try:
for rec in self:
for rec in self:
try:
if rec.type == 'out_invoice':
# Nota debito
if rec.origin:
......@@ -482,74 +493,84 @@ class AccountInvoice(models.Model):
# Nota credito
type = 'credit-note'
requests_data = self.get_json_request()
requests_data = self.get_json_request()
if self.env.user.company_id.api_key:
token = self.env.user.company_id.api_key
else:
raise Warning("Debe configurar un token para poder facturar electrónicamente")
if self.env.user.company_id.api_key:
token = self.env.user.company_id.api_key
else:
raise Warning("Debe configurar un token para poder facturar electrónicamente")
if self.env.user.company_id.api_url:
api_url = self.env.user.company_id.api_url
else:
raise Warning("No ha configurado una URL API para la facturación electrónica")
if self.env.user.company_id.api_url:
api_url = self.env.user.company_id.api_url
else:
raise Warning("No ha configurado una URL API para la facturación electrónica")
header = {"accept": "application/json", "Content-Type": "application/json"}
header = {"accept": "application/json", "Content-Type": "application/json"}
api_url = api_url + "/api/ubl2.1/" + type + '/'
api_url = api_url + "/api/ubl2.1/" + type + '/'
if not self.env.user.company_id.is_not_test:
if self.env.user.company_id.test_set_id:
test_set_id = self.env.user.company_id.test_set_id
api_url = api_url + test_set_id
else:
raise Warning("No ha configurado un 'TestSetId'. "
"Sin este no puede hacer pruebas para habilitación.")
header.update({'Authorization': 'Bearer ' + token})
response = requests.post(api_url, json.dumps(requests_data), headers=header).json()
_logger.debug('API Response: %s', response)
# # start Debug
# response = {'is_valid': None, 'number': 'XXXXxxxxxxxxxxxxxxxxxxxxxx',
# 'uuid': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
# 'issue_date': 'xxxx-xx-xx', 'zip_key': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx', 'status_code': None,
# 'status_description': '', 'status_message': '', 'xml_file_name': '',
# 'zip_name': 'xxxxxxxxxxxxxxxxxxxxxxxx.zip', 'url_acceptance': None, 'url_rejection': None,
# 'xml_bytes': '', 'errors_messages': ['true'],
# 'qr_data': 'xxxxxxxxxxxxxxxxxxxxxxxxxxx...',
# 'application_response_base64_bytes': '', 'attached_document_base64_bytes': None,
# 'pdf_base64_bytes': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...',
# 'zip_base64_bytes': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...',
# 'dian_response_base64_bytes': 'xxxxxxxxxxxxxxxxxxxxxxxxxx...'
# }
# response = json.loads(json.dumps(response))
# # End debug
if 'message' in response:
if response['message'] == 'Unauthenticated.' or response['message'] == '':
raise Warning("Error de autenticación con la API de facturación electrónica. "
"Verifique que sus credenciales sean validas")
else:
raise Warning(response['message'])
elif 'is_valid' in response:
self.write_response(response)
if response['is_valid']:
self.write({'state': 'open'})
self.env.user.notify_info(message="La validación ante la DIAN ha sido exitosa.")
elif 'uuid' in response:
if response['uuid'] != "":
if not self.env.user.company_id.is_not_test:
self.write({'state': 'open'})
self.env.user.notify_info(message="El documento ha sido enviado, en modo habilitación.")
if not rec.ei_is_not_test:
if self.env.user.company_id.test_set_id:
test_set_id = self.env.user.company_id.test_set_id
api_url = api_url + test_set_id
else:
raise Warning("No ha configurado un 'TestSetId'. "
"Sin este no puede hacer pruebas para habilitación.")
header.update({'Authorization': 'Bearer ' + token})
response = requests.post(api_url, json.dumps(requests_data), headers=header).json()
_logger.debug('API Response: %s', response)
# # start Debug
# response = {'is_valid': None, 'number': 'XXXXxxxxxxxxxxxxxxxxxxxxxx',
# 'uuid': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
# 'issue_date': 'xxxx-xx-xx', 'zip_key': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx', 'status_code': None,
# 'status_description': '', 'status_message': '', 'xml_file_name': '',
# 'zip_name': 'xxxxxxxxxxxxxxxxxxxxxxxx.zip', 'url_acceptance': None, 'url_rejection': None,
# 'xml_bytes': '', 'errors_messages': ['true'],
# 'qr_data': 'xxxxxxxxxxxxxxxxxxxxxxxxxxx...',
# 'application_response_base64_bytes': '', 'attached_document_base64_bytes': None,
# 'pdf_base64_bytes': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...',
# 'zip_base64_bytes': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...',
# 'dian_response_base64_bytes': 'xxxxxxxxxxxxxxxxxxxxxxxxxx...'
# }
# response = json.loads(json.dumps(response))
# # End debug
if 'message' in response:
if response['message'] == 'Unauthenticated.' or response['message'] == '':
raise Warning("Error de autenticación con la API de facturación electrónica. "
"Verifique que sus credenciales sean validas")
else:
raise Warning('No se ha obtenido un UUID valido. Intente nuevamente.')
raise Warning(response['message'])
elif 'is_valid' in response:
self.write_response(response)
if response['is_valid']:
rec.write({'state': 'open'})
self.env.user.notify_info(message="La validación ante la DIAN ha sido exitosa.")
elif 'uuid' in response:
if response['uuid'] != "":
if not rec.ei_is_not_test:
rec.write({'state': 'open'})
self.env.user.notify_info(message="El documento ha sido enviado, en modo habilitación.")
else:
raise Warning('No se ha obtenido un UUID valido. Intente nuevamente.')
else:
raise Warning('No se ha podido validar el documento ante la DIAN.')
else:
raise Warning('No se ha podido validar el documento ante la DIAN.')
else:
raise Warning("No se ha obtenido una respuesta logica por parte de la API")
except Exception as e:
raise Warning("Error al procesar la solicitud: %s" % e)
raise Warning("No se ha obtenido una respuesta logica por parte de la API")
except Exception as e:
raise Warning("Error al procesar la solicitud: %s" % e)
@api.multi
def skip_validate_dian(self):
for rec in self:
rec.write({'state': 'open'})
self.env.user.notify_info(message="Se ha saltado el proceso de validación.")
@api.multi
def validate_dian_test(self):
self.validate_dian()
@api.multi
def write(self, vals):
......@@ -559,4 +580,5 @@ class AccountInvoice(models.Model):
if 'state' in vals:
if rec.state == 'draft' and vals['state'] == 'open':
vals['state'] = 'validate'
vals['ei_is_not_test'] = self.env.user.company_id.is_not_test
return super(AccountInvoice, self).write(vals)
......@@ -25,3 +25,4 @@ from . import res_config_settings
from . import resolution
from . import account_taxes
from . import account_product
from . import ir_sequence
# -*- coding: utf-8 -*-
#
# Jorels S.A.S. - Copyright (2019-2020)
#
# This file is part of l10n_co_edi_jorels.
#
# l10n_co_edi_jorels is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# l10n_co_edi_jorels is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with l10n_co_edi_jorels. If not, see <https://www.gnu.org/licenses/>.
#
# email: info@jorels.com
#
import logging
from odoo import api, fields, models, tools
_logger = logging.getLogger(__name__)
class IrSequence(models.Model):
_inherit = "ir.sequence"
resolution_id = fields.Many2one('l10n_co_edi_jorels.resolution', string="Resoluciones")
......@@ -33,7 +33,7 @@ import logging
_logger = logging.getLogger(__name__)
class Resolution(models.TransientModel):
class Resolution(models.Model):
_name = 'l10n_co_edi_jorels.resolution'
_description = 'Electronic invoice resolution'
_rec_name = 'resolution_resolution'
......
......@@ -24,24 +24,48 @@
<template id="report_invoice_document_custom" inherit_id="account.report_invoice_document">
<xpath expr="//t[@t-set='address']" position="replace">
<div class="container">
<div class="container" name="custom_address_header">
<div class="row">
<div class="col-7">
<div t-if="o.company_id.report_custom_text" class="mt16">
<h4>Nit.:
<span t-field="o.company_id.vat"/>
</h4>
<strong>Tipo de organización:</strong>
<span t-field="o.company_id.type_organization_id"/>
<br/>
<strong>Tipo de regimen:</strong>
<span t-field="o.company_id.type_regime_id"/>
<br/>
<strong>Tipo de responsabilidad:</strong>
<span t-field="o.company_id.type_liability_id"/>
<br/>
<br/>
<span t-field="o.company_id.report_custom_text"/>
</div>
</div>
<div class="col-5">
<address t-field="o.partner_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
<h4>Cliente</h4>
<div t-if="o.partner_id.vat" class="mt16">
<t t-esc="o.company_id.country_id.vat_label or 'Tax ID'"/>:
<!-- <t t-esc="o.partner_id.l10n_co_document_type or 'Tax ID'"/>:-->
<span t-if="o.partner_id.l10n_co_document_type == 'civil_registration'">R.C.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'id_card'">T.I.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'id_document'">C.C.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'national_citizen_id'">C.C.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'residence_document'">T.E.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'foreign_id_card'">C.E.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'rut'">NIT:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'passport'">PAS:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'external_id'">D.I.E.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'diplomatic_card'">Tax ID:</span>
<span t-field="o.partner_id.vat"/>
</div>
<address t-field="o.partner_id"
t-options='{"widget": "contact", "fields": ["address", "name", "phone", "email"], "no_marker": True}'/>
</div>
</div>
</div>
<br/>
</xpath>
</template>
......@@ -67,22 +91,87 @@
</template>
<template id="report_electronic_invoice_document" inherit_id="account.report_invoice_document" primary="True">
<xpath expr="//div[@name='custom_address_header']" position="replace">
<div class="container">
<div class="row">
<div class="col-3">
<!-- With OCA -->
<!-- <img t-att-src="'/report/qr/?value=%s&amp;error_correction=%s' % (o.ei_qr_data, 1)" style="width:100;height:100;"/>-->
<!-- With Odoo-->
<!-- <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('QR', o.ei_qr_data, 100, 100)"/>-->
<!-- With image -->
<span t-field="o.ei_qr_image" t-options="{'widget':'image'}"/>
</div>
<div class="col-5">
<div t-if="o.company_id.report_custom_text" class="mt16">
<h4>Nit.:
<span t-field="o.company_id.vat"/>
</h4>
<strong>Tipo de organización:</strong>
<span t-field="o.company_id.type_organization_id"/>
<br/>
<strong>Tipo de regimen:</strong>
<span t-field="o.company_id.type_regime_id"/>
<br/>
<strong>Tipo de responsabilidad:</strong>
<span t-field="o.company_id.type_liability_id"/>
<br/>
<br/>
<span t-field="o.company_id.report_custom_text"/>
</div>
</div>
<div class="col-4">
<h4>Cliente</h4>
<div t-if="o.partner_id.vat" class="mt16">
<span t-if="o.partner_id.l10n_co_document_type == 'civil_registration'">R.C.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'id_card'">T.I.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'id_document'">C.C.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'national_citizen_id'">C.C.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'residence_document'">T.E.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'foreign_id_card'">C.E.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'rut'">NIT:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'passport'">PAS:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'external_id'">D.I.E.:</span>
<span t-if="o.partner_id.l10n_co_document_type == 'diplomatic_card'">Tax ID:</span>
<span t-field="o.partner_id.vat"/>
</div>
<address t-field="o.partner_id"
t-options='{"widget": "contact", "fields": ["address", "name", "phone", "email"], "no_marker": True}'/>
</div>
</div>
</div>
</xpath>
<xpath expr="//div[@class='page']" position="inside">
<!-- Aquí va una nueva seccion con los nuevos campos de la factura electrónica -->
<!-- Por ejemplo -->
<div class="container">
<div class="row">
<div class="col-12">
<div class="mt16">
<!-- Por ejemplo el codigo QR -->
<!-- With OCA -->
<!-- <img t-att-src="'/report/qr/?value=%s&amp;error_correction=%s' % (o.ei_qr_data, 1)" style="width:100;height:100;"/>-->
<!-- With Odoo-->
<!-- <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('QR', o.ei_qr_data, 100, 100)"/>-->
<!-- With image -->
<span t-field="o.ei_qr_image" t-options="{'widget':'image'}"/>
<div class="mt16 text-center">
<strong t-if="o.type == 'out_invoice' and not o.origin">CUFE:</strong>
<strong t-if="o.type == 'out_invoice' and o.origin">CUDE:</strong>
<strong t-if="o.type == 'out_refund'">CUDE:</strong>
<span t-field="o.ei_uuid"/>
<br/>
<strong>Número de Autorización:</strong>
<span t-field="o.journal_id.sequence_id.resolution_id.resolution_resolution"/>
<strong>Fecha:</strong>
<span t-field="o.journal_id.sequence_id.resolution_id.resolution_resolution_date"/>
<br/>
<strong>Rango autorizado desde:</strong>
<span t-field="o.journal_id.sequence_id.resolution_id.resolution_from"/>
<strong>Rango autorizado hasta:</strong>
<span t-field="o.journal_id.sequence_id.resolution_id.resolution_to"/>
<strong>Vigencia desde:</strong>
<span t-field="o.journal_id.sequence_id.resolution_id.resolution_date_from"/>
<strong>Vigencia hasta:</strong>
<span t-field="o.journal_id.sequence_id.resolution_id.resolution_date_to"/>
<br/>
<strong>Representación grafica de factura electrónica impresa por computador por
</strong>
<strong t-field="o.company_id.name"/>
</div>
</div>
</div>
......
......@@ -20,3 +20,5 @@ access_l10n_co_edi_jorels_type_environments,access_l10n_co_edi_jorels_type_envir
access_l10n_co_edi_jorels_type_item_identifications,access_l10n_co_edi_jorels_type_item_identifications,model_l10n_co_edi_jorels_type_item_identifications,l10n_co_edi_jorels_group_user,1,0,0,0
access_l10n_co_edi_jorels_type_regimes,access_l10n_co_edi_jorels_type_regimes,model_l10n_co_edi_jorels_type_regimes,l10n_co_edi_jorels_group_user,1,0,0,0
access_l10n_co_edi_jorels_unit_measures,access_l10n_co_edi_jorels_unit_measures,model_l10n_co_edi_jorels_unit_measures,l10n_co_edi_jorels_group_user,1,0,0,0
access_l10n_co_edi_jorels_resolution,access_l10n_co_edi_jorels_resolution,model_l10n_co_edi_jorels_resolution,l10n_co_edi_jorels_group_user,1,0,0,0
edit_l10n_co_edi_jorels_resolution,access_l10n_co_edi_jorels_resolution,model_l10n_co_edi_jorels_resolution,l10n_co_edi_jorels_group_manager,1,1,1,1
\ No newline at end of file
......@@ -27,39 +27,49 @@
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_invoice_open']" position="after">
<button name="validate_dian" type="object" states="validate" string="Validar DIAN" class="oe_highlight o_invoice_validate" groups="account.group_account_invoice"/>
</xpath>
<xpath expr="//field[@name='state']" position="replace">
<field name="state" widget="statusbar" nolabel="1" statusbar_visible="draft,validate,open,paid"/>
<button name="validate_dian" type="object" string="Validar DIAN"
class="oe_highlight o_invoice_validate" groups="account.group_account_invoice"
attrs="{'invisible': ['|',('ei_is_not_test','=',False),('state','!=','validate')]}"/>
<button name="skip_validate_dian" type="object" string="Saltar validación DIAN"
class="oe_highlight o_invoice_validate" groups="account.group_account_invoice"
attrs="{'invisible': ['|',('ei_is_not_test','=',True),('state','!=','validate')]}"/>
<button name="validate_dian_test" type="object" string="Validar DIAN Test"
class="o_invoice_validate" groups="base.group_no_one"
attrs="{'invisible': [('state','!=','validate')]}"/>
</xpath>
<!-- <xpath expr="//field[@name='state']" position="replace">-->
<!-- <field name="state" widget="statusbar" nolabel="1" statusbar_visible="draft,validate,open,paid"/>-->
<!-- </xpath>-->
<xpath expr="//page[@name='other_info']" position="after">
<page string="Respuesta DIAN" name="info_Dian">
<group name="dian_response">
<group name="dian_left">
<field name="ei_is_valid"/>
<field name="ei_uuid"/>
<field name="ei_issue_date"/>
<field name="ei_zip_key"/>
<field name="ei_status_code"/>
<field name="ei_status_description"/>
<field name="ei_status_message"/>
<field name="ei_is_valid" readonly="True"/>
<field name="ei_is_not_test" readonly="True"/>
<field name="ei_sync" readonly="True"/>
<field name="ei_uuid" readonly="True"/>
<field name="ei_issue_date" readonly="True"/>
<field name="ei_zip_key" readonly="True"/>
<field name="ei_status_code" readonly="True"/>
<field name="ei_status_description" readonly="True"/>
<field name="ei_status_message" readonly="True"/>
</group>
<group name="dian_right">
<field name="ei_xml_file_name"/>
<field name="ei_zip_name"/>
<field name="ei_url_acceptance"/>
<field name="ei_url_rejection"/>
<field name="ei_xml_bytes"/>
<field name="ei_errors_messages"/>
<field name="ei_application_response_base64_bytes"/>
<field name="ei_attached_document_base64_bytes"/>
<field name="ei_pdf_base64_bytes"/>
<field name="ei_zip_base64_bytes"/>
<field name="ei_dian_response_base64_bytes"/>
<field name="ei_xml_file_name" readonly="True"/>
<field name="ei_zip_name" readonly="True"/>
<field name="ei_url_acceptance" readonly="True"/>
<field name="ei_url_rejection" readonly="True"/>
<field name="ei_xml_bytes" readonly="True"/>
<field name="ei_errors_messages" readonly="True"/>
<field name="ei_application_response_base64_bytes" readonly="True"/>
<field name="ei_attached_document_base64_bytes" readonly="True"/>
<field name="ei_pdf_base64_bytes" readonly="True"/>
<field name="ei_zip_base64_bytes" readonly="True"/>
<field name="ei_dian_response_base64_bytes" readonly="True"/>
</group>
<group name="dian_qr">
<field name="ei_qr_data"/>
<field name="ei_qr_image" widget="image"/>
<field name="ei_qr_data" readonly="True"/>
<field name="ei_qr_image" widget="image" readonly="True"/>
</group>
</group>
</page>
......
<?xml version="1.0" encoding="utf-8"?>
<!--Jorels S.A.S. - Copyright (2019-2020)-->
<!--This file is part of l10n_co_edi_jorels.-->
<!--l10n_co_edi_jorels is free software: you can redistribute it and/or modify-->
<!--it under the terms of the GNU Lesser General Public License as published by-->
<!--the Free Software Foundation, either version 3 of the License, or-->
<!--(at your option) any later version.-->
<!--l10n_co_edi_jorels is distributed in the hope that it will be useful,-->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of-->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-->
<!--GNU Lesser General Public License for more details.-->
<!--You should have received a copy of the GNU Lesser General Public License-->
<!--along with l10n_co_edi_jorels. If not, see <https://www.gnu.org/licenses/>.-->
<!--email: info@jorels.com-->
<odoo>
<data>
<record id="ir_sequence_form_view_inherit_l10n_co_edi_jorels" model="ir.ui.view">
<field name="name">ir.sequence.form.inherit.l10n_co_edi_jorels</field>
<field name="model">ir.sequence</field>
<field name="inherit_id" ref="base.sequence_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='implementation']" position="after">
<field name="resolution_id"/>
</xpath>
</field>
</record>
</data>
</odoo>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment