Created
May 9, 2020 13:41
-
-
Save gigidn/c4d1ded1410981f0b7d102dfb44cbad8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class OdooFatturaElettronica(models.Model): | |
_inherit = 'account.invoice' | |
state = fields.Selection(selection_add=[ | |
('waiting', 'Waiting'), | |
('send_sdi', 'Send SDI'), | |
]) | |
electronic_invoice_state = fields.Selection([ | |
('0', 'Non Elaborata'), | |
('1', 'Presa in carico',), | |
('2', 'Errore Elaborazione'), | |
('3', 'Inviata'), | |
('4', 'Scartata'), | |
('5', 'Non Consegnata'), | |
('6', 'Recapito Impossibile'), | |
('7', 'Consegnata'), | |
('8', 'Accettata'), | |
('9', 'Rifiutata'), | |
('10', 'Decorrenza Termini') | |
],string='e-Invoice Status', index=True, readonly=True, default='0', | |
track_visibility='onchange', copy=False, | |
help = " 1 - Presa in carico: La fattura è in attesa di essere elaborata dai sistemi di Teuron/Aruba e " \ | |
"non risulta ancora trasmessa a SDI.\n " \ | |
" 2 - Errore Elaborazione: Si è verificato un errore nell’elaborazione della fattura " \ | |
"(Problema tecnico nell'invio allo SDI).\n " \ | |
" 3 - Inviata: La fattura è stata inviata al Sistema di Interscambio(SDI).\n " \ | |
" 4 - Scartata: [NS] La fattura è stata rifiutata dal Sistema di Interscambio(SDI) " \ | |
"che ha restituito un codice di errore specifico.\n" \ | |
" 5 - Non Consegnata: [MC] La consegna della fattura da parte del " \ | |
"Sistema di Interscambio(SDI) è fallita. Solo per le PA, verranno fatti " \ | |
"ulteriori tentativi di consegna nei 10 giorni seguenti.\n " \ | |
" 6 - Recapito Impossibile: [AT] La consegna della fattura da parte del " \ | |
"Sistema di Intercambio(SDI) non è andata a buon fine. " \ | |
"Non verranno effettuati ulteriori tentativi di consegna.\n" \ | |
" 7 - Consegnata: [RC] La fattura è stata consegnata da parte del Sistema di Interscambio(SDI).\n" \ | |
" 8 - Accettata: [NE(EC01)] Il cliente ha accettato la fattura consegnata " \ | |
"dal Sistema di Interscambio(SDI).\n" \ | |
" 9 - Rifiutata: [NE(EC02)] Il cliente ha rifiutato la fattura consegnata " \ | |
"dal Sistema di Interscambio(SDI).\n" \ | |
" 10 - Decorrenza Termini: [DT] La fattura è stata consegnata da parte del " \ | |
"sistema di Interscambio(SDI) ma il cliente non ha inoltrato alcuna risposta " \ | |
"nei 15 successivi alla consegna.\n" \ | |
" 0 - La fattura non è ancora stata inviata." | |
) | |
doc_count = fields.Integer(compute='_compute_attached_docs_count', | |
string="Number of documents attached") | |
message_count = fields.Integer(compute='_compute_message_count', | |
string="Number of elettronic invoice message") | |
is_elettronic_invoice = fields.Boolean(compute='_compute_fe_nature', readonly=True) | |
@api.multi | |
def _compute_message_state(self): | |
StatiMsg ={'0': 'Non Elaborata', | |
'1': 'Presa in carico', | |
'2': 'Errore Elaborazione', | |
'3': 'Inviata', | |
'4': 'Scartata', | |
'5': 'Non Consegnata', | |
'6': 'Recapito Impossibile', | |
'7': 'Consegnata', | |
'8': 'Accettata', | |
'9': 'Rifiutata', | |
'10': 'Decorrenza Termini' } | |
for invoice in self: | |
messages_ids = self.env['fe.message'].search([ | |
('res_id', '=', invoice.id) | |
]) | |
last_messages= messages_ids and max(messages_ids) | |
if str(last_messages.state): | |
if str(last_messages.state) in StatiMsg.keys(): | |
invoice.electronic_invoice_state = StatiMsg[str(last_messages.state)] | |
# timestamp = last_messages.create_date | |
# date_time = datetime.fromtimestamp(timestamp) | |
# data = datetime.fromtimestamp(timestamp) | |
if type(last_messages.date_receipt) is fields.datetime: | |
invoice.datereceipt=last_messages.create_date.strftime('%Y-%m-%d %H:%M:%S') | |
datereceipt = fields.Datetime(compute='_compute_message_state', store=True, track_visibility='onchange', | |
string="Date of Message of elettronic invoice") | |
related_documents = fields.One2many( | |
'fatturaelettronica.related_document', 'invoice_id', | |
'Related Documents', copy=False | |
) | |
# other_management_data = fields.One2many( | |
# 'account.invoice.line', 'id', 'test' | |
# #'Other Management Data'#, copy=False | |
#) | |
stamp_amount = fields.Monetary('Digital Stamp') | |
autoinvoice = fields.Boolean('Autoinvoice') | |
@api.multi | |
def _check_duplicate_supplier_reference(self): | |
for invoice in self: | |
# refuse to validate a vendor bill/credit note if there already exists one with the same reference for the same partner, | |
# because it's probably a double encoding of the same bill/credit note | |
if invoice.type in ('in_invoice', 'in_refund') and invoice.reference: | |
if self.search([('type', '=', invoice.type), ('reference', '=', invoice.reference), ('company_id', '=', invoice.company_id.id), | |
('commercial_partner_id', '=', invoice.commercial_partner_id.id), ('id', '!=', invoice.id)]).filtered(lambda r: r.date_invoice.year == invoice.date_invoice.year): | |
# if self.search([('type', '=', invoice.type), ('reference', '=', invoice.reference), ('company_id', '=', invoice.company_id.id), ('commercial_partner_id', '=', invoice.commercial_partner_id.id), ('id', '!=', invoice.id)]): | |
raise UserError(_("Duplicated vendor reference detected. You probably encoded twice the same vendor bill/credit note.")) | |
def _check_exist_xml(self,inv_id): | |
messages = self.env['fe.message'].search( | |
[('res_model', '=', 'account.invoice'), | |
('res_id', '=', inv_id), | |
('is_part', '=', False), | |
('state', '=', '0') | |
] | |
) | |
for message in messages: | |
message.ir_attachment_id.unlink() | |
@api.multi | |
def action_invoice_open(self): | |
#self.ensure_one() | |
# if self: | |
#self.ensure_one() | |
for invoice in self: | |
messages_ids = self.env['fe.message'].search([ | |
('res_id', '=', invoice.id) | |
]) | |
for msg in messages_ids: | |
if msg.fe_version == 'FSM10': | |
if invoice.amount_total <= 0: | |
raise UserError(_("E' possibile confermare solo fatture positive")) | |
if invoice.is_elettronic_invoice: | |
self._check_exist_xml(invoice.id) | |
return super(OdooFatturaElettronica, self).action_invoice_open() | |
#Metodi per gestire il workflow ed i passaggi di stato della fattura | |
@api.multi | |
def sign_invoice(self): | |
""" | |
Questo metodo ha il solo scopo di essere esteso ma moduli | |
specilizzati che ne gestiscono il comportamento. | |
L'implementazione base imposta lo stato della fattura come firmata | |
ma non esegue nessuna firma reale sul file. | |
Lo stato della fattura elettronica passa ad 1 . presa in carico. | |
:return: | |
""" | |
for invoice in self: | |
if invoice.state != 'open': | |
raise UserError(_("E' possibile firmare solo fatture validate")) | |
self.write({ | |
'electronic_invoice_state': '0' | |
}) | |
@api.multi | |
def waiting(self): | |
""" | |
Segna la fattura come attesa invio al sistema di interscambio (SDI) | |
e ne blocca ogni azione su di esse in attesa di conferma. | |
:return: | |
""" | |
self.write({ | |
'state': 'waiting', | |
'electronic_invoice_state': '0' | |
}) | |
@api.multi | |
def force_open(self): | |
""" | |
Metodo tecnico, da user con funzioni di amministrazione per riportare | |
la fattura nello stato aperto in caso di errori sulla sincronia | |
degli stati | |
:return: | |
""" | |
self.write({ | |
'state': 'open', | |
'electronic_invoice_state': '2' | |
}) | |
@api.multi | |
def send_sdi(self): | |
""" | |
Segna la fattura come inviata al sistema di interscambio (SDI) | |
e ne blocca ogni azione su di esse in attesa di conferma. | |
Se le fatture si trovano nello stato bozza vengono validate. | |
:return: | |
""" | |
for inv in self: | |
try: | |
if inv.state == 'draft': | |
inv.action_invoice_open() | |
elif inv.state in ('paid', 'open'): | |
if inv.state == 'paid': | |
self.env['account.move.line'].search([ | |
('invoice_id', '=', inv.id) | |
]).remove_move_reconcile() | |
date = inv.date | |
inv.action_cancel() | |
inv.action_invoice_draft() | |
inv.write({ | |
'electronic_invoice_state': '0', | |
'state': 'draft', | |
'date': date | |
}) | |
self._check_exist_xml(inv.id) | |
inv.action_invoice_open() | |
femessage = self.env['fe.message'].search([ | |
('res_id','=',inv.id), | |
('res_model','=','account.invoice'), | |
('state','=','0') | |
]) | |
femessage.send_sdi() | |
inv.write({ | |
'state': 'send_sdi', | |
'electronic_invoice_state': femessage.state | |
}) | |
except Exception as ex: | |
raise UserError('***GENERIC ERROR ON:' + '\n' + str(ex)) | |
def error_process(self, err_msg=None): | |
""" | |
Il sistema di interscambio ha rifiutato la fattura. | |
:return: | |
""" | |
for inv in self: | |
inv.action_cancel() | |
inv.action_invoice_draft() | |
inv.write({ | |
'electronic_invoice_state': '2' | |
}) | |
inv.message_post( | |
subject=_("Error Processing"), | |
body=_("HUB error sending invoice: %s " | |
) % err_msg | |
) | |
def reject_sdi(self, datarec=None): | |
""" | |
Il sistema di interscambio ha rifiutato la fattura. | |
:return: | |
""" | |
for inv in self: | |
date = inv.date | |
inv.action_cancel() | |
inv.action_invoice_draft() | |
if datarec: | |
inv.write({ | |
'electronic_invoice_state': '4', | |
'date' : date, | |
'datereceipt': datarec | |
}) | |
else: | |
inv.write({ | |
'electronic_invoice_state': '4' | |
}) | |
def delivery_sdi(self, datarec=None): | |
""" | |
Il sistema di interscambio ha correttamente inviato la fattura | |
al cliente. | |
:return: | |
""" | |
if datarec: | |
self.write({ | |
'state': 'open', | |
'electronic_invoice_state': '7', | |
'datereceipt': datarec | |
}) | |
else: | |
self.write({ | |
'state': 'open', | |
'electronic_invoice_state': '7' | |
}) | |
def delivery_sdi_fail(self, datarec=None): | |
""" | |
Il sistema di interscambio non è riuscito ad inviare la fattura | |
al cliente. La fattura si considera emessa ma bisogna informare | |
il cliente in altro modo. | |
:return: | |
""" | |
if datarec: | |
self.write({ | |
'state': 'open', | |
'electronic_invoice_state': '6', | |
'datereceipt': datarec | |
}) | |
else: | |
self.write({ | |
'state': 'open', | |
'electronic_invoice_state': '6' | |
}) | |
# self.write({ | |
# 'state': 'open', | |
# 'electronic_invoice_state': '6' | |
# }) | |
def sdi_unable_to_delivery(self, datarec=None): | |
vals = { | |
'state': 'open', | |
'electronic_invoice_state': '5', | |
} | |
if datarec: | |
vals['datereceipt'] = datarec | |
self.write(vals) | |
def accept_from_client(self, datarec=None): | |
""" | |
Il cliente ha accettato la fattura, lo stato della fattura elettronica | |
passa a 8 - Accettata: [NE(EC01)]. Si ha a disposizione la notifica esito | |
che andrebbe allegata al file della comunicazione. | |
:return: | |
""" | |
if datarec: | |
self.write({ | |
'state': 'open', | |
'electronic_invoice_state': '8', | |
'datereceipt': datarec | |
}) | |
else: | |
self.write({ | |
'electronic_invoice_state': '8' | |
}) | |
def maxtime_reached(self, datarec=None): | |
""" | |
Il cliente ha accettato la fattura, lo stato della fattura elettronica | |
passa a 8 - Accettata: [NE(EC01)]. Si ha a disposizione la notifica esito | |
che andrebbe allegata al file della comunicazione. | |
:return: | |
""" | |
if datarec: | |
self.write({ | |
'state': 'open', | |
'electronic_invoice_state': '10', | |
'datereceipt': datarec | |
}) | |
else: | |
self.write({ | |
'electronic_invoice_state': '10' | |
}) | |
def reject_from_client(self, datarec=None): | |
""" | |
Il cliente ha rifiutato la fattura. Solo per le fatture emesse verso una PA | |
il sistema di interscambio restituisce NE | |
Stato fattura elettronica: 9 - Rifiutata: [NE(EC02)]. | |
La fattura viene riportata in bozza. | |
:return: | |
""" | |
for inv in self: | |
inv.action_cancel() | |
inv.action_invoice_draft() | |
if datarec: | |
inv.write({ | |
'electronic_invoice_state': '9', | |
'datereceipt': datarec | |
}) | |
else: | |
inv.write({ | |
'electronic_invoice_state': '9' | |
}) | |
@api.multi | |
def get_receivable_payable_line(self): | |
# return the move line receivable or payable | |
self.ensure_one() | |
return self.sudo().move_id.line_ids.filtered( | |
lambda r: r.account_id.internal_type in ('receivable', 'payable')) | |
def pre_validate(self): | |
raise Warning( | |
_("Funzione non ancora implementata ")) | |
def _get_vat(self,tax_ids): | |
tax_ids = [tax_id for tax_id in tax_ids if tax_id.is_vat] | |
if len(tax_ids) != 1: | |
raise ValidationError( | |
_('One and only one VAT for line are allowed')) | |
return tax_ids[0] | |
def _compute_attached_docs_count(self): | |
attachment = self.env['ir.attachment'] | |
for invoice in self: | |
invoice.doc_count = attachment.search_count([ | |
'&', | |
('res_model', '=', 'account.invoice'), | |
('res_id', '=', invoice.id) | |
]) | |
def _compute_message_count(self): | |
message = self.env['fe.message'] | |
for invoice in self: | |
invoice.message_count = message.search_count([ | |
'&', | |
('res_model', '=', 'account.invoice'), | |
('res_id', '=', invoice.id) | |
]) | |
def _compute_message_state(self): | |
StatiMsg ={'0': 'Non Elaborata', | |
'1': 'Presa in carico', | |
'2': 'Errore Elaborazione', | |
'3': 'Inviata', | |
'4': 'Scartata', | |
'5': 'Non Consegnata', | |
'6': 'Recapito Impossibile', | |
'7': 'Consegnata', | |
'8': 'Accettata', | |
'9': 'Rifiutata', | |
'10': 'Decorrenza Termini' } | |
for invoice in self: | |
messages_ids = self.env['fe.message'].search([ | |
('res_id', '=', invoice.id) | |
]) | |
last_messages= messages_ids and max(messages_ids) | |
if str(last_messages.state): | |
if str(last_messages.state) in StatiMsg.keys(): | |
invoice.messagestate = StatiMsg[str(last_messages.state)] | |
# timestamp = last_messages.create_date | |
# date_time = datetime.fromtimestamp(timestamp) | |
# data = datetime.fromtimestamp(timestamp) | |
if type(last_messages.create_date) is fields.datetime: | |
invoice.date_create=last_messages.create_date.strftime('%Y-%m-%d %H:%M:%S') | |
def _compute_fe_nature(self): | |
for invoice in self: | |
if (invoice.partner_id and invoice.partner_id.electronic_invoice_subjected) or invoice.autoinvoice: | |
invoice.is_elettronic_invoice = True | |
@api.multi | |
def invoice_validate(self): | |
result = super(OdooFatturaElettronica, self).invoice_validate() | |
for invoice in self: | |
if invoice.is_elettronic_invoice and \ | |
(invoice.type == 'out_invoice' or invoice.type == 'out_refund' or invoice.autoinvoice): | |
num_line = 0 | |
for line in invoice.invoice_line_ids: | |
num_line += 1 | |
line.sequence = num_line | |
line.xml_line_id = num_line | |
try: | |
invoice.crea_fattura_elettronica() | |
except ( | |
SimpleFacetValueError, | |
SimpleTypeValueError, | |
pyxb.ValidationError | |
) as ve: | |
raise UserError(ve.details()) | |
invoice.waiting() | |
return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment