.. _tutorial_fatturazione/invoice_3: Lezione 7: Miglioramenti fattura ================================ In questa lezione miglioreremo la form della fattura. Inoltre vedremo come assegnare a un nuovo record valori di default e valori basati su contatori progressivi automatici. .. raw:: html
Testata fattura ----------------- Al termine della lezione precedente abbiamo lasciato la form della fattura ancora molto grezza ed incompleta. Procediamo ora a dividere la parte superiore in una zona di sinistra ed una di destra, e per far ciò utilizzeremo un ``borderContainer``. In quella di sinistra posizioneremo i campi ``protocollo``, ``data``, ``totale_imponibile``, ``totale_iva`` e ``totale_fattura``. Questi ultimi tre campi avranno l'attributo ``readOnly=True`` dal momento che vengono calcolati automaticamente dai trigger. La parte sinistra che accoglie i campi appena visti viene inserita in un elemento ``roundedGroup`` che incornicia un gruppo di campi con un titolo. Nella parte di destra inseriremo un ``linkerBox`` per la selezione del cliente con i seguenti paramentri: - ``openIfEmpty=True``, mostra il linkerBox aperto all'inserimento di una nuova fattura - ``newRecordOnly=True``, non permette il cambiamento del cliente alla fattura una volta salvata :: def th_form(self, form): bc = form.center.borderContainer() self.fatturaTestata(bc.borderContainer(region='top', datapath='.record', height='150px')) self.fatturaRighe(bc.contentPane(region='center')) def fatturaTestata(self, bc): left = bc.roundedGroup(title='Dati fattura', region='left', width='300px') fb = left.formbuilder(cols=1, border_spacing='4px') fb.field('protocollo') fb.field('data') fb.field('totale_imponibile', readOnly=True) fb.field('totale_iva', readOnly=True) fb.field('totale_fattura', readOnly=True) bc.contentPane(region='center').linkerBox('cliente_id', margin='2px', openIfEmpty=True, newRecordOnly=True) Il linkerBox -------------- Fino ad ora per selezionare il cliente avevamo usato un widget chiamato ``dbselect`` che è un widget che viene inserito in modo automatico dalla funzione ``field`` ogni volta che si riferisce ad un campo in relazione. Infatti se un ``formbuilder`` è associato ad una tabella di database l'elemento ``field`` riconosce dal nome del campo il widget più adatto per l'input a seconda del tipo di dato. La ``dbselect`` fa egregiamente il suo lavoro e ci consente di selezionare il cliente desiderato. Non ci consente però di richiamare alla vista i suoi dati anagrafici ed evenutalmente modificarli se necessario. Per questo esiste il component ``linkerBox``, che si compone di una ``dbselect`` e di una zona template per visualizzare i dati del record selezionato opportunamente formattati. Per un approfondimento sul funzionamento dei widget **dbselect** e **linkerbox** vi rimandiamo alla spiegazione fornita nel `Manuale utente di Genropy `_. Andiamo ora a vedere come si presenta la pagina della fattura e notiamo che in alto a destra c'è un riquadro che ci avvisa che non esiste ancora un template collegato. Dal momento che il nostro utente *admin* ha i permessi necessari, con **shift + doppio click** andiamo a modificare il template. .. raw:: html
Il templateEditor ------------------ Per creare il template richiesto dal linkerBox utilizzeremo uno strumento chiamato **templateEditor** che si apre in una palette e ci consente di svolgere alcuni compiti. In primo luogo dall'albero nella colonna di sinistra della palette trasciniamo i campi che vorremmo usare nella griglia delle variabili in uso. Possiamo trascinare campi dalla tabella principale (cliente in questo caso), o da altre tabelle collegate. Il sistema provvederà automaticamente ad effettuare le query necessarie in modo da darci i dati richiesti. Andiamo poi nella pagina del template e trasciniamo le variabili precedentemente selezionate, formattandole a nostro gradimento e inserendo le parti di testo che desideriamo. Il salvataggio del template dal **templateEditor**, andrà a creare nella directory ``resources/tables/cliente/tpl`` il file ``default.xml`` (vedi allegato). defaultValues -------------- Al caricamento di una nuova fattura desideriamo assegnare la data di lavoro come data fattura. Per fare questo andiamo a modificare il model di ``fattura``, ed aggiungiamo il metodo ``defaultValues``. Questo deve restituire un *dict* che ha come chiavi i campi e come valori i loro default. :: def defaultValues(self): return dict(data=self.db.workdate) .. image:: /_static/images/2019-08-30-104724.gif :width: 700px :align: center Gestione automatica contatori ------------------------------ Nelle applicazioni gestionali è prassi frequente assegnare a dei documenti dei contatori progressivi per avere un riferimento univoco. Potremmo avere contatori per fatture cliente, note credito, documenti di trasporto, ordini ricevuti e via dicendo. Gestire questi contatori, verificando che sia rispettata la cronologia e che non si creino salti di numerazione, è un compito noioso e che richiede molta pazienza. In *Genropy* esiste un sottosistema di gestione contatori che fa capo al package **adm** che abbiamo incluso nel progetto. Per indicare che la nostra fattura desidera usare il gestore dei contatori definiamo un metodo ``counter_protocollo`` che ci dovrà restituire i parametri di gestione del contatore in questo contesto. Si tratta di un metodo *hook* formato dal prefisso **counter** seguito dal nome della colonna che utilizzerà il contatore. In particolare abbiamo qui deciso che il protocollo ovvero, il numero di fattura, sarà prefissato dalla lettera **F** (per distinguerlo ad esempio da una bolla che potrebbe usare la lettera **B**), conterrà poi le **ultime 2 cifre dell'anno** e di seguito **un numero di 6 cifre**. Gli elementi detti sono definiti in un un parametro stringa ``format``, secondo una sintassi dove si usano degli elementi *placeholder* preceduti da **$**. - **$K** è una parte di prefisso che viene riempita a partire dal parametro ``code`` - **$YY** (oppure potrebbe essere **$YYYY** o **$MM** o **$DD** o una loro combinazione) è l'elemento ottenuto dalla data di riferimento passata nel parametro ``date`` - **$N** rappresenta il numero restituito dal contatore :: def counter_protocollo(self, record=None): ##Formato desiderato F19/000001 return dict(format='$K$YY/$NNNNNN', code='F', period='YY', date_field='data', showOnLoad=True, recycle=True) Il gestore dei contatori è anche in grado, per una nuova fattura, di mostrarci il numero che verrà poi assegnato al salvataggio. Per fare questo utilizziamo il parametro ``showOnLoad`` . Se desideriamo che in caso di cancellazione il numero disponibile sia riutilizzato per evitare buchi di numerazione, utilizziamo il parametro ``recycle``. Collaudo finale ---------------- Possiamo ora vedere come all'aggiunta di una nuova fattura il numero di protocollo venga assegnato in modo automatico. E potremo pertanto mettere anche questo campo ``readOnly=True``. .. hint:: Nel video è anche mostrato come si effettuano le azioni di riallineamento dei contatori. Ma se avete eseguito correttamente le istruzioni finora riportate non dovrebbe essere necessario effettuare questa azione. A meno che non abbiate inserito delle fatture di prova. .. raw:: html
.. raw:: html
**Allegati:** - `default `_ - `fattura `_ - `th_fattura `_