compositeColumn

Le compositeColumn sono colonne che rappresentano la concatenazione di altre colonne, e sono per questo la base per la generazione di chiavi primarie composte.

Esempio:

class Table(object):
  def config_db(self,pkg):
      tbl=pkg.table('lotto', pkey='key_lotto', name_long='Lotto',
                                  name_plural='Lotti',caption_field='descrizione')
      self.sysFields(tbl, id=False)

      tbl.column('prodotto_id',size='22', group='_', name_long='Prodotto'
                  ).relation('prodotto.id', relation_name='lotti', mode='foreignkey', onDelete='raise')
      tbl.column('codice_lotto', size=':10', name_long='Codice Lotto', name_short='Lotto')
      tbl.column('descrizione', name_long='Descrizione')
      tbl.column('data_produzione', dtype='D', name_long='Data produzione')
      tbl.column('data_scadenza', dtype='D', name_long='Data scadenza')

      tbl.compositeColumn('key_lotto', columns='prodotto_id,codice_lotto', static=True)

Come possiamo notare, la chiave primaria della tabella non è un’id ma una key_lotto composta, costituita dalla combinazione di prodotto_id e codice_lotto.

Suggerimento

Si noti che non viene specificata una size né un dtype, essendo composta da elementi di tipo e dimensioni differenti

A questo punto nella fattura_riga avremo:

tbl.column('prodotto_id',size='22' ,group='_',name_long='!![it]Prodotto'
                  ).relation('prodotto.id',relation_name='righe_fattura', mode='foreignkey',onDelete='raise')
tbl.column('codice_lotto', size=':10', name_long='Lotto')

tbl.compositeColumn('lotto_key',  columns='prodotto_id,codice_lotto'
                  ).relation('lotto.key_lotto', mode='foreignkey')

Anche qui abbiamo quindi un’altra compositeColumn, in relazione con la tabella lotto.

E nell’interfaccia? Aggiorniamo la ViewFromFattura di fattura_riga:

class ViewFromFattura(BaseComponent):

  def th_struct(self,struct):
      r = struct.view().rows()
      r.fieldcell('_row_count',counter=True,hidden=True)
      r.fieldcell('prodotto_id',edit=dict(validate_notnull=True))
      r.fieldcell('codice_lotto',edit=dict(table='fatt.lotto', tag='dbSelect',
                              condition='$prodotto_id=:prd_id', condition_prd_id='=#ROW.prodotto_id',
                              hasDownArrow=True, alternatePkey='codice_lotto'), width='8em')
      r.fieldcell('quantita',edit=dict(validate_notnull=True),width='7em')
      r.fieldcell('prezzo_unitario')
      r.fieldcell('aliquota_iva')
      r.fieldcell('prezzo_totale',totalize='.totale_lordo',formula='quantita*prezzo_unitario')
      r.fieldcell('iva',totalize='.totale_iva',formula='aliquota_iva*prezzo_totale/100')
      r.fieldcell('@lotto_key.data_scadenza', width='6em', name='Scad.')

In sostanza, il campo codice_lotto sarà condizionato a un lotto presente per quello specifico prodotto_id. L’individuazione contestuale dei due campi per quel record permetterà di valorizzare correttamente la compositeColumn che abbiamo costruito.

I benefici di una chiave composta

L’uso della chiave composta, rispetto a una normale pkey di una tabella di relazione:

  • Riflette una unicità reale nel dominio: un lotto è identificato univocamente da quel prodotto e da un certo codice.

  • Evita duplicazioni: non è possibile avere due lotti con stesso codice_lotto per lo stesso prodotto_id.

  • L’univocità è garantita a livello logico e strutturale, non affidata a una convenzione.

Rispetto a una normale pkey, insomma, l’ORM di Genropy è in grado di riconoscere che è costituita da due colonne e può usarla come vera chiave primaria. Viene inoltre salvata come JSON array, ed è quindi leggibile, esportabile, e supportata pienamente dal model per gestire validazioni, indici e join su colonne composite.


Parametri:

Nome parametro

Tipo

Descrizione

columns

T

Permette di specificare le colonne da concatenare, come stringa di valori separati da virgola (es: columns=”prodotto_id,codice_lotto”)

Autore della sezione: Davide Paci