campo-sirio/sl/sl0100.cpp

1562 lines
40 KiB
C++
Raw Blame History

#include <automask.h>
#include <colors.h>
#include <controls.h>
#include <execp.h>
#include <printer.h>
#include <relapp.h>
#include <utility.h>
#include "sl0100a.h"
#include "sl0101.h"
#include "sl0200.h"
#include "../ca/calib01.h"
#include "../ve/velib.h"
#include "../db/rdist.h"
#include "../mg/anamag.h"
#include "../ca/commesse.h"
///////////////////////////////////////////////////////////
// TSAL_app
///////////////////////////////////////////////////////////
class TSAL_app : public TRelation_application
{
TMask* _qmsk;
TMask* _emsk;
TRelation* _rel;
protected:
int save_rows(const TMask& m);
virtual const char* extra_modules() const { return "ci"; }
const char* record_description(const TRelation& r) const;
bool save_and_print(TPrtype mode);
public:
virtual bool user_create();
virtual bool user_destroy();
virtual bool changing_mask(int mode) { return true; }
virtual TMask* get_mask(int mode) { return mode == MODE_QUERY ? _qmsk : _emsk; }
virtual TRelation* get_relation() const { return _rel; }
virtual bool has_filtered_cursor() const { return true; }
virtual TCursor& get_filtered_cursor() const;
virtual bool get_next_key(TToken_string& key);
virtual void init_insert_mode(TMask& m);
virtual void init_modify_mode(TMask& m);
virtual int read(TMask& m);
virtual int write(const TMask& m);
virtual int rewrite(const TMask& m);
virtual bool remove();
virtual void print();
bool report(const char* name);
void update_tools(TMask& m);
};
inline TSAL_app& app() { return (TSAL_app&)main_app(); }
///////////////////////////////////////////////////////////
// TSAL_msk
///////////////////////////////////////////////////////////
// Classe di base per maschere preventivi (query ed edit)
class TSAL_msk : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
virtual TMask_field* parse_field(TScanner& s);
public:
const TString& fget(const char* fld) const;
void fset(const char* fld, const TString& val, int hit=0x0);
TSAL_msk(const char* name) { read_mask(name, 0, 8); set_handlers(); }
};
TMask_field* TSAL_msk::parse_field(TScanner& s)
{
if (s.key() == "TL")
set_full_screen_interface(page_win(1), true);
return TAutomask::parse_field(s);
}
// Legge il valore di un campo multiplo (commessa, fase, ...) da maschera e lo restituisce come unico valore
const TString& TSAL_msk::fget(const char* fld) const
{
TString& val = get_tmp_string();
FOR_EACH_MASK_FIELD(*this, i, f)
{
const TFieldref* fr = f->field();
if (fr != NULL && fr->name() == fld)
{
if (fr->from() > 0 || fr->to() > 0)
val.overwrite(f->get(), fr->from());
else
{
val = f->get();
break;
}
}
}
return val;
}
// Spezza un valore unico su pi<70> sottocampi (commessa, fase, ...)
void TSAL_msk::fset(const char* fld, const TString& val, int hit)
{
FOR_EACH_MASK_FIELD(*this, i, f)
{
const TFieldref* fr = f->field();
if (fr != NULL && fr->name() == fld)
{
if (fr->from() > 0 || fr->to() > 0)
{
const TString& str = val.sub(fr->from(), fr->to());
f->set(str);
}
else
f->set(val);
if ((f->active() || f->ghost()))
{
f->set_dirty();
if (hit & 0x2)
f->check();
if (hit & 0x1)
f->on_hit();
}
}
}
}
bool TSAL_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
// switch (o.dlg())
// {
// default:
if ((e == fe_modify || e == fe_close) && (!o.empty() && o.is_edit()))
{
const TFieldref* fr = o.field();
if (fr != NULL && fr->name() == RDOC_CODCMS)
{
const TString& cms = fget(RDOC_CODCMS);
const TRectype& rec = cache().get(LF_COMMESSE, cms);
if (rec.get_bool(COMMESSE_CHIUSA))
return error_box(FR("Impossibile utilizzare la commessa chiusa %s"), (const char*)cms);
}
}
// break;
// }
return true;
}
///////////////////////////////////////////////////////////
// TSAL_qmsk
///////////////////////////////////////////////////////////
class TSAL_qmsk : public TSAL_msk
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
bool choose_best(TCursor& cur, const char* codtab);
public:
TSAL_qmsk();
};
// Inizialmente seleziona solo i documenti cliente
static const char* m_tipocf = "C";
static bool tipoc_filter(const TRelation* rel)
{
const TCodice_numerazione& codnum = cached_numerazione(rel->curr().get("CODTAB"));
for (int i = 0; ; i++)
{
const TString& td = codnum.tipo_doc(i);
if (td.blank())
break;
const TTipo_documento& tipodoc = cached_tipodoc(td);
TFilename ini; tipodoc.profile_name(ini);
if (ini.custom_path())
{
const TString& tipocf = ini_get_string(ini, "MAIN", "TIPOCF");
if (tipocf == m_tipocf)
return true;
}
}
return false;
}
// Seleziona solo gli ordini
static bool ord_filter(const TRelation* rel)
{ return rel->curr().get_int("I1") == 3 && tipoc_filter(rel); }
// Seleziona solo le bolle
static bool sal_filter(const TRelation* rel)
{ return rel->curr().get_int("I1") == 1 && tipoc_filter(rel); }
bool TSAL_qmsk::choose_best(TCursor& cur, const char* codtab)
{
const TRecnotype recs = cur.items();
if (recs > 0)
{
cur.freeze();
TRecnotype best = 0;
double score = 0;
for (cur = 0L; cur.pos() < recs; ++cur)
{
const TString& cod = cur.curr().get("CODTAB");
const double s = xvt_str_fuzzy_compare(cod, codtab);
if (s > score)
{
score = s;
best = cur.pos();
}
}
cur = best;
cur.freeze(false);
}
return recs > 0;
}
bool TSAL_qmsk::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_TIPOCF:
if (e == fe_modify)
{
m_tipocf = get(F_TIPOCF); // Seleziona Clienti o Fornitori
on_field_event(efield(F_CODNUM_ORD), fe_init, 0);
on_field_event(efield(F_CODNUM), fe_init, 0);
}
break;
case F_CODNUM_ORD:
if (e == fe_init)
{
TEdit_field& codnum_ord = (TEdit_field&)o;
TCursor& cur_ord = *codnum_ord.browse()->cursor();
cur_ord.set_filterfunction(ord_filter);
if (choose_best(cur_ord, "ORC"))
codnum_ord.browse()->do_output(STARTING_CHECK);
}
break;
case F_CODNUM:
if (e == fe_init)
{
TEdit_field& codnum_sal = (TEdit_field&)o;
TCursor& cur_sal = *codnum_sal.browse()->cursor();
cur_sal.set_filterfunction(sal_filter);
if (choose_best(cur_sal, "SAL"))
{
codnum_sal.browse()->do_output(RUNNING_CHECK);
e = fe_modify;
}
}
if (e == fe_modify && !o.empty())
{
const TString& sal = o.get();
const TCodice_numerazione& codnum = cached_numerazione(sal);
int best = 0;
double score = 0;
for (int i = 0; ; i++)
{
const TString& td = codnum.tipo_doc(i);
if (td.blank())
break;
const double s = xvt_str_fuzzy_compare(td, sal);
if (s > score)
{
score = s;
best = i;
}
}
set(F_TIPODOC, codnum.tipo_doc(best), 0x2);
}
break;
case F_NSAL:
if (e == fe_modify && !o.empty())
{
static bool blocked = false;
if (!blocked)
{
blocked = true;
const int nsal = atoi(o.get());
TEdit_field& fld_nsal = efield(F_NDOC);
TCursor& cur_nsal = *fld_nsal.browse()->cursor();
int n = 0;
for (cur_nsal = 0L; cur_nsal.ok(); ++cur_nsal)
{
n = cur_nsal.curr().get_int(DOC_NUMANT);
if (n == nsal)
break;
}
if (nsal > n)
{
o.reset();
send_key(K_SPACE, DLG_NEWREC, &o);
}
else
{
fld_nsal.browse()->do_output();
stop_run(K_AUTO_ENTER);
}
blocked = false;
}
}
break;
default:
if (e == fe_modify && o.is_edit() && o.dlg() > F_CDC0) // Probabile commessa?
{
const TFieldref* fr = o.field();
if (fr != NULL && fr->name() == DOC_CODCMS) // Campo commessa
{
const TRectype& cur = ((TEdit_field&)o).browse()->cursor()->curr();
const long codcf = cur.get_long(COMMESSE_CODCF);
if (codcf > 0) set(F_CLIFO, codcf);
const int anno = cur.get_int(COMMESSE_ANNO);
if (anno > 0) set(F_ANNO_ORD, anno);
}
}
break;
}
return TSAL_msk::on_field_event(o, e, jolly);
}
TSAL_qmsk::TSAL_qmsk() : TSAL_msk("sl0100a")
{
TMask_field& cdc0 = field(F_CDC0);
RCT rct0; cdc0.get_rect(rct0);
const int yca = rct0.top / ROWY + 1; // Riga del primo campo di analitica
short idcdc, idcms, idfase, idconto;
ca_create_fields_ext(*this, 0, 2, yca, F_CDC0+1, idcdc, idcms, idfase, idconto,
DOC_CODCOSTO, DOC_CODCMS /*, DOC_FASCMS */); // Niente fasi qui!
set_handlers();
}
///////////////////////////////////////////////////////////
// TSAL_emsk
///////////////////////////////////////////////////////////
class TSAL_emsk : public TSAL_msk
{
TSAL_tree* _tree;
TString80 _idfase, _iddist, _edit_fase;
int _edit_dist, _edit_misu;
int _curr_dist, _curr_misu;
bool _locked;
private:
// bool on_fasi_button(TOperable_field& btn, TField_event e, long jolly);
bool on_fasi_event(TTree_field& s, TField_event e, long jolly);
bool set_fase(const TString& idf);
bool set_dist(const TString& idd);
bool set_dist(int row);
void update_dist(const real& val, const TDate& dt);
void update_dist_qta();
bool on_misu_event(TOperable_field& o, TField_event e, long jolly);
bool on_dist_event(TOperable_field& o, TField_event e, long jolly);
protected:
virtual bool on_key(KEY k);
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
void set_sheet_color(short id, COLOR col);
bool sync_totdoc();
bool sync_tree();
bool msk2rec(const TMask& msk, TRectype& rec) const;
public:
TSAL_tree& tree(bool reset = false);
TSAL_emsk();
};
TSAL_tree& TSAL_emsk::tree(bool reset)
{
if (_tree == NULL)
{
_tree = new TSAL_tree(tfield(F_FASI));
reset = true;
}
if (reset)
{
TRectype doc(LF_DOC);
doc.put(DOC_PROVV, 'D');
doc.put(DOC_ANNO, get(F_ANNO));
doc.put(DOC_CODNUM, get(F_CODNUM));
doc.put(DOC_NDOC, get(F_NDOC));
_tree->append_row(doc);
TTree_field& tf = tfield(F_FASI);
tf.set_tree(_tree);
tf.hide_leaves();
}
return *_tree;
}
static bool rec2field(TMask_field& f, const TRectype& rec)
{
const TFieldref* fr = f.field();
if (fr == NULL)
return false;
if (fr->name() == RDOC_DESCR)
{
TString descr(255);
descr = rec.get(RDOC_DESCR);
if (rec.get_bool(RDOC_DESCLUNGA))
descr << rec.get(RDOC_DESCEST);
f.set(descr);
}
else
{
const TString& val = fr->read(rec);
f.set(val);
if (!f.empty() && f.is_edit() && f.shown())
{
const TBrowse* b = ((TEdit_field&)f).browse();
if (b != NULL)
{
const TFixed_string inf = b->get_input_fields();
const TFixed_string outf = b->get_output_fields();
if (outf.find('|') > 0) // C'<27> un pipe nell'output, per cui ci sono almeno due campi di output
{
f.check(STARTING_CHECK);
}
}
}
}
return true;
}
static bool chk_field(TMask_field& f)
{
const TFieldref* fr = f.field();
if (fr == NULL)
{
if (f.ghost())
return f.on_hit();
}
return true;
}
// Riempie gli sheet di articoli e misure della distinta selezionata
bool TSAL_emsk::set_dist(const TString& idd)
{
TSAL_tree& t = tree();
bool ok = idd.full();
if (_iddist != idd)
{
_iddist = idd;
// Svuota sheet misure
TSheet_field& s = sfield(F_MISURE);
s.hide();
s.destroy();
// Scandisce i figli della distinta e li smista tra i due sheet
ok = idd.full() && t.goto_node(idd);
if (ok)
{
_locked = true; // Diabilita ricalcolo prezzi
int n = 0;
for (bool ok = t.goto_firstson(); ok; ok = t.goto_rbrother())
{
const TRectype& rec = *t.curr_row();
TMask& m = s.sheet_row_mask(n);
FOR_EACH_MASK_FIELD(m, i, f) if (f->field())
rec2field(*f, rec);
FOR_EACH_MASK_FIELD(m, i, c) if (c->is_edit())
chk_field(*c);
s.update_row(n++);
}
_locked = false;
}
// Visualizza nuovamente lo sheet eventualemente riempito
s.force_update(); s.show();
}
_curr_dist = -1;
if (ok && t.goto_node(idd))
{
_curr_dist = 0;
while(t.goto_lbrother())
_curr_dist++;
}
return ok;
}
bool TSAL_emsk::set_dist(int row)
{
TSAL_tree& t = tree();
bool ok = _idfase.full() && t.dist(_idfase, row) != NULL;
if (ok)
{
TString16 idd; t.curr_id(idd);
ok = set_dist(idd);
CHECK(ok && row == _curr_dist, "Distinta sospetta");
}
return ok;
}
// Riempie lo sheet delle distinte della fase selezionata
bool TSAL_emsk::set_fase(const TString& idfase)
{
_idfase = idfase;
// Svuota lo sheet delle distinte
TSheet_field& d = sfield(F_DISTINTE);
d.destroy();
TString idd;
TSAL_tree& t = tree();
bool ok = idfase.full() && t.goto_node(idfase);
if (ok)
{
// Scandisce le distinte della fase corrente
if (t.goto_firstson())
{
t.curr_id(idd); // Memorizza la prima distinta per dopo...
int n = 0;
do
{
const TRectype& rec = *t.curr_row();
TMask& m = d.sheet_row_mask(n);
FOR_EACH_MASK_FIELD(m, i, f) if (f->field())
rec2field(*f, rec);
FOR_EACH_MASK_FIELD(m, i, c) if (c->is_edit())
chk_field(*c);
d.update_row(n++);
} while (t.goto_rbrother());
}
}
d.force_update();
set_dist(idd);
return ok;
}
bool TSAL_emsk::msk2rec(const TMask& msk, TRectype& rec) const
{
TRelation rel(rec.num());
rel.curr() = rec;
msk.autosave(rel);
rec = rel.curr();
const TString& desc = msk.get(RDOC_DESCR);
const int maxlen = rec.length(RDOC_DESCR);
int spc = desc.find('\n');
if (spc >= 0 || desc.len() > maxlen)
{
if (spc < 0 || spc > maxlen)
{
spc = desc.left(maxlen).rfind(' ');
if (spc < maxlen/2)
spc = maxlen;
}
rec.put(RDOC_DESCR, desc.left(spc));
rec.put(RDOC_DESCLUNGA, "X");
rec.put(RDOC_DESCEST, desc.mid(spc));
}
else
{
rec.put(RDOC_DESCR, desc);
rec.zero(RDOC_DESCLUNGA);
rec.put(RDOC_DESCEST, "");
}
return !rec.empty();
}
bool TSAL_emsk::on_key(KEY k)
{
if (k == K_SHIFT + K_F12)
{
enable(F_STATO);
return true;
}
return TAutomask::on_key(k);
}
/*
bool TSAL_emsk::on_fasi_button(TOperable_field& o, TField_event e, long jolly)
{
TSAL_tree& t = tree();
TTree_field& fasi = t.owner();
TSAL_level pl = sl_documento;
if (fasi.goto_selected())
pl = t.level();
else
return false;
if (pl == sl_documento && o.dlg() == F_FASENEW)
pl = sl_fase1;
if (pl < sl_fase1 || pl > sl_distinta)
return false;
o.disable();
switch (o.dlg())
{
case F_FASENEW:
{
TMask m("Nuovo", 1, 46, 7);
m.add_string(S_CODART, 0, "Codice ", 1, 1, 20).check_type(CHECK_REQUIRED);
m.add_string(S_DESCR, 0, "Descrizione ", 1, 2, 50, "", 30).check_type(CHECK_REQUIRED);
m.add_button(DLG_OK, 0, "", -12, -1, 10, 2);
m.add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2);
if (m.run() == K_ENTER)
{
TRectype* rec = t.new_row(pl);
rec->put(RDOC_CODART, m.get(S_CODART));
rec->put(RDOC_DESCR, m.get(S_DESCR));
if (tree().level() == pl)
t.add_rbrother(rec);
else
{
t.append_row(*rec);
delete rec;
}
}
}
break;
case F_FASEDIT:
{
TRectype& rec = *t.curr_row();
TMask m("Modifica", 1, 46, 7);
m.add_string(S_CODART, 0, "Codice ", 1, 1, 20).check_type(CHECK_REQUIRED);
m.add_string(S_DESCR, 0, "Descrizione ", 1, 2, 50, "", 30).check_type(CHECK_REQUIRED);
m.add_button(DLG_OK, 0, "", -13, -1, 10, 2);
m.add_button(DLG_DELREC, 0, "", -23, -1, 10, 2);
m.add_button(DLG_CANCEL, 0, "", -33, -1, 10, 2);
m.set(S_CODART, rec.get(RDOC_CODART));
m.set(S_DESCR, rec.get(RDOC_DESCR));
switch (m.run())
{
case K_ENTER:
rec.put(RDOC_CODART, m.get(S_CODART));
rec.put(RDOC_DESCR, m.get(S_DESCR));
break;
case K_DEL:
t.kill_node();
break;
default:
break;
}
}
break;
default:
break;
}
o.enable();
fasi.select_current();
fasi.force_update();
return true;
}
*/
bool TSAL_emsk::on_fasi_event(TTree_field& fasi, TField_event e, long jolly)
{
bool modified = false;
bool can_edit = false;
bool can_goup = false;
bool can_godn = false;
switch (e)
{
case fe_modify:
if (fasi.goto_selected())
{
modified = true;
TSAL_tree& t = tree();
TSAL_level td = t.level();
if (td > sl_documento)
{
can_edit = true;
can_goup = t.has_lbrother();
can_godn = t.has_rbrother();
if (td < sl_distinta) // Cambio fase
{
TString16 id;
t.curr_id(id);
set_fase(id);
}
else
{
while (td > sl_distinta)
{
t.goto_father();
td = t.level();
}
TString idd; t.curr_id(idd);
if (t.goto_father())
{
TString idf; t.curr_id(idf);
if (idf != _idfase)
set_fase(idf);
}
set_dist(idd);
}
}
}
break;
default:
break;
}
// if (modified) enable(F_FASEDIT, can_edit);
return true;
}
bool TSAL_emsk::on_dist_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case S_CODART:
if (e == fe_modify && !o.empty())
{
const TString& codart = o.get();
TMask& m = o.mask();
TToken_string tok; tok << codart << "|1";
const TString& um = cache().get(LF_UMART, tok, "UM");
if (um.full())
m.set(S_UMART, um);
TEdit_field& iva = m.efield(S_CODIVA);
if (iva.empty())
on_dist_event(iva, fe_init, jolly);
}
break;
case S_CODIVA:
if ((e == fe_init || e == fe_close) && o.empty())
{
const TString& codcms = fget(DOC_CODCMS);
TString4 codiva = cache().get(LF_COMMESSE, codcms, COMMESSE_CODIVA);
if (codiva.blank())
{
const TString& codart = o.mask().get(S_CODART);
codiva = cache().get(LF_ANAMAG, codart, ANAMAG_CODIVA);
}
o.set(codiva);
}
break;
case F_DISTINTE:
switch (e)
{
case se_enter:
_edit_dist = -1;
set_dist(_curr_dist = jolly);
break;
case se_query_add:
return _idfase.full();
case se_notify_add:
{
TSAL_tree& t = tree();
TRectype* rec = t.dist(_idfase, _curr_dist = jolly, true);
if (rec != NULL)
sync_tree();
}
break;
case se_query_modify:
if (jolly != _curr_dist)
set_dist(jolly);
_edit_fase = _idfase;
_edit_dist = _curr_dist = jolly;
break;
case se_leave:
case se_notify_modify:
if (_edit_dist >= 0)
{
const int r = _edit_dist; // Memorizza numero riga corrente
_edit_dist = -1; // Annulla numero riga corrente
TRectype* rec = tree().dist(_edit_fase, r, false);
if (rec != NULL)
{
const TSheet_field& sheet = (TSheet_field&)o;
const TMask& m = sheet.sheet_row_mask(r);
msk2rec(m, *rec);
sync_tree();
}
}
break;
case se_notify_del:
if (_curr_dist >= 0)
{
TSAL_tree& t = tree();
TRectype* rec = t.dist(_idfase, _curr_dist);
if (rec != NULL)
{
t.kill_node();
sync_tree();
}
}
break;
default: break;
}
break;
default: break;
}
return true;
}
bool TSAL_emsk::on_misu_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case 102:
case 103:
case 104:
case 105:
if (e == fe_modify && _curr_misu >= 0 && _curr_dist >= 0)
{
TSheet_field& misure = sfield(F_MISURE);
TEdit_field& tot = o.mask().efield(106);
tot.validate(K_TAB);
misure.row(_curr_misu).add(tot.get(), 5);
update_dist_qta();
}
break;
case F_MISURE:
switch (e)
{
case se_query_add:
return _iddist.full();
case se_notify_add:
tree().misu(_iddist, _edit_misu = jolly, true);
break;
case se_enter:
_edit_misu = -1;
_curr_misu = jolly;
break;
case se_query_modify:
_edit_fase = _idfase;
_edit_dist = _curr_dist;
_edit_misu = _curr_misu = jolly;
break;
case se_leave:
case se_notify_modify:
if (_edit_dist >= 0 && _edit_misu >= 0)
{
TSAL_tree& t = tree();
t.dist(_edit_fase, _edit_dist, false);
TString idd; t.curr_id(idd);
TRectype* rec = t.misu(idd, _edit_misu, false);
if (rec != NULL)
{
TSheet_field& sheet = (TSheet_field&)o;
const TMask& m = sheet.sheet_row_mask(_edit_misu);
msk2rec(m, *rec);
update_dist_qta();
}
_edit_misu = -1;
}
break;
case se_notify_del:
if (_curr_misu >= 0)
{
TSAL_tree& t = tree();
TRectype* rec = t.misu(_iddist, _curr_misu);
if (rec != NULL)
{
t.kill_node();
update_dist_qta();
}
}
break;
default: break;
}
default:
break;
}
return true;
}
void TSAL_emsk::update_dist(const real& val, const TDate& dt_new)
{
TSheet_field& dist = sfield(F_DISTINTE);
TToken_string& row = dist.row(_curr_dist);
row.add(val.string(), dist.cid2index(S_QTA));
if (dt_new.ok())
{
TDate dt_old; row.get(dist.cid2index(S_DATALAV), dt_old);
if (dt_new > dt_old)
row.add(dt_new.string(), dist.cid2index(S_DATALAV));
}
dist.update_mask(_curr_dist);
TOperable_field& o = dist.sheet_row_mask(_curr_dist).efield(S_QTA);
on_dist_event(o, fe_modify, 1);
dist.force_update(_curr_dist);
TRectype* rec = tree().dist(_idfase, _curr_dist);
if (rec)
msk2rec(dist.sheet_row_mask(_curr_dist), *rec);
}
void TSAL_emsk::update_dist_qta()
{
if (_curr_dist >= 0)
{
TSheet_field& sheet = sfield(F_MISURE);
real tot;
TDate data_lavori;
FOR_EACH_SHEET_ROW(sheet, i, row)
{
tot += real(row->get(sheet.cid2index(106))); // 106 = totale
const TDate data = row->get();
if (data > data_lavori)
data_lavori = data;
}
update_dist(tot, data_lavori);
sync_tree();
}
}
struct SAL_tot : public TObject
{
real _totdoc;
real _sicurezza;
real _esclusi;
real _t_totdoc;
real _t_sicurezza;
real _t_esclusi;
};
static bool calc_totdoc(TTree& tree, void* jolly, word)
{
const TSAL_tree& t = (const TSAL_tree&)tree;
const TRectype& rec = *t.curr_row();
if (t.level(rec) == sl_distinta)
{
const real qta = rec.get(RDOC_QTA); // da 3 a 5 decimali
const real prz = rec.get(RDOC_PREZZO); // da 0 a 3 decimali
if (!qta.is_zero() && !prz.is_zero())
{
const int tipo = rec.get_int(RDOC_TIPODET); // 0=lavori, ..., 3=Sicurezza, 4=esclusi
const TCurrency parziale(real(qta * prz)); // arrotonda all'euro
const real& imp = parziale.get_num();
SAL_tot& tot = *(SAL_tot*)jolly;
tot._totdoc += imp;
switch (tipo)
{
case 3: tot._sicurezza += imp; break;
case 4: tot._esclusi += imp; break;
default: break;
}
}
}
return false;
}
bool TSAL_emsk::sync_totdoc()
{
TSAL_tree& t = tree();
if (!t.goto_root())
return false;
const bool attivo = get(F_TIPOCF)[0] != 'F';
const TRectype& doc = *t.curr_row();
real importo_base, sicurezza_cantiere;
TString4 codiva;
SAL_tot tot;
t.scan_depth_first(calc_totdoc, &tot);
if (t.goto_firstson())
{
const TRiga_documento* row = (TRiga_documento*)t.curr_row();
const TRectype* ord = row->find_original_doc();
if (ord != NULL)
{
const TVariable_rectype ordine(*ord);
importo_base = ordine.get_real("TOTDOC");
if (!attivo)
{
TDocumento orig(*ord);
FOR_EACH_PHYSICAL_RDOC(orig, r, rdoc)
{
codiva = rdoc->get(RDOC_CODIVA);
if (codiva.full())
break;
}
}
}
}
const TRectype& cantiere = cache().get(LF_COMMESSE, doc.get(DOC_CODCMS));
const real& lor = tot._totdoc;
const real& esc = tot._esclusi;
real sic = tot._sicurezza;
real prib;
if (attivo)
{
if (importo_base.is_zero())
importo_base = cantiere.get_real(COMMESSE_IMPORTOB);
sicurezza_cantiere = cantiere.get_real(COMMESSE_SICUREZZA);
prib = cantiere.get_real(COMMESSE_RIBASSO);
if (codiva.blank())
codiva = cantiere.get(COMMESSE_CODIVA);
}
set(F_SAL_LOR, lor);
if (sic.is_zero() && !importo_base.is_zero())
{
sic = lor * sicurezza_cantiere / importo_base;
sic.round(2);
}
set(F_SAL_SIC, sic);
set(F_SAL_ESC, esc);
const real sicesc = sic + esc;
set(F_SAL_SIC2, sicesc);
const real idr = lor - sicesc;
set(F_SAL_IDR, idr);
set(F_SAL_PRIB, prib);
real rib = idr * prib / CENTO; rib.round(2);
set(F_SAL_RIB, rib);
const real irb = idr - rib;
set(F_SAL_IRB, irb);
const real sal = irb + sicesc;
set(F_SAL_SAL, sal);
real pgar = ZERO;
const TString& exp_gar = get(F_PGARANZIA);
if (exp_gar.full())
{
TString80 dummy;
if (scontoexpr2perc(exp_gar, false, dummy, pgar))
pgar = (UNO-pgar)*CENTO;
}
set(F_SAL_PGAR, pgar);
real gar = sal * pgar / CENTO; gar.round(2);
set(F_SAL_GAR, gar);
real ant = ZERO;
real pant = ZERO;
const TString& exp_ant = get(F_PANTICIPO);
if (exp_ant.full())
{
TString80 dummy;
real eant = ZERO;
if (scontoexpr2perc(exp_ant, false, dummy, eant))
{
pant = (UNO-eant)*CENTO;
ant = sal * pant / CENTO;
ant.round(2);
}
}
set(F_SAL_PANT, pant);
set(F_SAL_ANT, ant);
const real net = sal - ant - gar;
set(F_SAL_NET, net);
real piva = ZERO;
if (codiva.full())
piva = real(cache().get("%IVA", codiva, "R0"));
real iva = net * piva / CENTO; iva.round(2);
set(F_SAL_PIVA, piva);
set(F_SAL_IVA, iva);
set(F_SAL_TOT, real(net + iva));
return !sal.is_zero();
}
bool TSAL_emsk::sync_tree()
{
TSAL_tree& t = tree();
TTree_field& tf = t.owner();
tf.force_update();
return sync_totdoc();
}
bool TSAL_emsk::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_STATO:
if ((e == fe_init || e == fe_close) && o.empty())
o.set("1");
if (e == fe_modify && !o.empty())
app().update_tools(*this);
break;
case F_FASI:
return on_fasi_event((TTree_field&)o, e, jolly);
/*
case F_FASENEW:
case F_FASEDIT:
if (e == fe_button)
return on_fasi_button(o, e, jolly);
break;
*/
case F_DISTINTE:
return on_dist_event(o, e, jolly);
case F_MISURE:
return on_misu_event(o, e, jolly);
case DLG_PRINT:
if (e == fe_button)
app().report("sl1600");
break;
case B_PRINT_LIB:
if (e == fe_button)
app().report("sl1400");
break;
case B_PRINT_REG:
if (e == fe_button)
app().report("sl1500");
break;
case DLG_ELABORA:
if (e == fe_button)
{
const TString16 cod = sl_trova_elaborazione(*this);
if (cod.full())
{
app().rewrite(*this);
sl_genera_documento(app().get_relation()->curr(), cod);
}
}
break;
case DLG_ARCHIVE:
if (e == fe_button)
{
}
break;
case F_SAL_TOT:
if (e == fe_init && o.empty())
sync_totdoc();
break;
default:
if (jolly > 0 && o.dlg() >= DLG_USER && o.dlg() < 2*DLG_USER) // Sheet mask events
{
if (e == fe_modify)
{
switch (jolly)
{
case 1: return on_dist_event(o, e, jolly);
case 2: return on_misu_event(o, e, jolly);
default: CHECK(false, "Unknown sheet field event"); break;
}
}
}
break;
}
return TSAL_msk::on_field_event(o, e, jolly);
}
void TSAL_emsk::set_sheet_color(short id, COLOR col)
{
const COLOR rgb = blend_colors(NORMAL_BACK_COLOR, col, 0.75);
TSheet_field& s = sfield(id);
s.set_back_and_fore_color(rgb, NORMAL_COLOR, -1);
}
TSAL_emsk::TSAL_emsk() : TSAL_msk("sl0100b"), _tree(NULL), _locked(false)
{
TMask_field& cdc0 = field(F_CDC0);
RCT rct0; cdc0.get_rect(rct0);
const int yca = rct0.top / ROWY + 1; // Riga del primo campo di analitica
short idcdc, idcms, idfase, idconto;
ca_create_fields_ext(*this, 0, 2, yca, F_CDC0+1, idcdc, idcms, idfase, idconto,
DOC_CODCOSTO, DOC_CODCMS /*, DOC_FASCMS */); // Niente fasi qui!
set_sheet_color(F_DISTINTE, COLOR_YELLOW);
set_sheet_color(F_MISURE, COLOR_GRAY);
}
///////////////////////////////////////////////////////////
// TSAL_app
///////////////////////////////////////////////////////////
bool TSAL_app::user_create()
{
open_files(LF_TAB, LF_TABCOM, LF_CLIFO, LF_ANAMAG, LF_UMART,
LF_DOC, LF_RIGHEDOC, LF_COMMESSE, LF_FASI, 0);
_rel = new TRelation(LF_DOC);
_qmsk = new TSAL_qmsk;
_emsk = new TSAL_emsk;
return true;
}
bool TSAL_app::user_destroy()
{
delete _emsk;
delete _qmsk;
delete _rel;
return true;
}
const char* TSAL_app::record_description(const TRelation& r) const
{
TString& tmp = get_tmp_string();
tmp << title() << " n." << r.curr().get(DOC_NUMANT);
return tmp;
}
TCursor& TSAL_app::get_filtered_cursor() const
{
TEdit_field& f = _qmsk->efield(F_NDOC);
TCursor& cur = *f.browse()->cursor();
if (cur.items() == 0) // A volte deve scantarsi ...
f.check(); // ... forzo ricalcolo elementi
return cur;
}
int TSAL_app::read(TMask& m)
{
int err = TRelation_application::read(m);
if (err == NOERR)
{
const TRectype& doc = get_relation()->curr();
TSAL_tree& t = ((TSAL_emsk&)m).tree();
t.load(doc);
}
return err;
}
static bool tree_save_row(TTree& tree, void* jolly, word /*flags*/)
{
TSAL_tree& t = (TSAL_tree&)tree;
const TRectype* rec = t.curr_row();
if (rec && !rec->empty() && rec->num() == LF_RIGHEDOC)
{
const char* full_field[] = { RDOC_DESCR, RDOC_QTA, RDOC_PREZZO,
RDOC_QTAGG1, RDOC_QTAGG2, RDOC_QTAGG3,
RDOC_QTAGG4, RDOC_QTAGG5, RDOC_DATACONS,
NULL } ;
bool one_full = false;
for (int f = 0; full_field[f] && !one_full; f++)
{
if (f == 0)
one_full = rec->get(full_field[f]).full();
else
one_full = !rec->get_real(full_field[f]).is_zero();
}
if (one_full)
{
TDocumento& doc = *(TDocumento*)jolly;
const TString4 tiporiga = rec->get(RDOC_TIPORIGA);
TRectype& row = doc.new_row(tiporiga);
const TString80 codart = rec->get(RDOC_CODART);
TString80 codartmag;
if (codart.full())
codartmag = cache().get(LF_ANAMAG, codart, ANAMAG_CODART);
for (int f = rec->items()-1; f > 5; f--)
{
const char* fld = rec->fieldname(f);
if (rec->type(fld) == _memofld)
break;
const TString& src = rec->get(fld);
if (src.full())
{
const TString& dst = row.get(fld);
if (dst.blank())
row.put(fld, src);
}
}
row.put(RDOC_IDRIGA, row.get(RDOC_NRIGA));
row.put(RDOC_TIPORIGA, rec->get(RDOC_TIPORIGA));
row.put(RDOC_QTA, rec->get(RDOC_QTA));
row.put(RDOC_QTAEVASA, rec->get(RDOC_QTAEVASA));
row.put(RDOC_DESCR, rec->get(RDOC_DESCR));
row.put(RDOC_DESCLUNGA, rec->get(RDOC_DESCLUNGA));
row.put(RDOC_DESCEST, rec->get(RDOC_DESCEST));
row.put(RDOC_CODART, codart);
row.put(RDOC_CODARTMAG, codartmag);
row.put(RDOC_CHECKED, codartmag.full());
row.put(RDOC_UMQTA, rec->get(RDOC_UMQTA));
row.put(RDOC_QTAGG1, rec->get(RDOC_QTAGG1));
row.put(RDOC_QTAGG2, rec->get(RDOC_QTAGG2));
row.put(RDOC_QTAGG3, rec->get(RDOC_QTAGG3));
row.put(RDOC_QTAGG4, rec->get(RDOC_QTAGG4));
row.put(RDOC_QTAGG5, rec->get(RDOC_QTAGG5));
row.put(RDOC_PREZZO, rec->get(RDOC_PREZZO));
row.put(RDOC_DATACONS, rec->get(RDOC_DATACONS));
row.put(RDOC_TIPOCOLL, rec->get(RDOC_TIPOCOLL));
row.put(RDOC_IDRIGACOLL,rec->get(RDOC_IDRIGACOLL));
row.put(RDOC_TIPODET, rec->get(RDOC_TIPODET));
row.put(RDOC_CODCMS, doc.get(RDOC_CODCMS)); // Commessa/cantiere da DOC
row.put(RDOC_FASCMS, rec->get(RDOC_FASCMS)); // Fase specifica da riga
}
}
return false; // Don't stop scan
}
int TSAL_app::save_rows(const TMask& m)
{
TSAL_emsk& sm = (TSAL_emsk&)m;
TSAL_tree& tree = sm.tree();
TDocumento doc(get_relation()->curr());
doc.destroy_rows();
if (tree.goto_root() && tree.goto_firstson())
tree.scan_depth_first(tree_save_row, &doc);
// Estrae campi analitica da maschera principale e li riporta sulle righe
const TString80 cdc = sm.fget(DOC_CODCOSTO);
const TString80 cms = sm.fget(DOC_CODCMS);
TRecord_array& rdoc = doc.body();
rdoc.renum_key(RDOC_CODCOSTO, cdc);
rdoc.renum_key(RDOC_CODCMS, cms);
rdoc.renum_key(RDOC_DAPROVV, "D");
rdoc.renum_key(RDOC_DAANNO, _qmsk->get(F_ANNO_ORD));
rdoc.renum_key(RDOC_DACODNUM, _qmsk->get(F_CODNUM_ORD));
rdoc.renum_key(RDOC_DANDOC, _qmsk->get(F_NDOC_ORD));
FOR_EACH_MASK_FIELD(sm, i, f)
{
const TFieldref* fr = f->field();
if (fr != NULL)
{
const TString& value = f->get();
if (fr->name().starts_with("G1:"))
{
const TString& fname = fr->name().mid(3);
doc.put(fname, value);
}
else
fr->write(value, doc.head());
}
}
const int err = doc.rewrite(get_relation()->file());
return err;
}
int TSAL_app::write(const TMask& m)
{
get_relation()->curr().zero("G1");
int err = TRelation_application::write(m);
if (err == NOERR)
err = save_rows(m);
return err;
}
int TSAL_app::rewrite(const TMask& m)
{
get_relation()->curr().zero("G1");
int err = TRelation_application::rewrite(m);
if (err == NOERR)
err = save_rows(m);
return err;
}
bool TSAL_app::remove()
{
bool done = TRelation_application::remove();
if (done)
{
const TRectype& rec = get_relation()->curr();
TToken_string keytok;
keytok.add(rec.get(DOC_CODNUM));
keytok.add(rec.get(DOC_ANNO));
keytok.add(rec.get(DOC_PROVV));
keytok.add(rec.get(DOC_NDOC));
TRecord_array rdoc(keytok, LF_RIGHEDOC);
rdoc.remove();
}
return done;
}
void TSAL_app::update_tools(TMask& m)
{
const bool is_edit = m.edit_mode();
bool can_print = is_edit;
if (can_print)
{
TFilename rep = "sl1400.rep"; // Libretto delle misure
can_print = rep.custom_path();
}
m.enable(DLG_NEWREC, is_edit);
m.enable(DLG_PRINT, can_print);
m.enable(DLG_ELABORA, sl_trova_elaborazione(m).full());
m.enable(B_PRINT_LIB, can_print);
m.enable(B_PRINT_REG, can_print);
m.disable(F_STATO); // Enable with F12
}
bool TSAL_app::get_next_key(TToken_string& key)
{
const char provv = _qmsk->get(F_PROVV)[0];
const int anno = _qmsk->get_int(F_ANNO);
const TString& codnum = _qmsk->get(F_CODNUM);
if (anno < 2000 || codnum.blank())
return false; // Rinumera con anno e numerazione validi
long newdoc = 1L;
TLocalisamfile doc(LF_DOC);
doc.put(DOC_PROVV, provv);
doc.put(DOC_ANNO, anno);
doc.put(DOC_CODNUM, codnum);
doc.put(DOC_NDOC, 9999999);
int err = doc.read(_isgreat);
if (err == NOERR)
err = doc.prev();
else
err = doc.last();
if (err == NOERR && doc.get(DOC_CODNUM) == codnum)
newdoc += doc.get_long(DOC_NDOC);
key.cut(0);
key.add(F_PROVV); key.add(provv);
key.add(F_ANNO); key.add(anno);
key.add(F_CODNUM); key.add(codnum);
key.add(F_NDOC); key.add(newdoc);
return true;
}
void TSAL_app::init_insert_mode(TMask& m)
{
TRelation_application::init_insert_mode(m);
m.set(F_DATADOC, TDate(TODAY));
long nsal = 1;
const char ord_provv = _qmsk->get(F_PROVV)[0];
const int ord_anno = _qmsk->get_int(F_ANNO_ORD);
const TString& ord_codnum = _qmsk->get(F_CODNUM_ORD);
const long ord_ndoc = _qmsk->get_long(F_NDOC_ORD);
TString filter;
filter.format("DAPROVV=%c DAANNO=%d DACODNUM=%s DANDOC=%ld",
ord_provv, ord_anno, (const char*)ord_codnum, ord_ndoc);
TString query;
query << "USE 34 KEY 4\nJOIN 33 INTO PROVV=PROVV ANNO=ANNO CODNUM==CODNUM NDOC==NDOC\n"
<< "FROM " << filter << "\nTO " << filter;
TISAM_recordset rsal(query);
if (rsal.move_last())
nsal += rsal.cursor()->curr(LF_DOC).get_int(DOC_NUMANT);
m.set(F_NSAL, nsal);
TSAL_tree& t = ((TSAL_emsk&)m).tree();
const TRectype* model = &rsal.cursor()->curr(LF_DOC); // Usa come modello l'ultimo SAL
if (nsal <= 1) // Primo SAL
{
const TEdit_field& fld_ord = _qmsk->efield(F_NDOC_ORD);
model = &fld_ord.browse()->cursor()->curr(LF_DOC); // Usa come modello l'ordine
// Copia anticipo e granzia cliente
if (model->get_char(DOC_TIPOCF) != 'F')
{
const TRectype& cms = cache().get(LF_COMMESSE, model->get(DOC_CODCMS));
m.set(F_PANTICIPO, cms.get(COMMESSE_ANTICIPO));
m.set(F_PGARANZIA, cms.get(COMMESSE_GARANZIA));
}
}
TSAL_msk& sm = (TSAL_msk&)m;
FOR_EACH_MASK_FIELD(sm, i, f)
{
if (f->empty() && f->active() && f->field() != NULL)
{
const TString& name = f->field()->name();
sm.fset(name, model->get(name), 0x2);
}
}
t.load(*model, nsal);
update_tools(m);
}
void TSAL_app::init_modify_mode(TMask& m)
{
TRelation_application::init_modify_mode(m);
update_tools(m);
}
void TSAL_app::print()
{
app().report("sl1400");
}
bool TSAL_app::report(const char* name)
{
static bool already_printing = false;
if (already_printing)
return false;
already_printing = true;
TFilename rep = name; rep.ext("rep");
if (!rep.custom_path())
return cantread_box(rep.name());
if (rewrite(*_emsk) != NOERR)
return cantwrite_box("SAL");
TFilename ini; ini.tempdir(); ini.add(name); ini.ext("ini");
if (ini.full())
{
TConfig cfg(ini, "Transaction");
cfg.set("Action", printer().printtype() == screenvis ? "Preview" : "Print");
cfg.set_paragraph("Vars");
cfg.remove_all();
TSAL_msk& sm = *(TSAL_msk*)_emsk;
FOR_EACH_MASK_FIELD(sm, i, f) if (f->is_edit() && !f->empty())
{
const TFieldref* field = f->field();
if (field != NULL && field->from() == 0)
{
const TString& name = field->name();
cfg.set(name, sm.fget(name));
}
}
cfg.set(RDOC_DAPROVV, _qmsk->get(F_PROVV));
cfg.set(RDOC_DAANNO, _qmsk->get(F_ANNO_ORD));
cfg.set(RDOC_DACODNUM, _qmsk->get(F_CODNUM_ORD));
cfg.set(RDOC_DANDOC, _qmsk->get(F_NDOC_ORD));
}
TString cmd;
cmd << "ba8 -4 " << rep;
if (ini.exist())
cmd << " -i" << ini;
TExternal_app a(cmd);
a.run();
already_printing = false;
return true;
}
int sl0100(int argc, char* argv[])
{
TSAL_app a;
a.run(argc, argv, TR("S.A.L."));
return 0;
}