def _setSedeCessionario(self, partner, fatturapa): if not partner.street: raise UserError( _('Customer street is not set for %s.' % partner.name)) if not partner.city: raise UserError( _('Customer city is not set for %s.' % partner.name)) if not partner.country_id: raise UserError( _('Customer country is not set for %s.' % partner.name)) # TODO: manage address number in <NumeroCivico> if partner.codice_destinatario == 'XXXXXXX': fatturapa.FatturaElettronicaHeader.CessionarioCommittente.Sede = ( IndirizzoType(Indirizzo=encode_for_export(partner.street, 60), CAP='00000', Comune=encode_for_export(partner.city, 60), Provincia='EE', Nazione=partner.country_id.code)) else: if not partner.zip: raise UserError( _('Customer ZIP not set for %s.' % partner.name)) fatturapa.FatturaElettronicaHeader.CessionarioCommittente.Sede = ( IndirizzoType(Indirizzo=encode_for_export(partner.street, 60), CAP=partner.zip, Comune=encode_for_export(partner.city, 60), Nazione=partner.country_id.code)) if partner.state_id: fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ Sede.Provincia = partner.state_id.code return True
def _setSedeCedente(self, CedentePrestatore, company): if not company.street: raise UserError( _('Company %s, Street is not set.') % company.display_name) if not company.zip: raise UserError( _('Company %s, ZIP is not set.') % company.display_name) if not company.city: raise UserError( _('Company %s, City is not set.') % company.display_name) if not company.country_id: raise UserError( _('Company %s, Country is not set.') % company.display_name) # TODO: manage address number in <NumeroCivico> # see https://github.com/OCA/partner-contact/pull/96 CedentePrestatore.Sede = IndirizzoType( Indirizzo=encode_for_export(company.street, 60), CAP=company.zip, Comune=encode_for_export(company.city, 60), Nazione=company.country_id.code) if company.partner_id.state_id: CedentePrestatore.Sede.Provincia = company.partner_id.state_id.code return True
def _setSedeCedente(self, CedentePrestatore, company): res = super(WizardExportFatturapa, self)._setSedeCedente(CedentePrestatore, company) if self.env.context.get("rc_supplier"): partner = self.env.context["rc_supplier"] if not partner.street: raise UserError( _('Partner %s, Street is not set.') % partner.display_name) if not partner.city: raise UserError( _('Partner %s, City is not set.') % partner.display_name) if not partner.country_id: raise UserError( _('Partner %s, Country is not set.') % partner.display_name) if partner.codice_destinatario == 'XXXXXXX': CedentePrestatore.Sede = (IndirizzoType( Indirizzo=encode_for_export(partner.street, 60), CAP='00000', Comune=encode_for_export(partner.city, 60), Provincia='EE', Nazione=partner.country_id.code)) else: if not partner.zip: raise UserError( _('Partner %s, ZIP is not set.') % partner.display_name) CedentePrestatore.Sede = IndirizzoType( Indirizzo=encode_for_export(partner.street, 60), CAP=partner.zip, Comune=encode_for_export(partner.city, 60), Nazione=partner.country_id.code) if partner.state_id: CedentePrestatore.Sede.Provincia = partner.state_id.code return res
def setDettaglioLinee(self, invoice, body): super().setDettaglioLinee(invoice, body) force_dichiarazione_intento_ids = invoice.dichiarazione_intento_ids.browse( ) line_no = 1 for line in invoice.invoice_line_ids: if line.force_dichiarazione_intento_id: force_dichiarazione_intento_ids |= line.force_dichiarazione_intento_id line_no += 1 to_add = invoice.dichiarazione_intento_ids - force_dichiarazione_intento_ids if not to_add: return DettaglioLinea = DettaglioLineeType( NumeroLinea=str(line_no), Descrizione=encode_for_export("Altre lettere d'intento", 1000), PrezzoUnitario="0.00", PrezzoTotale="0.00", AliquotaIVA="0.00", Natura="N1", ) for dec in to_add: dati_gestionali = AltriDatiGestionaliType( TipoDato="INTENTO", RiferimentoTesto=encode_for_export(dec.telematic_protocol, 60), RiferimentoData=dec.date) DettaglioLinea.AltriDatiGestionali.append(dati_gestionali) body.DatiBeniServizi.DettaglioLinee.append(DettaglioLinea)
def get_all_taxes(record): """Generate summary data for taxes. Odoo does that for us, but only for nonzero taxes. SdI expects a summary for every tax mentioned in the invoice, even those with price_total == 0. """ out_computed = {} # existing tax lines tax_ids = record.line_ids.filtered(lambda line: line.tax_line_id) for tax_id in tax_ids: tax_line_id = tax_id.tax_line_id aliquota = format_numbers(tax_line_id.amount) key = "{}_{}".format(aliquota, tax_line_id.kind_id.code) out_computed[key] = { "AliquotaIVA": aliquota, "Natura": tax_line_id.kind_id.code, # 'Arrotondamento':'', "ImponibileImporto": tax_id.tax_base_amount, "Imposta": tax_id.price_total, "EsigibilitaIVA": tax_line_id.payability, } if tax_line_id.law_reference: out_computed[key][ "RiferimentoNormativo"] = encode_for_export( tax_line_id.law_reference, 100) out = {} # check for missing tax lines for line in record.invoice_line_ids: if line.display_type in ("line_section", "line_note"): # notes and sections # we ignore line.tax_ids altogether, # (it is popolated with a default tax usually) # and use another tax in the template continue for tax_id in line.tax_ids: aliquota = format_numbers(tax_id.amount) key = "{}_{}".format(aliquota, tax_id.kind_id.code) if key in out_computed: continue if key not in out: out[key] = { "AliquotaIVA": aliquota, "Natura": tax_id.kind_id.code, # 'Arrotondamento':'', "ImponibileImporto": line.price_subtotal, "Imposta": 0.0, "EsigibilitaIVA": tax_id.payability, } if tax_id.law_reference: out[key][ "RiferimentoNormativo"] = encode_for_export( tax_id.law_reference, 100) else: out[key]["ImponibileImporto"] += line.price_subtotal out[key]["Imposta"] += 0.0 out.update(out_computed) return out
def _setDatiAnagraficiCessionario(self, partner, fatturapa): fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici = DatiAnagraficiCessionarioType() if not partner.vat and not partner.fiscalcode: if ( partner.codice_destinatario == 'XXXXXXX' and partner.country_id.code and partner.country_id.code != 'IT' ): # SDI accepts missing VAT# for foreign customers by setting a # fake IdCodice and a valid IdPaese # Otherwise raise error if we have no VAT# and no Fiscal code fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici.IdFiscaleIVA = IdFiscaleType( IdPaese=partner.country_id.code, IdCodice='99999999999') else: raise UserError( _('VAT number and fiscal code are not set for %s.') % partner.name) if partner.fiscalcode: fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici.CodiceFiscale = partner.fiscalcode if partner.vat: fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici.IdFiscaleIVA = IdFiscaleType( IdPaese=partner.vat[0:2], IdCodice=partner.vat[2:]) if partner.company_name: # This is valorized by e-commerce orders typically fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici.Anagrafica = AnagraficaType( Denominazione=partner.company_name) elif partner.company_type == 'company': fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici.Anagrafica = AnagraficaType( Denominazione=encode_for_export(partner.name, 80)) elif partner.company_type == 'person': if not partner.lastname or not partner.firstname: raise UserError( _("Partner %s must have name and surname.") % partner.name) fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici.Anagrafica = AnagraficaType( Cognome=encode_for_export(partner.lastname, 60), Nome=encode_for_export(partner.firstname, 60) ) if partner.eori_code: fatturapa.FatturaElettronicaHeader.CessionarioCommittente.\ DatiAnagrafici.Anagrafica.CodEORI = partner.eori_code return True
def setDettaglioLinea(self, line_no, line, body, price_precision, uom_precision): if not line.invoice_line_tax_ids: raise UserError( _("Invoice line %s does not have tax.") % line.name) if len(line.invoice_line_tax_ids) > 1: raise UserError( _("Too many taxes for invoice line %s.") % line.name) aliquota = line.invoice_line_tax_ids[0].amount AliquotaIVA = '%.2f' % float_round(aliquota, 2) line.ftpa_line_number = line_no prezzo_unitario = self._get_prezzo_unitario(line) DettaglioLinea = DettaglioLineeType( NumeroLinea=str(line_no), Descrizione=encode_for_export(line.name, 1000), PrezzoUnitario='{prezzo:.{precision}f}'.format( prezzo=prezzo_unitario, precision=price_precision), Quantita='{qta:.{precision}f}'.format(qta=line.quantity, precision=uom_precision), UnitaMisura=line.uom_id and (unidecode(line.uom_id.name)) or None, PrezzoTotale='%.2f' % float_round(line.price_subtotal, 2), AliquotaIVA=AliquotaIVA) DettaglioLinea.ScontoMaggiorazione.extend( self.setScontoMaggiorazione(line)) if aliquota == 0.0: if not line.invoice_line_tax_ids[0].kind_id: raise UserError( _("No 'nature' field for tax %s.") % line.invoice_line_tax_ids[0].name) DettaglioLinea.Natura = line.invoice_line_tax_ids[0].kind_id.code if line.admin_ref: DettaglioLinea.RiferimentoAmministrazione = line.admin_ref if line.product_id: if line.product_id.default_code: CodiceArticolo = CodiceArticoloType( CodiceTipo=self.env['ir.config_parameter'].sudo( ).get_param('fatturapa.codicetipo.odoo', 'ODOO'), CodiceValore=encode_for_export( line.product_id.default_code, 35, 'ascii')) DettaglioLinea.CodiceArticolo.append(CodiceArticolo) if line.product_id.barcode: CodiceArticolo = CodiceArticoloType( CodiceTipo='EAN', CodiceValore=encode_for_export(line.product_id.barcode, 35, 'ascii')) DettaglioLinea.CodiceArticolo.append(CodiceArticolo) body.DatiBeniServizi.DettaglioLinee.append(DettaglioLinea) return DettaglioLinea
def setDatiRiepilogo(self, invoice, body): if not invoice.tax_line_ids: raise UserError( _("Invoice {invoice} has no tax lines").format( invoice=invoice.display_name)) for tax_line in invoice.tax_line_ids: tax = tax_line.tax_id riepilogo = DatiRiepilogoType( AliquotaIVA='%.2f' % float_round(tax.amount, 2), ImponibileImporto='%.2f' % float_round(tax_line.base, 2), Imposta='%.2f' % float_round(tax_line.amount, 2)) if tax.amount == 0.0: if not tax.kind_id: raise UserError( _("No 'nature' field for tax %s.") % tax.name) riepilogo.Natura = tax.kind_id.code if not tax.law_reference: raise UserError( _("No 'law reference' field for tax %s.") % tax.name) riepilogo.RiferimentoNormativo = encode_for_export( tax.law_reference, 100) if tax.payability: riepilogo.EsigibilitaIVA = tax.payability # TODO # el.remove(el.find('SpeseAccessorie')) # el.remove(el.find('Arrotondamento')) body.DatiBeniServizi.DatiRiepilogo.append(riepilogo) return True
def setDettaglioLinea(self, line_no, line, body, price_precision, uom_precision): if not line.invoice_line_tax_ids: raise UserError( _("Invoice line %s does not have tax.") % line.name) if len(line.invoice_line_tax_ids) > 1: raise UserError( _("Too many taxes for invoice line %s.") % line.name) aliquota = line.invoice_line_tax_ids[0].amount AliquotaIVA = '%.2f' % float_round(aliquota, 2) line.ftpa_line_number = line_no prezzo_unitario = self._get_prezzo_unitario(line) DettaglioLinea = DettaglioLineeType( NumeroLinea=str(line_no), Descrizione=encode_for_export(line.name, 1000), PrezzoUnitario='{prezzo:.{precision}f}'.format( prezzo=prezzo_unitario, precision=price_precision), Quantita='{qta:.{precision}f}'.format(qta=line.quantity, precision=uom_precision), UnitaMisura=line.uom_id and (unidecode(line.uom_id.name)) or None, PrezzoTotale='%.2f' % float_round(line.price_subtotal, 2), AliquotaIVA=AliquotaIVA) DettaglioLinea.ScontoMaggiorazione.extend( self.setScontoMaggiorazione(line)) if aliquota == 0.0: if not line.invoice_line_tax_ids[0].kind_id: raise UserError( _("No 'nature' field for tax %s.") % line.invoice_line_tax_ids[0].name) DettaglioLinea.Natura = line.invoice_line_tax_ids[0].kind_id.code if line.invoice_line_tax_ids[0].kind_id.code == 'N2.1' and \ line.invoice_id.partner_id.country_id.code in [ 'AT', 'BE', 'BG', 'CY', 'HR', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'CZ', 'RO', 'SK', 'SI', 'ES', 'SE', 'HU' ]: dati_gestionali = AltriDatiGestionaliType() dati_gestionali.TipoDato = 'INVCONT' DettaglioLinea.AltriDatiGestionali.append(dati_gestionali) if line.admin_ref: DettaglioLinea.RiferimentoAmministrazione = line.admin_ref if line.product_id: product_code = line.product_id.default_code if product_code: CodiceArticolo = CodiceArticoloType( CodiceTipo=self.env['ir.config_parameter'].sudo(). get_param('fatturapa.codicetipo.odoo', 'ODOO'), CodiceValore=product_code[:35], ) DettaglioLinea.CodiceArticolo.append(CodiceArticolo) product_barcode = line.product_id.barcode if product_barcode: CodiceArticolo = CodiceArticoloType( CodiceTipo='EAN', CodiceValore=product_barcode[:35], ) DettaglioLinea.CodiceArticolo.append(CodiceArticolo) body.DatiBeniServizi.DettaglioLinee.append(DettaglioLinea) return DettaglioLinea
def get_type_attachment(doc_id): mini_map = { "application/pdf": "PDF", "image/png": "PNG", } attachment_type = mini_map.get(doc_id.mimetype, False) return encode_for_export(attachment_type, 10) if attachment_type else False
def setAttachments(self, invoice, body): if invoice.fatturapa_doc_attachments: for doc_id in invoice.fatturapa_doc_attachments: file_name, file_extension = os.path.splitext(doc_id.name) attachment_name = doc_id.datas_fname if len( doc_id.datas_fname) <= 60 else ''.join([ file_name[:(60 - len(file_extension))], file_extension ]) AttachDoc = AllegatiType( NomeAttachment=encode_for_export(attachment_name, 60), Attachment=base64.decodestring(doc_id.datas)) body.Allegati.append(AttachDoc) return True
def setDettaglioLinea(self, line_no, line, body, price_precision, uom_precision): DettaglioLinea = super().setDettaglioLinea(line_no, line, body, price_precision, uom_precision) if line.force_dichiarazione_intento_id: dati_gestionali = AltriDatiGestionaliType( TipoDato="INTENTO", RiferimentoTesto=encode_for_export( line.force_dichiarazione_intento_id.telematic_protocol, 60), RiferimentoData=line.force_dichiarazione_intento_id.date) DettaglioLinea.AltriDatiGestionali.append(dati_gestionali) return DettaglioLinea
def get_causale(invoice): res = [] if invoice.narration: # max length of Causale is 200 caus_list = invoice.narration.split("\n") for causale in caus_list: if not causale: continue causale_list_200 = [ causale[i:i + 200] for i in range(0, len(causale), 200) ] for causale200 in causale_list_200: # Remove non latin chars, but go back to unicode string, # as expected by String200LatinType causale = encode_for_export(causale200, 200) res.append(causale) return res
def setDatiGeneraliDocumento(self, invoice, body): # TODO DatiSAL body.DatiGenerali = DatiGeneraliType() if not invoice.number: raise UserError( _('Invoice %s does not have a number.' % invoice.display_name)) TipoDocumento = invoice.fiscal_document_type_id.code ImportoTotaleDocumento = invoice.amount_total if invoice.split_payment: ImportoTotaleDocumento += invoice.amount_sp body.DatiGenerali.DatiGeneraliDocumento = DatiGeneraliDocumentoType( TipoDocumento=TipoDocumento, Divisa=invoice.currency_id.name, Data=invoice.date_invoice, Numero=invoice.number, ImportoTotaleDocumento='%.2f' % float_round(ImportoTotaleDocumento, 2)) # TODO: DatiRitenuta, DatiBollo, DatiCassaPrevidenziale, # ScontoMaggiorazione, Arrotondamento, if invoice.comment: # max length of Causale is 200 caus_list = invoice.comment.split('\n') for causale in caus_list: if not causale: continue causale_list_200 = \ [causale[i:i+200] for i in range(0, len(causale), 200)] for causale200 in causale_list_200: # Remove non latin chars, but go back to unicode string, # as expected by String200LatinType causale = encode_for_export(causale200, 200) body.DatiGenerali.DatiGeneraliDocumento.Causale\ .append(causale) if invoice.company_id.fatturapa_art73: body.DatiGenerali.DatiGeneraliDocumento.Art73 = 'SI' return True
def _setDatiAnagraficiRappresentanteFiscale(self, partner, fatturapa): fatturapa.FatturaElettronicaHeader.RappresentanteFiscale = ( RappresentanteFiscaleType()) fatturapa.FatturaElettronicaHeader.RappresentanteFiscale.\ DatiAnagrafici = DatiAnagraficiRappresentanteType() if not partner.vat and not partner.fiscalcode: raise UserError( _('VAT number and fiscal code are not set for %s.') % partner.name) if partner.fiscalcode: fatturapa.FatturaElettronicaHeader.RappresentanteFiscale.\ DatiAnagrafici.CodiceFiscale = partner.fiscalcode if partner.vat: fatturapa.FatturaElettronicaHeader.RappresentanteFiscale.\ DatiAnagrafici.IdFiscaleIVA = IdFiscaleType( IdPaese=partner.vat[0:2], IdCodice=partner.vat[2:]) fatturapa.FatturaElettronicaHeader.RappresentanteFiscale.\ DatiAnagrafici.Anagrafica = AnagraficaType( Denominazione=encode_for_export(partner.name, 80)) if partner.eori_code: fatturapa.FatturaElettronicaHeader.RappresentanteFiscale.\ DatiAnagrafici.Anagrafica.CodEORI = partner.eori_code return True
def get_nome_attachment(doc_id): file_name, file_extension = os.path.splitext(doc_id.name) attachment_name = ( doc_id.name if len(doc_id.name) <= 60 else "".join( [file_name[:(60 - len(file_extension))], file_extension])) return encode_for_export(attachment_name, 60)