08991b9696
git-svn-id: svn://10.65.10.50/trunk@2994 c028cbd2-c16b-5b4b-a496-9718f37d4682
1052 lines
43 KiB
C++
Executable File
1052 lines
43 KiB
C++
Executable File
// ve6200.cpp: modulo per la generazione dei documenti in modo BATCH.
|
|
|
|
#include <checks.h>
|
|
#include <config.h>
|
|
#include <mask.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
#include <relation.h>
|
|
#include <tabutil.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::get_row(long first, TToken_string& l)
|
|
{
|
|
*cursor() = (TRecnotype)first;
|
|
|
|
const int last = fields_array().last();
|
|
for (int i = 0; i <= last; i++)
|
|
{
|
|
const TRecfield* rf = (TRecfield*)fields_array().objptr(i);
|
|
const char* s = rf ? (const char*)*rf : "";
|
|
l.add(s);
|
|
}
|
|
|
|
// 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);
|
|
const real qtadaevadere = qta - qtaevasa;
|
|
l.add(qtadaevadere.string(11,3), TOKEN_QTA_DA_EVADERE);
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
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
|
|
_datadoc = _msk->get(F_DATA_ELAB); // Data documenti finali
|
|
_anno = _datadoc.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))
|
|
{
|
|
const real qta = pilota.get_real("QTA") + doc.row(prox).get_real("QTA");
|
|
pilota.put("QTA", 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;
|
|
}
|