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