Stampa griglia 1: Fatturato

Supponiamo di voler stampare un elenco di record sulla base di una query con delle condizioni specifiche.

In quest’esempio vedremo come definire la risorsa di stampa relativa al Fatturato di un esercizio, eventualmente filtrabile per singolo cliente. La stampa verrà lanciata dalla tabella Fattura del progetto Sandbox. In particolare, questo esempio ci permetterà di vedere come utilizzare il metodo gridQueryParameters per definire i criteri di selezione dei record da stampare.


Definizione della print action

Per prima cosa andiamo a definire la risorsa print che chiamiamo stampa_fatturato.py all’interno della cartella resources/tables/fattura/print.

All’interno di questa risorsa ridefiniamo innanzitutto la classe Main come segue:

class Main(BaseResourcePrint):
  batch_title = 'Stampa Statistiche Fatturato'
  batch_immediate='print'
  html_res = 'html_res/stats_fatturato'

Specificando batch_immediate='print' imponiamo l’apertura automatica della stampa una volta completata, mentre con html_res = 'html_res/stats_fatturato' segnaliamo quale risorsa di stampa dovrà essere utilizzata.

All’interno di Main ridefiniamo poi il metodo table_script_parameters_pane, che ci permetterà di richiedere all’utente alcuni parametri al momento del lancio della stampa:

def table_script_parameters_pane(self, pane,**kwargs):
      current_year = datetime.today().year
      last_years = [current_year, current_year-1, current_year-2, current_year-3, current_year-4]
      years = ','.join(str(e) for e in last_years)
      fb = pane.formbuilder(cols=1, width='220px')
      fb.filteringSelect(value='^.anno', values=years, validate_notnull=True, lbl='!![it]Anno')
      fb.dbselect(value='^.cliente_id', table='fatt.cliente', lbl='Cliente', selected_ragione_sociale='.ragione_sociale')

Il parametro anno, preimpostato come semplice stringa degli ultimi 5 anni separati da virgola, sarà obbligatorio, mentre cliente_id permetterà all’utente di selezionare un cliente tra quelli disponibili nella tabella Cliente (in modo opzionale).

Definizione della risorsa html_res

Passiamo a questo punto alla definizione della risorsa html_res che chiamiamo stats_fatturato.py all’interno della cartella resources/tables/fattura/html_res.

Anche qui ridefiniamo la classe Main come segue:

class Main(TableScriptToHtml):

  row_table = 'fatt.fattura'
  page_width = 210
  page_height = 297
  doc_header_height = 30
  doc_footer_height = 8
  grid_header_height = 5
  totalize_footer='Totale fatturato'
  empty_row=dict()

Oltre a una serie di parametri di layout, specifichiamo la tabella su cui eseguire la query con row_table = 'fatt.fattura', e l’etichetta da utilizzare nell’ultima riga di totalizzazione del documento con totalize_footer='Totale fatturato'.

Inoltre specifichiamo anche il parametro empty_row, a cui assegniamo un dizionario vuoto, per ottenere comunque la stampa dell’intestazione del documento anziché una pagina bianca qualora venisse lanciata la stampa di una griglia di dati vuota.

All’interno della classe procediamo poi a ridefinire una serie di metodi, il primo dei quali è il metodo docHeader , che specifica le caratteristiche che deve avere l’header della stampa.

Nel nostro caso andiamo a inserire una prima riga con un contenuto html, un titolo e l’indicazione dell’esercizio oggetto della stampa:

def docHeader(self, header):
      head = header.layout(name='doc_header', margin='5mm', border_width=0)
      row = head.row()
      row.cell("""<center><div style='font-size:18pt;'><strong>Statistiche fatturato per periodo</strong></div>
                  <div style='font-size:14pt;'>Esercizio {anno}</div></center>::HTML""".format(anno=self.parameter('anno')))
      if self.parameter('cliente_id'):
          row = head.row()
          row.cell("""<center><div style='font-size:14pt;'>{cliente}</div></center>::HTML""".format(
                              cliente=self.parameter('ragione_sociale')))

La seconda riga verrà mostrata esclusivamente nel caso in cui tra i parametri venga specificato anche il cliente_id.

Usiamo poi un defineCustomStyles di default per definire una serie di parametri di layout generali del documento:

def defineCustomStyles(self):
      self.body.style(""".cell_label{
                          font-size:8pt;
                          text-align:left;
                          color:grey;
                          text-indent:1mm;}

                          .footer_content{
                          text-align:right;
                          margin:2mm;
                          }
                          """)

Procediamo con l’impostare la struttura della griglia , ridefinendo il metodo di hook gridStruct come segue:

def gridStruct(self,struct):
      r = struct.view().rows()
      r.fieldcell('data', mm_width=15)
      r.fieldcell('mese_fattura', hidden=True, subtotal='Totale {breaker_value}', subtotal_order_by="$data")
      r.fieldcell('protocollo', mm_width=20, name='Documento')
      r.fieldcell('cliente_id', mm_width=0)
      r.fieldcell('totale_imponibile', mm_width=20, totalize=True)
      r.fieldcell('totale_iva', mm_width=20, totalize=True)
      r.fieldcell('totale_fattura', mm_width=20, totalize=True)

All’interno del metodo utilizziamo una serie di fieldcell esattamente come faremmo all’interno di una View di un Tablehandler per specificare quali colonne visualizzare nella nostra griglia di stampa. Utilizziamo la formulaColumn mese_fattura per generare dei subtotali per mese, che ordineremo per data. Per le colonne degli importi utilizziamo invece l’attributo totalize=True per mostrare in fondo al documento il totale calcolato di ogni colonna.

La specifica dei Dati da visualizzare in griglia viene invece effettuata dal metodo gridQueryParameters, che rifiniamo in questo modo:

def gridQueryParameters(self):
      condition=['$anno_fattura=:anno']
      if self.parameter('cliente_id'):
          condition.append('$cliente_id=:cliente')
      return dict(condition=' AND '.join(condition), condition_anno=self.parameter('anno'),
                      condition_cliente=self.parameter('cliente_id'))

Stabiliamo quindi una condizione di base che verrà utilizzata nella query sulla tabella, ovvero che l’anno del documento (altra formulaColumn appositamente creata) sia uguale all’anno specificato nei parametri della stampa. A questa condizione ne aggiungeremo poi un’altra, che però scatterà solo se specificato il cliente_id tra i parametri, che imponga anche l’uguaglianza tra il cliente della fattura e il cliente_id.

Nel metodo docFooter aggiungiamo poi una riga con la data in cui è stata effettuata la stampa:

def docFooter(self, footer, lastPage=None):
      foo = footer.layout('totali_fattura',top=1,
                         lbl_class='cell_label',
                         content_class = 'footer_content')
      r = foo.row()
      r.cell('Documento stampato il {oggi}'.format(oggi=self.db.workdate))

Infine, utilizziamo il metodo outputDocName per personalizzare anche il nome del file stampato, indicando l’anno e se specificata anche la ragione_sociale del cliente:

def outputDocName(self, ext=''):
      if ext and not ext[0] == '.':
          ext = '.%s' % ext
      if self.parameter('cliente_id'):
          doc_name = 'Fatturato_{anno}_{cliente}{ext}'.format(anno=self.parameter('anno'),
                      cliente=self.parameter('ragione_sociale'), ext=ext)
      else:
          doc_name = 'Fatturato_{anno}{ext}'.format(anno=self.parameter('anno'), ext=ext)
      return doc_name

Puoi provare la stampa direttamente su Sandbox, oppure scaricare i file di stampa qui di seguito.


Allegati: