campo-sirio/ca/ca3700.cpp
luca c66817d1c4 Patch level :4.0 744
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :superstampa adolfica (e braunica) terminata! (per ora) Sistemata la sparizione delle righe che venivano compattate a casaccio e quindi non riscritte.


git-svn-id: svn://10.65.10.50/trunk@15487 c028cbd2-c16b-5b4b-a496-9718f37d4682
2007-07-11 13:58:59 +00:00

1557 lines
51 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;
bool _reverse_cos_ric;
bool _implode_rows;
TString _prefix;
TAssoc_array _ratrisc;
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);
int sort_indbil(int indbil) const;
TString riclassifica(const int gruppo, const int conto, const long sottoconto, TRectype& tmpcurr);
real get_budget(const TString& conto, char tipo) const;
bool is_causale_rateo_risconto(const char* codcaus);
public:
virtual void set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row);
TPrint_rendiconto_ca_recordset(const TString& sql);
~TPrint_rendiconto_ca_recordset();
};
static TPrint_rendiconto_ca_recordset* myself = NULL;
TPrint_rendiconto_ca_recordset::TPrint_rendiconto_ca_recordset(const TString& sql)
: TISAM_recordset(sql), _riclassificato(false), _tmp(NULL)
{
//Controlla sul file di configurazione di CA (ditta.ini,[ca]) se esistono causali di tipo..
//..rateo/risconto che devono essere calcolate come solo maturato (Eva Braun request)
TConfig& config = ca_config();
//riempie l'assoc_array contenente i codici causale rateo/risconto
for (int j = 0;;j++)
{
const TString& codcaus = config.get("RR", NULL, j); //scansione delle righe RR(i)=.. sul paragrafo di configurazione CA
if (codcaus.blank())
break;
_ratrisc.add(codcaus, codcaus);
}
}
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("ORDCONT", 1);
darec.put("CONTO", _daconto);
}
if (_aconto.not_empty())
{
arec.put("ORDCONT", 5);
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 << ")";
}
if (_daconto.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(CONTO>='" << _daconto << "')";
}
if (_aconto.not_empty())
{
if (filtro.not_empty())
filtro << "&&";
filtro << "(CONTO<='" << _aconto << "~')";
}
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);
}
int TPrint_rendiconto_ca_recordset::sort_indbil(int indbil) const
{
if (_reverse_cos_ric) //sono del CRPA/CSA
{
if (indbil == 3 || indbil == 4)
indbil = 7 - indbil;
}
return indbil;
}
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;
}
static int bill2indbil(const TString& codconto, bool is_anal)
{
int indbil = 0;
if (is_anal)
{
const TAnal_bill bill(codconto);
indbil = bill.indicatore_bilancio();
}
else
{
const int gruppo = atoi(codconto.left(3));
const int conto = atoi(codconto.mid(3,3));
const long sottoconto = atol(codconto.mid(6,6));
const TBill bill(gruppo, conto, sottoconto);
indbil = bill.indicatore_bilancio();
}
return indbil;
}
//controlla se la causale passata e' di tipo rateo/risconto
bool TPrint_rendiconto_ca_recordset::is_causale_rateo_risconto(const char* codcaus)
{
return _ratrisc.objptr(codcaus) != NULL;
}
//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);
//----- CONTI -----//
TString codconto = rmovana.get(RMOVANA_CODCONTO);
TString codcontocg;
int indbil = 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!!!...
//Ricordare ch SOLO se si ha un conto contabile e' possibile riclassificare in analitico!!!
if (_riclassificato) //traduzione:sei il CRPA/CSA
{
//prende il gr/co/so dalla riga rmovana in esame
const int gruppo = atoi(codconto.left(3));
const int conto = atoi(codconto.mid(3,3));
const long sottoconto = atol(codconto.mid(6,6));
//stringa che conterr<72> il conto riclassificato (se sara' trovato)
const 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())
return;
//..senno' lo scrive come conto riclassificato
codcontocg = codconto;
codconto = conto_riclassificato;
indbil = bill2indbil(codcontocg, false);
} //if(_riclassificato)
else //...senn<6E> si usano..
{
if (_piano == "A") //..il normale piano dei conti analitico..
indbil = bill2indbil(codconto, true);
else //..o il normale piano dei conti contabile
{
codcontocg = codconto;
indbil = bill2indbil(codcontocg, false);
}
}
//mette i conti nel file (se piano dei conti puramente contabile i valori coincidono)
tmpcurr.put("CONTO", codconto); //conto
tmpcurr.put("CONTOCG", codcontocg); //conto_cg
//fa il sort l'indicatore di bilancio del conto e lo utilizza per ordinare i record nel file..
//..di appoggio;se sei del CRPA/CSA vuoi i costi dopo i ricavi!
const int ordcont = sort_indbil(indbil);
tmpcurr.put("ORDCONT", ordcont);
//---- FINE CONTI ----//
//---- DOC D'ORIGINE DELL' ANALMOV ----//
//tipo movimento CONSUNTIVO (o TEMPORANEO); per i movimenti di budget (P o V) vedi l'else
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
}
int selettore = 0;
bool inverti_sezione = false; //inversore D/A per causali rateo/risconto
const int anno_caus = movana.get_date(MOVANA_DATAREG).year();
const TCausale caus(movana.get(MOVANA_CODCAUS), anno_caus); //la causale serve un po' ovunque...
//ricerca del mitico documento padre della riga documento attuale!
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!)
//Altra richiesta Adolfica: nel caso di ripartizioni, per non perdere la connessione tra..
//..commessa/fase originale della riga analitica non ripartita e cms/fase della riga doc,..
//..e' necessario controllare l'esistenza dei campi ori che segnalano una ripartizione avvenuta.
//Se i campi ori sono compilati vanno usati!!! In caso contrario verrebbe perso il legame tra riga anal..
//..e riga doc e doc_babbo, perdendo la giusta configurazione del SELETTORE
TString codcms_rmovana = rmovana.get(RMOVANA_CODCMSORI);
if (!codcms_rmovana.full())
codcms_rmovana = rmovana.get(RMOVANA_CODCMS);
TString codfase_rmovana = rmovana.get(RMOVANA_CODFASEORI);
if (!codfase_rmovana.full())
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)
//---- FINE DOC ORIG DELL'ANALMOV ----//
/*[Tipo documento] //schema divino per destinare gli importi nei campi corretti
O=I**
B=IM*
BO=*M*
FB=**F
FO=*MF
F=IMF*/
//---- IMPEGNATO,MATURATO O FATTURATO? QUESTO E' IL PROBLEMA.. ----//
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!)
{
if (is_causale_rateo_risconto(caus.codice())) //movimenti con causali "rateo/risconto"
{
selettore = MATURATO;
inverti_sezione = true;
}
else //movimenti con causali "normali"
{
selettore = FATTURATO;
selettore |= MATURATO;
selettore |= IMPEGNATO;
}
} //if(newdoc != NULL)
//riempie i record del file temporaneo nel caso di rmovana con documento di origine
char sezione = rmovana.get_char(RMOVANA_SEZIONE);
if (inverti_sezione)
sezione = sezione == 'D' ? 'A' : 'D';
TImporto imp(sezione, rmovana.get_real(RMOVANA_IMPORTO));
TipoIVA tipoiva = caus.iva(); //tipo iva legato alla causale (codcaus e' letto ad inizio procedura)
char sezione_normale = sezione; //inizializza la sezione normale a sezione per evitare vuoti
if (tipoiva == iva_vendite)
sezione_normale = 'A';
else
if (tipoiva == iva_acquisti)
sezione_normale = 'D';
else
if (tipoiva == nessuna_iva)
{
if (caus.tipomov() > 0) //non e' stato specificato un tipo movimento nella causale (porcata)
{
if (caus.sezione_clifo() == 'D')
sezione_normale = 'A';
else
sezione_normale = 'D';
}
}
else
{ //iva errata -> non ha causali -> cerca di capire se cliente o fornitore
if (newdoc != NULL && newdoc->get_char(DOC_TIPOCF) == 'C')
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");
}
//scrive sul file di appoggio il record appena riempito
int err = _tmp->write();
//se e' in modalita' di ricompattamento righe ripartite..
if (_implode_rows)
{
//..se ha un errore di riscrittura significa che ci sono righe dello stesso movimento ricompattate..
//..in precedenza Quindi incrementa di 1 il numero riga fino al primo posto libero
while (err == _isreinsert)
{
const int new_nriga = tmpcurr.get_int("NRIGA") + 1;
tmpcurr.put("NRIGA", new_nriga);
err = _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)
{
//prende il tipocf che gli serve un po' ovunque in seguito..
const char tipocf = doc->get_char(DOC_TIPOCF);
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);
TString codconto, codcontocg;
//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))
codconto = codcontocg = conto.string(0x8);
}
else //se ivece usa il piano dei conti analitico -> _piano = A...
{
if (_riclassificato)
{
TContabilizzazione_analitica contab;
TBill conto;
if (contab.search_costo_ricavo(rigadoc, conto))
{
//stringa che conterr<72> il conto riclassificato (se sara' trovato)
codconto = riclassifica(conto.gruppo(), conto.conto(), conto.sottoconto(), tmpcurr);
codcontocg = conto.string(0x8);
}
} //if(_riclassificato)
else
{
if (rigadoc.is_articolo())
{
const TRectype& anamag = cache().get(LF_ANAMAG, rigadoc.get(RDOC_CODARTMAG));
codconto = 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);
codconto = tipocf == 'F' ? spp.conto_analitico_acquisti() : spp.conto_analitico_vendite();
}
}
}
}
//non trova il conto -> esce
if (codconto.empty())
return;
const int indbil = codcontocg.full() ? bill2indbil(codcontocg, false)
: bill2indbil(codconto, true) ;
tmpcurr.put("CONTO", codconto);
tmpcurr.put("CONTOCG", codcontocg);
tmpcurr.put("ORDCONT", sort_indbil(indbil));
//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 == nessuna_iva)
{
if (caus.sezione_clifo() == 'D')
sezione_normale = 'A';
else
sezione_normale = 'D';
}
else
{ //iva errata -> non ha causali -> cerca di capire se cliente o fornitore
if (doc != NULL && doc->get_char(DOC_TIPOCF) == 'C')
sezione_normale = 'A';
else
sezione_normale = 'D';
}
imp.normalize(sezione_normale);
//i documenti speciali vanno SOLO in FATTURATO
tmpcurr.put("FATTURATO", imp.valore());
}
else //if(codcaus.full()
{
//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);
//aggiunta adolfica di implosione righe movimenti eventualmente ripartite in precedenza..
//..modifica che serve solo al CRPA
//se si e' scelto di compattare le rmovana...
if (_implode_rows)
{
TRecord_array righe_attuali(LF_RMOVANA, RMOVANA_NUMRIG);
TRecord_array righe_compattate(LF_RMOVANA, RMOVANA_NUMRIG);
TRectype old_movana(LF_MOVANA);
long old_numreg = 0L;
//si usa <= per forzare il cambio testata anche sull'ultimo movimento (in modo da uscire correttamente)
//NON mettere < e basta che sbaglia l'ultimo!!!
for (cur_rmovana = 0; cur_rmovana.pos() <= rmovana_items; ++cur_rmovana)
{
//legge la testata iniziale
const long numreg = rmovana.get_long(RMOVANA_NUMREG);
//se la testata e' cambiata, allora ha cambiato movana e quindi le righe da compattare sono..
//..quelle che ha gia' messo nell'array delle righe_attuali
if (numreg != old_numreg)
{
if (righe_attuali.rows() > 0) //quando righe_attuali e' vuoto sei al primo giro
{
//quindi implode le righe attuali del movimento, generando l'array delle righe_compattate
ca_implode_rows(righe_attuali, righe_compattate);
//adesso fa la scrittura delle righe compattate
const int last_row = righe_compattate.last_row();
for (int i = righe_compattate.first_row(); i > 0 && i <= last_row; i = righe_compattate.succ_row(i))
scrive_riga(righe_compattate.row(i), old_movana, NULL);
}
//aggiorna il valore di testata con quella nuova per il prossimo movimento
old_movana = movana;
old_numreg = numreg;
//pulisce gli array che sono pronti ad essere nuovamente riempiti
righe_attuali.destroy_rows();
righe_compattate.destroy_rows();
}
//aggiunge le righe analitiche all'array da compattare (se rmovana e' vuoto ha gia' terminato)
if (numreg > 0)
{
righe_attuali.insert_row(rmovana);
}
else
break;
}
}
else //if(_implode_rows.. metodo standard senza ripartizioni
{
for (cur_rmovana = 0; cur_rmovana.pos() < rmovana_items; ++cur_rmovana)
{
if (!pi.addstatus(1))
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++)
{
const 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);
//documento NON contabilizzato
if (numregca == 0)
{
TAnal_mov mov;
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 (documenti speciali)
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 << 19 << endl;
of << "ORDCONT|1|1|0|Ordinatore in base a indicatore di bilancio" << 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 << "ORDCONT+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?
//Ovvero: sei il CRPA o un qualsiasi altro utente del mondo?
_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;
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;
}
}
//c'e' un range di conti da considerare?
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);
}
//vuoi l'ordinamento normale o sei la Roberta del CRPA?
_reverse_cos_ric = msk.get_bool(F_REV_COSRIC);
//sei al CRPA e vuoi implodere le righemovana ripartite in precedenza?
_implode_rows = msk.get_bool(F_IMPLODE_ROWS);
//c'e' un fottuto range di date?
_dadata = msk.get_date(F_DATAINI);
_adata = msk.get_date(F_DATAFIN);
//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;
}