File: fattura_semplificata.py

package info (click to toggle)
python-a38 0.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 440 kB
  • sloc: python: 4,065; xml: 174; makefile: 80; sh: 14
file content (159 lines) | stat: -rw-r--r-- 6,387 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
from __future__ import annotations

from . import consts, fields, models
from .fattura import (Allegati, FullNameMixin, IdFiscaleIVA, IdTrasmittente,
                      IscrizioneREA, Sede, StabileOrganizzazione)

NS10 = "http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.0"


class DatiTrasmissione(models.Model):
    id_trasmittente = IdTrasmittente
    progressivo_invio = fields.ProgressivoInvioField()
    formato_trasmissione = fields.StringField(length=5, choices=("FSM10",))
    codice_destinatario = fields.StringField(null=True, min_length=6, max_length=7, default="0000000")
    pec_destinatario = fields.StringField(null=True, min_length=8, max_length=256, xmltag="PECDestinatario")


class RappresentanteFiscale(FullNameMixin, models.Model):
    id_fiscale_iva = IdFiscaleIVA
    denominazione = fields.StringField(max_length=80, null=True)
    nome = fields.StringField(max_length=60, null=True)
    cognome = fields.StringField(max_length=60, null=True)


class CedentePrestatore(FullNameMixin, models.Model):
    id_fiscale_iva = IdFiscaleIVA
    codice_fiscale = fields.StringField(min_length=11, max_length=16, null=True)
    denominazione = fields.StringField(max_length=80, null=True)
    nome = fields.StringField(max_length=60, null=True)
    cognome = fields.StringField(max_length=60, null=True)
    sede = Sede
    stabile_organizzazione = fields.ModelField(StabileOrganizzazione, null=True)
    rappresentante_fiscale = models.ModelField(RappresentanteFiscale, null=True)
    iscrizione_rea = fields.ModelField(IscrizioneREA, null=True)
    regime_fiscale = fields.StringField(
            length=4, choices=("RF01", "RF02", "RF04", "RF05", "RF06", "RF07",
                               "RF08", "RF09", "RF10", "RF11", "RF12", "RF13",
                               "RF14", "RF15", "RF16", "RF17", "RF18", "RF19"))


class IdentificativiFiscali(models.Model):
    id_fiscale_iva = IdFiscaleIVA
    codice_fiscale = fields.StringField(min_length=11, max_length=16, null=True)


class AltriDatiIdentificativi(FullNameMixin, models.Model):
    denominazione = fields.StringField(max_length=80, null=True)
    nome = fields.StringField(max_length=60, null=True)
    cognome = fields.StringField(max_length=60, null=True)
    sede = Sede
    stabile_organizzazione = fields.ModelField(StabileOrganizzazione, null=True)
    rappresentante_fiscale = models.ModelField(RappresentanteFiscale, null=True)


class CessionarioCommittente(models.Model):
    identificativi_fiscali = IdentificativiFiscali
    altri_dati_identificativi = AltriDatiIdentificativi


class FatturaElettronicaHeader(models.Model):
    dati_trasmissione = DatiTrasmissione
    cedente_prestatore = CedentePrestatore
    cessionario_committente = CessionarioCommittente
    soggetto_emittente = fields.StringField(length=2, choices=("CC", "TZ"), null=True)


class DatiGeneraliDocumento(models.Model):
    tipo_documento = fields.StringField(length=4, choices=("TD07", "TD08", "TD09"))
    divisa = fields.StringField()
    data = fields.DateField()
    numero = fields.StringField(max_length=20)


class DatiFatturaRettificata(models.Model):
    numero_fr = fields.StringField(max_length=20, xmltag="NumeroFR")
    data_fr = fields.DateField(xmltag="DataFR")
    elementi_rettificati = fields.StringField(max_length=1000)


class DatiGenerali(models.Model):
    dati_generali_documento = DatiGeneraliDocumento
    dati_fattura_rettificata = fields.ModelField(DatiFatturaRettificata, null=True)


class DatiIVA(models.Model):
    imposta = fields.DecimalField(max_length=15)
    aliquota = fields.DecimalField(max_length=6)


class DatiBeniServizi(models.Model):
    descrizione = fields.StringField(max_length=1000)
    importo = fields.DecimalField(max_length=15)
    dati_iva = DatiIVA
    natura = fields.StringField(length=2, null=True, choices=consts.NATURA_IVA)
    riferimento_normativo = fields.StringField(max_length=100, null=True)


class FatturaElettronicaBody(models.Model):
    dati_generali = DatiGenerali
    dati_beni_servizi = fields.ModelListField(DatiBeniServizi)
    allegati = fields.ModelListField(Allegati, null=True)


class FatturaElettronicaSemplificata(models.Model):
    """
    Fattura elettronica semplificata
    """
    __xmlns__ = NS10
    fattura_elettronica_header = FatturaElettronicaHeader
    fattura_elettronica_body = fields.ModelListField(FatturaElettronicaBody, min_num=1)

    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)
        self.fattura_elettronica_header.dati_trasmissione.formato_trasmissione = self.get_versione()

    def get_versione(self):
        return "FSM10"

    def get_xmlattrs(self):
        return {"versione": self.get_versione()}

    def validate_model(self, validation):
        super().validate_model(validation)
        if self.get_versione() != self.fattura_elettronica_header.dati_trasmissione.formato_trasmissione:
            validation.add_error(
                    self.fattura_elettronica_header.dati_trasmissione._meta["formato_trasmissione"],
                    "formato_trasmissione should be {}".format(self.get_versione()),
                    code="00428")

    def to_xml(self, builder):
        with builder.element(self.get_xmltag(), **self.get_xmlattrs()) as b:
            with b.override_default_namespace(None) as b1:
                for name, field in self._meta.items():
                    field.to_xml(b1, getattr(self, name))

    def build_etree(self, lxml=False):
        """
        Build and return an ElementTree with the fattura in XML format
        """
        self.fattura_elettronica_header.dati_trasmissione.formato_trasmissione = self.get_versione()
        if lxml:
            from a38.builder import LXMLBuilder
            builder = LXMLBuilder()
        else:
            from a38.builder import Builder
            builder = Builder()
        builder.default_namespace = NS10
        self.to_xml(builder)
        return builder.get_tree()

    def from_etree(self, el):
        versione = el.attrib.get("versione", None)
        if versione is None:
            raise RuntimeError("root element {} misses attribute 'versione'".format(el.tag))

        if versione != self.get_versione():
            raise RuntimeError("root element versione is {} instead of {}".format(versione, self.get_versione()))

        return super().from_etree(el)