campo-sirio/ca/ca3700.cpp
luca 8ac4f47092 Patch level :4.0 494
Files correlati     :ca3.exe
Ricompilazione Demo : [ ]
Commento            :stampa rendiconto: nel caso una riga appartenga ad una fattura derivante da un ordine multiriga, la stampa della riga analitica corrispondente alla riga fattura deve mostrare la riga ordine originaria corrispondente per commessa e fase, non tutte le righe ordine. Adolfo!


git-svn-id: svn://10.65.10.50/trunk@14344 c028cbd2-c16b-5b4b-a496-9718f37d4682
2006-09-25 09:47:50 +00:00

1337 lines
43 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <execp.h>
#include <progind.h>
#include <reprint.h>
#include <doc.h>
#include <rdoc.h>
#include "../cg/cg2103.h"
#include "../cg/cglib01.h"
#include "../ve/velib04.h"
#include "panapdc.h"
#include "pconana.h"
#include "movana.h"
#include "rmovana.h"
#include "ca3.h"
#include "ca3700.h"
#include "calib01.h"
#include "calib02.h"
////////////////////////////////////////////////////////
// MASCHERA
////////////////////////////////////////////////////////
class TPrint_rendiconto_ca_mask : public TAnal_report_mask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
const TString& get_report_class() const;
bool test_compatible_report();
public:
TPrint_rendiconto_ca_mask();
virtual ~TPrint_rendiconto_ca_mask() {}
};
const TString& TPrint_rendiconto_ca_mask::get_report_class() const
{
TString& classe = get_tmp_string();
classe = "ca3700a";
return classe;
}
bool TPrint_rendiconto_ca_mask::test_compatible_report()
{
const TString& cls = get_report_class();
const TString& name = get(F_REPORT);
bool ok = name.not_empty();
if (ok)
{
TReport rep;
ok = rep.load(name);
if (ok)
{
const TString& classe = rep.get_class();
ok = classe == cls;
}
}
if (!ok)
{
set(F_REPORT, cls);
TFilename path = cls;
path.ext("rep");
ok = path.custom_path();
}
return ok;
}
bool TPrint_rendiconto_ca_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_RIGHE:
if (e == fe_init) //azzera le righe dello sheet con le commesse ad inizio programma
{ //esplicita e bizzarra richiesta del CRPA
TSheet_field& s = (TSheet_field&)o;
s.destroy();
s.force_update();
}
break;
case F_DATAINI:
case F_DATAFIN:
if (e == fe_close)
{
const int anno = get_int(F_ANNO);
if (anno > 0) //se viene selezionato un esercizio..
{
TEsercizi_contabili esc; //..le date devono essere incluse nell'esercizio selezionato!
const TDate data = o.get();
if (!data.empty() && esc.date2esc(data) != anno)
return error_box(TR("La data deve appartenere all'anno selezionato"));
}
/* else //se l'esercizio <20> vuoto le date diventano obbligatorie!!
{
if (o.empty())
return error_box(TR("La data <20> obbligatoria in quanto manca l'esercizio"));
}*/
}
break;
case F_REPORT:
if (e == fe_button)
{
const TString8 lib = get_report_class();
TFilename path = o.get();
if (select_custom_file(path, "rep", lib))
{
path = path.name();
path.ext("");
o.set(path);
}
} else
if (e == fe_close)
{
if (!test_compatible_report())
return error_box(TR("Impossibile trovare un report compatibile"));
}
break;
case F_PRE1:
case F_PRE2:
case F_PRE3:
if ((e == fe_init || e == fe_modify) && o.active())
{
const int k = o.dlg()-F_PRE1;
set(F_PAN1_INI + k, o.get(), 0x2);
disable(F_PAN1_INI + k);
disable(F_PANDES1_INI + k);
set(F_PAN1_FIN + k, o.get(), 0x2);
disable(F_PAN1_FIN + k);
disable(F_PANDES1_FIN + k);
}
break;
default:
break;
}
return TAnal_report_mask::on_field_event(o, e, jolly);
}
TPrint_rendiconto_ca_mask::TPrint_rendiconto_ca_mask()
:TAnal_report_mask("ca3700")
{
TConfig& cfg = ca_config();
const bool use_pdcc = cfg.get_bool("UsePdcc");
const TMultilevel_code_info& pconana_info = ca_multilevel_code_info(LF_PCONANA);
const int pconana_levels = pconana_info.levels();
int prefix = cfg.get_int("PdcPrefix");
if (prefix >= pconana_levels)
prefix = pconana_levels-1;
//setta nel campo F_PIANO il tipo di piano dei conti usato in base alla configurazione..
//..e disabilita il campo (non si puo' cambiare la configurazione in una stampa!!)
disable(F_PIANO);
set(F_PIANO, use_pdcc ? "C" : "A");
// Controllo se voglio (e posso) usare il conto analitico come prefisso di quello contabile
if (use_pdcc && prefix > 0)
{
const TMultilevel_code_info& info = ca_multilevel_code_info(LF_PCONANA);
const int levels = info.levels();
if (levels >= 2 && prefix < levels && esistono_riclassificazioni())
{
enable(F_PIANO);
ca_create_fields(*this, 1, LF_PCONANA, 2, 4, F_PRE1, F_PREDES1, 0x0, PCONANA_CODCONTO);
// Nascondi i campi che non fanno parte del prefisso
for (int i = 0; i < levels; i++)
{
if (i < prefix)
{
field(F_PRE1 + i).check_type(CHECK_REQUIRED);
field(F_PRE1 + i).set_group(6);
field(F_PREDES1 + i).set_group(6);
}
else
{
field(F_PRE1 + i).hide();
field(F_PREDES1 + i).hide();
}
}
}
}
for (int g = 5; g <= 6; g++)
{
const int logicnum = g == 5 ? LF_PCON : LF_PCONANA;
const short da_dlg = g == 5 ? F_PDC1_INI : F_PAN1_INI;
const short da_des = g == 5 ? F_PDCDES1_INI : F_PANDES1_INI;
const short a_dlg = g == 5 ? F_PDC1_FIN : F_PAN1_FIN;
const short a_des = g == 5 ? F_PDCDES1_FIN : F_PANDES1_FIN;
const int nfields = ca_create_fields(*this, 1, logicnum, 2, 10, da_dlg, da_des, 0x0, PCONANA_CODCONTO);
ca_create_fields(*this, 1, logicnum, 2, 16, a_dlg, a_des, 0x0, PCONANA_CODCONTO);
for (int i = 0; i < nfields; i++)
{
TMask_field& daconto = field(da_dlg + i);
daconto.set_group(1);
daconto.set_group(4);
daconto.set_group(g);
daconto.check_type(CHECK_SEARCH);
field(da_des+i).set_group(4);
field(da_des+i).set_group(g);
TMask_field& aconto = field(a_dlg + i);
aconto.set_group(2);
aconto.set_group(4);
aconto.set_group(g);
aconto.check_type(CHECK_SEARCH);
field(a_des+i).set_group(4);
field(a_des+i).set_group(g);
}
}
// creazione dei campi della pagina della maschera con lo sheet di cdc/cms/fasi
create_sheet(F_RIGHE);
// setta gli handlers a tutti i campi generati della maschera;senza questa chiamata la on_field_event
// non puo' funzionare sui campi generati!!!
set_handlers();
}
///////////////////////////////////////////////////////////////
// RECORDSET
///////////////////////////////////////////////////////////////
#define IMPEGNATO 1
#define MATURATO 2
#define FATTURATO 4
class TPrint_rendiconto_ca_recordset : public TISAM_recordset
{
TExternisamfile* _tmp;
bool _riclassificato;
TString _prefix;
protected:
int _anno;
TString4 _piano;
TDate _dadata, _adata;
long _danumreg, _anumreg;
TString _daconto, _aconto, _codcosto, _codcms, _codfas;
protected: //da libreria
virtual const TVariant& get(const char* column_name) const;
protected:
static bool mov_filter(const TRelation* rel);
bool valid_record(const TRelation& rel) const;
virtual void set_custom_filter(TCursor& cur) const;
void crea_righe_da_rmovana();
void crea_righe_da_rdoc(const TPrint_rendiconto_ca_mask& msk);
void crea_trr(const TFilename& trr) const;
void scrive_riga(const TRectype& rmovana, const TRectype& movana, const TDocumento* doc);
void scrive_riga_speciale(const TDocumento* doc, const TString_array& special_docs);
TString riclassifica(const int gruppo, const int conto, const long sottoconto, TRectype& tmpcurr);
real get_budget(const TString& conto, char tipo) const;
public:
virtual void set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row);
TPrint_rendiconto_ca_recordset(const TString& sql) : TISAM_recordset(sql), _riclassificato(false) { _tmp = NULL;}
~TPrint_rendiconto_ca_recordset();
};
static TPrint_rendiconto_ca_recordset* myself = NULL;
TPrint_rendiconto_ca_recordset::~TPrint_rendiconto_ca_recordset()
{ }
void TPrint_rendiconto_ca_recordset::set_custom_filter(TCursor& cur) const
{
relation()->replace(_tmp); //sostituisce il vero file rmovana con quello temporaneo
//filtro sul file esterno (_tmp, cio<69> 1000) sui conti selezionati sulla maschera
TRectype darec(cur.curr()), arec(cur.curr()); //curr perch<63> <20> il file externisamfile
darec.zero();
arec.zero();
if (_daconto.not_empty())
darec.put("CONTO", _daconto);
if (_aconto.not_empty())
arec.put("CONTO", _aconto);
//filtro sulla data(non avendo anche codnum non ho la chiave completa per mettere la data nella setregion)
TString filtro;
if (_dadata.ok())
filtro << "(ANSI(DATA)>=" << _dadata << ")";
if (_adata.ok())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(ANSI(DATA)<=" << _adata << ")";
}
cur.setregion(darec, arec);
cur.setfilter(filtro);
myself = (TPrint_rendiconto_ca_recordset*)this;
}
//sconvolgente metodo per la normalizzazione dei conti
real TPrint_rendiconto_ca_recordset::get_budget(const TString& conto, char tipo) const
{
//data del cazzo che per<65> serve per costruire il conto analitico
const TDate null_date;
//ecco il conto analitico...
TAnal_bill zio(conto, _codcosto, _codcms, _codfas);
//..adesso si necessita del saldo del conto analitico appena creato..
word tipo_movimento = 0;
switch (tipo)
{
case 'P': tipo_movimento |= _saldanal_preventivo; break;
case 'V': tipo_movimento |= _saldanal_variazione; break;
default: tipo_movimento |= _saldanal_consuntivo; break;
}
if (_riclassificato)
tipo_movimento |= _saldanal_riclassify;
//..ecco quindi il saldo..
const TSaldanal& saldo = ca_saldo(zio, null_date, null_date, tipo_movimento);
//..che deve essere normalizzato in base alla sua sezione ed all'indicatore di bilancio del conto
TImporto imp = saldo._fin;
switch (zio.indicatore_bilancio())
{
case 1:
case 3:
imp.normalize('D');
break;
case 2:
case 4:
imp.normalize('A');
break;
default:
break;
}
return imp.valore();
}
const TVariant& TPrint_rendiconto_ca_recordset::get(const char* column_name) const
{
if (*column_name == '#')
{
if (strcmp(column_name, "#COSTO") == 0)
{
TVariant& var = get_tmp_var();
var = _codcosto;
return var;
}
if (strcmp(column_name, "#COMMESSA") == 0)
{
TVariant& var = get_tmp_var();
var = _codcms;
return var;
}
if (strcmp(column_name, "#FASE") == 0)
{
TVariant& var = get_tmp_var();
var = _codfas;
return var;
}
if (strcmp(column_name, "#PIANO") == 0)
{
TVariant& var = get_tmp_var();
if (_piano == "A")
var = "Analitico";
else
var = "Contabile";
return var;
}
if (strcmp(column_name, "#DACONTO") == 0)
{
TVariant& var = get_tmp_var();
var = _daconto;
return var;
}
if (strcmp(column_name, "#ACONTO") == 0)
{
TVariant& var = get_tmp_var();
var = _aconto;
return var;
}
//cerca l'indicatore di bilancio del conto;utilizzato per stabilire il campo ove sommare..
//..i budget nella coda report
if (strcmp(column_name, "#INDBIL") == 0)
{
const TString& conto = TISAM_recordset::get("CONTO").as_string();
TAnal_bill zio(conto);
return get_tmp_var() = (long)zio.indicatore_bilancio();
}
//calcola il valore e la sezione del campo budget di un conto basandosi sull'indicatore di..
//..bilancio ed il saldo del conto (movimenti analitici di tipo preventivo)
if (strcmp(column_name, "#PREVENTIVO") == 0)
{
//stessa cosa del precedente ma per movimenti di tipo variazione preventivo
const TString& conto = TISAM_recordset::get("CONTO").as_string();
return get_tmp_var() = get_budget(conto, 'P');
}
if (strcmp(column_name, "#VARIAZIONE") == 0)
{
//prende il conto
const TString& conto = TISAM_recordset::get("CONTO").as_string();
return get_tmp_var() = get_budget(conto, 'V');
}
}
return TISAM_recordset::get(column_name);
}
TString TPrint_rendiconto_ca_recordset::riclassifica(const int gruppo, const int conto,
const long sottoconto, TRectype& tmpcurr)
{
TString conto_riclassificato;
//relazione e cursore su panapdc alla ricerca del conto riclassificato corrispondente
//alla triade gr/co/sottoc di rmovana
TRelation rel_panapdc(LF_PANAPDC);
//servono solamente i record con il gruppo = al gruppo di rmovana
TRectype da_panapdc(LF_PANAPDC);
da_panapdc.put(PANAPDC_GRUPPO, gruppo);
TString filtro;
if (_prefix.not_empty())
filtro << "(CODCONTO[1," << _prefix.len() << "]=='" << _prefix << "')";
TCursor cur_panapdc(&rel_panapdc, filtro, 2, &da_panapdc, &da_panapdc);
const long panapdc_items = cur_panapdc.items();
cur_panapdc.freeze();
if (panapdc_items > 0) //se non ci sono record con il gruppo=rmovana.gruppo ed il prefisso voluto->salta l'rmovana
{
TRectype& rec_panapdc = cur_panapdc.curr();
for (cur_panapdc = 0; cur_panapdc.pos() < panapdc_items; ++cur_panapdc)
{
int current_conto = rec_panapdc.get_int(PANAPDC_CONTO);
long current_sottoconto = rec_panapdc.get_long(PANAPDC_SOTTOCONTO);
if (current_conto == 0 && current_sottoconto == 0)
{
conto_riclassificato = rec_panapdc.get(PANAPDC_CODCONTO);
tmpcurr.put("CONTO", conto_riclassificato);
break; //esce dal casino e passa ai campi successivi
}
else if (conto == current_conto && current_sottoconto == 0)
{
conto_riclassificato = rec_panapdc.get(PANAPDC_CODCONTO);
tmpcurr.put("CONTO", conto_riclassificato);
break; //esce dal casino e passa ai campi successivi
}
else if (conto == current_conto && sottoconto == current_sottoconto)
{
conto_riclassificato = rec_panapdc.get(PANAPDC_CODCONTO);
tmpcurr.put("CONTO", conto_riclassificato);
break; //esce dal casino e passa ai campi successivi
}
} //for sugli elementi del cursore
} //if panapdc_items > 0
//ATTENZIONE! Se era stata operata una selezione sui conti riclassificati nella maschera
//ed il conto riclassificato attuale non ricade nell'intervallo selezionato il programma
//non deve aggiungere il record al file!!Quindi ritorna una stringa vuota che sara' il segnale..
//..per interrompere l'analisi del record corrente
if ((_daconto.not_empty() && conto_riclassificato < _daconto) ||
(_aconto.not_empty() && conto_riclassificato.compare(_aconto, _aconto.len()) > 0))
return EMPTY_STRING;
return conto_riclassificato;
}
//compila i campi del file temporaneo che sara' poi stampato
void TPrint_rendiconto_ca_recordset::scrive_riga(const TRectype& rmovana, const TRectype& movana, const TDocumento* doc)
{
TRectype& tmpcurr = _tmp->curr();
tmpcurr.zero();
TString8 codnum_desc; //codnum da usare sia per compilare il campo "CODNUM"
codnum_desc.cut(0);
// il conto puo' essere analitico o contabile...
//se <20> compilato l'archivio di collegamento PANAPDC
//si deve usare come conto il campo codconto del panapdc!!!...
if (_riclassificato)
{
//prende il gr/co/so dalla riga rmovana in esame
const int gruppo = atoi(rmovana.get(RMOVANA_CODCONTO).left(3));
const int conto = atoi(rmovana.get(RMOVANA_CODCONTO).mid(3,3));
const long sottoconto = atol(rmovana.get(RMOVANA_CODCONTO).mid(6,6));
//stringa che conterr<72> il conto riclassificato (se sara' trovato)
TString conto_riclassificato = riclassifica(gruppo, conto, sottoconto, tmpcurr);
//se il conto viene ritornato vuoto significa che non ricade nell'intervallo dei conti..
//..riclassificati selezionato dall'utente
if (conto_riclassificato == EMPTY_STRING)
return;
} //if(_riclassificato)
else //...senn<6E> si usa il normale piano dei conti analitico (cio<69> tutti tranne che il CRPA)
tmpcurr.put("CONTO", rmovana.get(RMOVANA_CODCONTO)); //conto
//in ogni caso riempio il campo conto_cg
tmpcurr.put("CONTOCG", rmovana.get(RMOVANA_CODCONTO)); //conto_cg
//tipo movimento CONSUNTIVO (o TEMPORANEO)
const char tipomov = movana.get_char(MOVANA_TIPOMOV);
if (tipomov <= ' ' || tipomov == 'T')
{
//serve un documento da cui ricavare i parametri di stampa
TDocumento* newdoc = (TDocumento*)doc;
bool should_delete = false;
if (newdoc == NULL && movana.get(MOVANA_DNDOC).not_empty())
{
const TString4 dacodnum = movana.get(MOVANA_DCODNUM);
newdoc = new TDocumento('D', movana.get_int(MOVANA_DANNO), dacodnum, movana.get_long(MOVANA_DNDOC));
should_delete = true; //settato true per cancellare il doc al termine del metodo(senn<6E> addio memoria!)
}
const bool dadoc = newdoc != NULL;
//i movimenti possono essere normali o generati da documento...
if (dadoc) //movimento generato da documento
{
codnum_desc = movana.get(MOVANA_DCODNUM); //serve anche in fondo al metodo
tmpcurr.put("CODNUM", codnum_desc); //codnum del documento che origina il movana
tmpcurr.put("ANNO", movana.get(MOVANA_DANNO)); //anno del doc di origine
tmpcurr.put("NUMRD", movana.get(MOVANA_DNDOC)); //numero del doc che origina movana
tmpcurr.put("DATA", newdoc->get(DOC_DATADOC)); //data del documento che genera movana..
} //..non esiste il campo in movana
else //movimento normale (senza documento)
{
tmpcurr.put("CODNUM", movana.get(MOVANA_CODCAUS)); //mette la causale del movimento
tmpcurr.put("ANNO", movana.get(MOVANA_ANNOES)); //anno del movimento
tmpcurr.put("NUMRD", movana.get(MOVANA_NUMREGCG)); //numregcg del movana
tmpcurr.put("DATA", movana.get(MOVANA_DATACOMP)); //data del movana
}
//ricerca del mitico documento padre della riga documento attuale!
int selettore = 0;
if (newdoc != NULL)
{
tmpcurr.put("NUMDOCRIF", newdoc->get(DOC_NUMDOCRIF)); //docrif del documento originante il movana
tmpcurr.put("DATADOCRIF", newdoc->get(DOC_DATADOCRIF)); //datadocrif del documento originante il movana
//procedura per ottenere i campi del documento
//deve tener conto del vero tipo del documento,nel caso sia classificato come _altro;in questo
//..caso si deve accorgere se e' in realta' una bolla o una fattura (utilizza la tipo_riclassificato())
const int tipo_documento = newdoc->tipo_riclassificato();
int tipo_babbo = TTipo_documento::_altro;
TToken_string riferimento(20, '\n'); //tokenstring su cui scrivere gli estremi dei docs padri (se li trova!)
TString80 rif; //stringa di lavoro su cui viene scritto un doc originale
const int rows = newdoc->physical_rows(); //righe del doc attuale
for (int i = 1; i <= rows; i++) //scandisce tutte le righe del doc..
{
const TRiga_documento& riga = (*newdoc)[i];
//commessa e fase della riga documento
const TString& codcms_rigadoc = riga.codice_commessa();
const TString& codfase_rigadoc = riga.fase_commessa();
//per evitare di scrivere per ogni riga documento tutte le righe del doc babbo (in pratica..
//..per evitare di avere n righe ordine ogni riga fattura) confronta commessa e fase..
//..della riga movimento analitico con quelli la riga movimento e procede solo nel..
//..caso coincidano (richiesta Adolfica!)
const TString codcms_rmovana = rmovana.get(RMOVANA_CODCMS);
const TString codfase_rmovana = rmovana.get(RMOVANA_CODFASE);
if (codcms_rigadoc == codcms_rmovana && codfase_rigadoc == codfase_rmovana)
{
const TRectype* babbo = riga.find_original_rdoc(); //cerca il doc padre della riga doc attuale
if (babbo != NULL) //se trova il doc padre..
{
const TString4 babbo_codnum = babbo->get(RDOC_CODNUM);
const int anno = babbo->get_int(RDOC_ANNO);
const long ndoc = babbo->get_long(RDOC_NDOC);
rif.cut(0) << babbo_codnum << '-' << anno << '-' << ndoc;
if (riferimento.get_pos(rif) < 0) //il doc originale va aggiunto solo se non esiste gia'!
{
riferimento.add(rif);
TDocumento doc_babbo('D', anno, babbo_codnum, ndoc); //crea una copia del doc padre per prendere..
tipo_babbo = doc_babbo.tipo_riclassificato(); //..il tipo documento..
}
} //if (babbo != NULL)..
}
} //for (int i..
tmpcurr.put("DOCORIG", riferimento); //documento di riferimento (mitologico documento originale)
/*[Tipo documento] //schema divino per destinare gli importi nei campi corretti
O=I**
B=IM*
BO=*M*
FB=**F
FO=*MF
F=IMF*/
switch (tipo_documento)
{
case TTipo_documento::_bolla: //bolla B -> IM a meno che non sia bolla da ordine BO -> M
selettore = MATURATO;
if (tipo_babbo != TTipo_documento::_ordine)
selettore |= IMPEGNATO;
break;
case TTipo_documento::_fattura:
selettore = FATTURATO; //fattura da bolla FB -> F
if (tipo_babbo == TTipo_documento::_ordine) //fattura da ordine FO -> MF
{
selettore |= MATURATO;
} else
if (tipo_babbo == TTipo_documento::_altro) //fattura senza padri F -> IMF
selettore |= (IMPEGNATO | MATURATO);
break;
case TTipo_documento::_ordine:
selettore = IMPEGNATO;
break;
case TTipo_documento::_altro:
CHECK(false, "Ma dove cavolo stai passando Willis?");
break;
default:
break;
}
} //if(newdoc != NULL)
else //movimenti puri di analitica (no documento di origine!)
{
selettore = FATTURATO;
selettore |= MATURATO;
selettore |= IMPEGNATO;
} //if(newdoc != NULL)
//riempie i record del file temporaneo nel caso di rmovana con documento di origine
const char sezione = rmovana.get_char(RMOVANA_SEZIONE);
TImporto imp(sezione, rmovana.get_real(RMOVANA_IMPORTO));
const int anno_caus = movana.get_date(MOVANA_DATAREG).year();
TCausale caus(movana.get(MOVANA_CODCAUS), anno_caus);
TipoIVA tipoiva = caus.iva();
char sezione_normale;
if (tipoiva == iva_vendite)
sezione_normale = 'A';
else
if (tipoiva == iva_acquisti)
sezione_normale = 'D';
else
{
if (caus.sezione_clifo() == 'D')
sezione_normale = 'A';
else
sezione_normale = 'D';
}
imp.normalize(sezione_normale);
//riempie i record del file temporaneo nel caso di rmovana con documento di origine
if (selettore & FATTURATO)
tmpcurr.put("FATTURATO", imp.valore());
if (selettore & MATURATO)
tmpcurr.put("MATURATO", imp.valore());
if (selettore & IMPEGNATO)
tmpcurr.put("IMPEGNATO", imp.valore());
//campi comuni a rmovana e rdoc senza particolari operazioni
TString descr = movana.get(MOVANA_DESCR);
int pos = descr.find('$'); //solo per il CRPA!
if (pos > 0)
{
descr.ltrim(pos+1);
descr.trim();
}
tmpcurr.put("NUMREG", rmovana.get(RMOVANA_NUMREG));
tmpcurr.put("NUMREGCG", movana.get(MOVANA_NUMREGCG)); //numero di registrazione contabile
tmpcurr.put("DESC", descr); //descrizione movana
tmpcurr.put("NRIGA", rmovana.get(RMOVANA_NUMRIG)); //numero riga
tmpcurr.put("DESCRIGA", rmovana.get(RMOVANA_DESCR)); //descrizione rmovana
if (should_delete)
delete newdoc;
} //if (tipomov == ..)
else
{
tmpcurr.put("HIDDEN", "X");
}
_tmp->write();
}
//compila i campi del file temporaneo che sara' poi stampato per i documenti speciali..
//..quali le fatture da emettere e ricevere, la cui lista e' nel ca_config
void TPrint_rendiconto_ca_recordset::scrive_riga_speciale(const TDocumento* doc, const TString_array& special_docs)
{
const int rows = doc->physical_rows();
for (int i = 1; i <= rows; i++)
{
const TRiga_documento& rigadoc = (*doc)[i];
if (special_docs.find(rigadoc.get(RDOC_DACODNUM)) > 0)
{
TRectype& tmpcurr = _tmp->curr();
tmpcurr.zero();
TString8 codnum_desc;
codnum_desc.cut(0);
//prende il tipocf che gli serve un po' ovunque in seguito..
const char tipocf = doc->get_char(DOC_TIPOCF);
//se usa il piano dei conti contabile -> _piano = C..
if (_piano == "C")
{
//trova il conto senza movana e rmovana!!!
TContabilizzazione_analitica contab;
TBill conto;
if (contab.search_costo_ricavo(rigadoc, conto))
{
const int gr = conto.gruppo();
const int co = conto.conto();
const long so = conto.sottoconto();
if (_riclassificato)
{
//stringa che conterr<72> il conto riclassificato (se sara' trovato)
TString conto_riclassificato = riclassifica(gr, co, so, tmpcurr);
if (conto_riclassificato == EMPTY_STRING)
return;
} //if(_riclassificato)
else //...senn<6E> si usa il conto
tmpcurr.put("CONTO", conto.string(0x8));
}
}
else //se ivece usa il piano dei conti analitico -> _piano = A...
{
TString80 conto_anal;
if (rigadoc.is_articolo())
{
const TRectype& anamag = cache().get(LF_ANAMAG, rigadoc.get(RDOC_CODARTMAG));
conto_anal = anamag.get(tipocf == 'F' ? ANAMAG_CONTOINDA : ANAMAG_CONTOINDV);
}
else
{
if (rigadoc.is_spese() || rigadoc.is_prestazione() ||
rigadoc.is_risorsa() || rigadoc.is_attrezzatura())
{
const char tipo = rigadoc.tipo().tipo();
const TSpesa_prest spp(rigadoc.get(RDOC_CODART), tipo);
conto_anal = tipocf == 'F' ? spp.conto_analitico_acquisti() : spp.conto_analitico_vendite();
}
}
tmpcurr.put("CONTO", conto_anal);
}
//comincia a riempire i record
//prima i campi che prende direttamente dal doc speciale
tmpcurr.put("CODNUM", doc->get(DOC_CODNUM));
tmpcurr.put("ANNO", doc->get(DOC_ANNO));
tmpcurr.put("NUMRD", doc->get(DOC_NDOC));
tmpcurr.put("DATA", doc->get(DOC_DATADOC));
tmpcurr.put("NUMDOCRIF", doc->get(DOC_NUMDOCRIF)); //docrif del documento
tmpcurr.put("DATADOCRIF", doc->get(DOC_DATADOCRIF)); //datadocrif del documento
tmpcurr.put("NUMREG", doc->get(DOC_NUMREGCA));
tmpcurr.put("NUMREGCG", doc->get(DOC_NUMREG)); //numero di registrazione contabile
tmpcurr.put("NRIGA", rigadoc.get(RDOC_NRIGA)); //numero riga
//procedura per ottenere i campi del documento origine di quello in esame
const int tipo_documento = doc->tipo_riclassificato();
int tipo_babbo = TTipo_documento::_altro;
TToken_string riferimento(20, '\n'); //tokenstring su cui scrivere gli estremi dei docs padri (se li trova!)
TString80 rif; //stringa di lavoro su cui viene scritto un doc originale
const int rows = doc->physical_rows(); //righe del doc attuale
const TRectype* babbo = rigadoc.find_original_rdoc(); //cerca il doc padre della riga doc attuale
if (babbo != NULL) //se trova il doc padre..
{
const TString4 babbo_codnum = babbo->get(RDOC_CODNUM);
const int anno = babbo->get_int(RDOC_ANNO);
const long ndoc = babbo->get_long(RDOC_NDOC);
rif.cut(0) << babbo_codnum << '-' << anno << '-' << ndoc;
tmpcurr.put("DOCORIG", rif); //documento di riferimento (mitologico documento originale)
} //if (babbo != NULL)..
const real importo = rigadoc.imponibile();
const TTipo_documento& tipodoc = doc->tipo();
const TString& codcaus = tipodoc.causale();
if (codcaus.full())
{
TImporto imp(tipocf == 'F' ? 'D' : 'A', importo);
const int anno_caus = doc->get_int(DOC_ANNO);
TCausale caus(codcaus, anno_caus);
TipoIVA tipoiva = caus.iva();
char sezione_normale;
if (tipoiva == iva_vendite)
sezione_normale = 'A';
else
{
if (tipoiva == iva_acquisti)
sezione_normale = 'D';
else
{
if (caus.sezione_clifo() == 'D')
sezione_normale = 'A';
else
sezione_normale = 'D';
}
}
imp.normalize(sezione_normale);
//i documenti speciali vanno SOLO in FATTURATO
tmpcurr.put("FATTURATO", imp.valore());
}
else
{
//i documenti speciali vanno SOLO in FATTURATO
tmpcurr.put("FATTURATO", importo);
}
_tmp->write();
} //if(special_docs...
} // for (inti=1;i<=rows...
}
//scanning delle righe dei movimenti di analitica
void TPrint_rendiconto_ca_recordset::crea_righe_da_rmovana()
{
TRelation rel_rmovana(LF_RMOVANA);
rel_rmovana.add(LF_MOVANA, "NUMREG==NUMREG"); //aggiunge le testate x avere tipi mov e descr
//..crea un cursore su rmovana per vedere se i conti selezionati hanno veri movimenti che soddisfano
//i parametri del filtro sulla maschera. ACHTUNG! Questo filtro ha senso solo se non esiste la
//riclassificazione!!!
TRectype da_rmovana(LF_RMOVANA);
TRectype a_rmovana(LF_RMOVANA);
if (!_riclassificato)
{
da_rmovana.put(RMOVANA_CODCONTO, _daconto);
a_rmovana.put(RMOVANA_CODCONTO, _aconto);
}
TString filtro;
if (_dadata.ok())
filtro << "(ANSI(DATACOMP)>=" << _dadata.date2ansi() << ")";
if (_adata.ok())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(ANSI(DATACOMP)<=" << _adata.date2ansi() << ")";
}
if (_codcosto.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(" << RMOVANA_CODCCOSTO << "?=\"" << _codcosto << "*\")";
}
if (_codcms.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(" << RMOVANA_CODCMS << "?=\"" << _codcms << "*\")";
}
if (_codfas.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(" << RMOVANA_CODFASE << "?=\"" << _codfas << "*\")";
}
TCursor cur_rmovana(&rel_rmovana, filtro, 2, &da_rmovana, &a_rmovana);
const TRecnotype rmovana_items = cur_rmovana.items();
//scorre le righe movimenti di analitica che soddisfano il filtro
//il join a movana serve nel caso necessitino dati di testata per la riga in questione
if (rmovana_items > 0)
{
cur_rmovana.freeze();
const TRectype& rmovana = cur_rmovana.curr();
const TRectype& movana = rel_rmovana.curr(LF_MOVANA);
TProgind pi(rmovana_items, "Scansione righe movimenti...", true, true);
for (cur_rmovana = 0; cur_rmovana.pos() < rmovana_items; ++cur_rmovana)
{
pi.addstatus(1);
if (pi.iscancelled())
break;
scrive_riga(rmovana, movana, NULL);
}
}
}
//scanning delle righe dei documenti
void TPrint_rendiconto_ca_recordset::crea_righe_da_rdoc(const TPrint_rendiconto_ca_mask& msk)
{
TRelation rel_rdoc(LF_RIGHEDOC);
rel_rdoc.add(LF_DOC, "CODNUM==CODNUM|ANNO==ANNO|PROVV==PROVV|NDOC==NDOC"); //aggiunge le testate
TRectype dardoc(LF_RIGHEDOC);
TRectype ardoc(LF_RIGHEDOC);
TString filtro_date;
dardoc.put(RDOC_PROVV, 'D');
ardoc.put(RDOC_PROVV, 'D');
//se siamo fortunati l'anno si pu<70> trovare cos<6F>..
int anno = msk.get_int(F_ANNO);
if (anno > 0)
{
dardoc.put(RDOC_ANNO, anno);
ardoc.put(RDOC_ANNO, anno);
}
else
{
dardoc.put(RDOC_ANNO, _dadata.year());
ardoc.put(RDOC_ANNO, _adata.year());
if (_dadata.year() == _adata.year())
anno = _dadata.year();
}
if (_dadata.ok())
filtro_date << "(ANSI(33->DATADOC)>=" << _dadata.date2ansi() << ")";
if (_adata.ok())
{
if (filtro_date.not_empty())
filtro_date << "&&";
filtro_date << "(ANSI(33->DATADOC)<=" << _adata.date2ansi() << ")";
}
TContabilizzazione_analitica cont_anal; //oggetto necessario per contabilizzare il documento in osservazione
//inizialmente il filtro di scansione delle righedoc coincide con quello sulle date
TString filtro = filtro_date;
//Controlla sul file di configurazione di CA (ditta.ini,[ca]) se esistono numerazioni relative
//..alle fatture da ricevere che devono essere trattate in modo particolare
TConfig& config = ca_config();
//TString_array contenente le numerazioni delle fatture da ricevere
TString_array num_fdr;
for (int j = 0;;j++)
{
TString codfdr(config.get("NF", NULL, j)); //scansione delle righe NF(i)=.. sul paragrafo di configurazione CA
if (codfdr.blank())
break;
num_fdr.add(codfdr);
}
//Filtro sulle righe documento (e testate collegate)
//Controlla sul file di configurazione di CA (ditta.ini,[ca]) se esistono numerazioni da escludere..
//..e se, per alcune numerazioni, deve tener conto dello stato del documento
bool update = false;
for (int i = 0;;i++) //scansione delle righe ND(i)=.. sul paragrafo di configurazione CA
{
TToken_string num_doc(config.get("ND", NULL, i));
const TString4 codnum = num_doc.get(0);
if (codnum.blank())
break;
const bool exclude = num_doc.get_char(1) == 'X';
if (filtro.not_empty())
filtro << "&&";
if (exclude) //numerazioni da escludere
{
filtro << "(CODNUM!=\"" << codnum << "\")";
}
else //numerazioni per le quali tener conto dello stato
{
filtro << "((CODNUM!=\"" << codnum << "\")";
filtro << "||((" << LF_DOC << "->STATO>=\"" << num_doc.get(2) << "\")";
filtro << "&&(" << LF_DOC << "->STATO<=\"" << num_doc.get(3) << "\")))";
update = true;
}
}
//poi deve aggiungere il filtro per cdc/cms/fas
if (_codcosto.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(" << RDOC_CODCOSTO << "==\"" << _codcosto << "\")";
}
if (_codcms.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(" << RDOC_CODCMS << "==\"" << _codcms << "\")";
}
if (_codfas.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(" << RDOC_FASCMS << "==\"" << _codfas << "\")";
}
//il filtro <20> completo;pu<70> eseguire la scansione
TCursor cur_rdoc(&rel_rdoc, "", 3, &dardoc, &ardoc);
cur_rdoc.setfilter(filtro, update);
const TRecnotype rdoc_items = cur_rdoc.items();
if (rdoc_items > 0)
{
cur_rdoc.freeze();
TProgind pi(rdoc_items, "Scansione righe documenti...", true, true);
//memorizza l'ultimo doc per evitare doppioni in caso di doc con pi<70> righe (rielaborerebbe..
//..lo stesso documento tante volte quante sono le sue righe!)
TString old_key;
//scanning del file dei documenti alla ricerca di quelli che hanno la data ed il CODNUM
//validi nei filtri impostati dall'utente
for (cur_rdoc = 0; cur_rdoc.pos() < rdoc_items; ++cur_rdoc)
{
pi.addstatus(1);
if (pi.iscancelled())
break;
//La riga esaminata deve avere una testata valida!!!!Se la testata non esiste va saltata..
//..la riga
const TRectype& curr_doc = cur_rdoc.curr(LF_DOC);
if (!curr_doc.empty())
{
//controlla se il documento cui appartiene la rigadoc e' stato contabilizzato;
//se e' stato contabilizzato lo salta in quanto la riga documento apparira' attraverso le righe
//dei movimenti di analitica
const long numregca = curr_doc.get_long(DOC_NUMREGCA);
//**Modifca richiesta dal CRPA!Le righe documento che hanno DACODNUM di tipo fattura da..
//..ricevere/emettere, vanno ri-contabilizzate lo stesso anche se lo sono gia' state. Il loro..
//..importo verra' poi messo nel fatturato.
const TRectype& curr_rdoc = cur_rdoc.curr();
const TString& rdoc_dacodnum = curr_rdoc.get(RDOC_DACODNUM);
const bool is_special_doc = num_fdr.find(rdoc_dacodnum) > 0;
//documento non contabilizzato o fattura da ricevere con numerazione configurata speciale
if (numregca == 0 || is_special_doc)
{
const TString curr_key = curr_doc.build_key();
if (curr_key == old_key)
continue;
else
old_key = curr_key;
TDocumento doc(curr_doc);
TAnal_mov mov;
if (numregca == 0)
{
cont_anal.elabora(doc, 0, NULL, false, mov);
//estrae il tipo ed il codice clifo dal documento per metterlo nel movana che ha generato
//con la elabora (richiesta puramente adolfica!)
TString16 key;
key << doc.get(DOC_TIPOCF) << '|' << doc.get(DOC_CODCF);
const TString clifo = cache().get(LF_CLIFO, key, CLI_RAGSOC);
mov.put(MOVANA_DESCR, clifo);
for (int j = 1; j <= mov.rows(); j++)
{
//controlla che la riga in esame abbia realmente la cms/cdc/fas indicata nel filtro;
//procedimento necessario per evitare la stampa di righe appartenenti a docs elaborati
//perch<63> contenenti 1 riga con cms corretta ed altre righe con cms sbagliate
const TRectype& rmov = mov.body()[j];
if (_codcms.not_empty() && rmov.get(RMOVANA_CODCMS) != _codcms)
continue;
if (_codcosto.not_empty() && rmov.get(RMOVANA_CODCCOSTO) != _codcosto)
continue;
if (_codfas.not_empty() && rmov.get(RMOVANA_CODFASE) != _codfas)
continue;
scrive_riga(rmov, mov, &doc); //documenti "normali"
} //for int j...
}
//righe di documento configurate come da emettere/ricevere
if (is_special_doc)
scrive_riga_speciale(&doc, num_fdr);
} //if (numregca==0...
} //if !curr_doc.empty()
//Ha trovato una riga senza testata! non puo' considerarla ma avverte l'utente del problema
else
{
const TRectype& bad_row = cur_rdoc.curr();
const TString4 bad_codnum = bad_row.get(RDOC_CODNUM);
const int bad_anno = bad_row.get_int(RDOC_ANNO);
const long bad_ndoc = bad_row.get_long(RDOC_NDOC);
const int bad_nriga = bad_row.get_int(RDOC_NRIGA);
TString error_string;
error_string << bad_codnum << "|" << bad_anno << "|D|" << bad_ndoc << "|" << bad_nriga;
warning_box("Riga documento %s priva di testata!", (const char*)error_string);
}
} //for cur_rdoc..
} //if rdoc_items
}
void TPrint_rendiconto_ca_recordset::crea_trr(const TFilename& trr) const
{
ofstream of(trr);
of << 1000 << endl;
of << 18 << endl;
of << "CONTO|1|20|0|Conto analitico" << endl;
of << "DATA|5|8|0|Data movimento o documento" << endl;
of << "CODNUM|1|4|0|Numerazione documento" << endl;
of << "NUMRD|3|7|0|Numero registrazione contabile o numero documento di origine" << endl;
of << "NRIGA|2|3|0|Riga movimento o documento" << endl;
of << "NUMREG|3|7|0|Numero registrazione del movimento analitico" << endl;
of << "NUMREGCG|3|7|Numero registrazione contabile" << endl;
of << "ANNO|9|4|0|Anno" << endl;
of << "NUMDOCRIF|1|7|0|Numero documento riferimento" << endl;
of << "DATADOCRIF|5|8|0|Data documento riferimento" << endl;
of << "DESC|1|50|0|Descrizione movimento o documento" << endl;
of << "DESCRIGA|1|50|0|Descrizione riga movimento o documento" << endl;
of << "DOCORIG|11|10|0|Riferimenti ordine/bolla" << endl;
of << "FATTURATO|4|18|5|Fatturato" << endl;
of << "MATURATO|4|18|5|Maturato" << endl;
of << "IMPEGNATO|4|18|5|Impegnato" << endl;
of << "CONTOCG|1|12|0|Conto contabile" << endl;
of << "HIDDEN|8|1|0|Record nascosto" << endl;
of << 1 << endl;
of << "CONTO+DATA+CODNUM+NUMRD+NRIGA" << endl;
}
void TPrint_rendiconto_ca_recordset::set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row)
{
//se esiste il file temporano con tracciato persomalizzato lo cancella e lo ricrea vuoto
TFilename trr; //file tracciato record
trr.tempdir();
trr.add("rendy");
TFilename dbf(trr); //file dati
trr.ext("trr");
dbf.ext("dbf");
//crea il file .trr in base ai parametri del metodo
crea_trr(trr);
//svuota la memoria dal vecchio file temporaneo
if (_tmp != NULL)
delete _tmp;
//crea in memoria il nuovo file temporaneo e lo azzera (non si sa mai..)
_tmp = new TExternisamfile(dbf, trr);
_tmp->zap();
//prende un po' di dati dalla maschera...
_piano, _daconto, _aconto, _codcosto, _codcms, _codfas = "";
if (cms_row >= 0)
{
TSheet_field& sf = msk.sfield(F_RIGHE);
TMask& sm = sf.sheet_mask();
sf.update_mask(cms_row);
TRelation rel(LF_RMOVANA);
sm.autosave(rel);
_codcosto = rel.curr().get(RMOVANA_CODCCOSTO);
_codcms = rel.curr().get(RMOVANA_CODCMS);
_codfas = rel.curr().get(RMOVANA_CODFASE);
}
const char tc = msk.get(F_PIANO)[0]; // Piano dei conti Contabile o Analitico?
const short dlg_da = tc == 'C' ? F_PDC1_INI : F_PAN1_INI;
const short dlg_al = tc == 'C' ? F_PDC1_FIN : F_PAN1_FIN;
//si utilizza la riclassificazione dei conti?
_piano = msk.get(F_PIANO);
if (_piano == "A")
{
TConfig& cfg = ca_config();
const bool use_pdcc = cfg.get_bool("UsePdcc");
_riclassificato = use_pdcc;
}
else
_riclassificato = false;
for (int i = 0; i < 4 && msk.id2pos(dlg_da+i) > 0; i++)
{
_daconto << msk.get(dlg_da+i);
_aconto << msk.get(dlg_al+i);
}
_dadata = msk.get_date(F_DATAINI);
_adata = msk.get_date(F_DATAFIN);
if (_riclassificato)
{
//esiste un prefisso a pi<70> livelli?
for (short id = F_PRE1; id <= F_PRE3 && msk.id2pos(id) > 0; id++)
{
const TString& pr = msk.get(id);
if (pr.not_empty())
_prefix << pr;
else
break;
}
}
//metodi per riempire il file da cui generare il report
//dati estratti dalle righe movimenti di contabilita' analitica
crea_righe_da_rmovana();
//dati estratti dalle righe documenti
crea_righe_da_rdoc(msk);
}
////////////////////////////////////////////////////////
// REPORT
////////////////////////////////////////////////////////
class TPrint_rendiconto_ca_rep : public TAnal_report
{
protected:
virtual bool set_recordset(const TString& sql);
virtual bool get_usr_val(const TString& name, TVariant& var) const;
public:
void set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row);
};
bool TPrint_rendiconto_ca_rep::get_usr_val(const TString& name, TVariant& var) const
{
return TAnal_report::get_usr_val(name, var);
}
bool TPrint_rendiconto_ca_rep::set_recordset(const TString& sql)
{
TPrint_rendiconto_ca_recordset* rs = new TPrint_rendiconto_ca_recordset(sql);
return TAnal_report::set_recordset(rs);
}
void TPrint_rendiconto_ca_rep::set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row)
{
TAnal_report::set_recordset(NULL); // Forza azzeramento file Rendy.dbf prima di ricostruirlo
const char* query ="USE 1000\nJOIN MOVANA INTO NUMREG==NUMRD\nJOIN RMOVANA INTO NUMREG==NUMRD NUMRIG==NRIGA";
TPrint_rendiconto_ca_recordset* recset = new TPrint_rendiconto_ca_recordset(query);
recset->set_filter(msk, cms_row);
TAnal_report::set_recordset(recset);
}
////////////////////////////////////////////////////////
// APPLICAZIONE
////////////////////////////////////////////////////////
class TPrint_rendiconto_ca : public TSkeleton_application
{
public:
const TMultilevel_code_info& get_first_level() const;
virtual void main_loop();
};
//metodo per accattarsi o' primo livello della configurazione CA
const TMultilevel_code_info& TPrint_rendiconto_ca::get_first_level() const
{
TConfig& cfg = ca_config();
const TString& first_lev = cfg.get("Level(1)");
const int logic = first_lev == "CDC" ? LF_CDC : LF_COMMESSE;
return ca_multilevel_code_info(logic);
}
void TPrint_rendiconto_ca::main_loop()
{
TPrint_rendiconto_ca_mask mask;
while (mask.run() == K_ENTER)
{
//report e book dei report
TReport_book book;
TString path = mask.get(F_REPORT);
if (path.empty())
path = "ca3700a";
TPrint_rendiconto_ca_rep rep;
rep.load(path);
TSheet_field& sheet = mask.sfield(F_RIGHE);
TString video_string; //stringa che compare nella progind
if (sheet.empty()) //se non ci sono righe sullo sheet (selezione su tutte le cms/cdc)...
{
TToken_string& row = sheet.row(-1); //crea la prima riga dello sheet
const TMultilevel_code_info& liv1 = get_first_level(); //stabilisce quale <20> il primo livello (tra CDC e CMS)..
TISAM_recordset set(liv1.logic() == LF_CDC ? "USE CDC" : "USE COMMESSE"); //..e di conseguenza scrive la use giusta
TProgind pi(set.items(), video_string, true, true);
for (int i = 0; set.move_to(i); i++) //fighissimo metodo per scandire un file in 1 riga!
{
pi.addstatus(1);
if (pi.iscancelled())
break;
row = set.get((unsigned int)0).as_string(); //prende il valore del primo campo del file (CDC o CMS code)
video_string = TR("Scansione");
video_string << " " << row; //completa la stringa da visualizzare sulla progind
pi.set_text(video_string);
for (int l = liv1.levels()-2; l >= 0; l--) //se la struttura <20> a pi<70> livelli costruisce la tokenstring
row.insert("|", liv1.total_len(l));
rep.set_filter(mask, 0); //fa la set filter sulla prima riga (che <20> quella usata)
book.add(rep);
}
sheet.destroy(); //cancella le commesse aggiunte in automatico sullo sheet
}
else //se ha almeno una riga sullo sheet delle cms/cdc...
{
FOR_EACH_SHEET_ROW(sheet, r, row) //per ogni cdc/cms che appare nello sheet di pag.1 della msk..
{
rep.set_filter(mask, r); //..chiama il metodone globale che crea e compila il file..
//..temporaneo i cui dati riempiranno il report
book.add(rep); //aggiunge il report relativo alla cdc/cms corrente al book
}
}
book.print_or_preview(); //stampa il book dei report
}
}
int ca3700(int argc, char* argv[])
{
TPrint_rendiconto_ca a;
a.run(argc, argv, TR("Stampa rendiconto"));
return 0;
}