1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/l10n_cl_edi_boletas/models/account_move.py
2024-12-10 09:04:09 +07:00

120 lines
5.6 KiB
Python

# -*- coding: utf-8 -*-
import base64
from psycopg2 import OperationalError
from markupsafe import Markup
from odoo import _, _lt, models, fields
from odoo.exceptions import UserError
from odoo.tools import html_escape
class AccountMove(models.Model):
_inherit = 'account.move'
def _l10n_cl_edi_post_validation(self):
if self.l10n_latam_document_type_id.code == '39':
if self.line_ids.filtered(lambda x: x.tax_group_id.id in [
self.env['account.chart.template'].with_company(self.company_id).ref('tax_group_ila').id,
self.env['account.chart.template'].with_company(self.company_id).ref('tax_group_retenciones').id,
]):
raise UserError(_('Receipts with withholding taxes are not allowed'))
if self.company_id.currency_id != self.currency_id:
raise UserError(_('It is not allowed to create receipts in a different currency than CLP'))
super()._l10n_cl_edi_post_validation()
def _l10n_cl_edi_validate_boletas(self):
# Override the method to allow create ticket.
return None
def l10n_cl_send_dte_to_sii(self, retry_send=True):
if not self.l10n_latam_document_type_id._is_doc_type_ticket():
return super().l10n_cl_send_dte_to_sii(retry_send)
try:
with self.env.cr.savepoint(flush=False):
self.env.cr.execute(f'SELECT 1 FROM {self._table} WHERE id IN %s FOR UPDATE NOWAIT', [tuple(self.ids)])
except OperationalError as e:
if e.pgcode == '55P03':
if not self.env.context.get('cron_skip_connection_errs'):
raise UserError(_('This electronic document is being processed already.'))
return
raise e
# To avoid double send on double-click
if self.l10n_cl_dte_status != "not_sent":
return None
digital_signature_sudo = self.company_id.sudo()._get_digital_signature(user_id=self.env.user.id)
if self.company_id.l10n_cl_dte_service_provider == 'SIIDEMO':
self.message_post(body=_('This DTE has been generated in DEMO Mode. It is considered as accepted and '
'it won\'t be sent to SII.'))
self.l10n_cl_dte_status = 'accepted'
return None
response = self._send_xml_to_sii_rest(
self.company_id.l10n_cl_dte_service_provider,
self.company_id.vat,
self.l10n_cl_sii_send_file.name,
base64.b64decode(self.l10n_cl_sii_send_file.datas),
digital_signature_sudo
)
if not response:
return None
self.l10n_cl_sii_send_ident = response.get('trackid')
sii_response_status = response.get('estado')
self.l10n_cl_dte_status = 'ask_for_status' if sii_response_status == 'REC' else 'rejected'
self.message_post(body=_('DTE has been sent to SII with response: %s',
self._l10n_cl_get_sii_reception_status_message_rest(sii_response_status)))
def l10n_cl_verify_dte_status(self, send_dte_to_partner=True):
if not self.l10n_latam_document_type_id._is_doc_type_ticket():
return super().l10n_cl_verify_dte_status(send_dte_to_partner)
digital_signature_sudo = self.company_id.sudo()._get_digital_signature(user_id=self.env.user.id)
response = self._get_send_status_rest(
self.company_id.l10n_cl_dte_service_provider,
self.l10n_cl_sii_send_ident,
self._l10n_cl_format_vat(self.company_id.vat),
digital_signature_sudo)
if not response:
self.l10n_cl_dte_status = 'ask_for_status'
return None
self.l10n_cl_dte_status = self._analyze_sii_result_rest(response)
message_body = self._l10n_cl_get_verify_status_msg_rest(response)
if self.l10n_cl_dte_status in ['accepted', 'objected']:
self.l10n_cl_dte_partner_status = 'not_sent'
if send_dte_to_partner:
self._l10n_cl_send_dte_to_partner()
self.message_post(body=message_body)
def _l10n_cl_get_verify_status_msg_rest(self, data):
msg = _('Asking for DTE status with response:')
if self.l10n_cl_dte_status in ['rejected', 'objected']:
detail = data['detalle_rep_rech']
if detail:
msg += Markup('<br/><li><b>ESTADO</b>: %s</li>') % detail[0]['estado']
errors = detail[0].get('error', [])
for error in errors:
msg += Markup('<br/><li><b>ERROR</b>: %s %s</li>') % (
error['descripcion'], error['detalle'] or "")
return msg
return msg + Markup('<br/><li><b>ESTADO</b>: %s</li>') % data['estado']
def _l10n_cl_get_sii_reception_status_message_rest(self, sii_response_status):
return {
'REC': _lt('Submission received'),
'EPR': _lt('Submission processed'),
'CRT': _lt('Cover OK'),
'FOK': _lt('Submission signature validated'),
'PRD': _lt('Submission in process'),
'RCH': _lt('Rejected due to information errors'),
'RCO': _lt('Rejected for consistency'),
'VOF': _lt('The .xml file was not found'),
'RFR': _lt('Rejected due to error in signature'),
'RPR': _lt('Accepted with objections'),
'RPT': _lt('Repeat submission rejected'),
'RSC': _lt('Rejected by schema'),
'SOK': _lt('Validated schema'),
'RCT': _lt('Rejected by error in covert'),
}.get(sii_response_status, sii_response_status)