.. _tutorial_fatturazione/product: Lezione 4: Tabelle gerarchiche ============================== In questa lezione verranno create le tabelle ``prodotto``, ``prodotto_tipo`` e le rispettive risorse di form. .. raw:: html
Tabella prodotto ----------------- In analogia a quanto fatto per il cliente creiamo il modulo ``prodotto.py`` e provvediamo a creare le colonne desiderate. In particolare desideriamo che il nostro archivio prodotti sia diviso in categorie gerarchiche e a tal fine definiamo una colonna ``prodotto_tipo_id``.:: class Table(object): def config_db(self, pkg): tbl = pkg.table('prodotto', pkey='id', name_long='Prodotto', name_plural='Prodotti', caption_field='descrizione') self.sysFields(tbl) tbl.column('codice', size=':10', name_long='Codice') tbl.column('descrizione', size=':50', name_long='Descrizione') tbl.column('prodotto_tipo_id', size='22', group='_', name_long='Tipo Prodotto', name_short='Tipo').relation( 'prodotto_tipo.id', relation_name='prodotti', mode='foreignkey', onDelete='raise') Tabella prodotto_tipo --------------------- Nelle applicazioni gestionali ci si trova spesso a dover gestire gerarchie. In Genropy esiste una tipologia di tabelle specifica per questo scopo. In genropy si definisce tabella gerarchica o **hierarchical table** una tabella i cui record hanno una relazione verso un altro record *padre*, appartenente alla tabella stessa. Tale relazione è associata alla foreignkey parent_id. Questo modello si adatta ad entità che sono intrinsecamente gerarchiche, ovvero in cui gli elementi sono contenuti gli uni negli altri. Definiamo quindi la tabella gerarchica prodotto_tipo creando il modulo ``prodotto_tipo.py``. In esso definiamo come al solito la classe Table ma alla chiamata ``self.sysFields`` aggiungiamo il parametro ``hierarchical="descrizione"`` per indicare che intendiamo creare una gerarchia e che vogliamo avere un campo descrizione gerarchica basato sulla colonna descrizione. L'uso del parametro ``hierarchical`` farà sì che vengano aggiunte automaticamente le colonne necessarie per rendere la tabella *gerarchica*, in particolare la relazione interna sulla colonna ``parent_id``.:: class Table(object): def config_db(self, pkg): tbl = pkg.table('prodotto_tipo', pkey='id', name_long='Tipo prodotto', name_plural='!!Tipi prodotto', caption_field='hierarchical_descrizione') self.sysFields(tbl, hierarchical='descrizione', counter=True, df=True) tbl.column('descrizione', size=':50', name_long='Descrizione') Risorsa tabella prodotto_tipo ----------------------------- Come già visto nella :ref:`Lezione 2` generiamo automaticamente con l'istruzione ``gnrmkthresource`` le risorse mancanti ed andiamo a lavorare sul modulo ``th_prodotto_tipo.py``. :: gnrmkthresource fatturazione:fatt Notiamo che il costruttore aggiunge molti campi che in realtà sono di uso interno; procediamo quindi a toglierli sia dalla view che dalla form. Per segnalare che desideriamo editare in modalità gerarchica, alla form aggiungiamo tra i valori restituiti da ``th_options`` l'attributo ``hierarchical=True``. :: class View(BaseComponent): def th_struct(self,struct): r = struct.view().rows() r.fieldcell('hierarchical_descrizione') def th_order(self): return 'hierarchical_descrizione' def th_query(self): return dict(column='hierarchical_descrizione', op='contains', val='') class Form(BaseComponent): def th_form(self, form): pane = form.record fb = pane.formbuilder(cols=2, border_spacing='4px') fb.field('descrizione') def th_options(self): return dict(dialog_height='400px', dialog_width='600px', hierarchical=True) Test delle tabelle prodotto e prodotto_tipo ------------------------------------------- Dopo aver modificato il menu di package per includere le due tabelle appena create riallineamo il db e riavviamo il server. Iniziamo a creare un record di ``prodotto_tipo`` e ci accorgiamo che nelle tabelle gerarchiche abbiamo una colonna di destra con un albero per visualizzarne gli elementi. Creiamo alcuni record e notiamo la presenza di due distinti bottoni di +. Uno al termine di un **breadcrumb** che rappresenta il **path corrente** e che serve per aggiungere elementi **figli** dell'elemento corrente. L'altro bottone di + collocato nella solita posizione invece aggiunge elementi **fratelli** di quello corrente. Nel caso caricassimo elementi in posizioni errate potremo facilmente riorganizzarli semplicemente **trascinando** i nodi dell'albero. Il sistema automaticamente farà le scritture necessarie a riallineare la gerarchia. Trascinando nell'albero con il **tasto maiuscolo** potremo anche riordinare gli elementi nell'ordine preferito. Per un approfondimento sull'utilizzo delle pagine di gestione delle tabelle gerarchiche rimandiamo alla spiegazione fornita dal `manuale utente di Genropy `_. .. raw:: html
Modifichiamo prodotto e prodotto_tipo ------------------------------------- Nel collaudo della tabella ``prodotto_tipo`` ci accorgiamo che non esiste una validazione su descrizione e pertanto provvediamo ad aggiungere al campo *descrizione* l'attributo ``validate_notnull=True`` Vengono poi aggiunti alla tabella ``prodotto`` - il campo ``prezzo_unitario`` sia nel model che nelle resouces - il parametro ``validate_case='U'`` per convertire automaticamente in maiuscolo il codice caricato, ed il parametro ``validate_nodup=True`` per chiedere al sistema di controllare che non esistano prodotti con lo stesso codice, al campo *codice* nella form - il parametro ``validate_notnull=True`` per dire che è obbligatorio, su tutti i campi nella form - l'attributo ``tag='hdbselect'`` al campo *prodotto_tipo_id* nella form, che consente di ricercare il tipo prodotto sia in modo gerarchico che per descrizione. Collaudo finale ----------------- Testiamo ora la form dei prodotti e possiamo caricare alcune voci verificando che il controllo sulla duplicazione di codici prevenga effettivamente questo tipo di problema. .. raw:: html
.. raw:: html
**Allegati:** - `prodotto `_ - `th_prodotto_tipo `_ - `prodotto_tipo `_ - `th_prodotto `_ - `menu `_