Lezione 4: Tabelle gerarchiche

In questa lezione verranno create le tabelle prodotto, prodotto_tipo e le rispettive risorse di form.

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 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.

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

Viene poi aggiunto il campo prezzo_unitario alla tabella prodotto, al campo codice vengono aggiunti 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, e su tutti i campi viene aggiunto il parametro validate_notnull=True per dire che è obbligatorio.

Notiamo inoltre che il campo prodotto_tipo_id ha un atributo tag='hdbselect'. Questo attributo 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.

Attachments: