.. _tutorial_fatturazione/invoice_1: Lezione 5: Fattura e righe fattura ================================== In questa lezione verranno create le tabelle ``fattura``, ``fattura_riga`` e le rispettive risorse. .. raw:: html
Tabella fattura --------------- Creiamo ora la tabella ``fattura.py`` e mettiamo la colonna ``protocollo`` (ovvero un numero progressivo che dovrà ripartire ad ogni anno), ``cliente_id`` per collegare la tabella ``cliente``, e poi le colonne ``data``, ``totale_imponibile``, ``totale_iva`` e ``totale_fattura``. :: class Table(object): def config_db(self, pkg): tbl = pkg.table('fattura', pkey='id', name_long='Fattura', name_plural='Fattura', caption_field='protocollo') self.sysFields(tbl) tbl.column('protocollo', size='10', name_long='Protocollo') tbl.column('cliente_id', size='22', group='_', name_long='Cliente' ).relation('cliente.id', relation_name='fatture', mode='foreignkey', onDelete='raise') tbl.column('data', dtype='D', name_long='Data') tbl.column('totale_imponibile', dtype='N', name_long='Totale imponibile') tbl.column('totale_iva', dtype='N', name_long='Totale Iva') tbl.column('totale_fattura', dtype='N', name_long='Totale') Tabella fattura_riga ---------------------- Procediamo quindi a creare la tabella ``fattura_riga`` definendo le colonne necessarie. :: class Table(object): def config_db(self, pkg): tbl = pkg.table('fattura_riga', pkey='id', name_long='Fattura riga', name_plural='Fattura righe') self.sysFields(tbl) tbl.column('fattura_id', size='22', group='_', name_long='Fattura' ).relation('fattura.id', relation_name='righe', mode='foreignkey', onDelete='cascade') tbl.column('prodotto_id', size='22', group='_', name_long='Prodotto').relation( 'prodotto.id', relation_name='righe_fattura', mode='foreignkey', onDelete='raise') tbl.column('quantita', dtype='I', name_long=u'Quantità', name_short='Q.') tbl.column('prezzo_unitario', dtype='N', name_long='Prezzo unitario', name_short='P.U.') tbl.column('aliquota_iva', dtype='N', name_long='Aliquota iva', name_short='Iva') tbl.column('prezzo_totale', dtype='N', name_long='Prezzo totale', name_short='P.T.') tbl.column('iva', dtype='N', name_long='Tot.Iva') In particolare la colonna ``fattura_id`` rappresenta il collegamento con la fattura. Notiamo che nel descrivere la relazione aggiungeremo l'attributo ``onDelete='cascade'`` per indicare che in caso di cancellazione della fattura le righe fattura dovranno parimenti essere cancellate. Al contrario nella relazione con il ``prodotto_id`` useremo ``onDelete='raise'`` per indicare che il sistema dovrà impedire la cancellazione del record prodotto, se questo è referenziato da una riga fattura. Creazione tabella tipo_iva -------------------------- Per tenere conto del possibile diverso trattamento fiscale dei vari prodotti provvediamo a modificare la table ``prodotto`` aggiungendo la colonna ``tipo_iva_codice`` :: tbl.column('tipo_iva_codice', size=':5', group='_', name_long='!![it]Tipo iva').relation( 'tipo_iva.codice', relation_name='prodotti', mode='foreignkey', onDelete='raise') in relazione con l'apposita tabella di lookup ``tipo_iva`` che provvediamo a creare, come già visto nella :ref:`Lezione 3` :: class Table(object): def config_db(self, pkg): tbl = pkg.table('tipo_iva', pkey='codice', name_long='Tipo iva', name_plural='Tipi iva', caption_field='descrizione', lookup=True) self.sysFields(tbl, id=False) tbl.column('codice', size=':5', name_long='Codice') tbl.column('descrizione', name_long='Descrizione') tbl.column('aliquota', dtype='N', name_long='Aliquota') Inoltre modificheremo la form del prodotto per aggiungere il campo ``tipo_iva`` :: fb.field('tipo_iva_codice', validate_notnull=True) Quindi dopo aver - riallineato il database - resettato il server Procediamo a popolare la tabella ``tipo_iva`` e ad assegnare i valori di ``tipo_iva_codice`` ai prodotti già creati. .. raw:: html
Form fattura -------------- Adesso facciamo generare le risorse ``th_fattura`` e ``th_fattura_riga`` e modifichiamole per migliorarle. Come già visto precedentemente per il cliente, usiamo un ``BorderContainer`` per dividere la form in 2 regioni: quella superiore che conterrà i dati di testata e quella centrale dove verranno caricate le righe fattura. Creiamo quindi il metodo ``fatturaTestata`` che andrà a definire la form in un ``contentPane`` posto nella regione superiore. Eliminiamo quindi i campi relativi ai totali, infatti questi saranno calcolati in modo automatico. :: def th_form(self, form): bc = form.center.borderContainer() self.fatturaTestata(bc.contentPane(region='top', datapath='.record', height='150px')) self.fatturaRighe(bc.contentPane(region='center')) def fatturaTestata(self, pane): fb = pane.formbuilder(cols=2, border_spacing='4px') fb.field('protocollo') fb.field('data') fb.field('cliente_id') Le righe della fattura ---------------------- Definiamo poi il metodo ``fatturaRighe``. In questo ``contentPane`` inseriremo il component ``inlineTableHandler`` che è un gestore completo di tabella con editing in linea dei dati. Questo component si occuperà di gestire la tabella, ci darà modo di aggiungere righe, cancellarle e modificarle. :: def fatturaRighe(self, pane): pane.inlineTableHandler(relation='@righe', viewResource='ViewFromFattura') In seguito torneremo ampiamente sui ``tableHandler`` ma per il momento ci limitiamo a crearlo dando come parametro la relazione ``relation='@righe'`` che deve essere seguita al fine di riempire la griglia con le righe relative al record di fattura corrente. Inoltre mettiamo anche un attributo ``viewResource='ViewFromFattura'`` per specificare che useremo una classe di view della risorsa ``th_fattura_riga`` creata appositamente per essere visualizzata dalla form di fattura. la classe ViewFromFattura ------------------------- Procediamo a modificare il modulo ``th_fattura_riga`` creando la classe ``ViewFromFattura``. Nella struttura eliminiamo la colonna fattura_id in quanto non sarà necessario mostararla. Andiamo poi ad aggiungere sulle colonne **prodotto_id** e **quantita** l'attributo **edit=True** per indicare che desideriamo editare le celle corrispondenti. :: class ViewFromFattura(BaseComponent): def th_struct(self, struct): r = struct.view().rows() r.fieldcell('prodotto_id', edit=True) r.fieldcell('quantita', edit=True) r.fieldcell('prezzo_unitario') Primo collaudo ---------------- Procediamo a collaudare la fattura modificando prima il menu :: fatt.thpage(u"Fattura", table="fatt.fattura") e caricando il primo record. Per il momento non ci sono ancora automatismi e quindi metteremo manualmente un numero di fattura e la data. Sceglieremo quindi un cliente e con il bottone + della vista delle righe creeremo una riga nella quale scegliamo un prodotto e mettiamo una quantità. Salviamo quindi la fattura con la riga creata. Nel prossimo capitolo vedremo come migliorare la nostra pagina per la creazione delle fatture. .. raw:: html
.. raw:: html
**Allegati:** - `fattura_riga `_ - `tipo_iva `_ - `th_fattura_riga `_ - `th_prodotto `_ - `prodotto `_ - `fattura `_ - `menu `_ - `th_fattura `_