<commit_before># Copyright 2020 Binovo IT Human Project SL
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import base64
from ..utils import utils as tbai_utils
from ..ticketbai.xml_schema import XMLSchema, TicketBaiSchema
from odoo import models, fields, api, _


class TicketBaiCancellationResponseCode(tbai_utils.EnumValues):
    INCORRECT_SENDER_CERTIFICATE = '001'
    XSD_SCHEMA_NOT_COMPLY = '002'
    REQUIRED_FIELD_MISSING = '004'
    SERVICE_NOT_AVAILABLE = '006'
    INVALID_SENDER_CERTIFICATE = '007'
    WRONG_SIGNATURE = '008'
    INVALID_TBAI_LICENSE = '012'
    DEVICE_NOT_REGISTERED = '013'
    EXPIRED_SENDER_CERTIFICATE = '015'
    EXPIRED_SIGNER_CERTIFICATE = '016'
    MESSAGE_TOO_LONG = '017'
    INVOICE_NOT_REGISTERED = '018'
    INVOICE_ALREADY_CANCELLED = '019'


class TicketBaiInvoiceResponseCode(tbai_utils.EnumValues):
    INCORRECT_SENDER_CERTIFICATE = '001'
    XSD_SCHEMA_NOT_COMPLY = '002'
    INVOICE_WITHOUT_LINES = '003'
    REQUIRED_FIELD_MISSING = '004'
    INVOICE_ALREADY_REGISTERED = '005'
    SERVICE_NOT_AVAILABLE = '006'
    INVALID_SENDER_CERTIFICATE = '007'
    WRONG_SIGNATURE = '008'
    INCORRECT_INVOICE_CHAINING = '010'
    BUSINESS_VALIDATION_DATA_ERROR = '011'
    INVALID_TBAI_LICENSE = '012'
    DEVICE_NOT_REGISTERED = '013'
    EXPIRED_SENDER_CERTIFICATE = '015'
    EXPIRED_SIGNER_CERTIFICATE = '016'
    MESSAGE_TOO_LONG = '017'


class TicketBaiResponseState(tbai_utils.EnumValues):
    BUILD_ERROR = '-2'
    REQUEST_ERROR = '-1'
    RECEIVED = '00'
    REJECTED = '01'


class TicketBaiResponse(models.Model):
    _name = 'tbai.response'
    _order = 'id desc'
    _description = 'TicketBAI Tax Agency Invoice response'

    tbai_invoice_id = fields.Many2one(
        comodel_name='tbai.invoice', required=True, ondelete='cascade')
    xml = fields.Binary(string='XML Response', attachment=True)
    xml_fname = fields.Char('File Name')
    state = fields.Selection(selection=[
        (TicketBaiResponseState.RECEIVED.value, 'Received'),
        (TicketBaiResponseState.REJECTED.value, 'Rejected'),
        (TicketBaiResponseState.REQUEST_ERROR.value, 'Request error'),
        (TicketBaiResponseState.BUILD_ERROR.value, 'Build error')
    ], required=True)
    tbai_response_message_ids = fields.One2many(
        comodel_name='tbai.response.message', inverse_name='tbai_response_id')

    @api.model
    def prepare_tbai_api_error_values(self, msg, **kwargs):
        values = kwargs
        values.update({
            'state': TicketBaiResponseState.BUILD_ERROR.value,
            'tbai_response_message_ids': [
                (0, 0, {
                    'code': _("TicketBAI API required fields missing."),
                    'description': msg
                })
            ]
        })
        return values

    @api.model
    def prepare_tbai_response_values(self, response, **kwargs):
        values = kwargs
        if response.error:
            errno = response.errno
            strerror = response.strerror
            values.update({
                'state': TicketBaiResponseState.REQUEST_ERROR.value,
                'tbai_response_message_ids': [
                    (0, 0, {
                        'code': errno,
                        'description': strerror
                    })
                ]
            })
        else:
            xml_dict = XMLSchema(
                TicketBaiSchema.TicketBaiResponse.value).parse_xml(
                response.data)['TicketBaiResponse'] or {}
            state = xml_dict['Salida']['Estado']
            values.update({
                'xml': base64.encodebytes(response.data.encode('utf-8')),
                'state': state
            })
            if state == TicketBaiResponseState.RECEIVED.value:
                tbai_response_message_ids = [(0, 0, {
                    'code': xml_dict['Salida']['CSV'],
                    'description': {
                        'es_ES': xml_dict['Salida']['Descripcion'],
                        'eu_ES': xml_dict['Salida']['Azalpena']
                    }
                })]
            elif state == TicketBaiResponseState.REJECTED.value:
                messages = xml_dict['Salida']['ResultadosValidacion']
                tbai_response_message_ids = []
                if isinstance(messages, dict):
                    messages = [messages]
                for msg in messages:
                    tbai_response_message_ids.append((0, 0, {
                        'code': msg['Codigo'],
                        'description': {
                            'es_ES': msg['Descripcion'],
                            'eu_ES': msg['Azalpena']
                        }
                    }))
            else:
                tbai_response_message_ids = [(0, 0, {
                    'code': state,
                    'description': _('Unknown TicketBAI response code.')
                })]
            values.update(tbai_response_message_ids=tbai_response_message_ids)<commit_msg>[IMP] l10n_es_ticketbai_api Save warning messages from IRS also when invoices get accepted<commit_after># Copyright 2020 Binovo IT Human Project SL
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import base64
from ..utils import utils as tbai_utils
from ..ticketbai.xml_schema import XMLSchema, TicketBaiSchema
from odoo import models, fields, api, _


class TicketBaiCancellationResponseCode(tbai_utils.EnumValues):
    INCORRECT_SENDER_CERTIFICATE = '001'
    XSD_SCHEMA_NOT_COMPLY = '002'
    REQUIRED_FIELD_MISSING = '004'
    SERVICE_NOT_AVAILABLE = '006'
    INVALID_SENDER_CERTIFICATE = '007'
    WRONG_SIGNATURE = '008'
    INVALID_TBAI_LICENSE = '012'
    DEVICE_NOT_REGISTERED = '013'
    EXPIRED_SENDER_CERTIFICATE = '015'
    EXPIRED_SIGNER_CERTIFICATE = '016'
    MESSAGE_TOO_LONG = '017'
    INVOICE_NOT_REGISTERED = '018'
    INVOICE_ALREADY_CANCELLED = '019'


class TicketBaiInvoiceResponseCode(tbai_utils.EnumValues):
    INCORRECT_SENDER_CERTIFICATE = '001'
    XSD_SCHEMA_NOT_COMPLY = '002'
    INVOICE_WITHOUT_LINES = '003'
    REQUIRED_FIELD_MISSING = '004'
    INVOICE_ALREADY_REGISTERED = '005'
    SERVICE_NOT_AVAILABLE = '006'
    INVALID_SENDER_CERTIFICATE = '007'
    WRONG_SIGNATURE = '008'
    INCORRECT_INVOICE_CHAINING = '010'
    BUSINESS_VALIDATION_DATA_ERROR = '011'
    INVALID_TBAI_LICENSE = '012'
    DEVICE_NOT_REGISTERED = '013'
    EXPIRED_SENDER_CERTIFICATE = '015'
    EXPIRED_SIGNER_CERTIFICATE = '016'
    MESSAGE_TOO_LONG = '017'


class TicketBaiResponseState(tbai_utils.EnumValues):
    BUILD_ERROR = '-2'
    REQUEST_ERROR = '-1'
    RECEIVED = '00'
    REJECTED = '01'


class TicketBaiResponse(models.Model):
    _name = 'tbai.response'
    _order = 'id desc'
    _description = 'TicketBAI Tax Agency Invoice response'

    tbai_invoice_id = fields.Many2one(
        comodel_name='tbai.invoice', required=True, ondelete='cascade')
    xml = fields.Binary(string='XML Response', attachment=True)
    xml_fname = fields.Char('File Name')
    state = fields.Selection(selection=[
        (TicketBaiResponseState.RECEIVED.value, 'Received'),
        (TicketBaiResponseState.REJECTED.value, 'Rejected'),
        (TicketBaiResponseState.REQUEST_ERROR.value, 'Request error'),
        (TicketBaiResponseState.BUILD_ERROR.value, 'Build error')
    ], required=True)
    tbai_response_message_ids = fields.One2many(
        comodel_name='tbai.response.message', inverse_name='tbai_response_id')

    @api.model
    def prepare_tbai_api_error_values(self, msg, **kwargs):
        values = kwargs
        values.update({
            'state': TicketBaiResponseState.BUILD_ERROR.value,
            'tbai_response_message_ids': [
                (0, 0, {
                    'code': _("TicketBAI API required fields missing."),
                    'description': msg
                })
            ]
        })
        return values

    @api.model
    def prepare_tbai_response_values(self, response, **kwargs):
        values = kwargs
        if response.error:
            errno = response.errno
            strerror = response.strerror
            values.update({
                'state': TicketBaiResponseState.REQUEST_ERROR.value,
                'tbai_response_message_ids': [
                    (0, 0, {
                        'code': errno,
                        'description': strerror
                    })
                ]
            })
        else:
            xml_dict = XMLSchema(
                TicketBaiSchema.TicketBaiResponse.value).parse_xml(
                response.data)['TicketBaiResponse'] or {}
            state = xml_dict['Salida']['Estado']
            values.update({
                'xml': base64.encodebytes(response.data.encode('utf-8')),
                'state': state
            })
            if state == TicketBaiResponseState.RECEIVED.value:
                tbai_response_message_ids = [(0, 0, {
                    'code': xml_dict['Salida']['CSV'],
                    'description': {
                        'es_ES': xml_dict['Salida']['Descripcion'],
                        'eu_ES': xml_dict['Salida']['Azalpena']
                    }
                })]
                messages = xml_dict.get('Salida').get('ResultadosValidacion', False)
                if messages:
                    if isinstance(messages, dict):
                        messages = [messages]
                    for msg in messages:
                        tbai_response_message_ids.append((0, 0, {
                            'code': msg['Codigo'],
                            'description': {
                                'es_ES': msg['Descripcion'],
                                'eu_ES': msg['Azalpena']
                            }
                        }))
            elif state == TicketBaiResponseState.REJECTED.value:
                messages = xml_dict['Salida']['ResultadosValidacion']
                tbai_response_message_ids = []
                if isinstance(messages, dict):
                    messages = [messages]
                for msg in messages:
                    tbai_response_message_ids.append((0, 0, {
                        'code': msg['Codigo'],
                        'description': {
                            'es_ES': msg['Descripcion'],
                            'eu_ES': msg['Azalpena']
                        }
                    }))
            else:
                tbai_response_message_ids = [(0, 0, {
                    'code': state,
                    'description': _('Unknown TicketBAI response code.')
                })]
            values.update(tbai_response_message_ids=tbai_response_message_ids)
{'fraction_non_alphanumeric': 0.10155148095909731, 'fraction_numerical': 0.021626704278326282, 'mean_word_length': 1.9977452085682075, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 23}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4223758', 'n_tokens_mistral': 3504, 'n_tokens_neox': 3197, 'n_words': 537}