.. _le_stampe/stampe_genropy/stampe_risorsa/esempi_stampa/stampa_griglia_2: Stampa griglia 2: Prodotti ========================== Supponiamo di voler stampare un elenco di record sulla base di una **query con delle condizioni** specifiche, **raggruppando i risultati** sulla base di un determinato criterio. In quest'esempio vedremo come definire la risorsa di stampa relativa alle **Statistiche di vendita dei prodotti in un esercizio**, **raggruppati per prodotto**, eventualmente filtrabili per singolo cliente. La stampa verrà lanciata dalla tabella *Prodotti* del progetto `Sandbox `_. In particolare, questo esempio ci permetterà di vedere come utilizzare il metodo ``gridData`` per definire i criteri di selezione dei record da stampare. Definizione della print action ------------------------------ Per prima cosa andiamo a definire la :ref:`risorsa print` che chiamiamo *stampa_prodotti.py* all'interno della cartella ``resources/tables/prodotto/print``, esattamente come abbiamo fatto nella :ref:`Stampa con griglia 1: Fatturato per esercizio` . Non essendoci particolari variazioni sui parametri richiesti per la stampa rimandiamo al caso precedente per una trattazione più completa. Definizione della risorsa html_res ---------------------------------- Passiamo a questo punto alla definizione della :ref:`risorsa html_res` che chiamiamo *stats_prodotti.py* all'interno della cartella ``resources/tables/prodotto/html_res``. Rimandiamo alla :ref:`Stampa con griglia 1: Fatturato per esercizio` per la trattazione della definizione dei parametri della classe *Main*, dei metodi ``defineCustomStyles``, ``docHeader``, ``docFooter`` e ``outputDocName``, che non variano in questo caso in modo significativo. Ci concentriamo invece in questa stampa sull'utilizzo del metodo ``gridData`` per raccogliere i dati delle righe. In questo caso, diversamente dal precedente, il nostro obiettivo di raggruppamento delle vendite di ogni prodotto non può essere raggiunto in alcun modo dalla query di *default*, e non sarà quindi sufficiente limitarsi a stabilire delle condizioni tramite il metodo ``gridQueryParameters``. Andremo infatti a ridefinire direttamente il metodo ``gridData``, intervenendo sulla query e imponendo i criteri di raggruppamento, nonché modificando poi l'esito della ricerca:: def gridData(self): condition=['@fattura_id.anno_fattura=:anno'] if self.parameter('cliente_id'): condition.append('@fattura_id.cliente_id=:cliente') where=' AND '.join(condition) fatturato_grouped_by_prodotto = self.db.table('fatt.fattura_riga').query(columns=""" SUM($prezzo_totale) AS prezzo_totale, SUM($iva) AS iva, @prodotto_id.codice AS codice, @prodotto_id.descrizione AS descrizione, @prodotto_id.@prodotto_tipo_id.hierarchical_descrizione AS prodotto_gerarchia, @prodotto_id.@prodotto_tipo_id.descrizione AS prodotto_tipo""", where=where, anno=self.parameter('anno'), cliente=self.parameter('cliente_id'), group_by="""@prodotto_id.codice, @prodotto_id.descrizione, @prodotto_id.@prodotto_tipo_id.hierarchical_descrizione, @prodotto_id.@prodotto_tipo_id.descrizione""").fetch() for prodotto in fatturato_grouped_by_prodotto: categoria_principale = prodotto['prodotto_gerarchia'].split('/')[0] prodotto['categoria_principale'] = categoria_principale return fatturato_grouped_by_prodotto La prima parte sostanzialmente è in linea con quanto abbiamo fatto nel caso precedente con il metodo ``gridQueryParameters``, imponendo cioè la corrispondenza tra l'anno della fattura e l'anno inserito nei parametri, ed eventualmente anche la corrispondenza con il cliente selezionato. Si noti che in questo caso la *query* verrà fatta su un'altra tabella, la ``fatt.fattura_riga``, di conseguenza anche la condizione andrà applicata sulle colonne di questa tabella. Nella query andremo a sommare i vari campi importo, mentre raggrupperemo tutti gli altri valori non sommati. A questo punto il risultato della query sarà una bag piatta, che però non ci limitiamo a prendere così com'è ma vogliamo andare a personalizzare. La tabella *prodotto_tipo* di `Sandbox `_, infatti, è una tabella gerarchica, dalla quale andremo a metterci da parte innanzitutto il ``prodotto_tipo`` (che è l'ultimo livello "figlio" della gerarchia), ma anche la struttura gerarchica intera (``prodotto_gerarchia``). Infatti, siamo interessati a calcolare un subtotale per macro-categoria, ma non essendo la gerarchia necessariamente uniforme (alcune volte sono presenti 2 livelli, altre 3, ecc), l'unica strada che abbiamo per recuperare la macrocategoria è individuare il primo elemento della ``prodotto_gerarchia``:: categoria_principale = prodotto['prodotto_gerarchia'].split('/')[0] Ad es. "Giardinaggio/Mobili da Giardino/Sedie" darà come risultato di questa operazione "Giardinaggio". A questo punto andiamo a immagazzinare il dato della *categoria_principale* direttamente in questa bag piatta di risultati, rendendolo disponibile per l'utilizzo all'interno del nostro metodo ``gridStruct``:: def gridStruct(self,struct): r = struct.view().rows() r.fieldcell('codice', mm_width=15) r.fieldcell('descrizione', mm_width=0) r.cell('prodotto_tipo', mm_width=20, name='Tipo prodotto') r.cell('categoria_principale', hidden=True, subtotal='Totale {breaker_value}') r.cell('prezzo_totale', mm_width=20, name='Fatturato tot.', totalize=True) r.cell('iva', mm_width=20, name='IVA tot.',totalize=True) .. raw:: html
Puoi provare la stampa direttamente su `Sandbox `_, oppure scaricare i file di stampa qui di seguito. .. raw:: html
**Allegati:** - `stats_prodotti `_ - `stampa_prodotti `_ - `prodotti_2019 `_