ebeaf18246
Files correlati : ca3 Ricompilazione Demo : [ ] Commento : Riporto modifiche di Bonazzi git-svn-id: svn://10.65.10.50/branches/R_10_00@22607 c028cbd2-c16b-5b4b-a496-9718f37d4682
2256 lines
78 KiB
C++
Executable File
2256 lines
78 KiB
C++
Executable File
#include <applicat.h>
|
||
#include <defmask.h>
|
||
#include <execp.h>
|
||
#include <progind.h>
|
||
#include <reprint.h>
|
||
#include <reputils.h>
|
||
#include <doc.h>
|
||
#include <rdoc.h>
|
||
#include "../cg/cg2103.h"
|
||
#include "../cg/cglib01.h"
|
||
#include "../ve/velib04.h"
|
||
|
||
#include "cdc.h"
|
||
#include "commesse.h"
|
||
#include "panapdc.h"
|
||
#include "pconana.h"
|
||
#include "movana.h"
|
||
#include "rmovana.h"
|
||
#include "saldana.h"
|
||
|
||
#include "ca3.h"
|
||
#include "ca3700.h"
|
||
#include "calib01.h"
|
||
#include "calib02.h"
|
||
|
||
////////////////////////////////////////////////////////
|
||
// MASCHERA
|
||
////////////////////////////////////////////////////////
|
||
class TPrint_rendiconto_ca_mask : public TAnal_report_mask
|
||
{
|
||
char _print_mode;
|
||
|
||
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:
|
||
char print_mode() const { return _print_mode; }
|
||
|
||
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 DLG_PREVIEW: //gestione del tasto anteprima!
|
||
if (e == fe_button)
|
||
{
|
||
stop_run('A');
|
||
}
|
||
break;
|
||
case DLG_EXPORT:
|
||
if (e == fe_button)
|
||
{
|
||
TString path = get(F_PATH);
|
||
if (path.empty())
|
||
return error_box(TR("Specificare una cartella dove creare il file rendiconto.xls!"));
|
||
}
|
||
break;
|
||
#ifndef DBG
|
||
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;
|
||
#endif
|
||
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"));
|
||
}
|
||
if (e == fe_init)
|
||
_print_mode = 'S';
|
||
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();
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////
|
||
// TRiclass
|
||
///////////////////////////////////////////////////////////////
|
||
|
||
class TRiclass : public TCache
|
||
{
|
||
TString16 _prefix;
|
||
|
||
protected:
|
||
TObject* key2obj(const char* key);
|
||
|
||
public:
|
||
void set_prefix(const TString& p) { _prefix = p; }
|
||
bool is_riclassificato(const TString& str_conto) const;
|
||
TRiclass() : TCache(883) {}
|
||
};
|
||
|
||
TObject* TRiclass::key2obj(const char* key)
|
||
{
|
||
CHECK(_prefix.full(), "Empty pconana prefix");
|
||
const TFixed_string str_conto(key);
|
||
|
||
TRelation panarel(LF_PANAPDC);
|
||
TString filter;
|
||
filter << '(' << PANAPDC_CODCONTO << "[1," << _prefix.len() << "]==\"" << _prefix << "\")";
|
||
|
||
TRectype& fromto = panarel.curr();
|
||
if (str_conto.len() >= 3)
|
||
fromto.put(PANAPDC_GRUPPO, str_conto.left(3));
|
||
|
||
if (str_conto.len() >= 6)
|
||
fromto.put(PANAPDC_CONTO, str_conto.mid(3,3));
|
||
else
|
||
filter << "&&(" << PANAPDC_CONTO << "=\"\")";
|
||
|
||
if (str_conto.len() >= 12)
|
||
fromto.put(PANAPDC_SOTTOCONTO, str_conto.mid(6,6));
|
||
else
|
||
filter << "&&(" << PANAPDC_SOTTOCONTO << "=\"\")";
|
||
|
||
TCursor panacur(&panarel, filter, 2, &fromto, &fromto);
|
||
|
||
bool ok = panacur.items() > 0;
|
||
return new real(ok ? UNO : ZERO);
|
||
}
|
||
|
||
//cerca se str_conto <20> riclassificato
|
||
bool TRiclass::is_riclassificato(const TString& str_conto) const
|
||
{
|
||
TString80 codice = str_conto;
|
||
|
||
const real* o = (const real*)((TRiclass*)this)->objptr(codice); //Allah!!!
|
||
if (o->is_zero() && codice.len() == 12)
|
||
{
|
||
codice.cut(6);
|
||
o = (const real*)((TRiclass*)this)->objptr(codice); //Budda!!!
|
||
}
|
||
if (o->is_zero() && codice.len() == 6)
|
||
{
|
||
codice.cut(3);
|
||
o = (const real*)((TRiclass*)this)->objptr(codice); //Jeowah!!!
|
||
}
|
||
return !o->is_zero();
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////
|
||
// RECORDSET
|
||
///////////////////////////////////////////////////////////////
|
||
#define IMPEGNATO 1
|
||
#define MATURATO 2
|
||
#define FATTURATO 4
|
||
|
||
class TPrint_rendiconto_ca_recordset : public TISAM_recordset
|
||
{
|
||
bool _riclassificato;
|
||
bool _reverse_cos_ric;
|
||
bool _implode_rows;
|
||
TString _prefix;
|
||
TAssoc_array _ratrisc;
|
||
TString_array _num_fdr;
|
||
TString_array _num_par;
|
||
TRiclass _ricl;
|
||
|
||
protected:
|
||
int _anno;
|
||
TString4 _piano;
|
||
TDate _dadata, _adata;
|
||
bool _vitaintera;
|
||
long _danumreg, _anumreg;
|
||
TString _daconto, _aconto, _codcosto, _codcms, _codfas;
|
||
|
||
protected:
|
||
static bool mov_filter(const TRelation* rel);
|
||
bool valid_record(const TRelation& rel) const;
|
||
virtual void set_custom_filter(TCursor& cur) const;
|
||
|
||
void calcola_date_da_maschera(const TMask& msk, TDate& dal, TDate& al);
|
||
int crea_filtro_rmovana(const TMask& msk, TRectype& da_rmovana, TRectype& a_rmovana, TString& filtro);
|
||
void crea_righe_da_rmovana(TLocalisamfile& tmp, const TPrint_rendiconto_ca_mask& msk, TLog_report& log);
|
||
int crea_filtro_rdoc(const TMask& msk, TRectype& da_rdoc, TRectype& a_rdoc, TString& filtro_date);
|
||
void crea_righe_da_rdoc(TLocalisamfile& tmp, const TPrint_rendiconto_ca_mask& msk, TLog_report& log);
|
||
|
||
void crea_trr(const TFilename& trr) const;
|
||
void scrive_riga(TLocalisamfile& tmp, const TRectype& rmovana, const TRectype& movana, const TDocumento* doc,
|
||
TLog_report& log);
|
||
void scrive_riga_speciale(TLocalisamfile& tmp, const TDocumento* doc, const TString_array& special_docs);
|
||
|
||
int sort_indbil(int indbil) const;
|
||
const TString& riclassifica(const TBill& zio, TRectype& tmpcurr) const;
|
||
const TString& riclassifica(const TString& contone, TRectype& tmpcurr) const;
|
||
bool is_causale_rateo_risconto(const char* codcaus) const;
|
||
int ricava_tipo_documento (const TDocumento& doc) const;
|
||
|
||
public: //da libreria
|
||
virtual const TVariant& get(const char* column_name) const;
|
||
|
||
public:
|
||
void set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row, TLog_report& log);
|
||
void set_cms_cdc_fase(const char* cdc, const char* cms, const char* fase);
|
||
real get_budget_print(const TString& conto, char tipo) const; //per la stampa
|
||
void get_budget_export(const TString& codcdc, const TString& codcms, const TString& codfase,
|
||
TImporto& att, TImporto& pas, TImporto& cos, TImporto& ric) const; //per l'esportazione
|
||
|
||
|
||
TPrint_rendiconto_ca_recordset(const TString& sql);
|
||
~TPrint_rendiconto_ca_recordset();
|
||
};
|
||
|
||
TPrint_rendiconto_ca_recordset::TPrint_rendiconto_ca_recordset(const TString& sql)
|
||
: TISAM_recordset(sql), _riclassificato(false)
|
||
{
|
||
//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);
|
||
}
|
||
|
||
//TString_array contenente le numerazioni delle fatture da ricevere
|
||
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);
|
||
}
|
||
|
||
//TString_array contenente le numerazioni delle parcelle e lo stato da cui considerarle fatture
|
||
for (int j = 0;;j++)
|
||
{
|
||
TToken_string num_par(config.get("PA", NULL, j)); //scansione delle righe PA(i)=.. sul paragrafo di configurazione CA
|
||
if (num_par.empty_items())
|
||
break;
|
||
_num_par.add(num_par);
|
||
}
|
||
}
|
||
|
||
|
||
TPrint_rendiconto_ca_recordset::~TPrint_rendiconto_ca_recordset()
|
||
{ }
|
||
|
||
|
||
//filtro ulteriore sul file rendy.dbf gi<67> creato
|
||
//questo filtro, all'apparenza inutile, serve per filtrare sulle rmovana create al volo dagli rdoc..
|
||
//..che potrebbero presentare conti non pertinenti dovuti ai conti stessi legati ai codart ecc.
|
||
void TPrint_rendiconto_ca_recordset::set_custom_filter(TCursor& cur) const
|
||
{
|
||
//la region serve solo nella chiave 1!!!
|
||
if (cur.key() == 1)
|
||
{
|
||
//filtro sul file esterno (tmp, cio<69> rendy.dbf) 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);
|
||
}
|
||
cur.setregion(darec, arec);
|
||
}
|
||
//filtro sulla data(non avendo anche codnum non ho la chiave completa per mettere la data nella setregion)
|
||
TString filtro;
|
||
if (_dadata.ok() || _adata.ok())
|
||
{
|
||
if (_vitaintera)
|
||
filtro << "(BETWEEN(DATA," << _dadata.date2ansi() << ",0))";
|
||
else
|
||
filtro << "(BETWEEN(DATA," << _dadata.date2ansi() << "," << _adata.date2ansi() << "))";
|
||
}
|
||
|
||
//vera selezione sui conti
|
||
if (_daconto.full() || _aconto.full())
|
||
{
|
||
if (filtro.not_empty())
|
||
filtro << "&&";
|
||
if (_daconto == _aconto)
|
||
filtro << "(CONTO[1," << _daconto.len() << "]==\"" << _daconto << "\")";
|
||
else
|
||
filtro << "(BETWEEN(CONTO,\"" << _daconto << "\",\"" << _aconto << "~\"))";
|
||
}
|
||
|
||
cur.setfilter(filtro);
|
||
}
|
||
|
||
void TPrint_rendiconto_ca_recordset::set_cms_cdc_fase(const char* cdc, const char* cms, const char* fase)
|
||
{
|
||
_codcosto = cdc;
|
||
_codcms = cms;
|
||
_codfas = fase;
|
||
}
|
||
|
||
void TPrint_rendiconto_ca_recordset::get_budget_export(const TString& codcdc, const TString& codcms, const TString& codfase,
|
||
TImporto& att, TImporto& pas, TImporto& cos, TImporto& ric) const
|
||
{
|
||
TString query;
|
||
query << "USE SALDANA\nSELECT ";
|
||
if (codcdc.full())
|
||
query << "(COSTO='" << codcdc << "')&&";
|
||
if (codcms.full())
|
||
query << "(COMMESSA='" << codcms << "')&&";
|
||
if (codfase.full())
|
||
query << "(FASE='" << codfase << "')&&";
|
||
query.rtrim(2);
|
||
|
||
TISAM_recordset saldana(query);
|
||
for (bool ok = saldana.move_first(); ok; ok = saldana.move_next())
|
||
{
|
||
const TString80 str_conto = saldana.get("CONTO").as_string();
|
||
if (_riclassificato && !_ricl.is_riclassificato(str_conto))
|
||
continue;
|
||
|
||
const TAnal_bill zio(str_conto);
|
||
const int indbil = zio.indicatore_bilancio();
|
||
|
||
TImporto saldo = ca_get_imp(saldana, SALDANA_SEZIONEP, SALDANA_SALDOP);
|
||
saldo += ca_get_imp(saldana, SALDANA_SEZIONEV, SALDANA_SALDOV);
|
||
|
||
switch(indbil)
|
||
{
|
||
case 1: att += saldo; break;
|
||
case 2: pas += saldo; break;
|
||
case 3: cos += saldo; break;
|
||
case 4: ric += saldo; break;
|
||
default: break;
|
||
}
|
||
}
|
||
|
||
att.normalize('D');
|
||
cos.normalize('D');
|
||
|
||
pas.normalize('A');
|
||
ric.normalize('A');
|
||
}
|
||
|
||
//sconvolgente metodo per la normalizzazione dei conti
|
||
real TPrint_rendiconto_ca_recordset::get_budget_print(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_print(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_print(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/DINAMICA
|
||
{
|
||
if (indbil == 3 || indbil == 4)
|
||
indbil = 7 - indbil;
|
||
}
|
||
return indbil;
|
||
}
|
||
|
||
|
||
const TString& TPrint_rendiconto_ca_recordset::riclassifica(const TBill& zio, TRectype& tmpcurr) const
|
||
{
|
||
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, zio.gruppo());
|
||
|
||
TString filtro;
|
||
if (_prefix.full())
|
||
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 (zio.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 (zio.conto() == current_conto && zio.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 get_tmp_string() = conto_riclassificato;
|
||
}
|
||
|
||
const TString& TPrint_rendiconto_ca_recordset::riclassifica(const TString& contone, TRectype& tmpcurr) const
|
||
{
|
||
CHECK(contone.len() == 12, "Conto di lunghezza assurda");
|
||
const int gruppo = atoi(contone.left(3));
|
||
const int conto = atoi(contone.mid(3,3));
|
||
const long sottoconto = atol(contone.mid(6,6));
|
||
const TBill zio(gruppo, conto, sottoconto);
|
||
|
||
return riclassifica(zio, tmpcurr);
|
||
}
|
||
|
||
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) const
|
||
{
|
||
return _ratrisc.objptr(codcaus) != NULL;
|
||
}
|
||
|
||
int TPrint_rendiconto_ca_recordset::ricava_tipo_documento (const TDocumento& doc) const
|
||
{
|
||
int tipo_documento = doc.tipo_riclassificato();
|
||
|
||
if (tipo_documento == TTipo_documento::_fattura)
|
||
{
|
||
//attenzione! se il documento fosse una ignorantissima parcella, il tipo documento verrebbe..
|
||
//..deciso in base allo stato del documento stesso, secondo la regola data nella configurazione del..
|
||
//..rendiconto
|
||
const TString4 codnum = doc.numerazione();
|
||
const TString4 stato = doc.get(DOC_STATO);
|
||
|
||
FOR_EACH_ARRAY_ROW(_num_par, r, riga)
|
||
{
|
||
const TString4 par_codnum = riga->get(0);
|
||
if (par_codnum == codnum)
|
||
{
|
||
const TString4 par_stato = riga->get(1);
|
||
if (stato < par_stato)
|
||
tipo_documento = TTipo_documento::_bolla;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return tipo_documento;
|
||
}
|
||
|
||
//compila i campi del file temporaneo che sara' poi stampato
|
||
void TPrint_rendiconto_ca_recordset::scrive_riga(TLocalisamfile& tmp, const TRectype& rmovana, const TRectype& movana,
|
||
const TDocumento* doc, TLog_report& log)
|
||
{
|
||
TRectype& tmpcurr = tmp.curr();
|
||
tmpcurr.zero();
|
||
TString8 codnum; //codnum da usare sia per compilare il campo "CODNUM"
|
||
|
||
//----- CONTI -----//
|
||
const TString80 codconto_originale = rmovana.get(RMOVANA_CODCONTO);
|
||
if (codconto_originale.blank())
|
||
{
|
||
TString error_string;
|
||
const long error_numreg = rmovana.get_long(RMOVANA_NUMREG);
|
||
const int error_numrig = rmovana.get_int(RMOVANA_NUMRIG);
|
||
error_string.format("NON esiste il conto sulla riga %d del movimento %ld !!", error_numrig, error_numreg);
|
||
log.log(2, error_string);
|
||
return;
|
||
}
|
||
TString80 codconto = codconto_originale;
|
||
|
||
TString codcontocg;
|
||
int indbil = 0;
|
||
bool conto_non_riclass = false; //indicatore che serve per tener conto di specialissimi conti del CRPA...
|
||
//E' una lampante dimostrazione di quanto sia generico questo programma...
|
||
|
||
// 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 che SOLO se si ha un conto contabile e' possibile riclassificare in analitico!!!
|
||
if (_riclassificato) //traduzione:sei il CRPA/DINAMICA
|
||
{
|
||
//stringa che conterr<72> il conto riclassificato (se sara' trovato)
|
||
const TString conto_riclassificato = riclassifica(codconto, tmpcurr);
|
||
//se il conto viene ritornato vuoto significa che non ricade nell'intervallo dei conti..
|
||
//..riclassificati selezionato dall'utente...non puo' essere scartato a priori perche' puo'..
|
||
//..essere un conto speciale del CRPA
|
||
codcontocg = codconto;
|
||
indbil = bill2indbil(codcontocg, false);
|
||
|
||
if (conto_riclassificato.empty())
|
||
{
|
||
conto_non_riclass = true;
|
||
codconto.cut(0);
|
||
}
|
||
else //..senno' lo scrive come conto riclassificato
|
||
codconto = conto_riclassificato;
|
||
|
||
} //if(_riclassificato) Se non e' un conto riclassificato -> analitico puro o contabile puro
|
||
else //...senn<6E> si usano..
|
||
{
|
||
if (_piano == "A") //..il normale piano dei conti analitico.. Conto analitico puro
|
||
indbil = bill2indbil(codconto, true);
|
||
else //..o il normale piano dei conti contabile Conto contabile puro
|
||
{
|
||
codcontocg = codconto;
|
||
indbil = bill2indbil(codcontocg, false);
|
||
}
|
||
}
|
||
|
||
//La scrittura dei conti su tmpcurr e' rinviata in fondo al metodo...
|
||
//---- 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);
|
||
#ifdef DBG
|
||
const long movana_numreg = movana.get_long(MOVANA_NUMREG);
|
||
if (movana_numreg == 19571)
|
||
const int cazzone = 1;
|
||
#endif
|
||
|
||
//serve un documento da cui ricavare i parametri di stampa
|
||
TDocumento* original_doc = (TDocumento*)doc;
|
||
bool should_delete = false;
|
||
if (original_doc == NULL && movana.get_long(MOVANA_DNDOC) > 0)
|
||
{
|
||
const TString4 dacodnum = movana.get(MOVANA_DCODNUM);
|
||
original_doc = 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 = original_doc != NULL;
|
||
//i movimenti possono essere normali o generati da documento...
|
||
if (dadoc) //movimento generato da documento
|
||
{
|
||
codnum = movana.get(MOVANA_DCODNUM); //serve anche in fondo al metodo
|
||
tmpcurr.put("CODNUM", codnum); //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", original_doc->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;
|
||
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...
|
||
|
||
//caso in cui il movimento derivi da un documento
|
||
//ricerca del mitico documento padre della riga documento attuale!
|
||
if (original_doc != NULL)
|
||
{
|
||
tmpcurr.put("NUMDOCRIF", original_doc->get(DOC_NUMDOCRIF)); //docrif del documento originante il movana
|
||
tmpcurr.put("DATADOCRIF", original_doc->get(DOC_DATADOCRIF)); //datadocrif del documento originante il movana
|
||
|
||
//procedura per ottenere i campi del documento
|
||
int tipo_babbo = TTipo_documento::_altro;
|
||
//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 = ricava_tipo_documento(*original_doc);
|
||
|
||
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 = original_doc->physical_rows(); //righe del doc attuale
|
||
|
||
for (int i = 1; i <= rows; i++) //scandisce tutte le righe del doc..
|
||
{
|
||
const TRiga_documento& riga = (*original_doc)[i];
|
||
//commessa e fase della riga documento
|
||
const TString codcms_rigadoc = riga.codice_commessa();
|
||
const TString codfase_rigadoc = riga.fase_commessa();
|
||
const TString codcdc_rigadoc = riga.codice_costo();
|
||
//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 e cdc..
|
||
//..della riga movimento analitico con quelli la riga movimento e procede solo nel..
|
||
//..caso coincidano (richiesta Adolfica! heil Magnavakken!)
|
||
|
||
//Altra richiesta Adolfica: nel caso di ripartizioni, per non perdere la connessione tra..
|
||
//..commessa/fase/cdc originale della riga analitica non ripartita e cms/fase/cdc 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);
|
||
TString codcdc_rmovana = rmovana.get(RMOVANA_CODCCORI);
|
||
if (!codcdc_rmovana.full())
|
||
codcdc_rmovana = rmovana.get(RMOVANA_CODCCOSTO);
|
||
|
||
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 (tipo_babbo == TTipo_documento::_altro)
|
||
{
|
||
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 (codcms_rigadoc == codcms_rmovana && codfase_rigadoc == codfase_rmovana && codcdc_rigadoc == codcdc_rmovana)
|
||
{
|
||
//caso particolare dei conti del CRPA. Se il conto non e' riclassificato (ma siamo in presenza..
|
||
//.di un piano dei conti riclassificato)...
|
||
if (conto_non_riclass)
|
||
{
|
||
//Controlla se il documento di origine (padre del documento da cui deriva l'attuale riga..
|
||
//..di analitica) era una FDR/FDE...
|
||
const TCodice_numerazione kodice_num(babbo_codnum);
|
||
//Se lo era...
|
||
if (kodice_num.fattura_emettere_ricevere())
|
||
{
|
||
//Ricrea il documento origine
|
||
TDocumento doc_babbo('D', anno, babbo_codnum, ndoc);
|
||
//elaborazione analitica del documento originale
|
||
TContabilizzazione_analitica cont_anal;
|
||
TAnal_mov mov_babbo;
|
||
//se riesce a contabilizzare il documento origine (si spera, senno' so' cazzi!)..
|
||
cont_anal.elabora(doc_babbo, 0, NULL, false, mov_babbo);
|
||
if (mov_babbo.rows() > 0)
|
||
{
|
||
const int anal_rows = mov_babbo.rows();
|
||
for (int k = 1; k <= anal_rows; k++)
|
||
{
|
||
//cerca la riga con il conto che gli serve e lo assegna a codconto, attualmente vuoto..
|
||
//..in quanto non e' stato riclassificato
|
||
const TRectype& mov_babbo_riga = mov_babbo.body()[k];
|
||
const TString& conto_babbo = mov_babbo_riga.get(RMOVANA_CODCONTO);
|
||
if (conto_babbo != codcontocg)
|
||
{
|
||
//ovviamente deve riclassificare il conto_babbo!
|
||
codconto = riclassifica(conto_babbo, tmpcurr);
|
||
indbil = bill2indbil(codconto, true);
|
||
break;
|
||
}
|
||
}
|
||
} //if (mov_babbo.rows() > 0)
|
||
}
|
||
else
|
||
continue;
|
||
}
|
||
|
||
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 (codcms_rigadoc == codcms_rmovana..
|
||
} //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;
|
||
}
|
||
|
||
const TString4 dacodnum = movana.get(MOVANA_DCODNUM);
|
||
|
||
if (_num_fdr.find(dacodnum) >= 0) // is_special_doc
|
||
{
|
||
TLocalisamfile rdoc(LF_RIGHEDOC);
|
||
|
||
rdoc.setkey(4);
|
||
|
||
rdoc.put(RDOC_DAPROVV, movana.get(MOVANA_DPROVV));
|
||
rdoc.put(RDOC_DAANNO, movana.get(MOVANA_DANNO));
|
||
rdoc.put(RDOC_DACODNUM, dacodnum);
|
||
rdoc.put(RDOC_DANDOC, movana.get(MOVANA_DNDOC));
|
||
|
||
if (rdoc.read(_isgteq) == NOERR &&
|
||
rdoc.get(RDOC_DAPROVV) == movana.get(MOVANA_DPROVV) &&
|
||
rdoc.get_int(RDOC_DAANNO) == movana.get_int(MOVANA_DANNO) &&
|
||
rdoc.get(RDOC_DACODNUM) == dacodnum &&
|
||
rdoc.get_long(RDOC_DANDOC) == movana.get_long(MOVANA_DNDOC))
|
||
selettore &= ~FATTURATO;
|
||
}
|
||
} //if(original_doc != NULL)
|
||
else //movimenti puri di analitica (no documento di origine!)
|
||
{
|
||
if (is_causale_rateo_risconto(caus.codice())) //movimenti con causali "rateo/risconto"
|
||
{
|
||
selettore = MATURATO;
|
||
}
|
||
else //movimenti con causali "normali"
|
||
{
|
||
selettore = FATTURATO;
|
||
selettore |= MATURATO;
|
||
selettore |= IMPEGNATO;
|
||
}
|
||
} //if(original_doc != NULL)
|
||
|
||
//riempie i record del file temporaneo nel caso di rmovana con documento di origine
|
||
char sezione = rmovana.get_char(RMOVANA_SEZIONE);
|
||
|
||
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 && caus.tipomov() < 3) //solo causali Fattura e Nota di Credito!
|
||
{
|
||
if (caus.sezione_clifo() == 'D')
|
||
sezione_normale = 'A';
|
||
else
|
||
sezione_normale = 'D';
|
||
}
|
||
else
|
||
{
|
||
if (indbil == 1 || indbil == 3) //attivita' e costi sono in DARE
|
||
sezione_normale = 'D';
|
||
else //passivita' e ricavi sono in AVERE
|
||
sezione_normale = 'A';
|
||
}
|
||
}
|
||
else
|
||
{ //iva errata -> non ha causali -> cerca di capire se cliente o fornitore
|
||
if (original_doc != NULL)
|
||
{
|
||
if (original_doc->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();
|
||
}
|
||
|
||
//----Scrittura Conti sul file----//
|
||
//Scrittura dei conti (i valori delle variabili sono stati settati nella parte iniziale del metodo)
|
||
//mette i conti nel file (se piano dei conti puramente contabile i valori coincidono)
|
||
if (codconto.blank())
|
||
{
|
||
TString error_message;
|
||
error_message.format("Il conto %s non <20> riclassificato!", (const char*)codcontocg);
|
||
log.log(2, error_message);
|
||
}
|
||
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);
|
||
|
||
//----Scrittura dati riga movimento----//
|
||
tmpcurr.put("NUMREG", rmovana.get(RMOVANA_NUMREG)); //numero di registrazione analitica
|
||
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
|
||
tmpcurr.put("CODCMS", rmovana.get(RMOVANA_CODCMS)); //codice commessa
|
||
tmpcurr.put("CODCOSTO", rmovana.get(RMOVANA_CODCCOSTO)); //codice cdc
|
||
tmpcurr.put("CODFASE", rmovana.get(RMOVANA_CODFASE)); //codice fase
|
||
|
||
if (should_delete)
|
||
delete original_doc;
|
||
|
||
//I movimenti di budget (preventivi e variazioni) vanno nascosti nei body!!! Devono essere considerati in..
|
||
//..quanto servono per sapere quali conti sono stati movimentati per i budget, in modo che per ogni conto..
|
||
//..il report si crei la testata e faccia il relativo calcolo del saldo del conto! (cerca #PREVENTIVO)
|
||
if (tipomov == 'P' || tipomov == 'V')
|
||
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(TLocalisamfile& tmp, 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();
|
||
|
||
TContabilizzazione_analitica contab;
|
||
|
||
for (int i = 1; i <= rows; i++)
|
||
{
|
||
const TRiga_documento& rigadoc = (*doc)[i];
|
||
const TString& dacodnum = rigadoc.get(RDOC_DACODNUM);
|
||
|
||
if (special_docs.find(dacodnum) >= 0) // Riga proveniente da special doc
|
||
{
|
||
TString codconto, codcontocg;
|
||
TRectype& tmpcurr = tmp.curr();
|
||
tmpcurr.zero();
|
||
|
||
//se usa il piano dei conti contabile -> _piano = C..
|
||
if (_piano == "C")
|
||
{
|
||
//trova il conto senza movana e rmovana!!!
|
||
TBill conto;
|
||
if (contab.search_costo_ricavo(rigadoc, conto, false)) // was true
|
||
codconto = codcontocg = conto.string(0x8);
|
||
}
|
||
else //se ivece usa il piano dei conti analitico -> _piano = A...
|
||
{
|
||
if (_riclassificato)
|
||
{
|
||
TBill conto;
|
||
if (contab.search_costo_ricavo(rigadoc, conto, true))
|
||
{
|
||
//stringa che conterr<72> il conto riclassificato (se sara' trovato)
|
||
codconto = riclassifica(conto, 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 dalla riga e passa alla successiva
|
||
if (codconto.empty())
|
||
continue;
|
||
|
||
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)); //numerazione doc speciale
|
||
tmpcurr.put("ANNO", doc->get(DOC_ANNO)); //anno doc speciale
|
||
tmpcurr.put("NUMRD", doc->get(DOC_NDOC)); //numero del doc speciale
|
||
tmpcurr.put("DATA", doc->get(DOC_DATADOC)); //data del doc speciale
|
||
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)); //numero di registrazione analitica
|
||
tmpcurr.put("NUMREGCG", doc->get(DOC_NUMREG)); //numero di registrazione contabile
|
||
|
||
TToken_string clifo_key;
|
||
clifo_key.add(tipocf);
|
||
clifo_key.add(doc->get(DOC_CODCF));
|
||
const TString& ragsoc = cache().get(LF_CLIFO, clifo_key, CLI_RAGSOC);
|
||
|
||
tmpcurr.put("DESC", ragsoc); //descrizione doc: ci mette il clifo (come nei movana normali)
|
||
tmpcurr.put("DESCRIGA", rigadoc.get(RDOC_DESCR)); //descrizione rdoc
|
||
|
||
tmpcurr.put("NRIGA", rigadoc.get(RDOC_NRIGA)); //numero riga
|
||
tmpcurr.put("CODCMS", rigadoc.get(RDOC_CODCMS)); //codice commessa
|
||
tmpcurr.put("CODCOSTO", rigadoc.get(RDOC_CODCOSTO)); //codice cdc
|
||
tmpcurr.put("CODFASE", rigadoc.get(RDOC_FASCMS)); //codice fase
|
||
|
||
//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...
|
||
}
|
||
|
||
void TPrint_rendiconto_ca_recordset::calcola_date_da_maschera(const TMask& msk, TDate& dal, TDate& al)
|
||
{
|
||
//se siamo fortunati l'anno si pu<70> trovare cos<6F>..
|
||
int anno = msk.get_int(F_ANNO);
|
||
if (anno > 0)
|
||
{
|
||
TEsercizi_contabili esc;
|
||
esc.code2range(anno, dal, al);
|
||
}
|
||
if (_dadata.ok())
|
||
dal = _dadata;
|
||
if (_adata.ok())
|
||
al = _adata;
|
||
}
|
||
|
||
|
||
//nuovo modo di costruire il filtro e darec arec, da quando esistono le chiavi per codcm e codcdc su lf_rmovana
|
||
int TPrint_rendiconto_ca_recordset::crea_filtro_rmovana(const TMask& msk, TRectype& da_rmovana, TRectype& a_rmovana, TString& filtro)
|
||
{
|
||
int cur_key = 4;
|
||
//intanto sistema darec arec
|
||
da_rmovana.put(RMOVANA_CODCMS, _codcms);
|
||
da_rmovana.put(RMOVANA_CODCCOSTO, _codcosto);
|
||
a_rmovana = da_rmovana;
|
||
|
||
//se c'<27> solo cdc deve cambiare la chiave..
|
||
if (_codcms.blank() && _codcosto.full())
|
||
cur_key = 5;
|
||
|
||
//adesso tocca al filtro
|
||
//conti
|
||
if (!_riclassificato && (_daconto.full() || _aconto.full()))
|
||
{
|
||
if (_daconto == _aconto)
|
||
filtro << "(CODCONTO[1," << _daconto.len() << "]==\"" << _daconto << "\")";
|
||
else
|
||
filtro << "BETWEEN(CODCONTO,\"" << _daconto << "\",\"" << _aconto << "~\")";
|
||
}
|
||
|
||
//date
|
||
if (!_vitaintera)
|
||
{
|
||
TDate dal, al;
|
||
calcola_date_da_maschera(msk, dal, al);
|
||
|
||
if (filtro.not_empty())
|
||
filtro << "&&";
|
||
filtro << "(BETWEEN(DATACOMP," << dal.date2ansi() << ',' << al.date2ansi() << "))";
|
||
}
|
||
|
||
//fase
|
||
if (_codfas.not_empty())
|
||
{
|
||
if (filtro.not_empty())
|
||
filtro << "&&";
|
||
filtro << "(" << RMOVANA_CODFASE << "==\"" << _codfas << "\")";
|
||
}
|
||
|
||
return cur_key;
|
||
}
|
||
|
||
//scanning delle righe dei movimenti di analitica
|
||
void TPrint_rendiconto_ca_recordset::crea_righe_da_rmovana(TLocalisamfile& tmp, const TPrint_rendiconto_ca_mask& msk,
|
||
TLog_report& log)
|
||
{
|
||
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);
|
||
TString filtro;
|
||
|
||
//nuovo metodo di filtraggio (chiave 4 o 5)
|
||
int cur_key = crea_filtro_rmovana(msk, da_rmovana, a_rmovana, filtro);
|
||
|
||
TCursor cur_rmovana(&rel_rmovana, filtro, cur_key, &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);
|
||
#ifdef DBG
|
||
if (numreg == 32736)
|
||
const int cazzissimo = 1;
|
||
#endif
|
||
//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(tmp, righe_compattate.row(i), old_movana, NULL, log);
|
||
}
|
||
//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(tmp, rmovana, movana, NULL, log);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//fatta su chiave 6 e 7 di lf_rdoc; non controlla le date, ammettendo movimenti non rientranti nell'intervallo di..
|
||
//..date scelto dalla maschera, purch<63> tali movimenti appartengano a commessa/cdc in esame
|
||
int TPrint_rendiconto_ca_recordset::crea_filtro_rdoc(const TMask& msk, TRectype& da_rdoc, TRectype& a_rdoc, TString& filtro_date)
|
||
{
|
||
int cur_key = 6;
|
||
//intanto sistema darec arec
|
||
da_rdoc.put(RDOC_CODCMS, _codcms);
|
||
da_rdoc.put(RDOC_CODCOSTO, _codcosto);
|
||
a_rdoc = da_rdoc;
|
||
|
||
//se c'<27> solo cdc..
|
||
if (_codcms.blank() && _codcosto.full())
|
||
cur_key = 7;
|
||
|
||
//filtro date
|
||
if (!_vitaintera)
|
||
{
|
||
TDate dal, al;
|
||
calcola_date_da_maschera(msk, dal, al);
|
||
|
||
if (filtro_date.not_empty())
|
||
filtro_date << "&&";
|
||
filtro_date << "(BETWEEN(33->DATADOC," << dal.date2ansi() << ',' << al.date2ansi() << "))";
|
||
}
|
||
return cur_key;
|
||
}
|
||
|
||
//scanning delle righe dei documenti
|
||
void TPrint_rendiconto_ca_recordset::crea_righe_da_rdoc(TLocalisamfile& tmp, const TPrint_rendiconto_ca_mask& msk,
|
||
TLog_report& log)
|
||
{
|
||
TRelation rel_rdoc(LF_RIGHEDOC);
|
||
rel_rdoc.add(LF_DOC, "CODNUM==CODNUM|ANNO==ANNO|PROVV==PROVV|NDOC==NDOC"); //aggiunge le testate
|
||
|
||
TRectype da_rdoc(LF_RIGHEDOC);
|
||
TRectype a_rdoc(LF_RIGHEDOC);
|
||
TString filtro_date;
|
||
|
||
//metodo moderno
|
||
const int cur_key = crea_filtro_rdoc(msk, da_rdoc, a_rdoc, filtro_date);
|
||
|
||
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;
|
||
|
||
|
||
//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;
|
||
TConfig& config = ca_config();
|
||
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 (cur_key == 3) //questo solo se si usa la chiave 3 (metodo restrittivo antico)
|
||
{
|
||
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()) //questo in ogni modo, anche con chiave 6 o 7 (oltre che 3)
|
||
{
|
||
if (filtro.not_empty())
|
||
filtro << "&&";
|
||
filtro << "(" << RDOC_FASCMS << "==\"" << _codfas << "\")";
|
||
}
|
||
|
||
//il filtro <20> completo;pu<70> eseguire la scansione
|
||
TCursor cur_rdoc(&rel_rdoc, "", cur_key, &da_rdoc, &a_rdoc);
|
||
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)
|
||
{
|
||
if (!pi.addstatus(1))
|
||
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);
|
||
#ifdef DBG
|
||
if (rdoc_dacodnum == "FDE" && curr_rdoc.get_int(RDOC_ANNO) == 2011 && curr_rdoc.get_int(RDOC_NDOC) == 3)
|
||
const int culone = 1;
|
||
#endif
|
||
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, false);
|
||
|
||
//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(tmp, rmov, mov, &doc, log); //documenti "normali"
|
||
} //for int j...
|
||
}
|
||
else
|
||
{
|
||
//righe di documento configurate come da emettere/ricevere (documenti speciali)
|
||
scrive_riga_speciale(tmp, &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 << 22 << 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 << "CODCMS|1|20|0|Codice commessa" << endl;
|
||
of << "CODCOSTO|1|20|0|Codice centro di costo" << endl;
|
||
of << "CODFASE|1|20|0|Codice fase (eventualmente legato a CODCMS)" << 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|1|50|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 << 3 << endl;
|
||
of << "ORDCONT+CONTO+DATA+CODNUM+NUMRD+NUMREG+NRIGA" << endl;
|
||
of << "CODCMS+ORDCONT+CONTO+DATA+CODNUM+NUMRD+NUMREG+NRIGA|X" << endl;
|
||
of << "CODCOSTO+ORDCONT+CONTO+DATA+CODNUM+NUMRD+NUMREG+NRIGA|X" << endl;
|
||
}
|
||
|
||
void TPrint_rendiconto_ca_recordset::set_filter(const TPrint_rendiconto_ca_mask& msk, int cms_row, TLog_report& log)
|
||
{
|
||
//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);
|
||
|
||
//crea in memoria il nuovo file temporaneo e lo azzera (non si sa mai..)
|
||
TExternisamfile tmp(dbf, trr, true);
|
||
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.full())
|
||
_prefix << pr;
|
||
else
|
||
break;
|
||
}
|
||
_ricl.set_prefix(_prefix);
|
||
}
|
||
|
||
//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? oppure si va a vita intera?
|
||
_dadata = msk.get_date(F_DATAINI);
|
||
_adata = msk.get_date(F_DATAFIN);
|
||
_vitaintera = msk.get_bool(F_VITAINTERA);
|
||
|
||
//metodi per riempire il file da cui generare il report
|
||
//dati estratti dalle righe movimenti di contabilita' analitica
|
||
crea_righe_da_rmovana(tmp, msk, log);
|
||
//dati estratti dalle righe documenti
|
||
crea_righe_da_rdoc(tmp, msk, log);
|
||
|
||
}
|
||
|
||
////////////////////////////////////////////////////////
|
||
// 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, const int recset_key, TLog_report& log);
|
||
};
|
||
|
||
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, const int recset_key, TLog_report& log)
|
||
{
|
||
TAnal_report::set_recordset(NULL); // Forza azzeramento file Rendy.dbf prima di ricostruirlo
|
||
|
||
TString query ="USE RENDY.DBF";
|
||
query << " KEY " << recset_key << "\n";
|
||
query << "JOIN 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, log);
|
||
TAnal_report::set_recordset(recset);
|
||
}
|
||
|
||
////////////////////////////////////////////////////////
|
||
// APPLICAZIONE
|
||
////////////////////////////////////////////////////////
|
||
class TPrint_rendiconto_ca : public TSkeleton_application
|
||
{
|
||
TPrint_rendiconto_ca_mask* _msk;
|
||
|
||
protected:
|
||
virtual void print();
|
||
void esporta_csv_row(ostream& file_to_date, const int first_level, const TString& cod_cms_cdc,
|
||
const real importi[5][4], real importi_totali[5][4]);
|
||
void esporta_csv(TPrint_rendiconto_ca_recordset& rendy, const int r);
|
||
void incrementa(TToken_string& riga, const int col, const real& valore) const;
|
||
|
||
public:
|
||
const TMultilevel_code_info& get_first_level() const;
|
||
virtual void main_loop();
|
||
};
|
||
|
||
void TPrint_rendiconto_ca::print()
|
||
{
|
||
if (_msk != NULL)
|
||
_msk->send_key(K_SPACE, DLG_PRINT);
|
||
}
|
||
|
||
void TPrint_rendiconto_ca::incrementa(TToken_string& riga, const int col, const real& valore) const
|
||
{
|
||
real r; riga.get(col, r);
|
||
r += valore;
|
||
riga.add(r.string(), col);
|
||
}
|
||
|
||
void TPrint_rendiconto_ca::esporta_csv_row(ostream& file_to_date, const int first_level, const TString& cod_cms_cdc,
|
||
const real importi[5][4], real importi_totali[5][4])
|
||
{
|
||
const int posizione_importi = first_level == LF_COMMESSE ? 5 : 2;
|
||
//crea una token string su cui mettere i valori dei record letti dal file .dbf
|
||
TToken_string riga(512, '\t');
|
||
|
||
riga.add(cod_cms_cdc);
|
||
//decodifica della commessa/cdc (non <20> ammessa una commessa "TOTALI" che lo incasina
|
||
if (cod_cms_cdc != "TOTALI")
|
||
{
|
||
const TRectype& rec = cache().get(first_level, cod_cms_cdc);
|
||
const TString& descrizione = rec.get("DESCRIZ");
|
||
riga.add(descrizione);
|
||
if (first_level == LF_COMMESSE)
|
||
{
|
||
riga.add(rec.get(COMMESSE_DATAINIZIO));
|
||
riga.add(rec.get(COMMESSE_DATAFINE));
|
||
riga.add(rec.get(COMMESSE_DATAPROR));
|
||
}
|
||
}
|
||
|
||
//in base al valore di indbil e budget i valori degli importi vengono posizionati nel record
|
||
for (int indbil = 1; indbil <= 4; indbil++)
|
||
{
|
||
int col = 0;
|
||
switch (indbil)
|
||
{
|
||
case 1: col = posizione_importi + 14; break; //attivit<69>
|
||
case 2: col = posizione_importi + 21; break; //passivit<69>
|
||
case 3: col = posizione_importi; break; //costi
|
||
case 4: col = posizione_importi + 7; break; //ricavi
|
||
default: break;
|
||
}
|
||
|
||
//colonne budget/impegnato/maturato/fatturato
|
||
for (int j = 0; j < 4; j++)
|
||
{
|
||
riga.add(importi[indbil][j].string(), col + j);
|
||
importi_totali[indbil][j] += importi[indbil][j];
|
||
}
|
||
|
||
//colonne da_impegnare/da_maturare/da_fatturare
|
||
const real da_impegnare = importi[indbil][0] - importi[indbil][1];
|
||
riga.add(da_impegnare.string(), col + 4);
|
||
|
||
const real da_maturare = importi[indbil][1] - importi[indbil][2];
|
||
riga.add(da_maturare.string(), col + 5);
|
||
|
||
const real da_fatturare = importi[indbil][1] - importi[indbil][3];
|
||
riga.add(da_fatturare.string(), col + 6);
|
||
}
|
||
//scrive in excel mode
|
||
for (int i = posizione_importi; i < posizione_importi + 28; i++)
|
||
{
|
||
const real r = riga.get(i);
|
||
if (!r.is_zero())
|
||
{
|
||
TString80 str;
|
||
str << r;
|
||
str.replace('.', ',');
|
||
riga.add(str, i);
|
||
}
|
||
}
|
||
|
||
//aggiunge la riga al file da esportare
|
||
file_to_date << riga << endl;
|
||
}
|
||
|
||
//metodo di alto livello per l'esportazione dei dati di totale in un file per excel
|
||
void TPrint_rendiconto_ca::esporta_csv(TPrint_rendiconto_ca_recordset& rendy, const int r)
|
||
{
|
||
//primo livello di configurazione
|
||
const int first_level = get_first_level().logic();
|
||
//piano dei conti riclassificato?
|
||
TConfig& cfg = ca_config();
|
||
const bool riclassificato = cfg.get_bool("UsePdcc");
|
||
|
||
//aggiorna il file da esportare appendendo la nuova riga
|
||
TFilename path = _msk->get(F_PATH);
|
||
path.lower();
|
||
path.add("rendiconto.xls");
|
||
ofstream file_to_date(path, ios::app);
|
||
|
||
const bool invert_cosric = _msk->get_bool(F_REV_COSRIC);
|
||
|
||
//array bidimensionale con gli importi per indbil e colonna
|
||
real importi[5][4];
|
||
//array bidimensionale con gli importi totali finali
|
||
real importi_totali[5][4];
|
||
TString80 last_codice, curr_codice;
|
||
|
||
TSheet_field& sf = _msk->sfield(F_RIGHE);
|
||
TString80 codcms, codcdc, codfas;
|
||
if (first_level == LF_CDC)
|
||
{
|
||
ca_extract_sheet_field(sf, r, LF_COMMESSE, codcms);
|
||
ca_extract_sheet_field(sf, r, LF_FASI, codfas);
|
||
}
|
||
else
|
||
{
|
||
ca_extract_sheet_field(sf, r, LF_CDC, codcdc);
|
||
ca_extract_sheet_field(sf, r, LF_FASI, codfas);
|
||
}
|
||
|
||
//recordset sul file rendy.dbf, da scandire tutto un record per volta
|
||
rendy.requery();
|
||
for (bool ok = rendy.move_first(); ok; ok = rendy.move_next())
|
||
{
|
||
curr_codice = rendy.get(first_level == LF_COMMESSE ? "CODCMS" : "CODCOSTO").as_string();
|
||
|
||
//operazioni da fare al cambio commessa/cdc (codice primo livello)
|
||
if (curr_codice != last_codice)
|
||
{
|
||
//SCRIVE UNA RIGA SUL FILE DA ESPORTARE
|
||
//lo schema <20> questo: budget\impegnato\maturato\fatturato\da impegnare\da maturare\da fatturare
|
||
//controlla se last_codice sia pieno per non aggiungere una inutile riga di zeri all'inizio
|
||
if (last_codice.full())
|
||
esporta_csv_row(file_to_date, first_level, last_codice, importi, importi_totali);
|
||
|
||
memset(importi, 0, sizeof(importi)); //Allah! Azzeratore dell'array con i totali per commessa (o cdc)
|
||
last_codice = curr_codice; //memorizza il cambio codice (cms/cdc)
|
||
|
||
//calcolatore dei saldi: va fatta attraverso i saldi!!! perch<63> i budget sono multianno
|
||
TImporto att, pas, ric, cos;
|
||
if (first_level == LF_CDC)
|
||
rendy.get_budget_export(curr_codice, codcms, codfas, att, pas, cos, ric);
|
||
else
|
||
rendy.get_budget_export(codcdc, curr_codice, codfas, att, pas, cos, ric);
|
||
|
||
//aggiunge i valori dei saldi all'array con gli importi; li mette nella colonna [0] che <20> quella dei budget..
|
||
//..e nella riga corrispondente all'indicatore bilancio
|
||
importi[1][0] = pas.valore();
|
||
importi[2][0] = att.valore();
|
||
importi[3][0] = cos.valore();
|
||
importi[4][0] = ric.valore();
|
||
}
|
||
|
||
//aggiorna tutti gli altri valori dell'array degli importi che non siano budget (cosa che fa solo a cambio codice)..
|
||
//..come si vede sopra
|
||
const bool hidden = rendy.get("HIDDEN").as_bool();
|
||
if (!hidden)
|
||
{
|
||
const real impegnato = rendy.get("IMPEGNATO").as_real();
|
||
const real fatturato = rendy.get("FATTURATO").as_real();
|
||
const real maturato = rendy.get("MATURATO").as_real();
|
||
|
||
//occhio all'inversione ricavi/costi, che causa il ribaltamento del significato di ordcont
|
||
int indbil = rendy.get("ORDCONT").as_int();
|
||
if (invert_cosric && (indbil == 3 || indbil == 4))
|
||
indbil = 7 - indbil;
|
||
|
||
//aggiornamento degli importi non budget di commessa/cdc
|
||
importi[indbil][1] += impegnato;
|
||
importi[indbil][2] += maturato;
|
||
importi[indbil][3] += fatturato;
|
||
}
|
||
|
||
} //for (bool ok = rendy.move_first()...
|
||
|
||
//gestione speciale dell'ultima riga
|
||
if (last_codice.full())
|
||
{
|
||
//SCRIVE L'ULTIMA RIGA RELATIVA A CMS/CDC SUL FILE DA ESPORTARE
|
||
esporta_csv_row(file_to_date, first_level, last_codice, importi, importi_totali);
|
||
|
||
//AGGIUNGE L'EVENTUALE RIGA DEI TOTALI
|
||
TToken_string str_tot = _msk->sfield(F_RIGHE).row(r);
|
||
//la riga con i totali ci va solo se non <20> stato specificato il primo livello (es. commessa o cdc)
|
||
const TFixed_string first_field = str_tot.get(0);
|
||
if (first_field.blank())
|
||
{
|
||
str_tot.replace('|', ' ');
|
||
str_tot.strip_double_spaces();
|
||
str_tot.insert("TOTALI\t");
|
||
//riga con gli importi totali;per ottenerla basta chiamare la esporta_csv_row con gli array invertiti, in modo che..
|
||
//..venga aggiornato l'array degli importi_totali; l'altro verr<72> sputtanato ma chi se ne frega! <20> gi<67> stato..
|
||
//..esportato qualche riga sopra
|
||
esporta_csv_row(file_to_date, first_level, str_tot, importi_totali, importi);
|
||
//doppia riga vuota di stacco
|
||
file_to_date << endl << endl;
|
||
}
|
||
} //if(last_codice.full())
|
||
|
||
}
|
||
|
||
//metodo per accattarsi o' primo livello della configurazione CA
|
||
const TMultilevel_code_info& TPrint_rendiconto_ca::get_first_level() const
|
||
{
|
||
const TString& first_lev = ca_config().get("Level", "ca", 1);
|
||
const int logic = first_lev == "CDC" ? LF_CDC : LF_COMMESSE;
|
||
return ca_multilevel_code_info(logic);
|
||
}
|
||
|
||
void TPrint_rendiconto_ca::main_loop()
|
||
{
|
||
_msk = new TPrint_rendiconto_ca_mask;
|
||
TPrint_rendiconto_ca_mask& mask = *_msk;
|
||
const int first_level = get_first_level().logic(); //primo livello nella configurazione CA
|
||
|
||
while (true)
|
||
{
|
||
//il programma deve cominciare l'eleaborazione solo nel caso di Stampa/Anteprima (K_ENTER) o Esportazione CSV (K_F6)
|
||
KEY key = mask.run();
|
||
if (key == K_QUIT)
|
||
break;
|
||
|
||
//chiave di ordinamento del recordset; di base <20> 1 (utilizzato per la stampa); va lasciata qui per essere resettata..
|
||
//..ad ogni giro, in modo da sistemarsi quando si passa da esportazione a stampa e viceversa!
|
||
int recset_key = 1;
|
||
|
||
//resetta e prepara le intestazioni del file rendiconto.xls
|
||
if (key == K_F6)
|
||
{
|
||
TFilename file_xls = mask.get(F_PATH);
|
||
file_xls.lower();
|
||
file_xls.add("rendiconto.xls");
|
||
ofstream file_to_date(file_xls);
|
||
|
||
const int posizione_importi = first_level == LF_COMMESSE ? 5 : 2;
|
||
|
||
//intestazione primaria
|
||
TToken_string intestazione_1(512, '\t');
|
||
//l'intestazione primaria dipende anche dalla configurazione dei livelli!
|
||
if (first_level == LF_COMMESSE) //commessa-cdc
|
||
{
|
||
intestazione_1.add("Commessa");
|
||
intestazione_1.add("Descr. commessa");
|
||
intestazione_1.add("Data inizio");
|
||
intestazione_1.add("Data fine");
|
||
intestazione_1.add("Data proroga");
|
||
recset_key = 2; //chiave del recordset per commessa
|
||
}
|
||
else //cdc-commessa
|
||
{
|
||
intestazione_1.add("C.d.C.");
|
||
intestazione_1.add("Descr. cdc");
|
||
recset_key = 3; //chiave del recordset per centro di costo
|
||
}
|
||
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
switch (i)
|
||
{
|
||
case 0: intestazione_1.add("Costi"); break;
|
||
case 1: intestazione_1.add("Ricavi"); break;
|
||
case 2: intestazione_1.add("Attivit<EFBFBD>"); break;
|
||
case 3: intestazione_1.add("Passivit<EFBFBD>"); break;
|
||
}
|
||
for (int j = 0; j < 6; j++)
|
||
intestazione_1.add("");
|
||
}
|
||
file_to_date << intestazione_1 << endl;
|
||
|
||
//intestazione secondaria
|
||
TToken_string intestazione_2(512, '\t');
|
||
//campi descrittivi iniziali vuoti (solo intestazione_1)
|
||
intestazione_2.add(" ", posizione_importi - 1);
|
||
|
||
for (int l = 0; l < 4; l++)
|
||
{
|
||
for (int n = 0; n < 7; n++)
|
||
{
|
||
switch (n)
|
||
{
|
||
case 0: intestazione_2.add("Budget"); break;
|
||
case 1: intestazione_2.add("Impegnato"); break;
|
||
case 2: intestazione_2.add("Maturato"); break;
|
||
case 3: intestazione_2.add("Fatturato"); break;
|
||
case 4: intestazione_2.add("Da impegnare"); break;
|
||
case 5: intestazione_2.add("Da maturare"); break;
|
||
case 6: intestazione_2.add("Da fatturare"); break;
|
||
}
|
||
}
|
||
}
|
||
file_to_date << intestazione_2 << endl;
|
||
} //if(key==K_F6)
|
||
|
||
//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);
|
||
|
||
//log report con segnalazioni su errori (tipo conti inesistenti o robaccia simile..)
|
||
TLog_report log(TR("Errori rilevati"));
|
||
log.kill_duplicates();
|
||
|
||
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
|
||
|
||
//si amplia il range di ricerca temporale di 1 anno nel passato perch<63> i movana..
|
||
//..preventivi possono essere stati decisi prima dell'inizio effettivo commessa
|
||
TDate dataini, datafin;
|
||
const int anno = mask.get_int(F_ANNO);
|
||
if (anno > 0) //se non <20> stata specificata alcuna dataini, ma <20> stato specificato un anno di esercizio...
|
||
{
|
||
TEsercizi_contabili esc;
|
||
esc.code2range(anno, dataini, datafin);
|
||
}
|
||
if (!mask.field(F_DATAINI).empty())
|
||
dataini = mask.get_date(F_DATAINI);
|
||
if (!mask.field(F_DATAFIN).empty())
|
||
datafin = mask.get_date(F_DATAFIN);
|
||
|
||
const TMultilevel_code_info& liv1 = get_first_level(); //stabilisce quale <20> il primo livello (tra CDC e CMS)..
|
||
const bool is_cms = liv1.logic() == LF_COMMESSE;
|
||
TISAM_recordset set(is_cms ? "USE COMMESSE" : "USE CDC"); //..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!
|
||
{
|
||
if (!pi.addstatus(1))
|
||
break;
|
||
|
||
//Filtro sulle date
|
||
//DATE VALIDE STRETTAMENTE PER COMMESSE
|
||
//per prima cosa controlla se veramente la commessa rientri nei parametri temporali impostati sulla maschera
|
||
//Se infatti <20> completamente al di fuori di tale intervallo, che cavolo la controlla a fare
|
||
row = set.get((unsigned int)0).as_string(); //prende il valore del primo campo del file (CDC o CMS code)
|
||
|
||
if (is_cms && (dataini.ok() || datafin.ok()))
|
||
{
|
||
const TRectype& rec_commesse = set.cursor()->curr();
|
||
TDate datainicms, datafcomp;
|
||
ca_durata_commessa(rec_commesse, datainicms, datafcomp);
|
||
if ((dataini.ok() && datafcomp < dataini) || (datafin.ok() && datainicms > datafin))
|
||
continue;
|
||
}
|
||
|
||
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, recset_key, log); //fa la set filter sulla prima riga (che <20> quella usata)
|
||
|
||
//se stampa o anteprima..
|
||
if (key == K_F6)
|
||
esporta_csv((TPrint_rendiconto_ca_recordset&)*rep.recordset(), 0); //esportazione in excel
|
||
else
|
||
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, recset_key, log); //..chiama il metodone globale che crea e compila il file..
|
||
//..temporaneo i cui dati riempiranno il report
|
||
//se stampa o anteprima
|
||
if (key == K_F6) //esportazione in excel
|
||
esporta_csv((TPrint_rendiconto_ca_recordset&)*rep.recordset(), r); //il recordset <20> del tipo TPrint_rendiconto
|
||
else
|
||
book.add(rep); //aggiunge il report relativo alla cdc/cms corrente al book
|
||
}
|
||
}
|
||
//anteprima report degli errori rilevati
|
||
if (log.recordset()->items() > 0)
|
||
log.preview();
|
||
|
||
if (key == K_ENTER)
|
||
book.print(); //stampa il book dei report
|
||
else
|
||
book.preview(); //anteprima del book dei report
|
||
|
||
} //while(true)...
|
||
|
||
delete _msk;
|
||
_msk = NULL;
|
||
}
|
||
|
||
int ca3700(int argc, char* argv[])
|
||
{
|
||
TPrint_rendiconto_ca a;
|
||
a.run(argc, argv, TR("Stampa rendiconto"));
|
||
return 0;
|
||
}
|