1072 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1072 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
// ve6200.cpp: modulo per la generazione dei documenti in modo BATCH.
 | 
						|
 | 
						|
#include <config.h>
 | 
						|
#include <applicat.h>
 | 
						|
#include <mask.h>
 | 
						|
#include <maskfld.h>
 | 
						|
#include <urldefid.h>
 | 
						|
#include <utility.h>
 | 
						|
#include <validate.h>
 | 
						|
#include <progind.h>
 | 
						|
#include <extcdecl.h>
 | 
						|
#include <execp.h>
 | 
						|
#include <lffiles.h>
 | 
						|
#include <rectypes.h>
 | 
						|
#include <isam.h>
 | 
						|
#include <tabutil.h>
 | 
						|
#include <date.h>
 | 
						|
#include <checks.h>
 | 
						|
#include <relation.h>
 | 
						|
#include <sheet.h>
 | 
						|
#include "ve6000.h"
 | 
						|
#include "ve6retv.h"    // valori di ritorno dalle varie funzioni
 | 
						|
#include "ve6gen.h"             // dichiarazione della classe base
 | 
						|
 | 
						|
#define  TOKEN_QTA  5
 | 
						|
#define  TOKEN_QTAEVASA 7
 | 
						|
#define  TOKEN_QTA_DA_EVADERE 9
 | 
						|
#define  CAMPO_DAEVADERE 101
 | 
						|
 | 
						|
// è stata derivata la classe TSheet, perchè in alcuni documenti (es. Ordini)
 | 
						|
// l'utente (tramite Ve6 -3, applicazione derivata dalla presente)
 | 
						|
// può specificare di evadere una sola parte della quantità di merci indicate
 | 
						|
// nella riga, così è stato necessario chiedere all'utente la quantità da evadere
 | 
						|
// e riportarla nell'ultima colonna dello sheet: prima non era possibile, in quanto
 | 
						|
// tale quantità non era un campo del record del file righedoc
 | 
						|
 | 
						|
/***********************************/
 | 
						|
/**** Classe TInterattivo_sheet ****/
 | 
						|
/***********************************/
 | 
						|
 | 
						|
// funzione quasi uguale a quella del TSheet
 | 
						|
 | 
						|
void TInterattivo_sheet::page_build(long first, byte rows)
 | 
						|
{
 | 
						|
  TToken_string l(256);
 | 
						|
 | 
						|
  *cursor() = (TRecnotype)first;
 | 
						|
  for (int r = 0; r < rows; r++, ++(*cursor()))
 | 
						|
  {
 | 
						|
    l.cut(0);
 | 
						|
    const int last = fields().last();
 | 
						|
    for (int i = 0; i <= last; i++)
 | 
						|
    {
 | 
						|
      const TRecfield* rf = (TRecfield*)fields().objptr(i);
 | 
						|
      const char* s = rf ? (const char*)*rf : "";
 | 
						|
      l.add(s);
 | 
						|
    }
 | 
						|
// cambiamenti dalla routine TSheet::page_build :
 | 
						|
// stabilisce per default che la quantità da evadere è quella non ancora evasa
 | 
						|
    const long qta = l.get_long(TOKEN_QTA);
 | 
						|
    const long qtaevasa = l.get_long(TOKEN_QTAEVASA);
 | 
						|
//    char buffer[16];
 | 
						|
//    _ltoa(qta-qtaevasa,buffer,10);
 | 
						|
//    TString daevadere(buffer);
 | 
						|
    real n(qta-qtaevasa);
 | 
						|
    l.add((const char *)n.string(11,3),TOKEN_QTA_DA_EVADERE);
 | 
						|
    set_row(l, r);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// quando l'utente fa doppio click o preme selezione, la on_key riceve un K_ENTER
 | 
						|
// e qui apro una mascherina in cui chiedo la qta da evadere, CONFERMA o ANNULLA
 | 
						|
bool TInterattivo_sheet::on_key (KEY k)
 | 
						|
{
 | 
						|
// K_ENTER e' E_MOUSE_DBL, mentre K_SPACE e' E_MOUSE_DOWN
 | 
						|
   if (k==K_ENTER)
 | 
						|
   {
 | 
						|
// maschera per l'inserimento del valore
 | 
						|
      TMask m("Modifica", 1, 33, 7);
 | 
						|
      m.add_number (CAMPO_DAEVADERE, 0, "Quantità da evadere", 1, 3, 11);
 | 
						|
      m.add_button (DLG_OK, 0, "", 1, 4);
 | 
						|
      m.add_button (DLG_CANCEL, 0, "", 1, 5);
 | 
						|
      if (m.run()==K_ENTER)
 | 
						|
      {
 | 
						|
// aggiorna il campo "quantita' evasa della riga selezionata
 | 
						|
  // TOKEN_QTAEVASA = posizione del campo QTAEVASA nel file ve0300b.dat,
 | 
						|
  // file gestito da Matteo e coincidente con i campi di righedoc,
 | 
						|
  // da lui utilizzato per lo spreadsheet delle righe nel suo Motore
 | 
						|
         long n = selected();
 | 
						|
         TToken_string temp = row(n);              // riga selezionata
 | 
						|
         real qtaev   (temp.get(TOKEN_QTAEVASA));  // valore di qtaevasa
 | 
						|
         real qtaspec (m.get(CAMPO_DAEVADERE));    // quantita' da evadere specificata
 | 
						|
         qtaev += real (qtaspec);                  // aggiorna il campo
 | 
						|
         real qtatot (temp.get(TOKEN_QTA));        // quantità totale della merce della riga
 | 
						|
// controlla che qta_evasa + qta_da_evadere < qta_totale
 | 
						|
         if (qtaev>qtatot) error_box("Qtà da evadere superiore alla Qta non ancora evasa");
 | 
						|
          else {
 | 
						|
// se corretto, setta la riga dello sheet
 | 
						|
                temp.add (qtaspec.string(), TOKEN_QTA_DA_EVADERE);  // aggiunge il campo aggiornato nella stessa posizione
 | 
						|
                set_row (temp, (byte)n);       // aggiorna lo sheet
 | 
						|
               }
 | 
						|
         check(n, TRUE);
 | 
						|
      }
 | 
						|
      return FALSE;
 | 
						|
   }
 | 
						|
   return TCursor_sheet::on_key(k);
 | 
						|
}
 | 
						|
     
 | 
						|
/******************************/
 | 
						|
/*** Classe TBatch_crea_doc ***/
 | 
						|
/******************************/
 | 
						|
 | 
						|
// L'applicazione TBatch_crea_doc crea n documenti finali partendo da m doc. iniziali,
 | 
						|
// individuati tramite una maschera attivata prima dell'elaborazione, ve6000a.uml, che chiede:
 | 
						|
// Data elaborazione (del documento da creare)
 | 
						|
// Da Codice cli/for a Codice cli/for (doc. originale)
 | 
						|
// Da Data documento a Data documento (doc. originale)
 | 
						|
// Da Codice agente  a Codice agente  (doc. originale)
 | 
						|
// Da Codice zona    a Codice zona    (doc. originale)
 | 
						|
// Ordinamento della sequenza dei documenti creati per ognuna delle voci precedenti
 | 
						|
// Raggruppa più documenti sorgente in un solo doc. destinazione quando possibile
 | 
						|
// Raggruppa articoli : quando possibile raggruppa più righe dello stesso articolo,
 | 
						|
//                      accumulandone le quantità
 | 
						|
// Stampa immediata (non gestito)
 | 
						|
 | 
						|
inline TBatch_crea_doc& app() { return (TBatch_crea_doc&) main_app(); } // per accedere ai data members della TElaborazioni dalla filterfunct()
 | 
						|
 | 
						|
bool TBatch_crea_doc::create()
 | 
						|
{
 | 
						|
// BATCH --> non interattivo; questo serve perché le routines di TBatch_crea_doc
 | 
						|
// sono usate anche da TInterattivo_crea_doc, classe figlia di    "
 | 
						|
  _interattivo = FALSE;
 | 
						|
  _crea_doc = TRUE;
 | 
						|
 | 
						|
  dispatch_e_menu(BAR_ITEM(1));         // chiama il metodo menu
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
bool TBatch_crea_doc::destroy()
 | 
						|
{
 | 
						|
  return TRUE;  
 | 
						|
}
 | 
						|
 | 
						|
bool TBatch_crea_doc::menu(MENU_TAG)
 | 
						|
{
 | 
						|
  int err;
 | 
						|
// contengono i limiti Da - a per l'individuazione dei documenti originali
 | 
						|
  TRectype first(LF_DOC), last(LF_DOC);
 | 
						|
  if (errore_fatale (run_mask(first, last))) // richiede e setta i parametri, tramite maschera
 | 
						|
    return FALSE;
 | 
						|
  
 | 
						|
  switch (_ordinamento) // in base all'ordinamento, lancia la procedura con diversi parametri
 | 
						|
  {
 | 
						|
  case CLIFO :
 | 
						|
    // crea documenti ordinando per cli./for.
 | 
						|
    err = per_cliente(first, last, "TIPOCF|CODCF");
 | 
						|
    break;
 | 
						|
  case AGENTE:
 | 
						|
    // crea documenti ordinando per agente
 | 
						|
    err = per_cliente(first, last, "TIPOCF|CODAG");
 | 
						|
    break;
 | 
						|
  case ZONA:
 | 
						|
    // crea documenti ordinando per zona
 | 
						|
    err = per_cliente(first, last, "TIPOCF|ZONA");
 | 
						|
    break;
 | 
						|
  case DATA:
 | 
						|
    // crea documenti ordinando per data
 | 
						|
    err = per_cliente(first, last, "TIPOCF|DATADOC");
 | 
						|
    break;              
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  if (errore_fatale(err))
 | 
						|
     fatal_box ("A fatal error has occured!");
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
// run_mask():
 | 
						|
// imposta i records first e last con gli estremi Da - a
 | 
						|
// per individuare i documenti originali da elaborare
 | 
						|
int TBatch_crea_doc::run_mask(TRectype& first, TRectype& last)
 | 
						|
{
 | 
						|
//  int err;
 | 
						|
  first.zero();
 | 
						|
  last.zero();
 | 
						|
  TMask *_msk = new TMask ("ve6000");
 | 
						|
  
 | 
						|
// --- parte di Marcello, già disabilitata: a cosa serviva ?
 | 
						|
  // Imposta il flag di autorizzazione agente   
 | 
						|
/*  TTable t("%TIP");
 | 
						|
  t.zero();
 | 
						|
  t.put ("CODTAB", _tipo_doc_org);  // tipo del documento originale
 | 
						|
  if (err = t.read (_isgteq))   // si posiziona sul record relativo al documento del tipo specificato
 | 
						|
  {
 | 
						|
    error_box ("TElaborazioni::run_mask() : errore di lettura %d da tab(TIP)", err);
 | 
						|
    return READ_ERROR;
 | 
						|
  }
 | 
						|
  if (t.get ("CODTAB") != _tipo_doc_org)   // verifica che il tipo di documento trovato sia quello richiesto
 | 
						|
  {
 | 
						|
    error_box ("TElaborazioni::run_mask() : non esiste il tipo documento %s in tab(TIP)", (const char *)_tipo_doc_org);
 | 
						|
    return DOC_TYPE_NOT_FOUND;
 | 
						|
  }
 | 
						|
  TFilename profilo(t.get ("S4"));    // nome del profilo documento (nome del .ini associato al tipo documento originale)
 | 
						|
  profilo.ext("ini");
 | 
						|
  TConfig profilo_doc(profilo);         // file di configurazione (ini) del documento
 | 
						|
*/
 | 
						|
    TConfig p(CONFIG_DITTA);
 | 
						|
// gestione agente abilitata <==> abilitata in profilo documento e nel .ini della ditta
 | 
						|
// int agente = (profilo_doc.get_int ("CODAG", "PROFILO") && p.get_int("AGENTE", "VE"));
 | 
						|
  int agente = (p.get_int("AGENTE", "VE"));
 | 
						|
  
 | 
						|
  /* se il flag per la gestione agenti è != 0, allora visualizza i campi agente ed
 | 
						|
     adotta la stessa convenzione usata per CODICE CLIENTE e ZONA per gestire l'eventualita' che
 | 
						|
     l'utente non specifichi nulla.
 | 
						|
     Se è disabilitata, allora lascia vuoti i campi CODICE AGENTE DA e CODICE AGENTE A, in modo
 | 
						|
     da eliminare una condizione durante il filtraggio dei records.
 | 
						|
     */
 | 
						|
  
 | 
						|
// nasconde i campi se la gestione agenti è disabilitata
 | 
						|
  if (!agente)          
 | 
						|
  {
 | 
						|
    _msk->show (F_CODICE_AGENTE_DA, FALSE);
 | 
						|
    _msk->show (F_CODICE_AGENTE_A, FALSE);
 | 
						|
  }
 | 
						|
  
 | 
						|
// nasconde il codice elaborazione: ?
 | 
						|
  _msk->show (F_CODICE_ELAB, FALSE);
 | 
						|
 | 
						|
  if (_msk->run() == K_ESC) // runna la maschera: se premuto esc, esci
 | 
						|
  {
 | 
						|
    delete _msk;
 | 
						|
    return ESC_PRESSED;
 | 
						|
  }
 | 
						|
  
 | 
						|
  _ordinamento = _msk->get_int (F_ORDINAMENTO_EMISSIONE); // ordinamento (RadioButton)
 | 
						|
  _raggruppa = _msk->get_bool (F_RAGGRUPPA);      // raggruppa più doc. originali ?
 | 
						|
  _per_articolo = _msk->get_bool (F_RAGGR_ARTICOLI);    // raggruppa linee con lo stesso articolo
 | 
						|
  TDate d((const char*) _msk->get(F_DATA_ELAB));    // Data documenti finali
 | 
						|
  _datadoc = d;
 | 
						|
  _anno = d.year(); // anno è una componente della chiave
 | 
						|
 | 
						|
  TString temps;      // temporanea per rilevare i valori dei campi della maschera
 | 
						|
  TLocalisamfile f(LF_DOC);
 | 
						|
 | 
						|
  // i due seguenti campi non sono discriminanti, in quanto due documenti diversi
 | 
						|
  // (es.: BollaC e Fattura Acc.) sono raggruppabili nella stessa fattura
 | 
						|
  // e lo stato in cui devono essere dipende solo dal .ini di quel tipo di documento originale
 | 
						|
 | 
						|
//  first.put ("TIPODOC", _tipo_doc_org);    // tipo documento (da tab. ELD)
 | 
						|
//  last.put ("TIPODOC", _tipo_doc_org);
 | 
						|
//  first.put ("STATO", _stato_i_doc_i);     // stato documento originale
 | 
						|
//  last.put ("STATO", _stato_i_doc_i);
 | 
						|
  
 | 
						|
  temps = _msk->get(F_CODICE_CLIFO_DA);
 | 
						|
  if (temps.not_empty())
 | 
						|
    first.put ("CODCF", temps);     // codice cliente (v. filterfunct)
 | 
						|
  temps = _msk->get(F_CODICE_CLIFO_A);
 | 
						|
  if (temps.not_empty())
 | 
						|
    last.put ("CODCF", temps);      // codice cliente  (v. filterfunct)
 | 
						|
  
 | 
						|
// data
 | 
						|
  first.put ("DATADOC", _msk->get(F_DATA_DOCUMENTO_DA));        // nessun controllo perché data doc. da e data doc. a sono checktype required
 | 
						|
  last.put  ("DATADOC", _msk->get(F_DATA_DOCUMENTO_A));
 | 
						|
  
 | 
						|
// codice zona
 | 
						|
  temps = _msk->get (F_CODICE_ZONA_DA);                      // mette in temps il valore del campo codice zona da
 | 
						|
  if (temps.not_empty())                                     // se è stato inserito un valore...
 | 
						|
    first.put("ZONA", temps);                          // mettilo nel campo zona
 | 
						|
  temps = _msk->get (F_CODICE_ZONA_A);
 | 
						|
  if (temps.not_empty())
 | 
						|
    last.put ("ZONA", temps); 
 | 
						|
  
 | 
						|
// codice agente: imposta i campi solo se ne è abilitata la gestione
 | 
						|
// se agente è disabilitato, i campi agente rimangono vuoti
 | 
						|
  if (agente)
 | 
						|
  {
 | 
						|
    temps = _msk->get (F_CODICE_AGENTE_DA);
 | 
						|
    if (temps.not_empty())
 | 
						|
      first.put("CODAG", temps);
 | 
						|
    temps = _msk->get (F_CODICE_AGENTE_A);
 | 
						|
    if (temps.not_empty())
 | 
						|
      last.put ("CODAG", temps);
 | 
						|
  }
 | 
						|
  
 | 
						|
  delete _msk;
 | 
						|
  
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
// crea fatture ordinate tramite la elab_princ()
 | 
						|
// first e last sono 2 rectype che contengono i dati da a per filtrare i documenti originali
 | 
						|
// campo_ordinamento è una stringa contenente la chiave di ordinamento (per cliente o per altro)
 | 
						|
// da specificare nel TCursor usato per individuare i documenti originali
 | 
						|
 | 
						|
int TBatch_crea_doc::per_cliente(TRectype& first, TRectype& last, const char* campo_ordinamento)
 | 
						|
{
 | 
						|
  TRelation rel (LF_DOC); // relazione sul file dei documenti
 | 
						|
// filtro per il TCursor:
 | 
						|
// DATADOC è obbligatoria, ma TIPOCF non dovrebbe essere per forza "C"
 | 
						|
  TString filter("(ANSI(DATADOC)>=\"");   // include nel filtro i tests sui campo obbligatori
 | 
						|
  filter << first.get_date("DATADOC").string(ANSI) << "\")&&(ANSI(DATADOC)<=\"";
 | 
						|
  filter << last.get_date("DATADOC").string(ANSI) << "\")&&(TIPOCF==\"C\")";
 | 
						|
 | 
						|
// se per i campi opzionali sono stati specificati dei valori, include i tests nel filtro:
 | 
						|
// CODICE AGENTE
 | 
						|
  if (!first.get("CODAG").empty())
 | 
						|
     filter << "&&(CODAG>=\"" << first.get("CODAG") << "\")";
 | 
						|
  if (!last.get("CODAG").empty())
 | 
						|
     filter << "&&(CODAG<=\"" << last.get("CODAG") << "\")";
 | 
						|
     
 | 
						|
// CODICE ZONA
 | 
						|
  if (!first.get("ZONA").empty())
 | 
						|
     filter << "&&(ZONA>=\"" << first.get("ZONA") << "\")";
 | 
						|
  if (!last.get("ZONA").empty())
 | 
						|
     filter << "&&(ZONA<=\"" << last.get("ZONA") << "\")";
 | 
						|
 | 
						|
// setta i limiti dei codici CLIENTI/FORNITORI per la funzione filterfunct del TCursor
 | 
						|
  _first_codcf = first.get_long ("CODCF");
 | 
						|
  _last_codcf  = last.get_long ("CODCF");
 | 
						|
 | 
						|
#ifdef _TDD_IN_FILTER
 | 
						|
// filtro costruito in base a tutti i tipi di doc. che hanno un record ELABORAZIONE DIFFERITA (ELD)
 | 
						|
// che li trasforma in _tipo_doc_des
 | 
						|
  TString tdfilter(1024);
 | 
						|
  tdfilter = td_ELD_to_filter(_tipo_doc_des);
 | 
						|
// se non è vuoto, lo aggiunge al filtro già creato
 | 
						|
  if (!tdfilter.empty())
 | 
						|
     filter << "&&(" << tdfilter << ")";
 | 
						|
#endif
 | 
						|
// crea, tramite un TCursor, un elenco dei documenti sorgente che rispondono alle caratteristiche
 | 
						|
  TSorted_cursor curs(&rel, campo_ordinamento, filter, _chiave, &first, &last);
 | 
						|
// la filterfunct limita i documenti a quelli con un codice CLI/FO fra _first_codcf e _last_codcf
 | 
						|
// (cioé quelli indicati nella maschera richiesta in precedenza)
 | 
						|
  curs.set_filterfunction(filterfunct);
 | 
						|
 | 
						|
  return elab_princ(curs);
 | 
						|
}
 | 
						|
 | 
						|
// esegue tutta l'elaborazione in modo BATCH, sui documenti individuati nel TCursor curs
 | 
						|
int TBatch_crea_doc::elab_princ(TSorted_cursor &curs)
 | 
						|
{
 | 
						|
  int err;              // errori ritornati dalle funzioni
 | 
						|
  long n;             // numero della fattura nella numerazione corrente
 | 
						|
  bool no_select = TRUE;  // TRUE se non sono stati selezionati documenti dallo sheet
 | 
						|
  bool no_elab = TRUE;      // TRUE se non ha ancora elaborato nessun documento
 | 
						|
  TLocalisamfile f(LF_DOC);     // per gestire la testata dei documenti
 | 
						|
  TLocalisamfile rdoc(LF_RIGHEDOC); // per gestire le righe dei documenti
 | 
						|
  int current = 0;                              // chiave corrente
 | 
						|
  TRectype pilota (LF_DOC);     // record per il documento pilota
 | 
						|
  TTable t("NUM");                              // tabella numerazioni documenti
 | 
						|
  TRectype tempr(LF_DOC);               // record del documento originale che si sta elaborando
 | 
						|
  TRectype temprdoc (LF_RIGHEDOC);      // record per le righe dei documenti originali
 | 
						|
  int nrdoc;                                    // numero di righe scritte nel doc finale
 | 
						|
  bool altri;     // TRUE se ci sono altri documenti da includere nello stesso doc. finale
 | 
						|
 | 
						|
  if (curs.items() == 0)            // se non ha individuato doc. originali, indica errore
 | 
						|
  {
 | 
						|
    error_box ("Nessun documento da elaborare.");
 | 
						|
    return NO_ORG_DOCS;
 | 
						|
  }
 | 
						|
  curs.freeze();  // non perdere tempo a riaggiornarti
 | 
						|
//  curs=0;     // comincia dal primo documento della lista
 | 
						|
 | 
						|
// _processed è un array di flag che indica se il documento relativo a ciascun flag
 | 
						|
// sia da processare (FALSE) o da ignorare/già processato (TRUE).
 | 
						|
 | 
						|
// le prossime sono righe fossili, rimaste da quanto BATCH e INTERATTIVO erano ancora assieme
 | 
						|
//*********************
 | 
						|
// Inizio righe fossili
 | 
						|
//*********************
 | 
						|
 | 
						|
  TString80 Titolo("documenti elaborabili che possono diventare");
 | 
						|
  Titolo << _tipo_doc_des;
 | 
						|
  TCursor_sheet docs_sheet(&curs,
 | 
						|
     " |NDOC|TIPODOC|DATADOC|TIPOCF|CODCF|OCFPI",
 | 
						|
       Titolo,
 | 
						|
     "@1|Numero@7|Tipo@4|Data@10|C/F|Cod. cliente|CF o P.IVA@16");
 | 
						|
 | 
						|
  docs_sheet.enable_check();
 | 
						|
  if (_interattivo)
 | 
						|
    {
 | 
						|
    if (docs_sheet.run()==K_ESC) return ESC_PRESSED;
 | 
						|
    for (int i=0; i<docs_sheet.items(); i++)
 | 
						|
      if (!docs_sheet.checked(i))_processed.set(i);
 | 
						|
        else no_select = FALSE;
 | 
						|
    if (no_select)
 | 
						|
      {
 | 
						|
        error_box ("Nessun documento selezionato.");
 | 
						|
        return NO_ORG_DOCS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
//*********************
 | 
						|
// Fine righe fossili
 | 
						|
//*********************
 | 
						|
 | 
						|
// Scandaglia tutto curs e setta _processed in tutti i doc. originali che non hanno il
 | 
						|
// relativo record di ELABORAZIONE DIFFERITA (ELD) per essere trasformati in doc. destinazione
 | 
						|
 | 
						|
  for (int i=0; i<curs.items();i++)  if (!_processed[i]) esiste_ELD(curs,i,SET_PROCESSED);
 | 
						|
 | 
						|
// ciclo di generazione fattura: finchè vi è ancora un documento da elaborare,...
 | 
						|
  while (next_pilota(curs,pilota))  // locka automaticamente il documento (pilota) che sta elaborando
 | 
						|
  {
 | 
						|
    get_info(pilota); // setta un mare di variabili che dipendono dal documento originale
 | 
						|
 | 
						|
//*****************************************************
 | 
						|
//* questa sezione serve a CREARE il documento finale *
 | 
						|
//*****************************************************
 | 
						|
 | 
						|
// le prossime sono righe fossili, rimaste da quanto BATCH e INTERATTIVO erano ancora assieme
 | 
						|
//*********************
 | 
						|
// Inizio righe fossili
 | 
						|
//*********************
 | 
						|
 | 
						|
    if (_interattivo)
 | 
						|
      {
 | 
						|
      TDate d(TODAY);
 | 
						|
      _datadoc = d;
 | 
						|
      _anno = d.year();
 | 
						|
      // inserisce il record di testata della fattura che va a creare
 | 
						|
      f.put ("CODNUM", _codnum);        // la fattura va numerata in base alla codnum specificata in ELD
 | 
						|
      f.put ("ANNO",   _anno);          // imposta l'anno del documento
 | 
						|
      f.put ("PROVV",  _provv);         // imposta provv./def. del documento
 | 
						|
      f.put ("NDOC",   _ndoc);          // imposta il numero del documento
 | 
						|
      if (!_crea_doc)
 | 
						|
        {
 | 
						|
        err = f.read(_isgteq);          // cerca il documento
 | 
						|
        if (err)   // guarda se si è verificato un errore
 | 
						|
          {
 | 
						|
          error_box ("Errore di lettura %d in doc, cercando il documento", err);
 | 
						|
          return READ_ERROR;
 | 
						|
          }
 | 
						|
        } else f.curr() = pilota; // tutti i campi della fattura sono uguali al documento pilota, tranne alcuni (impostati più sotto)
 | 
						|
      _tipo_doc_des  = f.get ("TIPODOC");   // imposta il tipo di documento
 | 
						|
      _stato_f_doc_f = f.get ("STATO");     // stato della fattura appena creata
 | 
						|
      }
 | 
						|
    else
 | 
						|
//*********************
 | 
						|
// Fine righe fossili
 | 
						|
//*********************
 | 
						|
  {
 | 
						|
// dovendo creare un nuovo documento TIPODOCDES, prende il primo numero disponibile nella numerazione
 | 
						|
// relativa, aggiornando il record della numerazione
 | 
						|
// (chiedi a Matteo se vuoi delle spiegazioni, oppure a me, se credi di non riuscire a capire Matteo)
 | 
						|
 | 
						|
   t.zero();  // azzera il record della tabella NUMerazioni
 | 
						|
   t.put ("CODTAB", _codnum);      // cerca NUMerazione del documento destinazione
 | 
						|
                                   // (codice preso dalla get_info)
 | 
						|
   if (err = t.read (_isgteq, _lock))  // legge lockando il record per evitare conflitti
 | 
						|
   {
 | 
						|
     error_box ("TBatch_crea_doc::per_cliente : errore %d di lettura su tab(NUM)", err);
 | 
						|
     return READ_ERROR;
 | 
						|
   }
 | 
						|
   if (t.get("CODTAB") == _codnum)     // controlla che il codice numerazione sia effettivamente quello cercato (?)
 | 
						|
   {                                   
 | 
						|
     n = t.get_long("I1");             // legge l'ultimo numero di documento utilizzato
 | 
						|
     n++;                              // ora n è il numero della mia fattura (da mettere in NDOC);
 | 
						|
   }
 | 
						|
   else
 | 
						|
      n = 1;           // se non esiste alcun documento con il codice numerazione specificato, allora la fattura corrente è la n° 1
 | 
						|
    // inserisce il record di testata del doc_destinazione che va a creare
 | 
						|
   f.curr() = pilota;          // tutti i campi del doc_destinazione sono uguali al documento pilota,
 | 
						|
                               // tranne quelli impostati qui sotto:
 | 
						|
   f.put ("NDOC", n);          // imposta il numero del documento
 | 
						|
   f.put ("TIPODOC", _tipo_doc_des);   // imposta il tipo di documento
 | 
						|
   f.put ("STATO", _stato_f_doc_f);    // stato del documento appena creato
 | 
						|
   f.put ("DATADOC", _datadoc);    // data di creazione del documento (indicata nella maschera)
 | 
						|
   f.put ("CODNUM", _codnum);        // la fattura va numerata in base alla codnum specificata
 | 
						|
    if ((err = f.write()) == NOERR)     // scrive il record in doc. Se non ci sono errori...
 | 
						|
     {
 | 
						|
       t.put ("I1", n);                  // imposta nuovo numero del documento
 | 
						|
       t.rewrite();                      // aggiorna il numero del documento nella tabella NUMerazioni
 | 
						|
       t.read (_isequal, _unlock);       // unlocka il record
 | 
						|
     }
 | 
						|
     else   // se vi e' stato un errore nello scrivere il doc_destinazione,...
 | 
						|
     {
 | 
						|
       t.read (_isequal, _unlock);   // unlocka il record in anche in caso di errore
 | 
						|
       switch (err)
 | 
						|
       {
 | 
						|
          case _isreinsert:
 | 
						|
            fatal_box ("ve6100: Errore fatale: il record con la chiave specificata esiste già: impossibile sovrascrivere");
 | 
						|
            break;
 | 
						|
          default:
 | 
						|
            fatal_box ("ve6100: Errore fatale: %d scrivendo sulla tabella NDOC", err);
 | 
						|
            break;
 | 
						|
       }
 | 
						|
       return RECORD_WRITE_ERROR;    // indica al chiamante un errore nella scrittura di un record
 | 
						|
     }
 | 
						|
  }
 | 
						|
 | 
						|
    tempr = pilota;             // il primo documento originale da elaborare è quello pilota
 | 
						|
    
 | 
						|
// qui inizia il ciclo per la creazione della fattura
 | 
						|
// N.B.: appende ogni documento originale nella fattura
 | 
						|
    nrdoc = 0;                      // numero riga documento
 | 
						|
    bool endsearch = FALSE;         // true quando non ci sono piu' doc_originali per questo doc_destinazione
 | 
						|
    TRecord_array doc_destinazione (LF_RIGHEDOC, "NRIGA");        // array contenente le righe della fattura
 | 
						|
 | 
						|
// costruisce ed imposta il record filtro per trovare le righe di doc_destinazione
 | 
						|
    TRectype r (LF_RIGHEDOC);
 | 
						|
    r.zero();
 | 
						|
    _ndoc = "";
 | 
						|
    _ndoc << n;
 | 
						|
// imposta i dati della chiave
 | 
						|
    r.put ("CODNUM", _codnum);
 | 
						|
    r.put ("ANNO", _anno);
 | 
						|
    r.put ("PROVV", _provv);
 | 
						|
    r.put ("NDOC", _ndoc);
 | 
						|
// _crea_doc = FALSE <==> interattivo = TRUE: nel BATCH, _crea_doc = TRUE, sempre
 | 
						|
    if (!_crea_doc) doc_destinazione.read(r); // se non deve crearlo, legge le righe gia' presenti
 | 
						|
//    doc_destinazione.set_key(&r);
 | 
						|
    
 | 
						|
// legge tutti i doc_originali che vanno nel doc_destinazione
 | 
						|
    do
 | 
						|
    {
 | 
						|
/*      TRecord_array doc_originale (LF_RIGHEDOC, "NRIGA");           // array per leggere le righe del doc. org. da elaborare
 | 
						|
      // carica il documento corrente da rdoc:
 | 
						|
      // imposta i campi della chiave
 | 
						|
      temprdoc.zero();
 | 
						|
      temprdoc.put ("CODNUM", tempr.get("CODNUM"));     // tempr = record del documento originale da inserire
 | 
						|
      temprdoc.put ("ANNO", tempr.get ("ANNO"));
 | 
						|
      temprdoc.put ("PROVV", tempr.get("PROVV"));
 | 
						|
      temprdoc.put ("NDOC", tempr.get("NDOC"));
 | 
						|
      // lascia il campo "NRDOC" come campo per il conteggio
 | 
						|
      // legge le righe del documento originale, distruggendo quelle precedentemente memorizzate
 | 
						|
      // legge solo i records che corrispondono alla chiave (temprdoc)
 | 
						|
      int err = doc_originale.read(temprdoc);
 | 
						|
      CHECK (err==NOERR, "read da rdoc fallita");
 | 
						|
 */     
 | 
						|
      // appende il documento originale al documento di destinazione
 | 
						|
// per ogni doc_originale legge i dati (per il primo non e' necessario)
 | 
						|
      get_info(tempr);
 | 
						|
// legge dal .ini del doc_originale tempr. il flag che dice se le righe di tempr
 | 
						|
// possono essere evase parzialmente o devono essere evase per intero: controllo fossile,
 | 
						|
// dal momento che in modo BATCH i documenti vengono evasi completamente
 | 
						|
      bool raggr_parz = get_raggr_parz(tempr,err);
 | 
						|
// legge il metodo (es. B01F01) di elaborazione (trasformazione) delle righe
 | 
						|
      TString met = metodo(tempr);
 | 
						|
// elabora le righe, scrivendole nel doc_destinazione tramite l'omonimo TRecord_array
 | 
						|
      elab_righe(met,raggr_parz,tempr,doc_destinazione,temprdoc);
 | 
						|
 | 
						|
      _processed.set(curs.pos());   // indica che il documento e' stato processato
 | 
						|
 | 
						|
// aggiorna lo stato del documento originale e lo scrive
 | 
						|
      curs.file(LF_DOC).put ("STATO", _stato_f_doc_i);
 | 
						|
      curs.file(LF_DOC).setkey(1);
 | 
						|
      if (err = curs.file(LF_DOC).rewrite())
 | 
						|
      {
 | 
						|
         error_box ("ve6200: Errore fatale: %d scrivendo sul file DOC", err);
 | 
						|
         return RECORD_WRITE_ERROR;
 | 
						|
      }
 | 
						|
      curs.file(LF_DOC).setkey(2);
 | 
						|
      curs.unlock();  // unlocka il record del documento processato
 | 
						|
 | 
						|
// cerca il prossimo doc_originale da inserire. Se non ce ne sono piu', termina la generazione del doc_destinazione
 | 
						|
// se ce ne sono ancora, mette nel TRectype tempr il record del prossimo doc_originale da aggiungere
 | 
						|
 | 
						|
      if (_raggruppa)   // se deve raggruppare piu' doc_originali in uno solo, ne cerca altri
 | 
						|
         altri = search(pilota, tempr, curs);
 | 
						|
      else          // altrimenti passa al prossimo doc_destinazione
 | 
						|
         altri = FALSE;
 | 
						|
    }
 | 
						|
    while (altri);    // fine del ciclo che raggruppa i doc_originali in un solo doc_destinazione
 | 
						|
    
 | 
						|
// controlla se deve raggruppare le righe per codice articolo:
 | 
						|
// se vi sono piu' righe con lo stesso codice articolo e altre caratteristiche in comune,
 | 
						|
// le riunisce in una sola riga
 | 
						|
 | 
						|
    if (_per_articolo && (doc_destinazione.rows() > 1)) // se deve raggr. e ci sono almeno 2 righe
 | 
						|
       raggruppa_righe (doc_destinazione);
 | 
						|
        
 | 
						|
// salva le righe del doc_destinazione creato
 | 
						|
    if (err = doc_destinazione.write())
 | 
						|
    {
 | 
						|
      error_box ("Errore nella scrittura del doc. destinazione. err = %d", err);
 | 
						|
      return RECORD_WRITE_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
     no_elab = FALSE;      // ha elaborato almeno un documento
 | 
						|
 | 
						|
// cerca il prossimo documeto pilota per il prossimo doc_destinazione
 | 
						|
  };         // finche' i doc_originali non finiscono
 | 
						|
  if (no_elab)            // se non ha elaborato (trovato)doc_originali da elaborare, indica errore
 | 
						|
  {
 | 
						|
    error_box ("Nessun documento elaborato.");
 | 
						|
    return NO_ORG_DOCS;
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}//*** fino a qua ***//
 | 
						|
 | 
						|
int TBatch_crea_doc::get_info(TRectype &doc)
 | 
						|
{
 | 
						|
  int err;
 | 
						|
  // informazioni dalla tabella elaborazioni differite
 | 
						|
  TRectype reld(LF_TAB); // reld e' un record di tipo tabella
 | 
						|
  leggi_da_ELD(reld,doc.get("TIPODOC"));
 | 
						|
 | 
						|
  // Imposta i dati relativi all'elaborazione differita corrente
 | 
						|
  _tipo_doc_org = reld.get ("S6");   // tipo documento originale
 | 
						|
  _tipo_doc_des = reld.get ("S8");   // tipo documento destinazione
 | 
						|
  TConfig doc_config (getini(doc,err), "RAGGRUPPA"); // prende il .ini di doc
 | 
						|
  _stati_validi_doc_i = doc_config.get ("STATIVALIDI");  // stato iniziale del documento originale
 | 
						|
  _stato_f_doc_i = doc_config.get ("STATOFINALE");       // stato finale (dopo l'elaborazione) del documento originale
 | 
						|
// ha qualche senso che _stato_f_doc_f e _codnum siano indicati nel record ELD di ciascun documento iniziale ?
 | 
						|
  if (!_interattivo)
 | 
						|
    {
 | 
						|
    _stato_f_doc_f = reld.get ("S9");  // stato finale (dopo l'elaborazione) del documento finale
 | 
						|
    _codnum = reld.get ("S5");         // codice numerazione per il documento finale
 | 
						|
    }
 | 
						|
          // il flag di sospensione imposta da controllare va preso dal registro a cui
 | 
						|
          // la numerazione del documento e' collegata
 | 
						|
  _sosp_imposta = getflag(doc, SOSPENSIONE_IMPOSTA); // T/F sospensione imposta
 | 
						|
  _cod_sconto =   getflag(doc, CODICE_SCONTO);       // T/F codice sconto
 | 
						|
  _stesso_anno = stesso_anno_fiscale(doc);           // T/F per STESSOANNOFISCALE in [RAGGR.] del .ini di reld
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
bool TBatch_crea_doc::stesso_anno_fiscale(TRectype& rec)
 | 
						|
{                                      
 | 
						|
    bool stesso = FALSE;
 | 
						|
//  bool stesso = _stesso_anno_fiscale;
 | 
						|
  int err;
 | 
						|
//  if (!stesso)
 | 
						|
//    {
 | 
						|
    TString name(getini(rec, err));
 | 
						|
    if (!err){
 | 
						|
             TConfig config (name, "RAGGRUPPA"); // prende il .ini di rec
 | 
						|
             stesso = (config.get("STESSOANNOFISCALE")[0] == '1'); // trova se si possono evadere parzialmente le righe
 | 
						|
             }
 | 
						|
//    }
 | 
						|
  return stesso;
 | 
						|
}
 | 
						|
 | 
						|
// ritorna la stringa metodo di trasf. dal record ELD per rec->_tipo_destinazione
 | 
						|
TString TBatch_crea_doc::metodo(TRectype &rec)
 | 
						|
{
 | 
						|
  TString metodo;
 | 
						|
  TString _tipo_pilota = rec.get("TIPODOC");
 | 
						|
  TRectype reld(LF_TAB);  // = rec solo per inizializzarlo
 | 
						|
  leggi_da_ELD(reld,_tipo_pilota);
 | 
						|
  metodo = reld.get("S1");
 | 
						|
  return metodo;
 | 
						|
}
 | 
						|
 | 
						|
// trova il .ini di rec e lo restituisce
 | 
						|
TString TBatch_crea_doc::getini(TRectype& rec, int &err)
 | 
						|
{
 | 
						|
// aggiustare con una new ad un TConfig
 | 
						|
  TTable teld("%TIP");  // nella tabella %TIP
 | 
						|
  teld.zero();
 | 
						|
  teld.put ("CODTAB", rec.get("TIPODOC"));  // tipo del documento pilota
 | 
						|
  err = teld.read (_isgteq);   // legge il record
 | 
						|
  if (err)
 | 
						|
    {
 | 
						|
    error_box("Non riesco a leggere nella tabella %s il tipo documento %s",teld.name(),(const char *)rec.get("TIPODOC"));
 | 
						|
    return err;
 | 
						|
    }
 | 
						|
  TRectype& rtip = teld.curr(); // e lo mette in dest
 | 
						|
  TFilename inifile (rtip.get("S4")); // il nome del .ini e' nel campo S4
 | 
						|
  inifile.ext("ini");
 | 
						|
  return (TString)inifile;
 | 
						|
}
 | 
						|
 | 
						|
// prende i dati della sezione [RAGGRUPPA]
 | 
						|
bool TBatch_crea_doc::get_raggr_parz(TRectype& rec, int &err)
 | 
						|
{
 | 
						|
  bool raggr_parz = FALSE;
 | 
						|
  err = FALSE;
 | 
						|
  TString name(getini(rec, err));
 | 
						|
  // if (err) return err;
 | 
						|
  // _stati_validi = config.get("STATIVALIDI");  // trova gli stati validi
 | 
						|
  if (!err) {
 | 
						|
            TConfig config (name,"RAGGRUPPA"); // prende il .ini di rec
 | 
						|
            raggr_parz = (config.get("RAGGRPARZ")[0] == '1'); // trova se si possono evadere parzialmente le righe
 | 
						|
            }
 | 
						|
  return raggr_parz;
 | 
						|
}
 | 
						|
 | 
						|
// controlla che il documento rec sia in uno degli stati validi indicati nella sezione [RAGGRUPPA] del suo .ini
 | 
						|
int TBatch_crea_doc::statovalido(TRectype& rec)
 | 
						|
{
 | 
						|
  int err;
 | 
						|
//  TConfig config (getini(rec, err), "RAGGRUPPA"); // prende il .ini di rec
 | 
						|
//  if (err) return err;
 | 
						|
//  TString80 _stati_validi;
 | 
						|
//  _stati_validi = config.get("STATIVALIDI");  // trova gli stati validi
 | 
						|
  err = _stati_validi_doc_i.find((rec.get("STATO"))[0]);  // cerca lo stato (-1 e' non trovato)
 | 
						|
  if (err == -1) err = STATO_NON_VALIDO;
 | 
						|
          else  err = STATO_VALIDO;
 | 
						|
  return err;
 | 
						|
}
 | 
						|
 | 
						|
// ritorna TRUE se esiste una ELD che passa dal tipo documento di pilota a _tipo_doc_des
 | 
						|
int TBatch_crea_doc::esiste_ELD(TSorted_cursor &curs,int i,bool set_proc)
 | 
						|
{
 | 
						|
//*************
 | 
						|
// bisognerebbe affidarsi ad un decoder
 | 
						|
//*************
 | 
						|
  curs = i;  
 | 
						|
  TRectype &pilota = curs.curr();         // imposta il primo documento da verificare : pilota
 | 
						|
  TString _tipo_pilota = pilota.get("TIPODOC");
 | 
						|
  TRectype dummy(LF_TAB); // = pilota solo per inizializzarlo
 | 
						|
  int err = leggi_da_ELD(dummy,_tipo_pilota);
 | 
						|
  if (err == ELAB_NOT_FOUND)
 | 
						|
    if (set_proc==SET_PROCESSED) _processed.set(curs.pos());
 | 
						|
      else error_box ("TElaborazioni::per_cliente() : non esiste il tipo di elaborazione %s -> %s in tab(ELD)", (const char *)_tipo_pilota, (const char *)_tipo_doc_des);
 | 
						|
  return err;
 | 
						|
}
 | 
						|
// ritorna ELAB_FOUND se esiste una ELD che passa dal tipo documento di pilota a _tipo_dest
 | 
						|
// (o _tipo_doc_dest, se _tipo_dest non viene specificato) e riempie eventualmente dest con la prima ELD
 | 
						|
int TBatch_crea_doc::leggi_da_ELD(TRectype &dest,TString _tipo_pilota,TString _tipo_dest)
 | 
						|
{
 | 
						|
   TRelation rel("ELD");
 | 
						|
   TString80 filter;
 | 
						|
   filter << "((S6==\"" << _tipo_pilota << "\")";
 | 
						|
   if (!_tipo_dest.empty())  filter << "&&(S8==\"" << _tipo_doc_des << "\")";
 | 
						|
      else if (!_tipo_doc_des.empty())  filter << "&&(S8==\"" << _tipo_doc_des << "\")";
 | 
						|
   filter << ")";
 | 
						|
   TCursor curs(&rel, filter);
 | 
						|
   if (curs.items() == 0) return ELAB_NOT_FOUND;
 | 
						|
   curs = 0;
 | 
						|
   dest = curs.curr();
 | 
						|
   return ELAB_FOUND;
 | 
						|
/*
 | 
						|
  int err;
 | 
						|
  TTable teld("ELD");
 | 
						|
  teld.zero();
 | 
						|
  teld.put ("S6", _tipo_pilota);  // tipo del documento pilota
 | 
						|
  teld.put ("S8", _tipo_doc_des);  // tipo del documento finale
 | 
						|
  err = teld.read (_isgteq);   // legge il record
 | 
						|
  dest = teld.curr(); // e lo mette in dest
 | 
						|
  if (err)   // guarda se si è verificato un errore
 | 
						|
  {
 | 
						|
    error_box ("TElaborazioni::per_cliente() : errore di lettura %d da tab(ELD)", err);
 | 
						|
    return READ_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((teld.get ("S6") != _tipo_pilota)||(teld.get ("S8") != _tipo_doc_des))   // verifica che il tipo di documento trovato sia quello richiesto
 | 
						|
  {
 | 
						|
//    error_box ("TElaborazioni::per_cliente() : non esiste il tipo di elaborazione %s -> %s in tab(ELD)", (const char *)_tipo_pilota, (const char *)_tipo_doc_des);
 | 
						|
// se non esiste una ELD, setta processed (set_proc permettendo),
 | 
						|
// in modo da ignorare questo documento nei controlli successivi
 | 
						|
    return ELAB_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  teld.read (_isequal, _unlock);   // unlocka il record in ogni caso
 | 
						|
  return ELAB_FOUND;
 | 
						|
*/
 | 
						|
}
 | 
						|
 | 
						|
const char *TBatch_crea_doc::td_ELD_to_filter(TString &_tipo_doc_des)
 | 
						|
{
 | 
						|
  bool first = TRUE;
 | 
						|
  TString td_filter(1024);
 | 
						|
  TRelation rel("ELD");
 | 
						|
  TString80 filter;
 | 
						|
  if (_tipo_doc_des.empty())  return "";
 | 
						|
  filter << "(S8==\"" << _tipo_doc_des << "\")";
 | 
						|
  TCursor curs(&rel, filter);
 | 
						|
  if (curs.items() == 0) return "";
 | 
						|
  for (int i=0; i<curs.items();i++)
 | 
						|
    {
 | 
						|
    if (first)  first=FALSE;
 | 
						|
      else td_filter << "||";
 | 
						|
    td_filter << "(TIPODOC==\"" << curs.curr().get("S6") << "\")";
 | 
						|
    }
 | 
						|
  return (const char *)td_filter;
 | 
						|
}
 | 
						|
 | 
						|
// cerca il prossimo documeto pilota in cursor
 | 
						|
bool TBatch_crea_doc::next_pilota(TSorted_cursor &curs,TRectype &pilota)
 | 
						|
{
 | 
						|
  bool cont = TRUE;
 | 
						|
  TRecnotype temp = curs.items();
 | 
						|
  int err = FALSE;
 | 
						|
  for (int i=0; i < temp && cont && (_processed[i] || ((err = esiste_ELD(curs,i)) != READ_ERROR)); i++)    // prossimo documento non processato
 | 
						|
  switch (err)
 | 
						|
    {
 | 
						|
    case ELAB_FOUND:   // se ne ha trovato uno
 | 
						|
         curs=i;
 | 
						|
         if (statovalido(curs.curr()))
 | 
						|
            {
 | 
						|
            pilota = curs.curr();    // nuovo documento pilota
 | 
						|
            curs.lock();
 | 
						|
            cont = FALSE;
 | 
						|
            }
 | 
						|
         break;
 | 
						|
    default:;
 | 
						|
    };
 | 
						|
  if (i>=temp) return FALSE;  // se sono stati tutti processati --> termina
 | 
						|
  return TRUE;  // altrimenti continua a processare
 | 
						|
}
 | 
						|
 | 
						|
// elabora le righe di doc_originale in doc_destinazione, sul TRectype temprdoc, col metodo metodo
 | 
						|
bool TBatch_crea_doc::elab_righe(TString metodo,bool raggr_parz,TRectype &tempr,TRecord_array &doc_destinazione,TRectype &temprdoc)
 | 
						|
{
 | 
						|
    bool tutte_le_righe_elab = TRUE;
 | 
						|
//  switch (metodo)
 | 
						|
//    {
 | 
						|
//    case "B01F01":
 | 
						|
   TRecord_array righe_tmp (LF_RIGHEDOC, "NRIGA");        // array contenente le righe della fattura
 | 
						|
   TRelation rel(LF_RIGHEDOC);
 | 
						|
//   rel.lfile().zero();
 | 
						|
   TString80 ndoc_filter = "(";
 | 
						|
   ndoc_filter << "(CODNUM==\"" << tempr.get("CODNUM") << "\")&&";
 | 
						|
   ndoc_filter << "(ANNO==\""   << tempr.get("ANNO")   << "\")&&";
 | 
						|
   ndoc_filter << "(PROVV==\""  << tempr.get("PROVV")  << "\")&&";
 | 
						|
   ndoc_filter << "(NDOC==\""   << tempr.get("NDOC")   << "\")";
 | 
						|
   ndoc_filter << ")";
 | 
						|
   TSorted_cursor curs_righe(&rel, "NRIGA", ndoc_filter);
 | 
						|
   curs_righe.read();   // legge le righe del documento originale corrente
 | 
						|
         
 | 
						|
   // qui sostituisci le costanti stringa per testata e fields col tuo frammento di
 | 
						|
   // codice che interpreta l'apposita sezione del profilo documento.
 | 
						|
   TTable t("%TIP");
 | 
						|
   t.zero();
 | 
						|
   t.put ("CODTAB", tempr.get("TIPODOC"));
 | 
						|
   t.read (_isgteq);
 | 
						|
   TString _descr_tipodocorg (t.get("S4"));
 | 
						|
   TInterattivo_sheet righe_sheet(&curs_righe,"|NRIGA|CODART|DESCR|PREZZO|QTA|UMQTA|QTAEVASA|UMQTA|QTA",
 | 
						|
      _descr_tipodocorg << " - righe",
 | 
						|
      "@1|N.riga|Codice articolo@20|Descrizione@50|Prezzo@18|Quantità@11|um|Q.tà evasa@11|um|Q.tà da evadere");
 | 
						|
   righe_sheet.add_button(DLG_OK, "Conferma", K_YES);
 | 
						|
/*     if (_raggruppa_intero)
 | 
						|
   {
 | 
						|
      righe_sheet.enable();     // seleziona tutte le righe
 | 
						|
      righe_sheet.disable_check();  // impedisce di toglierne alcune
 | 
						|
   }
 | 
						|
*/
 | 
						|
   KEY key=0;
 | 
						|
   int _rdoc = 1;
 | 
						|
   bool batch = !((raggr_parz)&&(_interattivo));
 | 
						|
   if (!batch)
 | 
						|
     key = righe_sheet.run();
 | 
						|
   if (batch||(key==K_YES))
 | 
						|
        for (int i=0; i<righe_sheet.items(); i++) // copia le righe selezionate nel documento finale
 | 
						|
           if (batch||righe_sheet.checked(i))
 | 
						|
           {
 | 
						|
              curs_righe = i;
 | 
						|
              righe_tmp.row (_rdoc++, TRUE) = curs_righe.file(LF_RIGHEDOC).curr();
 | 
						|
           }
 | 
						|
           else tutte_le_righe_elab = FALSE;
 | 
						|
  if (metodo == "B01F01")
 | 
						|
      {
 | 
						|
      for (int i=1; i<=righe_tmp.rows(); i++)               // per tutte le righe del documento originale
 | 
						|
        {
 | 
						|
          temprdoc = righe_tmp.row (i); // prende la riga del documento originale
 | 
						|
          temprdoc.put ("CODNUM", _codnum); // chiave per la fattura (indicata nella tabella ELD)
 | 
						|
          temprdoc.put ("ANNO", _anno);     //
 | 
						|
          temprdoc.put ("PROVV", _provv);   //
 | 
						|
          temprdoc.put ("NDOC", _ndoc);     //
 | 
						|
          int nrdoc = doc_destinazione.last_row()+1;
 | 
						|
          TRectype& r = doc_destinazione.row(nrdoc, TRUE);  // il parametro TRUE indica di creare la riga se non esiste già
 | 
						|
          temprdoc.put ("NRIGA", r.get("NRIGA"));  // imposta il numero di riga
 | 
						|
          temprdoc.put("DESCEST","");       // azzera i campi memo
 | 
						|
          temprdoc.put("G1","");            //
 | 
						|
          r = temprdoc;           // imposta la i-esima riga (perché r è una reference)
 | 
						|
        }
 | 
						|
      }
 | 
						|
//    }
 | 
						|
    return tutte_le_righe_elab;
 | 
						|
}
 | 
						|
 | 
						|
// Ritorna due flag a seconda del parametro.
 | 
						|
bool TBatch_crea_doc::getflag (TRectype& rec, int n)
 | 
						|
{
 | 
						|
/*
 | 
						|
  TTable t("%TIP");
 | 
						|
  t.zero();
 | 
						|
  t.put ("CODTAB", rec.get("TIPODOC"));
 | 
						|
  t.read (_isgteq);
 | 
						|
 | 
						|
  TFilename filename(t.get("S4"));
 | 
						|
  filename.ext ("ini");
 | 
						|
  
 | 
						|
  TConfig conf(filename);
 | 
						|
*/
 | 
						|
  int err;
 | 
						|
  TConfig conf(getini(rec,err));
 | 
						|
  if (err) return READ_ERROR;
 | 
						|
  switch (n)            // determina quale flag leggere
 | 
						|
  {
 | 
						|
    case SOSPENSIONE_IMPOSTA: return TRUE;
 | 
						|
    /*
 | 
						|
      return conf.get_bool (" ", "   ");            // sezione, nome flag
 | 
						|
      // il flag da controllare va preso dal registro a cui la numerazione del documento
 | 
						|
      // e' collegata
 | 
						|
      */
 | 
						|
    case CODICE_SCONTO:
 | 
						|
      return conf.get_bool ("CAMBIO" , "PROFILO");        // sezione, nome flag
 | 
						|
  }
 | 
						|
  error_box ("getflag: Errore: parametro 2 = %d, non valido .", n);
 | 
						|
  return READ_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
/* Cerca tra i documenti selezionati da curs il prossimo, a partire da curs.curr() che puo' essere
 | 
						|
   raggruppato con il documento pilota. Il record eventualmente trovato e' ritornato in tempr.
 | 
						|
   La ricerca e' effettuata tra i documenti di curs.
 | 
						|
   Ritorna FALSE se non trova documenti da raggruppare, TRUE altrimenti. */
 | 
						|
bool TBatch_crea_doc::search (TRectype& pilota, TRectype& tempr, TSorted_cursor& curs)
 | 
						|
{
 | 
						|
  //   static bool csi = controlla_sosp_imp();  // determina se controllare il flag di sospensione d'imposta
 | 
						|
  TRectype campi_pilota (LF_DOC);       // usato per settare solo i campi importanti.
 | 
						|
  
 | 
						|
  campi_pilota.zero();
 | 
						|
  // campi_pilota.put ("CODNUM", pilota.get ("CODNUM"));
 | 
						|
  // campi_pilota.put ("STATO",  pilota.get ("STATO"));
 | 
						|
  campi_pilota.put ("CODCF",  pilota.get ("CODCF"));
 | 
						|
  campi_pilota.put ("TIPOCF", pilota.get ("TIPOCF"));
 | 
						|
  // se pilota ha settato STESSOANNOFISCALE, cerca solo i doc. dello stesso anno
 | 
						|
//  bool stesso_anno = stesso_anno_fiscale(pilota);
 | 
						|
  if (_stesso_anno)
 | 
						|
    campi_pilota.put ("ANNO",   _anno);
 | 
						|
  // campi_pilota.put ("ANNO",   pilota.get ("ANNO"));
 | 
						|
  // campi_pilota.put ("TIPODOC", _tipo_doc_org);
 | 
						|
  
 | 
						|
  //?? campi_pilota.put ("PROVV",  pilota.get ("PROVV"));
 | 
						|
  campi_pilota.put ("RAGGR",  pilota.get ("RAGGR"));
 | 
						|
  campi_pilota.put ("CODVAL", pilota.get ("CODVAL"));
 | 
						|
  campi_pilota.put ("CAMBIO", pilota.get ("CAMBIO"));
 | 
						|
  campi_pilota.put ("CODLIN", pilota.get ("CODLIN"));
 | 
						|
  campi_pilota.put ("SCONTOPERC", pilota.get ("SCONTOPERC"));
 | 
						|
  //?? campi_pilota.put ("NUMDOCRIF", pilota.get ("NUMDOCRIF"));
 | 
						|
  // controllo sul codice sconto
 | 
						|
 | 
						|
  bool found = FALSE;
 | 
						|
  TRecnotype items = curs.items();
 | 
						|
  for (int i = 0; i<items && !found; i++)
 | 
						|
    if (!_processed[i])
 | 
						|
    {
 | 
						|
      curs = i;
 | 
						|
      TRectype& temp = curs.curr();
 | 
						|
      if ((esiste_ELD(curs,i)==ELAB_FOUND)          // se esiste la ELD
 | 
						|
          &&(statovalido(temp)==STATO_VALIDO)  // e lo stato del documento e' valido (vedi il .ini)
 | 
						|
          &&(temp == campi_pilota))   // campi_pilota a destra per ignorare il confronto dei campi vuoti
 | 
						|
            found = doc_i_compatibili(campi_pilota,temp);
 | 
						|
        // il codice sconto non e' da leggere nell'ini ma in nel record di ogni documento
 | 
						|
    }
 | 
						|
  
 | 
						|
  curs.lock();
 | 
						|
  tempr = curs.curr();
 | 
						|
  return found;
 | 
						|
}
 | 
						|
 | 
						|
// guarda se i documenti pil e pil2 sono compatibili per essere uniti nello stesso documento finale
 | 
						|
bool TBatch_crea_doc::doc_i_compatibili(TRectype &pil,TRectype &pil2)
 | 
						|
{
 | 
						|
  bool _sosp_imposta;           // T/F sospensione imposta
 | 
						|
  bool _cod_sconto;             // T/F codice sconto
 | 
						|
  if (!(getflag(pil2, SOSPENSIONE_IMPOSTA) == _sosp_imposta)) return FALSE;
 | 
						|
  if (!(getflag(pil2, CODICE_SCONTO)       == _cod_sconto))  return FALSE;
 | 
						|
/*  if (!_stesso_anno) // if (_stesso_anno) -> search() ha gia' settato la ricerca sull'anno
 | 
						|
    if (!(pil.get("ANNO") == pil2.get("ANNO")))
 | 
						|
      if (stesso_anno_fiscale(pil2))  return FALSE;
 | 
						|
*/
 | 
						|
// _stesso_anno si riferisce solo a pil2, dato che lo STESSOANNOFISCALE che conta e' quello
 | 
						|
// dei doc originali e l'_anno e' quello di oggi (TODAY)
 | 
						|
  if ((_stesso_anno) && (pil2.get("ANNO")!=_anno)) return FALSE;
 | 
						|
  TRectype dest(LF_TAB); // reld e' un record di tipo tabella
 | 
						|
  leggi_da_ELD(dest,pil2.get("TIPODOC"));
 | 
						|
//  if (!(_stato_f_doc_f == dest.get("S9"))) return FALSE;
 | 
						|
  if (!(_codnum        == dest.get("S5"))) return FALSE;
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
// filterfunction per il campo numerico CODCF (la TExpression::eval() sbaglia perche' considera tutti i dati come stringhe)
 | 
						|
bool TBatch_crea_doc::filterfunct(const TRelation* r)
 | 
						|
{
 | 
						|
   TRectype& temp = r->curr();    // per accedere al record corrente senza dover sempre chiamare la funzione curr() della relazione
 | 
						|
   bool result = TRUE;
 | 
						|
   long l;
 | 
						|
   long firstcodcf, lastcodcf;    // per non chiamare sempre app()
 | 
						|
   
 | 
						|
#ifndef _TDD_IN_FILTER
 | 
						|
   if (!_tipo_doc_dest.empty())
 | 
						|
     {
 | 
						|
     TRectype dummy(LF_TAB); // = pilota solo per inizializzarlo
 | 
						|
     result = result && ((leggi_da_ELD(dummy,_temp.get("TIPODOC"),_tipo_doc_des) == ELAB_FOUND);
 | 
						|
     }
 | 
						|
#endif
 | 
						|
 | 
						|
   l = temp.get_long("CODCF");
 | 
						|
   if ((firstcodcf = app()._first_codcf) > 0)
 | 
						|
      result = result && (l >= firstcodcf);
 | 
						|
 | 
						|
   if ((lastcodcf = app()._last_codcf) > 0)
 | 
						|
      result = result && (l <= lastcodcf);
 | 
						|
   return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Raggruppa tutte le righe del documento doc che hanno uguali i seguenti campi:
 | 
						|
   - codice articolo (deve essere non blank)
 | 
						|
   - unita' di misura
 | 
						|
   - prezzo
 | 
						|
   - IVA
 | 
						|
*/
 | 
						|
void TBatch_crea_doc::raggruppa_righe (TRecord_array& doc)
 | 
						|
{
 | 
						|
   TRectype pilota (LF_RIGHEDOC); // record corrente di raggruppamento
 | 
						|
   TRectype tempr (LF_RIGHEDOC);  // prossimo record da raggruppare
 | 
						|
   TBit_array processed;      // array per indicare quali righe sono gia' state processate
 | 
						|
   TBit_array tocopy(doc.rows()); // array che indica quali righe debbono essere copiate in doc2
 | 
						|
   
 | 
						|
   tocopy.set();    // indica che tutte le righe sono da copiare
 | 
						|
   // si posiziona sul primo record che ha il codice articolo non vuoto
 | 
						|
   int i;
 | 
						|
   // salta le righe senza codice articolo (con CODART vuoto)
 | 
						|
   for (i=1; i<=doc.rows() && doc.row(i).get("CODART").empty() ; i++);
 | 
						|
   if (i>doc.rows())
 | 
						|
   {
 | 
						|
      message_box ("Tutti gli articoli sono privi di codice. Nessuna riga raggruppata.");
 | 
						|
      return;
 | 
						|
   } 
 | 
						|
 | 
						|
   TRectype confronto(LF_RIGHEDOC);     // record per il confronto dei campi significativi
 | 
						|
   int current;   // posizione dell'ultimo record valido trovato (per non ripetere sempre la ricerca dall'inizio)
 | 
						|
   do
 | 
						|
   {
 | 
						|
      current = i;
 | 
						|
      pilota = doc.row(i);
 | 
						|
      confronto.zero();   // imposta i campi significativi per il raggruppamento delle righe
 | 
						|
      confronto.put ("CODART", pilota.get ("CODART"));
 | 
						|
      confronto.put ("CODIVA", pilota.get ("CODIVA"));
 | 
						|
      confronto.put ("PREZZO", pilota.get ("PREZZO"));
 | 
						|
      confronto.put ("UMQTA",  pilota.get ("UMQTA"));
 | 
						|
      processed.set(i);   // la riga trovata e' processata (e' la riga pilota)
 | 
						|
      int prox;       // numero della prossima riga da raggruppare
 | 
						|
      while (prox_riga (prox, doc, processed, confronto))
 | 
						|
      {
 | 
						|
         pilota.put("QTA", pilota.get_real("QTA") + doc.row(prox).get_real("QTA")); // aggiorna il contenuto della riga pilota
 | 
						|
         doc.row(current, FALSE) = pilota;
 | 
						|
         processed.set(prox);   // indica che la riga e' stata processata
 | 
						|
         tocopy.reset(prox);    // indica che la riga non e' da copiare, perche' inglobata nella riga pilota
 | 
						|
      }
 | 
						|
      // cerca la prossima riga pilota
 | 
						|
      bool skip = TRUE;
 | 
						|
      for (i=current+1; i<=doc.rows() && skip; i++)
 | 
						|
         skip = doc.row(i).get("CODART").empty() || processed[i];
 | 
						|
      i--;
 | 
						|
   }
 | 
						|
   while (i<=doc.rows());  // finche' ci sono righe da elaborare
 | 
						|
   // necessario usare questa var. nel ciclo for seguente perche'doc.rows viene valutata ad ogni ciclo,
 | 
						|
   // e diminuisce di una unita' ogni volta che viene cancellata una riga. Cio' provocherebbe la mancata cancellazione
 | 
						|
   // delle ultime righe della fattura.
 | 
						|
   int drows = doc.rows();
 | 
						|
   for (i=1; i<=drows; i++) // cancella le righe raggruppate
 | 
						|
      if (!tocopy[i])
 | 
						|
         doc.destroy_row (i, FALSE);
 | 
						|
}
 | 
						|
 | 
						|
bool TBatch_crea_doc::prox_riga (int& prox, TRecord_array& doc, TBit_array& processed, TRectype& confronto)
 | 
						|
{
 | 
						|
   bool found = FALSE;
 | 
						|
 | 
						|
   for (int i=1; !found && i<=doc.rows(); i++)
 | 
						|
      if (!processed[i] && !doc.row(i).get("CODART").empty())
 | 
						|
         found = (doc.row(i) == confronto);
 | 
						|
   prox = i-1;
 | 
						|
   return found;
 | 
						|
}
 | 
						|
 | 
						|
int ve6200 (int argc, char **argv)
 | 
						|
{
 | 
						|
  TBatch_crea_doc a;
 | 
						|
  a.run (argc, argv, "Fatturazione");
 | 
						|
  return TRUE;
 | 
						|
}
 |