campo-sirio/ca/calib01.cpp
guy 1cf194aed9 Patch level : 2.2.
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
2005-07-07 17:05:02 +00:00

1344 lines
31 KiB
C++
Executable File

#include <currency.h>
#include <dongle.h>
#include <modaut.h>
#include <tree.h>
#include <pconti.h>
#include "calib01.h"
#include "calibmsk.h"
#include "../cg/cg2103.h"
#include "movana.h"
#include "rmovana.h"
#include "rip.h"
#include "rrip.h"
#include "saldana.h"
///////////////////////////////////////////////////////////
// TConfig_anal
///////////////////////////////////////////////////////////
TConfig_anal::TConfig_anal() : TConfig(CONFIG_DITTA, "ca"), _has_ca(dongle().active(CAAUT))
{
}
const TString& TConfig_anal::get(const char* var, const char* section, int index, const char* def)
{
if (_has_ca)
return TConfig::get(var, section, index, def);
//se il valore della variabile sul .ini e' vuoto controlla se e' possibile assegnarlo di default
TString& tmp = get_tmp_string();
if (var == "AttFasi")
tmp = "X"; else
if (var == "FathFasi")
tmp = "CMS"; else
if (var == "Level(1)")
tmp = "CMS"; else
if (var == "Cms(1)")
tmp = "LLLLLLLLLLLLLLLLLLLL"; else
if (var == "CmsDes(1)")
tmp = "Commessa"; else
if (var == "Fsc(1)")
tmp = "LLLLLLLLLL"; else
if (var == "FscDes(1)")
tmp == "Fase"; else
if (var == "EdMask")
tmp = "ca0300a"; else
if (var == "UsePdcc")
tmp = "X";
return tmp;
}
///////////////////////////////////////////////////////////
// TMultilevel_code_info
///////////////////////////////////////////////////////////
int TMultilevel_code_info::levels() const
{
return _picture.items();
}
const TString& TMultilevel_code_info::picture(int level) const
{
if (level < 0 || level >= levels())
return EMPTY_STRING;
return _picture.row(level);
}
bool TMultilevel_code_info::is_required(int level) const
{
bool yes = level <= 0;
return yes;
}
bool TMultilevel_code_info::is_numeric_picture(int level) const
{
const TString& pic = picture(level);
if (pic.blank())
return false;
for (int i = 0; pic[i]; i++)
if (pic[i] != '0' && pic[i] != '9')
return false;
return true;
}
int TMultilevel_code_info::len(int level) const
{
return picture(level).len();
}
int TMultilevel_code_info::total_len(int level) const
{
const int max_lev = levels();
if (level < 0) // -1 = fino al penultimo
level = max_lev+level-1;
int l = 0;
for (int i = 0; i <= level && i < max_lev; i++)
l += picture(i).len();
return l;
}
const TString& TMultilevel_code_info::prompt(int level) const
{
if (level < 0 || level >= _prompt.items())
return EMPTY_STRING;
return _prompt.row(level);
}
const TFieldref& TMultilevel_code_info::fieldref(int level, int key) const
{
const TArray& a = key <= 1 ? _key1_fields : _key2_fields;
const TFieldref& fr = (const TFieldref&)a[level];
return fr;
}
const char* TMultilevel_code_info::get_key_fieldname(int k) const
{
const RecDes& rd = prefix().get_recdes(_logicnum);
CHECKD(k > 0 && k <= rd.NKeys, "Invalid key ", k);
const KeyDes& ky = rd.Ky[k-1];
int idx = 0;
if (k == 1 && (_logicnum == LF_TAB || _logicnum == LF_TABCOM || _logicnum == LF_FASI))
idx = 1;
const int pos = ky.FieldSeq[idx] % MaxFields;
return rd.Fd[pos].Name;
}
bool TMultilevel_code_info::get_cfg_vars(TString& key, TString& des) const
{
switch (_logicnum)
{
case LF_PCONANA : key = "Pdci"; des = "PdciDes"; break;
case LF_CDC : key = "CdC"; des = "CdCDes"; break;
case LF_COMMESSE: key = "Cms"; des = "CmsDes"; break;
case LF_FASI : key = "Fsc"; des = "FscDes"; break;
default: break;
}
return key.not_empty();
}
void TMultilevel_code_info::add_fieldref(int k, int from, int to)
{
TArray& a = k == 1 ? _key1_fields : _key2_fields;
TString80 str = get_key_fieldname(k);
if (from > 0)
str << '[' << from << ',' << to << ']';
TFieldref* fr = new TFieldref(str, _logicnum);
a.add(fr);
}
TMultilevel_code_info::TMultilevel_code_info(int logicnum) : _logicnum(logicnum), _parentnum(0)
{
if (_logicnum == LF_PCON)
{
_key1_fields.add(new TFieldref(PCN_GRUPPO, LF_PCON));
_picture.add("999");
_prompt.add(TR("Gruppo"));
_key1_fields.add(new TFieldref(PCN_CONTO, LF_PCON));
_picture.add("999");
_prompt.add(TR("Conto"));
_key1_fields.add(new TFieldref(PCN_SOTTOCONTO, LF_PCON));
_picture.add("999999");
_prompt.add(TR("Sottoconto"));
_key2_fields.add(new TFieldref(PCN_DESCR, LF_PCON));
}
else
{
TConfig_anal cfg;
if (logicnum == LF_FASI)
{
const TString& father = cfg.get("FathFasi");
if (father == "CMS")
_parentnum = LF_COMMESSE; else
if (father == "CDC")
_parentnum = LF_CDC;
if (_parentnum != 0)
{
const TMultilevel_code_info& info = ca_multilevel_code_info(_parentnum);
for (int i = 0; i < info.levels(); i++)
{
_prompt.add(info.prompt(i));
_picture.add(info.picture(i));
TFieldref fr = info.fieldref(i);
fr.set_name("CODCMSFAS");
_key1_fields.add(fr);
}
}
}
TString16 keyvar, desvar;
get_cfg_vars(keyvar, desvar);
int from = 1, to = 1;
for (int level = 1; ; level++)
{
const TString& prompt = cfg.get(desvar, NULL, level);
if (prompt.blank())
break;
_prompt.add(prompt);
const TString& picture = cfg.get(keyvar, NULL, level);
_picture.add(picture);
const int keylen = picture.len();
to = from+keylen-1;
add_fieldref(1, from, to);
from = to+1;
}
add_fieldref(2, 0, 0);
}
}
const TMultilevel_code_info& ca_multilevel_code_info(int logicnum)
{
static TArray* cache = NULL;
if (cache == NULL)
cache = new TArray;
TMultilevel_code_info* info = (TMultilevel_code_info*)cache->objptr(logicnum);
if (info == NULL)
{
info = new TMultilevel_code_info(logicnum);
cache->add(info, logicnum);
}
return *info;
}
bool ca_test_multilevel_field(TEdit_field& fld, int level)
{
const int logic = fld.browse()->cursor()->curr().num();
const TMultilevel_code_info& info = ca_multilevel_code_info(logic);
const TString& pic = info.picture(level);
const TString& val = fld.get();
bool ok = val.len() <= pic.len();
for (int i = 0; val[i] && ok; i++)
{
const char v = val[i];
const char p = pic[i];
switch (p)
{
case 'A': ok = (v >= '0' && v <= '9') || (v >= 'A' && v <= 'Z'); break;
case '0': ok = (v >= '0' && v <= '9'); break;
case '9': ok = (v == ' ') || (v >= '0' && v <= '9'); break;
default : break;
}
}
if (!ok)
{
TString msg;
msg << TR("Il codice non rispetta il formato impostato nella configurazione")
<< '\n' << val << " <> " << pic;
return fld.error_box(msg);
}
return ok;
}
///////////////////////////////////////////////////////////
// Utilities
///////////////////////////////////////////////////////////
void ca_append_select_clause(ostream& out, int level, int logic)
{
TString str;
if (logic == LF_PCON)
{
switch (level)
{
case 0: str = "CONTO==\"\""; break;
case 1: str = "SOTTOCONTO==\"\""; break;
default: break;
}
}
else
{
const TMultilevel_code_info& mci = ca_multilevel_code_info(logic);
const TFieldref& key = mci.fieldref(level);
str << "STR(";
if (level > 1)
str << "(NUM(LEN(" << key.name() << "))>" << key.from() << ')'; // SE LEN(CODCONTO)>=4
if (level < mci.levels())
{
if (level > 1) str << "&&";
str << "(NUM(LEN(" << key.name() << "))<=" << key.to() << ')'; // SE LEN(CODCONTO)<=7
}
str << ')';
}
if (str.not_empty())
out << " SE " << str << endl;
}
void ca_append_run_clause(ostream& out, int logicnum)
{
const TRectype r(logicnum);
TString app; r.get_relapp(app);
if (app.not_empty())
out << "AD RU " << app << endl;
}
void ca_create_browse1(TEdit_field& kfld, int level, int logic, short key_id, short des_id)
{
const TMultilevel_code_info& main_info = ca_multilevel_code_info(logic);
if (logic == LF_FASI)
{
const int par = main_info.parent();
if (par > 0)
{
const TMultilevel_code_info& parinfo = ca_multilevel_code_info(par);
if (level < parinfo.levels())
logic = par;
}
}
const TMultilevel_code_info& mci = ca_multilevel_code_info(logic);
TFilename tmp; tmp.tempdir(); tmp.add("tmp.msk");
ofstream out(tmp);
out << "US " << logic << endl;
ca_append_select_clause(out, level, logic);
ca_append_run_clause(out, logic);
for (int i = 0; i <= level; i++)
{
const TString& picture = mci.picture(i);
const TString& prompt = mci.prompt(i);
const TFieldref& field = mci.fieldref(i);
const int length = field.to() - field.from();
out << "IN " << field << ' ' << (key_id+i) << endl;
out << "DI \"" << prompt;
if (length > prompt.len())
out << '@' << length;
out << "\" " << field << endl;
out << "OU " << (key_id+i) << ' ' << field << endl;
}
const TFieldref& field = mci.fieldref(0, 2);
out << "DI \"" << TR("Descrizione") << "@50\" " << field << endl;
out << "OU " << (des_id+level) << ' ' << field << endl;
out << "CH NO" << endl;
out << "FI " << main_info.fieldref(level) << endl;
out << "EN" << endl;
out.close();
TScanner scan(tmp);
while (scan.pop() != "EN")
kfld.parse_item(scan);
xvt_fsys_removefile(tmp);
}
void ca_create_browse2(TEdit_field& kfld, int level, int logic, short key_id, short des_id)
{
const TMultilevel_code_info& main_info = ca_multilevel_code_info(logic);
if (logic == LF_FASI)
{
const int par = main_info.parent();
if (par > 0)
{
const TMultilevel_code_info& parinfo = ca_multilevel_code_info(par);
if (level < parinfo.levels())
logic = par;
}
}
const TMultilevel_code_info& mci = ca_multilevel_code_info(logic);
const TFieldref& field = mci.fieldref(0, 2);
TString str2; str2 << field;
TFilename tmp; tmp.tempdir(); tmp.add("tmp.msk");
ofstream out(tmp);
out << "US " << logic << " KE 2" << endl;
ca_append_select_clause(out, level, logic);
ca_append_run_clause(out, logic);
out << "IN " << str2 << ' ' << kfld.dlg() << endl;
out << "DI \"" << TR("Descrizione") << "@50\" " << str2 << endl;
out << "OU " << kfld.dlg() << ' ' << str2 << endl;
for (int i = 0; i <= level; i++)
{
const TString& picture = mci.picture(i);
const TString& prompt = mci.prompt(i);
const TFieldref& field = mci.fieldref(i);
const int length = field.to() - field.from();
out << "DI \"" << prompt;
if (length > prompt.len())
{
out << '@' << length;
if (mci.is_numeric_picture(i))
out << 'R';
}
out << "\" " << field << endl;
out << "OU " << (key_id+i) << ' ' << field << endl;
}
out << "CH NO" << endl;
if (level == main_info.levels()-1)
out << "FI " << main_info.fieldref(0, 2) << endl;
out << "EN" << endl;
out.close();
TScanner scan(tmp);
while (scan.pop() != "EN")
kfld.parse_item(scan);
xvt_fsys_removefile(tmp);
}
int ca_create_fields(TMask& msk, int page, int logicnum, int x, int y,
short key_id, short des_id, unsigned int mode, const char* fieldname)
{
const TMultilevel_code_info& mci = ca_multilevel_code_info(logicnum);
int maxkeylen = 0, maxdeslen = 0;
for (int level = 0; level < mci.levels(); level++)
{
const TString& prompt = mci.prompt(level);
const TString& picture = mci.picture(level);
const int keylen = picture.len();
const int deslen = prompt.len();
if (keylen > maxkeylen) maxkeylen = keylen;
if (deslen > maxdeslen) maxdeslen = deslen;
}
maxdeslen++;
const int tab0 = x;
const int tab1 = tab0 + maxdeslen + maxkeylen + 4;
if (key_id > 0 && (mode == 0 || (mode & 0x1) != 0))
{
for (int i = 0; i < mci.levels(); i++)
{
const short kid = key_id+i;
const TString& picture = mci.picture(i);
TString80 prompt = mci.prompt(i);
prompt.left_just(maxdeslen);
const char* flags = picture[0] == '0' || picture[0] == '9' ? "BUZ" : "BU";
TEdit_field* kfld = NULL;
if (mci.is_numeric_picture(i)) // Numeric
kfld = &msk.add_number(kid, page, prompt, tab0, y+i, picture.len(), flags);
else
kfld = &msk.add_string(kid, page, prompt, tab0, y+i, picture.len(), flags);
ca_create_browse1(*kfld, i, logicnum, key_id, des_id);
if ((mode & 0x1) != 0 && fieldname == NULL)
kfld->set_key(1);
// Ho specificato un nome di campo speciale
if (fieldname && *fieldname)
{
const TFieldref& fr = *kfld->field();
TString80 str; str.format("%s[%d,%d]", fieldname, fr.from()+1, fr.to());
kfld->set_field(str);
}
}
}
if (des_id > 0 && (mode == 0 || (mode & 0x2) != 0))
{
for (int i = 0; i < mci.levels(); i++)
{
const short did = des_id+i;
TEdit_field& dfld = msk.add_string(did, page, "", tab1, y+i, 50, "B", 72+tab0-tab1);
ca_create_browse2(dfld, i, logicnum, key_id, des_id);
if ((mode & 0x2) != 0 && fieldname == NULL)
dfld.set_key(2);
else
dfld.set_field("");
}
}
return mci.levels();
}
///////////////////////////////////////////////////////////
// TAnal_tree
///////////////////////////////////////////////////////////
struct TAnal_tree_pos : public TObject
{
TRecnotype _recno;
TToken_string _key;
void as_string(TString& id) const;
int level() const { return _key.items(); }
void reset();
};
void TAnal_tree_pos::as_string(TString& id) const
{
id.format("%ld|%s", _recno, (const char*)_key);
}
void TAnal_tree_pos::reset()
{
_recno = 0;
_key.cut(0);
}
class TAnal_tree : public TBidirectional_tree
{
TLocalisamfile* _file;
TAnal_tree_pos _curr;
protected:
virtual void node2id(const TObject* node, TString& id) const;
virtual bool goto_firstson();
virtual bool goto_rbrother();
virtual bool goto_node(const TString &id);
virtual TObject* curr_node() const;
virtual bool goto_father();
virtual bool goto_lbrother();
virtual bool get_description(TString& desc) const;
protected:
void update_curr();
int level_of(const TToken_string& key) const;
int level_of_file() const;
const TToken_string& curr_of_file() const;
int curr_level() const;
int max_level() const;
const TToken_string& father_of(const TToken_string& key) const;
const TToken_string& father_of_file() const;
bool repos() const;
public:
virtual bool goto_root();
TAnal_tree(int logicnum);
virtual ~TAnal_tree();
};
///////////////////////////////////////////////////////////
// TAnal_msk
///////////////////////////////////////////////////////////
#define F_TREE 99
short TSimple_anal_msk::get_field_id(int n, int k) const
{
short id = 0;
if (n >= 0 && n < fieldrefs(1))
{
if (k == 1)
id = F_KEY1+n;
else
id = F_DES1+n;
}
return id;
}
bool TSimple_anal_msk::test_key_field(short id)
{
TEdit_field& fld = efield(id);
const int level = id - F_KEY1;
return ca_test_multilevel_field(fld, level);
}
bool TSimple_anal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_TREE:
if (e == fe_select)
{
if (edit_mode() && !dirty())
set_mode(MODE_QUERY);
if (query_mode())
{
const TTree_field& fld = (const TTree_field&)o;
const TTree& tree = *fld.tree();
TToken_string curr; tree.curr_id(curr);
for (int i = 0; ; i++)
{
const short id = get_field_id(i);
if (id <= 0)
break;
const char* tok = curr.get(i+1);
TEdit_field& e = efield(id);
e.set(tok);
e.show();
}
stop_run(K_AUTO_ENTER);
}
else
beep(0);
}
break;
case F_KEY1:
case F_KEY2:
case F_KEY3:
case F_KEY4:
if ((jolly == 0) &&(e == fe_modify || e == fe_close))
return test_key_field(o.dlg());
break;
default:
break;
}
return true;
}
int TSimple_anal_msk::compute_offset() const
{
int delta = 0;
RCT rct; xvt_vobj_get_client_rect(TASK_WIN, &rct);
if (rct.right > 720)
delta = (rct.right - 720) / 2 / CHARX;
return delta;
}
void TSimple_anal_msk::read(const char* name)
{
const int delta = compute_offset();
if (delta > 0)
{
TFilename outname; outname.tempdir(); outname.add("tmp.msk");
TFilename inpname = name; inpname.ext("msk");
inpname.custom_path();
ofstream out(outname);
TString line;
int status = 0;
TScanner inp(inpname);
while (!inp.eof())
{
line = inp.line();
switch (status)
{
case 0:
if (line.starts_with("PA"))
status = 1; // Ho trovato la prima pagina
break;
case 1:
if (line.starts_with("PR")) // Ho trovato un prompt sulla prima pagina
{
TToken_string l(line, ' ');
int x = l.get_int(1);
if (x >= 0)
{
x += delta;
l.add(x, 1);
line = l;
}
} else
if (line.starts_with("PA")) // Ho finito la prima pagina
{
status = 2;
}
break;
default:
break;
}
out << line << endl;
}
out.close();
read_mask(outname, 0, 0);
xvt_fsys_removefile(outname);
set_source_file(name);
}
else
read_mask(name, 0, 0);
create_key_fields();
create_tree_field();
}
short TSimple_anal_msk::create_tree_field()
{
short id = 0;
const int delta = compute_offset();
if (delta > 0)
{
id = F_TREE;
add_tree(id, 0, 0, 1, (delta-1)*2, -1);
TAnal_tree* t = new TAnal_tree(get_logicnum());
tfield(id).set_tree(t);
t->goto_root();
t->expand();
}
set_handlers();
return id;
}
void TSimple_anal_msk::update_tree_field()
{
const int pos = id2pos(F_TREE);
if (pos >= 0)
{
TTree_field& t = tfield(F_TREE);
t.win().force_update();
}
}
int TSimple_anal_msk::fieldrefs(int k) const
{
int n = 1;
if (k == 1)
{
const TMultilevel_code_info& mci = ca_multilevel_code_info(get_logicnum());
n = mci.levels();
}
return n;
}
const TFieldref& TSimple_anal_msk::fieldref(int n, int k) const
{
const TMultilevel_code_info& mci = ca_multilevel_code_info(get_logicnum());
return mci.fieldref(n, k);
}
const TToken_string& TSimple_anal_msk::get_key_value(const TRectype& rec, int c) const
{
TToken_string& val = get_tmp_string();
const int tot = fieldrefs(c);
for (int i = 0; i < tot; i++)
{
const TFieldref& field = fieldref(i, c);
val.add(field.read(rec));
}
return val;
}
const TToken_string& TSimple_anal_msk::get_key_value(int c) const
{
TToken_string& val = get_tmp_string();
for (TEditable_field* f = get_key_field(c, true); f != NULL; f = get_key_field(c, false))
{
val.add(f->get());
}
return val;
}
int TSimple_anal_msk::create_key_fields()
{
const int logic = get_logicnum();
const short kid = get_field_id(0, 1);
const short did = get_field_id(0, 2);
const int x = compute_offset()+3;
const int y = 1;
const int n = ca_create_fields(*this, 0, logic, x, y, kid, did, 0x1);
const int m = ca_create_fields(*this, 0, logic, x, y, kid, did, 0x2);
first_focus(kid);
return n;
}
///////////////////////////////////////////////////////////
// TAnal_tree
///////////////////////////////////////////////////////////
const TToken_string& TAnal_tree::curr_of_file() const
{
const TMultilevel_code_info& mci = ca_multilevel_code_info(_file->num());
const TRectype& rec = _file->curr();
TToken_string& k = get_tmp_string();
for (int i = 0; i < mci.levels(); i++)
{
const TFieldref& fld = mci.fieldref(i);
k.add(fld.read(rec));
}
for (int j = k.len()-1; j >= 0; j--)
{
if (k[j] == ' ' || k[j] == k.separator())
k.cut(j);
else
break;
}
return k;
}
int TAnal_tree::level_of(const TToken_string& k) const
{
return k.items();
}
int TAnal_tree::level_of_file() const
{
const TToken_string& str = curr_of_file();
return level_of(str);
}
int TAnal_tree::curr_level() const
{
return level_of(_curr._key);
}
int TAnal_tree::max_level() const
{
const TMultilevel_code_info& mci = ca_multilevel_code_info(_file->num());
return mci.levels();
}
const TToken_string& TAnal_tree::father_of(const TToken_string& key) const
{
const int pos = key.rfind(key.separator());
if (pos <= 0)
return EMPTY_STRING;
TToken_string& k = get_tmp_string();
k = key.left(pos);
return k;
}
const TToken_string& TAnal_tree::father_of_file() const
{
const TToken_string& k = curr_of_file();
return father_of(k);
}
void TAnal_tree::update_curr()
{
_curr._key = curr_of_file();
if (_curr._key.not_empty())
_curr._recno = _file->recno();
else
_curr.reset();
}
bool TAnal_tree::repos() const
{
bool ok = false;
if (_curr.level() > 0)
{
if (_file->recno() != _curr._recno)
ok = ((TLocalisamfile*)_file)->readat(_curr._recno) == NOERR;
else
ok = true;
}
return ok;
}
void TAnal_tree::node2id(const TObject* node, TString& id) const
{
const TAnal_tree_pos* pos = (const TAnal_tree_pos*)node;
pos->as_string(id);
}
bool TAnal_tree::goto_root()
{
const bool ok = _file->first() == NOERR;
if (ok)
update_curr();
else
_curr.reset();
return ok;
}
bool TAnal_tree::goto_firstson()
{
bool ok = _curr.level() < max_level() && repos();
if (ok)
{
ok = _file->next() == NOERR;
if (ok)
{
ok = father_of_file() == _curr._key;
if (ok)
update_curr();
}
}
return ok;
}
bool TAnal_tree::goto_rbrother()
{
bool ok = false;
if (repos())
{
const TToken_string curr_father = father_of(_curr._key);
while (_file->next() == NOERR)
{
const int lev = level_of_file();
if (lev > _curr.level())
continue;
const TToken_string& next_father = father_of_file();
ok = next_father == curr_father;
break;
}
if (ok)
update_curr();
}
return ok;
}
bool TAnal_tree::goto_node(const TString &id)
{
const TRecnotype rec = atol(id);
const int err = _file->readat(rec);
if (err == NOERR)
update_curr();
return err == NOERR;
}
bool TAnal_tree::goto_father()
{
const int lev = _curr.level();
bool ok = lev > 1;
if (ok)
{
TRectype& rec = _file->curr();
rec.zero();
const TMultilevel_code_info& mci = ca_multilevel_code_info(_file->num());
for (int i = 0; i < lev-1; i++)
{
const char* val = _curr._key.get(i);
const TFieldref& fld = mci.fieldref(i);
fld.write(val, rec);
}
ok = _file->read() == NOERR;
if (ok)
update_curr();
}
return ok;
}
bool TAnal_tree::goto_lbrother()
{
bool ok = false;
if (repos())
{
const TString curr_father = father_of(_curr._key);
while (_file->prev() == NOERR)
{
const int lev = level_of_file();
if (lev > _curr.level())
continue;
const TString& next_father = father_of_file();
ok = next_father == curr_father;
break;
}
if (ok)
update_curr();
}
return ok;
}
TObject* TAnal_tree::curr_node() const
{
return (TObject*)&_curr;
}
bool TAnal_tree::get_description(TString& desc) const
{
const bool ok = repos();
if (ok)
{
const int lev = _curr.level();
if (lev > 0)
{
const TMultilevel_code_info& mci = ca_multilevel_code_info(_file->num());
const TFieldref& fld1 = mci.fieldref(lev-1, 1);
const TFieldref& fld2 = mci.fieldref(0, 2);
const TRectype& rec = _file->curr();
desc = fld1.read(rec);
desc << ' ' << fld2.read(rec);
}
}
return ok;
}
TAnal_tree::TAnal_tree(int logicnum)
{
_file = new TLocalisamfile(logicnum);
}
TAnal_tree::~TAnal_tree()
{
delete _file;
}
///////////////////////////////////////////////////////////
// TAnal_app
///////////////////////////////////////////////////////////
void TAnal_app::init_key_fields(TSimple_anal_msk & m) const
{
int maxlev = 0;
for (maxlev = 0; maxlev < 4; maxlev++)
{
const short id = m.get_field_id(maxlev, 1);
if (id <= 0 || m.id2pos(id) < 0)
break;
m.disable(id);
const short did = m.get_field_id(maxlev, 2);
m.disable(did);
}
for (int i = maxlev-1; i >= 0; i--)
{
const short id = m.get_field_id(i, 1);
TEdit_field& e = m.efield(id);
const short did = m.get_field_id(i, 2);
TEdit_field& d = m.efield(did);
if (e.empty())
{
e.hide();
d.hide();
}
else
{
e.show();
e.check(STARTING_CHECK);
TString80 key2;
key2 << m.fieldref(0, 2);
d.set_field(key2);
d.show();
d.enable();
m.first_focus(d.dlg());
d.enable_check(false);
break;
}
}
}
TRelation* TAnal_app::create_relation() const
{
return new TRelation(_msk->get_logicnum());
}
bool TAnal_app::user_create()
{
_msk = create_mask();
_rel = create_relation();
return true;
}
void TAnal_app::init_query_mode(TMask& mask)
{
TSimple_anal_msk& m = (TSimple_anal_msk&)mask;
for (int i = 0; ; i++)
{
const short id = m.get_field_id(i, 1);
if (id <= 0 || m.id2pos(id) < 0)
break;
TEdit_field& e = m.efield(id);
e.show(); e.enable();
const short did = m.get_field_id(i, 2);
TEdit_field& d = m.efield(did);
d.show(); d.enable();
d.enable_check();
d.set_field("");
}
m.first_focus(m.get_field_id(0, 1));
}
void TAnal_app::init_modify_mode(TMask& mask)
{
init_key_fields((TSimple_anal_msk &)mask);
}
void TAnal_app::init_insert_mode(TMask& mask)
{
init_key_fields((TSimple_anal_msk &)mask);
}
int TAnal_app::write(const TMask& m)
{
_msk->update_tree_field();
return TRelation_application::write(m);
}
int TAnal_app::rewrite(const TMask& m)
{
_msk->update_tree_field();
return TRelation_application::rewrite(m);
}
bool TAnal_app::user_destroy()
{
if (_msk != NULL)
delete _msk;
if (_rel != NULL)
delete _rel;
return true;
}
///////////////////////////////////////////////////////////
// TAnal_mov
///////////////////////////////////////////////////////////
TImporto& TAnal_mov::saldo(const TRectype& row)
{
TToken_string key;
key.add(get(MOVANA_TIPOMOV));
key.add(get(MOVANA_ANNOES));
key.add(row.get(RMOVANA_CODCCOSTO));
key.add(row.get(RMOVANA_CODCMS));
key.add(row.get(RMOVANA_CODFASE));
key.add(row.get(RMOVANA_CODCONTO));
TImporto* imp = (TImporto*)_saldi.objptr(key);
if (imp == NULL)
{
imp = new TImporto;
_saldi.add(key, imp);
}
return *imp;
}
void TAnal_mov::load_saldi(bool reset)
{
if (reset)
_saldi.destroy();
const int dec = TCurrency::get_firm_dec();
const TRecord_array& a = body(LF_RMOVANA);
for (int i = a.last_row(); i > 0; i--)
{
const TRectype& row = a[i];
const TImporto imp(row.get_char(RMOVANA_SEZIONE), row.get_real(RMOVANA_IMPORTO));
TImporto& sld = saldo(row);
if (reset)
sld -= imp;
else
sld += imp;
sld.valore().round(dec);
}
}
void TAnal_mov::update_saldi(bool kill)
{
if (!kill)
load_saldi(false);
save_saldi();
if (kill)
_saldi.destroy();
else
load_saldi(true);
}
bool TAnal_mov::save_saldi()
{
TLocalisamfile saldi(LF_SALDANA);
FOR_EACH_ASSOC_OBJECT(_saldi, h, k, o)
{
const TImporto& imp = *(const TImporto*)o;
if (!imp.is_zero())
{
TToken_string key = k;
const char tipo = key.get_char(0);
saldi.put(SALDANA_ANNO, key.get());
saldi.put(SALDANA_COSTO, key.get());
saldi.put(SALDANA_COMMESSA, key.get());
saldi.put(SALDANA_FASE, key.get());
saldi.put(SALDANA_CONTO, key.get());
int err = saldi.read(_isequal, _testandlock);
if (err != NOERR)
{
saldi.zero();
saldi.put(SALDANA_ANNO, key.get(1));
saldi.put(SALDANA_COSTO, key.get());
saldi.put(SALDANA_COMMESSA, key.get());
saldi.put(SALDANA_FASE, key.get());
saldi.put(SALDANA_CONTO, key.get());
err = saldi.write();
}
if (err == NOERR)
{
const char* fld_sez = NULL;
const char* fld_val = NULL;
switch (tipo)
{
case 'P': fld_sez = SALDANA_SEZIONEP; fld_val = SALDANA_SALDOP; break;
case 'V': fld_sez = SALDANA_SEZIONEV; fld_val = SALDANA_SALDOV; break;
default : fld_sez = SALDANA_SEZIONE; fld_val = SALDANA_SALDO; break;
}
TImporto saldo(saldi.get_char(fld_sez), saldi.get_real(fld_val));
saldo += imp;
saldo.normalize();
saldi.put(fld_sez, saldo.sezione());
saldi.put(fld_val, saldo.valore());
err = saldi.rewrite();
}
if (err != NOERR)
return error_box(FR("Impossibile aggiornare i saldi: errore %d"), err);
}
}
return true;
}
int TAnal_mov::readat(TBaseisamfile& f, TRecnotype nrec, word lockop)
{
const int err = TMultiple_rectype::readat(f, nrec, lockop);
load_saldi(true);
return err;
}
int TAnal_mov::read(TBaseisamfile& f, word op, word lockop)
{
const int err = TMultiple_rectype::read(f, op, lockop);
load_saldi(true);
return err;
}
// Riporta su tutte le righe la data di competenza e l'esercizio dellla testata
void TAnal_mov::update_datacomp() const
{
body().renum_key(RMOVANA_ANNOES, get(MOVANA_ANNOES));
body().renum_key(RMOVANA_DATACOMP, get(MOVANA_DATACOMP));
}
int TAnal_mov::write(TBaseisamfile& f) const
{
update_datacomp();
const int err = TMultiple_rectype::write(f);
if (err == NOERR)
((TAnal_mov*)this)->update_saldi(false);
return err;
}
int TAnal_mov::rewrite(TBaseisamfile& f) const
{
update_datacomp();
const int err = TMultiple_rectype::rewrite(f);
if (err == NOERR)
((TAnal_mov*)this)->update_saldi(false);
return err;
}
int TAnal_mov::remove(TBaseisamfile& f) const
{
const int err = TMultiple_rectype::remove(f);
if (err == NOERR)
((TAnal_mov*)this)->update_saldi(true);
return err;
}
int TAnal_mov::read(long numreg, word lock)
{
put(MOVANA_NUMREG, numreg);
const int err = TMultiple_rectype::read(_isequal, lock);
load_saldi(true);
return err;
}
TAnal_mov::TAnal_mov(long numreg) : TMultiple_rectype(LF_MOVANA)
{
add_file(LF_RMOVANA, RMOVANA_NUMRIG);
if (numreg > 0)
read(numreg);
}
///////////////////////////////////////////////////////////
// TAnal_rip
///////////////////////////////////////////////////////////
TAnal_rip::TAnal_rip() : TMultiple_rectype(LF_RIP)
{
add_file(LF_RRIP, RRIP_NRIGA);
}
///////////////////////////////////////////////////////////
// TCache_ripartizioni
///////////////////////////////////////////////////////////
TObject* TCache_ripartizioni::key2obj(const char* key)
{
TToken_string parametro(key);
TLocalisamfile rip(LF_RIP);
const int nkey = parametro.get_int(0);
rip.setkey(nkey);
rip.put(RIP_TIPO, "B");
switch (nkey)
{
case 3: //chiave 3 (tipo+gr/co/stc)
rip.put(RIP_GRUPPO, parametro.get(1));
rip.put(RIP_CONTO, parametro.get());
rip.put(RIP_SOTTOCONTO, parametro.get());
break;
case 4: //chiave 4 (tipo+codcosto+codcms)
rip.put(RIP_CODCOSTO, parametro.get(1));
rip.put(RIP_CODCMS, parametro.get());
break;
default:
break;
}
TString80 chiave;
if (rip.read() == NOERR)
chiave << "B|" << rip.get(RIP_CODICE);
TRecord_array* rows = new TRecord_array(chiave, LF_RRIP);
return (TObject*)rows;
}
const TRecord_array& TCache_ripartizioni::righe(const char* costo, const char* commessa)
{
TToken_string parametro;
parametro << "4|" << costo << '|' << commessa; //per chiave 4
return *(const TRecord_array*)objptr(parametro);
}
const TRecord_array& TCache_ripartizioni::righe(const int gruppo, const int conto, const long sottoconto)
{
TToken_string parametro;
parametro << "3|" << gruppo << '|' << conto << '|' << sottoconto; //per chiave 3
return *(const TRecord_array*)objptr(parametro);
}
const TRecord_array& TCache_ripartizioni::righe(const TBill& bill)
{
return righe(bill.gruppo(), bill.conto(), bill.sottoconto());
}