Files correlati : Ricompilazione Demo : [ ] Commento : Aggiunto recordset per gestire "trasparentemente" i piani dei conti contabile o analitico. Potenziato calcolo saldi per gestire anche i livelli intermedi dei conti e soprattutto gestire la riclassificazione dei conti analitici tramite la tabella panapdc Potenziato il generatore di movimenti casuale per gestire anche il piano dei conti contabile nonche' la generazione automatica della tabela panapdc. git-svn-id: svn://10.65.10.50/trunk@13265 c028cbd2-c16b-5b4b-a496-9718f37d4682
845 lines
22 KiB
C++
Executable File
845 lines
22 KiB
C++
Executable File
#include <xvt.h>
|
|
|
|
#include "calib01.h"
|
|
#include "calib02.h"
|
|
|
|
#include "../cg/cglib01.h"
|
|
|
|
#include <rdoc.h>
|
|
#include <pconti.h>
|
|
|
|
#include "movana.h"
|
|
#include "pconana.h"
|
|
#include "rmovana.h"
|
|
#include "saldana.h"
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TPconana_recordset
|
|
///////////////////////////////////////////////////////////
|
|
|
|
const TVariant& TPconana_recordset::get(const char* field) const
|
|
{
|
|
const TFixed_string column_name(field);
|
|
if (*column_name == '#')
|
|
{
|
|
if (strcmp(column_name, "#CMSCDC") == 0)
|
|
{
|
|
const TMultilevel_code_info& info = ca_multilevel_code_info(LF_FASI);
|
|
switch (info.parent())
|
|
{
|
|
case LF_CDC : return get_tmp_var() = _bill.costo();
|
|
case LF_COMMESSE: return get_tmp_var() = _bill.commessa();
|
|
default : return NULL_VARIANT;
|
|
}
|
|
}
|
|
if (strcmp(column_name, "#COSTO") == 0)
|
|
return get_tmp_var() = _bill.costo();
|
|
if (strcmp(column_name, "#COMMESSA") == 0)
|
|
return get_tmp_var() = _bill.commessa();
|
|
if (strcmp(column_name, "#FASE") == 0)
|
|
return get_tmp_var() = _bill.fase();
|
|
}
|
|
else
|
|
{
|
|
if (column_name.compare(PCONANA_CODCONTO, 8) == 0)
|
|
{
|
|
TString80 str;
|
|
if (_tipo == 'C')
|
|
{
|
|
const TBill b(relation()->curr());
|
|
str = b.string(0x8);
|
|
}
|
|
else
|
|
str = TISAM_recordset::get(PCONANA_CODCONTO).as_string();
|
|
|
|
if (column_name[8] == ':')
|
|
{
|
|
const TMultilevel_code_info& info = ca_multilevel_code_info(_tipo == 'C' ? LF_PCON : LF_PCONANA);
|
|
const int level = column_name[9] - '1';
|
|
str.cut(info.total_len(level));
|
|
}
|
|
return get_tmp_var() = str;
|
|
}
|
|
if (column_name.compare(PCONANA_DESCR, 5) == 0)
|
|
{
|
|
TString80 str;
|
|
if (_tipo == 'C')
|
|
{
|
|
TBill b(relation()->curr());
|
|
if (column_name[5] == ':')
|
|
{
|
|
if (column_name[6] == '1')
|
|
b.set(b.gruppo(), 0, 0); else
|
|
if (column_name[6] == '2')
|
|
b.set(b.gruppo(), b.conto(), 0);
|
|
}
|
|
str = b.descrizione();
|
|
}
|
|
else
|
|
{
|
|
if (column_name[5] == ':')
|
|
{
|
|
const TMultilevel_code_info& info = ca_multilevel_code_info(LF_PCONANA);
|
|
const int level = column_name[6] - '1';
|
|
str = TISAM_recordset::get(PCONANA_CODCONTO).as_string();
|
|
str.cut(info.total_len(level));
|
|
str = cache().get(LF_PCONANA, str, PCONANA_DESCR);
|
|
}
|
|
else
|
|
str = TISAM_recordset::get(PCONANA_DESCR).as_string();
|
|
}
|
|
return get_tmp_var() = str;
|
|
}
|
|
|
|
if (column_name.compare("SALDO:", 6) == 0)
|
|
{
|
|
TString16 sub_field = column_name+6;
|
|
const char last = sub_field.right(1)[0];
|
|
int tipimov = 0;
|
|
switch (last)
|
|
{
|
|
case 'C': tipimov = _saldanal_consuntivo; sub_field.rtrim(1); break; // Consuntivo
|
|
case 'P':
|
|
case 'V': tipimov = _saldanal_preventivi; sub_field.rtrim(1); break; // Preventivo o variazione preventivo
|
|
default : tipimov = _tipimov; break;
|
|
}
|
|
|
|
((TAnal_bill&)_bill).set_conto(get(PCONANA_CODCONTO).as_string());
|
|
const TSaldanal& s = ca_saldo(_bill, _dal, _al, tipimov);
|
|
|
|
TVariant& var = get_tmp_var();
|
|
if (strcmp(sub_field, "INI_DARE") == 0)
|
|
{
|
|
var = s._ini.sezione() == 'D' ? s._ini.valore() : ZERO;
|
|
} else
|
|
if (strcmp(sub_field, "INI_AVERE") == 0)
|
|
{
|
|
var = s._ini.sezione() == 'A' ? s._ini.valore() : ZERO;
|
|
} else
|
|
if (strcmp(sub_field, "MOV_DARE") == 0)
|
|
{
|
|
var = s._dare.valore();
|
|
} else
|
|
if (strcmp(sub_field, "MOV_AVERE") == 0)
|
|
{
|
|
var = s._avere.valore();
|
|
} else
|
|
if (strcmp(sub_field, "FIN_DARE") == 0)
|
|
{
|
|
var = s._fin.sezione() == 'D' ? s._fin.valore() : ZERO;
|
|
} else
|
|
if (strcmp(sub_field, "FIN_AVERE") == 0)
|
|
{
|
|
var = s._fin.sezione() == 'A' ? s._fin.valore() : ZERO;
|
|
}
|
|
return var;
|
|
}
|
|
}
|
|
return TISAM_recordset::get(column_name);
|
|
}
|
|
|
|
bool TPconana_recordset::valid_record(const TRelation& rel) const
|
|
{
|
|
TString80 conto;
|
|
if (_tipo == 'C')
|
|
{
|
|
const TBill b(rel.curr());
|
|
if (b.sottoconto() <= 0 || !b.is_analitico())
|
|
return false;
|
|
conto = b.string(0x8);
|
|
}
|
|
else
|
|
{
|
|
conto = rel.curr().get(PCONANA_CODCONTO);
|
|
if (conto.len() <= _conto_minlen)
|
|
return false;
|
|
}
|
|
|
|
if (_movimentati || _nonnulli)
|
|
{
|
|
((TAnal_bill&)_bill).set_conto(conto);
|
|
const TSaldanal& s = ca_saldo(_bill, _dal, _al, _tipimov);
|
|
if (_movimentati && !s._movimentato)
|
|
return false;
|
|
if (_nonnulli && s._fin.is_zero())
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static const TPconana_recordset* _current_recset = NULL;
|
|
|
|
bool TPconana_recordset::pianoconti_filter(const TRelation* rel)
|
|
{ return _current_recset->valid_record(*rel); }
|
|
|
|
void TPconana_recordset::set_custom_filter(TCursor& cursor) const
|
|
{
|
|
if (_tipo == 'C')
|
|
{
|
|
TRectype darec(LF_PCON), arec(LF_PCON);
|
|
darec.put(PCN_GRUPPO, _da_conto.mid(0,3));
|
|
darec.put(PCN_CONTO, _da_conto.mid(3,3));
|
|
darec.put(PCN_SOTTOCONTO, _da_conto.mid(6,6));
|
|
arec.put(PCN_GRUPPO, _a_conto.mid(0,3));
|
|
arec.put(PCN_CONTO, _a_conto.mid(3,3));
|
|
arec.put(PCN_SOTTOCONTO, _a_conto.mid(6,6));
|
|
cursor.setregion(darec, arec);
|
|
}
|
|
else
|
|
{
|
|
TRectype darec(LF_PCONANA), arec(LF_PCONANA);
|
|
darec.put(PCONANA_CODCONTO, _da_conto);
|
|
arec.put(PCONANA_CODCONTO, _a_conto);
|
|
cursor.setregion(darec, arec);
|
|
}
|
|
|
|
_current_recset = this;
|
|
cursor.set_filterfunction(pianoconti_filter);
|
|
}
|
|
|
|
void TPconana_recordset::set_tipo(char tipo)
|
|
{
|
|
if (tipo != 'A' && tipo != 'C')
|
|
{
|
|
TConfig_anal cfg;
|
|
tipo = cfg.get_bool("UsePdcc") ? 'C' : 'A';
|
|
}
|
|
_tipo = tipo;
|
|
|
|
if (_tipo == 'A')
|
|
{
|
|
set("USE PCONANA");
|
|
const TMultilevel_code_info& info = ca_multilevel_code_info(LF_PCONANA);
|
|
_conto_minlen = info.total_len(-1); // Lunghezza fino al penultimo livello
|
|
}
|
|
else
|
|
{
|
|
set("USE PCON");
|
|
_conto_minlen = 6; // Gruppo(3)+Conto(3)
|
|
}
|
|
}
|
|
|
|
void TPconana_recordset::set_filter(char tipo, const char* da_conto, const char* a_conto,
|
|
const char* costo, const char* commessa, const char* fase,
|
|
const TDate& dal, const TDate& al,
|
|
word tipimov, bool movimentati, bool nonnulli)
|
|
{
|
|
set_tipo(tipo);
|
|
|
|
_da_conto = da_conto;
|
|
_a_conto = a_conto;
|
|
|
|
_dal = dal;
|
|
_al = al;
|
|
|
|
_tipimov= tipimov;
|
|
_movimentati = movimentati;
|
|
_nonnulli = nonnulli;
|
|
|
|
_bill.reset();
|
|
_bill.set_costo(costo);
|
|
_bill.set_commessa(commessa);
|
|
_bill.set_fase(fase);
|
|
}
|
|
|
|
TPconana_recordset::TPconana_recordset(char tipo) : TISAM_recordset("USE PCONANA")
|
|
{
|
|
set_tipo(tipo);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TAnal_report
|
|
///////////////////////////////////////////////////////////
|
|
|
|
size_t TAnal_report::get_usr_words(TString_array& words) const
|
|
{
|
|
TReport::get_usr_words(words);
|
|
|
|
const char* const name[] =
|
|
{
|
|
"CA_FORMAT_COSTO",
|
|
"CA_FORMAT_COMMESSA",
|
|
"CA_FORMAT_FASE",
|
|
"CA_FORMAT_CONTO",
|
|
"CA_FORMAT_CMSCDC",
|
|
NULL
|
|
};
|
|
|
|
((TAnal_report*)this)->_first_msg = words.items(); // Calcola il primo numero disponibile
|
|
size_t i;
|
|
for (i = 0; name[i] != NULL; i++)
|
|
words.add(name[i]);
|
|
|
|
return words.items();
|
|
}
|
|
|
|
void TAnal_report::msg_format(int logicnum, TVariant_stack& stack)
|
|
{
|
|
const TString& str_in = curr_field()->get().as_string();
|
|
if (str_in.not_empty())
|
|
{
|
|
TString80 separator = " ";
|
|
if (stack.items() > 0)
|
|
separator = stack.pop().as_string();
|
|
if (separator.not_empty())
|
|
{
|
|
const TMultilevel_code_info& mci = ca_multilevel_code_info(logicnum);
|
|
TString80 str_out = str_in;
|
|
for (int i = mci.levels()-2; i >= 0; i--)
|
|
str_out.insert(separator, mci.total_len(i));
|
|
curr_field()->set(str_out);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TAnal_report::msg_format_costo (TVariant_stack& stack)
|
|
{ msg_format(LF_CDC, stack); }
|
|
|
|
void TAnal_report::msg_format_commessa(TVariant_stack& stack)
|
|
{ msg_format(LF_COMMESSE, stack); }
|
|
|
|
void TAnal_report::msg_format_fase (TVariant_stack& stack)
|
|
{ msg_format(LF_FASI, stack); }
|
|
|
|
void TAnal_report::msg_format_conto (TVariant_stack& stack)
|
|
{
|
|
// Cerca di determinare se si usa il piano contabile o analitico
|
|
const TFixed_string gruppo(PCN_GRUPPO);
|
|
TVariant var;
|
|
get_record_field(gruppo, var);
|
|
if (var.is_null())
|
|
msg_format(LF_PCONANA, stack);
|
|
else
|
|
msg_format(LF_PCON, stack);
|
|
}
|
|
|
|
void TAnal_report::msg_format_commessa_costo(TVariant_stack& stack)
|
|
{
|
|
const TMultilevel_code_info& main_info = ca_multilevel_code_info(LF_FASI);
|
|
msg_format(main_info.parent(), stack);
|
|
}
|
|
|
|
bool TAnal_report::execute_usr_word(unsigned int opcode, TVariant_stack& stack)
|
|
{
|
|
if (opcode < _first_msg)
|
|
return TReport::execute_usr_word(opcode, stack);
|
|
opcode -= _first_msg;
|
|
switch (opcode)
|
|
{
|
|
case 0 : msg_format_costo(stack); break;
|
|
case 1 : msg_format_commessa(stack); break;
|
|
case 2 : msg_format_fase(stack); break;
|
|
case 3 : msg_format_conto(stack); break;
|
|
case 4 : msg_format_commessa_costo(stack); break;
|
|
default: break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TAnal_bill
|
|
///////////////////////////////////////////////////////////
|
|
|
|
int TAnal_bill::compare(const TSortable& s) const
|
|
{
|
|
const TAnal_bill& b = (const TAnal_bill&)s;
|
|
int cmp = _conto.compare(b._conto);
|
|
if (cmp == 0)
|
|
{
|
|
cmp = _costo.compare(b._costo);
|
|
if (cmp == 0)
|
|
{
|
|
cmp = _commessa.compare(b._commessa);
|
|
if (cmp == 0)
|
|
cmp = _fase.compare(b._fase);
|
|
}
|
|
}
|
|
return cmp;
|
|
}
|
|
|
|
bool TAnal_bill::match(const TAnal_bill& b) const
|
|
{
|
|
if (b._conto.not_empty() && _conto != b._conto)
|
|
return false;
|
|
if (b._costo.not_empty() && _costo != b._costo)
|
|
return false;
|
|
if (b._commessa.not_empty() && _commessa != b._commessa)
|
|
return false;
|
|
if (b._fase.not_empty() && _fase != b._fase)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void TAnal_bill::set_conto(const char* c)
|
|
{ _conto = c; _conto.trim(); }
|
|
|
|
void TAnal_bill::set_costo(const char* c)
|
|
{ _costo = c; _costo.trim(); }
|
|
|
|
void TAnal_bill::set_commessa(const char* c)
|
|
{ _commessa = c; _commessa.trim(); }
|
|
|
|
void TAnal_bill::set_fase(const char* c)
|
|
{ _fase = c; _fase.trim(); }
|
|
|
|
const TString& TAnal_bill::conto() const
|
|
{ return _conto; }
|
|
|
|
const TString& TAnal_bill::costo() const
|
|
{ return _costo; }
|
|
|
|
const TString& TAnal_bill::commessa() const
|
|
{ return _commessa; }
|
|
|
|
const TString& TAnal_bill::fase() const
|
|
{ return _fase; }
|
|
|
|
void TAnal_bill::reset()
|
|
{
|
|
_conto = _costo = _commessa = _fase = "";
|
|
}
|
|
|
|
bool TAnal_bill::get(const TRectype& rec)
|
|
{
|
|
bool ok = true;
|
|
reset();
|
|
switch(rec.num())
|
|
{
|
|
case LF_RMOVANA:
|
|
set_conto(rec.get(RMOVANA_CODCONTO));
|
|
set_costo(rec.get(RMOVANA_CODCCOSTO));
|
|
set_commessa(rec.get(RMOVANA_CODCMS));
|
|
set_fase(rec.get(RMOVANA_CODFASE));
|
|
break;
|
|
case LF_RIGHEDOC:
|
|
set_commessa(RDOC_CODCMS);
|
|
set_fase(RDOC_FASCMS);
|
|
break;
|
|
case LF_SALDANA:
|
|
set_conto(rec.get(SALDANA_CONTO));
|
|
set_costo(rec.get(SALDANA_COSTO));
|
|
set_commessa(rec.get(SALDANA_COMMESSA));
|
|
set_fase(rec.get(SALDANA_FASE));
|
|
break;
|
|
default:
|
|
ok = false;
|
|
break;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void TAnal_bill::copy(const TAnal_bill& b)
|
|
{
|
|
set_conto(b.conto());
|
|
set_costo(b.costo());
|
|
set_commessa(b.commessa());
|
|
set_fase(b.fase());
|
|
}
|
|
|
|
const TAnal_bill& TAnal_bill::operator=(const TAnal_bill& b)
|
|
{
|
|
copy(b);
|
|
return *this;
|
|
}
|
|
|
|
TAnal_bill::TAnal_bill()
|
|
{ }
|
|
|
|
TAnal_bill::TAnal_bill(const TAnal_bill& b)
|
|
{ copy(b); }
|
|
|
|
TAnal_bill::TAnal_bill(const char* conto, const char* costo, const char* commessa, const char* fase)
|
|
{
|
|
set_conto(conto);
|
|
set_costo(costo);
|
|
set_commessa(commessa);
|
|
set_fase(fase);
|
|
}
|
|
|
|
TAnal_bill::TAnal_bill(const TRectype& rec)
|
|
{
|
|
get(rec);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// TRiclassify_cache
|
|
////////////////////////////////////////////////////////
|
|
|
|
class TRiclassify_cache : public TCache
|
|
{
|
|
int _conto_min;
|
|
|
|
protected:
|
|
virtual TObject* key2obj(const char* key);
|
|
void extract(const char* conto, TString_array& conti) const;
|
|
|
|
public:
|
|
const TString_array& conti(const TString& conto);
|
|
TRiclassify_cache();
|
|
};
|
|
|
|
void TRiclassify_cache::extract(const char* conto, TString_array& conti) const
|
|
{
|
|
TRecord_array table(conto, LF_PANAPDC);
|
|
for (int r = table.last_row(); r > 0; r = table.pred_row(r))
|
|
{
|
|
const TRectype& row = table.row(r);
|
|
const TBill b(row);
|
|
conti.add(b.string(0x8));
|
|
}
|
|
}
|
|
|
|
TObject* TRiclassify_cache::key2obj(const char* key)
|
|
{
|
|
TString_array* k = new TString_array;
|
|
if (key && int(strlen(key)) > _conto_min)
|
|
{
|
|
extract(key, *k);
|
|
}
|
|
else
|
|
{
|
|
TString query = "USE PCONANA";
|
|
if (key && *key)
|
|
{
|
|
query << "\nFROM CODCONTO=" << key;
|
|
query << "\nTO CODCONTO=" << key;
|
|
}
|
|
TISAM_recordset pconana(query);
|
|
for (TRecnotype i = 0; pconana.move_to(i); i++)
|
|
{
|
|
const TString& conto = pconana.get(PCONANA_CODCONTO).as_string();
|
|
extract(conto, *k);
|
|
}
|
|
}
|
|
return k;
|
|
}
|
|
|
|
const TString_array& TRiclassify_cache::conti(const TString& conto)
|
|
{
|
|
return *(const TString_array*)objptr(conto);
|
|
}
|
|
|
|
TRiclassify_cache::TRiclassify_cache() : TCache(7)
|
|
{
|
|
const TMultilevel_code_info& info = ca_multilevel_code_info(LF_PCONANA);
|
|
_conto_min = info.total_len(-1); // Lunghezza conti fino al penultimo livello
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////
|
|
// TSaldi_cache
|
|
////////////////////////////////////////////////////////
|
|
|
|
class TSaldi_cache : private TCache
|
|
{
|
|
TEsercizi_contabili _esc;
|
|
TRiclassify_cache _riclass;
|
|
|
|
protected:
|
|
virtual TObject* key2obj(const char* key);
|
|
|
|
bool int_saldo_annuale(const TAnal_bill& bill, int annoini, int annofin, word tipo, TImporto& dare, TImporto& avere) const;
|
|
bool int_saldo_movimenti(const TAnal_bill& bill, const TDate& dal, const TDate& al, word tipo, TSaldanal& s) const;
|
|
|
|
protected:
|
|
bool saldo_annuale(const TAnal_bill& bill, int annoini, int annofin, word tipo, TImporto& dare, TImporto& avere);
|
|
bool saldo_movimenti(const TAnal_bill& bill, const TDate& dal, const TDate& al, word tipo, TSaldanal& s);
|
|
bool saldi(const TAnal_bill& bill, const TDate& dal, const TDate& al, word tipo, TSaldanal& s);
|
|
|
|
public:
|
|
const TSaldanal& saldo(const TAnal_bill& bill, const TDate& dal, const TDate& al, word tipi = 0x1);
|
|
TSaldi_cache();
|
|
};
|
|
|
|
// Calcolo saldo annuale di un conto reale NON riclassificato
|
|
bool TSaldi_cache::int_saldo_annuale(const TAnal_bill& b, int da_anno, int ad_anno, word tipo,
|
|
TImporto& dare, TImporto& avere) const
|
|
{
|
|
CHECKD(ad_anno > 0, "Anno saldo finale errato: ", ad_anno);
|
|
|
|
bool movim = false;
|
|
TString query, select;
|
|
|
|
if (b.costo().not_empty())
|
|
select << "(COSTO=='" << b.costo() << "')";
|
|
if (b.commessa().not_empty())
|
|
{
|
|
if (select.not_empty()) select << "&&";
|
|
select << "(COMMESSA=='" << b.commessa() << "')";
|
|
}
|
|
if (b.fase().not_empty())
|
|
{
|
|
if (select.not_empty()) select << "&&";
|
|
select << "(FASE=='" << b.fase() << "')";
|
|
}
|
|
if (b.conto().not_empty() && da_anno != ad_anno)
|
|
{
|
|
if (select.not_empty()) select << "&&";
|
|
select << "(CONTO[1," << b.conto().len() << "]=='" << b.conto() << "')";
|
|
}
|
|
|
|
query << "USE SALDANA";
|
|
if (select.not_empty())
|
|
query << " SELECT " << select;
|
|
if (da_anno > 0)
|
|
{
|
|
query << "\nFROM ANNO=" << da_anno;
|
|
if (b.conto().not_empty())
|
|
query << " CONTO='" << b.conto() << '\'';
|
|
query << '\n';
|
|
}
|
|
|
|
query << "\nTO ANNO=" << ad_anno;
|
|
if (b.conto().not_empty())
|
|
query << " CONTO='" << b.conto() << '\'';
|
|
query << '\n';
|
|
|
|
TISAM_recordset saldini(query);
|
|
|
|
for (TRecnotype i = 0; saldini.move_to(i); i++)
|
|
{
|
|
char sez = ' ';
|
|
real imp;
|
|
if (tipo & _saldanal_consuntivo)
|
|
{
|
|
sez = saldini.get(SALDANA_SEZIONE).as_string()[0];
|
|
imp = saldini.get(SALDANA_SALDO).as_real();
|
|
}
|
|
if (tipo & _saldanal_preventivo)
|
|
{
|
|
sez = saldini.get(SALDANA_SEZIONEP).as_string()[0];
|
|
imp = saldini.get(SALDANA_SALDOP).as_real();
|
|
}
|
|
if (tipo & _saldanal_variazione)
|
|
{
|
|
sez = saldini.get(SALDANA_SEZIONEV).as_string()[0];
|
|
imp = saldini.get(SALDANA_SALDOV).as_real();
|
|
}
|
|
if (sez > ' ')
|
|
{
|
|
if (sez == 'D')
|
|
dare += TImporto('D', imp);
|
|
else
|
|
avere += TImporto('A', imp);
|
|
movim = true;
|
|
}
|
|
}
|
|
|
|
return movim;
|
|
}
|
|
|
|
bool TSaldi_cache::saldo_annuale(const TAnal_bill& b, int da_anno, int ad_anno, word tipo,
|
|
TImporto& dare, TImporto& avere)
|
|
{
|
|
bool movim = false;
|
|
if (ad_anno > 0)
|
|
{
|
|
if (tipo & _saldanal_riclassify)
|
|
{
|
|
// Legge tabella di riclassificazione
|
|
const TString_array& table = _riclass.conti(b.conto());
|
|
if (!table.empty())
|
|
{
|
|
TAnal_bill c(b); // Conto riclassificato
|
|
FOR_EACH_ARRAY_ROW(table, i, row)
|
|
{
|
|
c.set_conto(*row);
|
|
movim |= int_saldo_annuale(c, da_anno, ad_anno, tipo, dare, avere);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
movim = int_saldo_annuale(b, da_anno, ad_anno, tipo, dare, avere);
|
|
}
|
|
return movim;
|
|
}
|
|
|
|
bool TSaldi_cache::int_saldo_movimenti(const TAnal_bill& b,
|
|
const TDate& dal, const TDate& al,
|
|
word tipo, TSaldanal& s) const
|
|
{
|
|
TDate dataini;
|
|
if (dal.ok())
|
|
{
|
|
const int annoprec = _esc.date2prevesc(dal);
|
|
if (annoprec > 0)
|
|
dataini = _esc[annoprec].fine()+1L;
|
|
}
|
|
|
|
TString query, select;
|
|
|
|
if (b.costo().not_empty())
|
|
{
|
|
if (select.not_empty())
|
|
select << "&&";
|
|
select << "(CODCOSTO==\"" << b.costo() << "\")";
|
|
}
|
|
if (b.commessa().not_empty())
|
|
{
|
|
if (select.not_empty())
|
|
select << "&&";
|
|
select << "(CODCMS==\"" << b.commessa() << "\")";
|
|
}
|
|
if (b.fase().not_empty())
|
|
{
|
|
if (select.not_empty())
|
|
select << "&&";
|
|
select << "(CODFASE==\"" << b.fase() << "\")";
|
|
}
|
|
|
|
query << "USE RMOVANA KEY 2\n";
|
|
if (select.not_empty())
|
|
query << "SELECT " << select << "\n";
|
|
|
|
// Faccio la join solo se mi serve il tipo movimento in testata
|
|
const bool filtra_tipo = (tipo & _saldanal_qualsiasi) != 0 &&
|
|
(tipo & _saldanal_qualsiasi) != _saldanal_qualsiasi;
|
|
if (filtra_tipo)
|
|
query << "JOIN MOVANA INTO NUMREG==NUMREG\n";
|
|
|
|
query << "FROM CODCONTO=" << b.conto();
|
|
if (dataini.ok())
|
|
query << " DATACOMP=" << dataini;
|
|
query << "\n";
|
|
|
|
query << "TO CODCONTO=" << b.conto();
|
|
if (al.ok())
|
|
query << " DATACOMP=" << al;
|
|
query << "\n";
|
|
|
|
TISAM_recordset rmovana(query);
|
|
|
|
for (TRecnotype i = 0; rmovana.move_to(i); i++)
|
|
{
|
|
// Controllo il tipo movimento solo se necessario
|
|
if (filtra_tipo)
|
|
{
|
|
const char tipomov = rmovana.get("107.TIPOMOV").as_string()[0];
|
|
int ntipomov = 0;
|
|
if (tipomov == 'P')
|
|
ntipomov = _saldanal_preventivo; else
|
|
if (tipomov == 'V')
|
|
ntipomov = _saldanal_variazione;
|
|
else
|
|
ntipomov = _saldanal_consuntivo;
|
|
if ((ntipomov & tipo) == 0)
|
|
continue;
|
|
}
|
|
|
|
const TDate data = rmovana.get(RMOVANA_DATACOMP).as_date();
|
|
const TImporto imp(rmovana.get(RMOVANA_SEZIONE).as_string()[0],
|
|
rmovana.get(RMOVANA_IMPORTO).as_real());
|
|
if (data >= dal)
|
|
{
|
|
if (imp.sezione() == 'D')
|
|
s._dare += imp;
|
|
else
|
|
s._avere += imp;
|
|
s._movimentato = true;
|
|
}
|
|
else
|
|
{
|
|
s._ini += imp;
|
|
}
|
|
}
|
|
return s._movimentato;
|
|
}
|
|
|
|
bool TSaldi_cache::saldo_movimenti(const TAnal_bill& b,
|
|
const TDate& dal, const TDate& al,
|
|
word tipo, TSaldanal& s)
|
|
{
|
|
bool movim = false;
|
|
if (tipo & _saldanal_riclassify)
|
|
{
|
|
// Legge tabella di riclassificazione
|
|
const TString_array& table = _riclass.conti(b.conto());
|
|
if (!table.empty())
|
|
{
|
|
TAnal_bill c(b); // Conto riclassificato
|
|
FOR_EACH_ARRAY_ROW(table, i, row)
|
|
{
|
|
c.set_conto(*row);
|
|
movim |= int_saldo_movimenti(c, dal, al, tipo, s);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
movim = int_saldo_movimenti(b, dal, al, tipo, s);
|
|
return movim;
|
|
}
|
|
|
|
bool TSaldi_cache::saldi(const TAnal_bill& bill,
|
|
const TDate& dal, const TDate& al, word tipo,
|
|
TSaldanal& s)
|
|
{
|
|
// Calcolo i saldi fino all'anno scorso.
|
|
// In assemza di data iniziale mi torna 0
|
|
const int anno_prec = _esc.date2prevesc(dal);
|
|
if (anno_prec > 0)
|
|
{
|
|
TImporto dare, avere;
|
|
saldo_annuale(bill, 0, anno_prec, tipo, dare, avere);
|
|
s._ini = dare;
|
|
s._ini += avere;
|
|
}
|
|
|
|
if (tipo & _saldanal_ultima_imm)
|
|
{
|
|
// Calcolo i saldi di quest'anno
|
|
// In assemza di data iniziale somma tutti gli anni (fino al 9999)
|
|
const int anno_ini = _esc.date2esc(dal);
|
|
const int anno_fin = anno_ini > 0 ? anno_ini : 9999;
|
|
s._movimentato = saldo_annuale(bill, anno_ini, anno_fin, tipo, s._dare, s._avere);
|
|
}
|
|
else
|
|
{
|
|
saldo_movimenti(bill, dal, al, tipo, s);
|
|
}
|
|
s._ini.normalize();
|
|
s._fin = s._ini;
|
|
s._fin += s._dare;
|
|
s._fin += s._avere;
|
|
s._fin.normalize();
|
|
|
|
return s._movimentato;
|
|
}
|
|
|
|
TObject* TSaldi_cache::key2obj(const char* key)
|
|
{
|
|
TSaldanal* s = new TSaldanal;
|
|
|
|
TToken_string tok(key);
|
|
const TAnal_bill bill(tok.get(0), tok.get(1), tok.get(2), tok.get(3));
|
|
const TDate dal = tok.get(4); // Le get precedenti avvengono in ordine inverso!
|
|
const TDate al = tok.get();
|
|
const int tipo = tok.get_int();
|
|
s->_movimentato = saldi(bill, dal, al, tipo, *s);
|
|
return s;
|
|
}
|
|
|
|
const TSaldanal& TSaldi_cache::saldo(const TAnal_bill& bill, const TDate& dal, const TDate& al, word tipi)
|
|
{
|
|
TToken_string key;
|
|
key.add(bill.conto(), 0);
|
|
key.add(bill.costo(), 1);
|
|
key.add(bill.commessa(), 2);
|
|
key.add(bill.fase(), 3);
|
|
key.add(dal, 4);
|
|
key.add(al, 5);
|
|
key.add(tipi, 6);
|
|
return *(const TSaldanal*)objptr(key);
|
|
}
|
|
|
|
|
|
TSaldi_cache::TSaldi_cache() : TCache(3881) // Numero primo
|
|
{ }
|
|
|
|
const TSaldanal& ca_saldo(const TAnal_bill& bill, const TDate& dal, const TDate& al, word tipi)
|
|
{
|
|
static TSaldi_cache* cache = NULL;
|
|
if (cache == NULL)
|
|
cache = new TSaldi_cache;
|
|
return cache->saldo(bill, dal, al, tipi);
|
|
}
|