1996-03-20 16:15:18 +00:00
// 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
// <20> stata derivata la classe TSheet, perch<63> in alcuni documenti (es. Ordini)
// l'utente (tramite Ve6 -3, applicazione derivata dalla presente)
// pu<70> specificare di evadere una sola parte della quantit<69> di merci indicate
// nella riga, cos<6F> <20> stato necessario chiedere all'utente la quantit<69> da evadere
// e riportarla nell'ultima colonna dello sheet: prima non era possibile, in quanto
// tale quantit<69> 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<69> da evadere <20> 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<EFBFBD> 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<69> totale della merce della riga
// controlla che qta_evasa + qta_da_evadere < qta_totale
if ( qtaev > qtatot ) error_box ( " Qt<EFBFBD> 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<70> documenti sorgente in un solo doc. destinazione quando possibile
// Raggruppa articoli : quando possibile raggruppa pi<70> righe dello stesso articolo,
// accumulandone le quantit<69>
// 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<63> 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<67> 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 <20> != 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 <EFBFBD> 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 <20> 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<70> 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 <20> 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<63> 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 <20> 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 <20> abilitata la gestione
// se agente <20> 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 <20> 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 <20> 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 <20> vuoto, lo aggiunge al filtro gi<67> 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<69> 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 <20> un array di flag che indica se il documento relativo a ciascun flag
// sia da processare (FALSE) o da ignorare/gi<67> 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<63> vi <20> 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 <20> 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<70> 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 <20> 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 <20> 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<67> : 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 <20> 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 <20> 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<69> @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<67>
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<63> r <20> 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 ;
}