campo-sirio/ha/ha3900.cpp
luca d4647d0c49 Patch level :
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :


git-svn-id: svn://10.65.10.50/branches/R_10_00@22000 c028cbd2-c16b-5b4b-a496-9718f37d4682
2011-04-20 15:44:15 +00:00

623 lines
18 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <automask.h>
#include <colors.h>
#include <defmask.h>
#include <execp.h>
#include <recarray.h>
#include <recset.h>
#include <relation.h>
#include <tabmod.h>
#include <tree.h>
#include <treectrl.h>
#include "../mg/anamag.h"
#include "ha3.h"
#include "ha3900a.h"
//////////////////////////////////////////////
// Albero
//////////////////////////////////////////////
//Albero per la gestione delle macchine di un cliente
class TCoffee_tree : public TBidirectional_tree
{
TString8 _curr_node;
long _codcf;
long _progressivo;
TString8 _codart;
TString16 _matricola, _cespite;
TISAM_recordset _recset;
public:
virtual bool goto_root();
virtual bool goto_firstson() { return false; }
virtual bool goto_rbrother();
virtual bool goto_node(const TString &id);
virtual bool could_have_son() const { return false; }
virtual bool has_son() const { return false; }
virtual bool has_rbrother() const;
virtual TObject* curr_node() const { return (TObject*)&_curr_node; }
virtual void node2id(const TObject* obj, TString& id) const { id = *(TString*)obj; }
virtual bool has_root() const;
virtual bool has_father() const { return false; }
virtual bool has_lbrother() const;
virtual bool goto_father() { return false; }
virtual bool goto_lbrother();
virtual bool get_description(TString& desc) const;
virtual TFieldtypes get_var(const TString& name, TVariant& var) const;
virtual TImage* image(bool selected) const { return get_res_icon(10232); } //mai dimenticarsi la moka!
public:
bool set_clifo(long codcf);
bool select_attr(const TString& codart, const long progressivo);
const long get_codcf() const;
const TString& get_codart() const;
const long get_progressivo() const;
const TString& get_matricola() const;
const TString& get_cespite() const;
TCoffee_tree() : _codcf(0), _recset("USE &ATT") { set_clifo(0L); }
};
bool TCoffee_tree::has_root() const
{
return _recset.items() > 0L;
}
bool TCoffee_tree::goto_root()
{
const bool ok = _recset.move_first();
if (ok)
_curr_node = "0";
else
_curr_node.cut(0);
return ok;
}
bool TCoffee_tree::has_rbrother() const
{
const long pos = atol(_curr_node);
return pos < _recset.items() - 1;
}
bool TCoffee_tree::goto_rbrother()
{
const long pos = atol(_curr_node) + 1;
const bool ok = _recset.move_to(pos);
if (ok)
_curr_node.format("%ld", pos);
return ok;
}
bool TCoffee_tree::has_lbrother() const
{
return atol(_curr_node) > 0L;
}
bool TCoffee_tree::goto_lbrother()
{
const long pos = atol(_curr_node) - 1;
const bool ok = pos >= 0 && _recset.move_to(pos);
if (ok)
_curr_node.format("%ld", pos);
return ok;
}
bool TCoffee_tree::goto_node(const TString &id)
{
const long pos = atol(id);
const bool ok = _recset.move_to(pos);
if (ok)
_curr_node = id;
return ok;
}
bool TCoffee_tree::get_description(TString& desc) const
{
desc = _recset.get("CODTAB").as_string();
return desc.full();
}
TFieldtypes TCoffee_tree::get_var(const TString& name, TVariant& var) const
{
//se il campo richiesto <20> la descrizione ci vuole quella dell'articolo, non dell'attrezzatura..
//..che risulta vuota
if (name == "S10")
{
TString8 codart = _recset.get("CODTAB[1,5]").as_string();
codart.trim();
var = cache().get(LF_ANAMAG, codart, ANAMAG_DESCR);
}
else
var = _recset.get(name);
return var.type();
}
const TString& TCoffee_tree::get_codart() const
{
return _codart;
}
const long TCoffee_tree::get_progressivo() const
{
return _progressivo;
}
const TString& TCoffee_tree::get_matricola() const
{
return _matricola;
}
const TString& TCoffee_tree::get_cespite() const
{
return _cespite;
}
const long TCoffee_tree::get_codcf() const
{
return _codcf;
}
bool TCoffee_tree::set_clifo(long codcf)
{
_codcf = codcf;
TString query;
query << "USE &ATT\nSELECT I0=" << codcf;
_recset.set(query);
return goto_root();
}
bool TCoffee_tree::select_attr(const TString& codart, const long progressivo)
{
bool found = false;
for (bool ok = _recset.move_first(); ok; ok = _recset.move_next())
{
TString8 curr_codart = _recset.get("CODTAB[1,5]").as_string();
curr_codart.trim();
if (curr_codart == codart)
{
_codart = codart;
const long curr_progressivo = _recset.get("CODTAB[6,12]").as_int();
if (curr_progressivo == progressivo)
{
_curr_node.format("%ld", _recset.current_row());
found = true;
_progressivo = progressivo;
_matricola = _recset.get("S0[6,20]").as_string();
_cespite = _recset.get("S1").as_string();
break;
}
}
}
return found;
}
//////////////////////////////////////////////
// Metodi static di ordinamento dello sheet
//////////////////////////////////////////////
static int sort_by_data(TSheet_field& s, int r1, int r2)
{
TToken_string& s1 = s.row(r1);
TToken_string& s2 = s.row(r2);
//prima ordina per data dalla piu' recente alla piu' antica..
const int datacomp_pos = s.cid2index(S_DATA);
const TDate d1 = s1.get(datacomp_pos);
const TDate d2 = s2.get(datacomp_pos);
int cmp = int(d2 - d1);
//..poi per tipo (dal vuoto in avanti
if (cmp == 0)
{
const int tipo_pos = s.cid2index(S_TIPO);
const char c1 = s1.get_char(tipo_pos);
const char c2 = s2.get_char(tipo_pos);
cmp = int (c1 - c2);
}
return cmp;
}
//////////////////////////////////////////////
// Maschera
//////////////////////////////////////////////
class TGestione_attrezzature_mask : public TAutomask
{
bool _sheet_dirty;
protected:
void fill_sheet_storico(const TString& codattr);
bool write();
void save_if_dirty();
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TGestione_attrezzature_mask();
};
//metodo che riempie il primo sheet delle attrezzature in base ai filtri su cliente/attrezztura
void TGestione_attrezzature_mask::fill_sheet_storico(const TString& codattr)
{
//riempie lo sheet dello storico in base all'attrezzatura scelta nell'albero
TString query;
query << "USE &HIS";
query << "\nFROM CODTAB=#CODATTR";
query << "\nTO CODTAB=#CODATTR";
TISAM_recordset recset(query);
recset.set_var("#CODATTR", codattr);
const long recset_items = recset.items();
TSheet_field& sf_righe = sfield(F_STORICO);
sf_righe.destroy();
//maschera di sheet
TMask& msk = sf_righe.sheet_mask();
//record del recordset con i valori da mettere sulla riga sheet
const TRectype& rec = recset.cursor()->curr();
const long present_clifo = get_long(F_CODCF);
//new style (seza _pos_campo!)
for (bool ok = recset.move_first(); ok; ok = recset.move_next())
{
TToken_string& row = sf_righe.row(-1); //riga sheet da riempire
const long line_clifo = rec.get_long("I0");
//se il clifo presente sulla riga e' diverso da quello attuale la riga assumera' un vago colore pervinca
if (line_clifo != present_clifo)
sf_righe.set_back_and_fore_color(DISABLED_BACK_COLOR, DISABLED_COLOR, sf_righe.items()-1);
//per ogni campo della maschera di sheet setta..
//..il valore di quei campi che hanno un field
FOR_EACH_MASK_FIELD(msk, i, f)
{
const short id = f->dlg();
if (id >= 101 && id < 200)
{
const TFieldref* fr = f->field();
if (fr != NULL)
row.add(fr->read(rec), id - 101);
}
}
}
//mostra e aggiorna lo sheet ordinato per data (in alto le date maggiori)
sf_righe.sort(sort_by_data);
sf_righe.show();
sf_righe.force_update();
}
//metodo di salvataggio dei record dello sheet
bool TGestione_attrezzature_mask::write()
{
TTreelist_field& tf = (TTreelist_field&)field(F_ATTREZZATURE);
TCoffee_tree* ct = (TCoffee_tree*)tf.tree();
if (ct == NULL)
return false;
const TString& codart = ct->get_codart();
const long progressivo = ct->get_progressivo();
TSheet_field& sf_righe = sfield(F_STORICO);
//maschera di riga dello sheet
TMask& sm = sf_righe.sheet_mask();
//tabella di modulo con lo storico interventi
TModule_table his("&HIS");
TRectype& rec_his = his.curr();
//codice articolo + progressivo (prima parte del CODTAB del record di tabmod)
TString80 codtab;
codtab.format("%-5s%07d", (const char*)codart, progressivo);
//contatore delle righe che vengono salvate
int righe_tot = 0;
//giro su tutte le righe dello sheet
FOR_EACH_SHEET_ROW(sf_righe, r, riga)
{
short id = 101;
//giro su tutti i campi della riga (che <20> una sporca token_string)
//per prima cosa mette la chiave del record che <20> cos<6F> fatta:
// codart=codtab[1,5] - progressivo=codtab[6,12] - nriga=codtab[31,35]
TString80 curr_codtab;
curr_codtab.format("%05d", sf_righe.items() - r);
curr_codtab.insert(codtab);
//azzera il record senno' nei campi vuoti ci metterebbe quelli del record precedente
//deve azzerare la tabella, senno' perde il codice modulo HA ed il codice tabella HIS
his.zero();
rec_his.put("CODTAB", curr_codtab);
//poi quelli specifici della riga
FOR_EACH_TOKEN(*riga, str)
{
const TMask_field& mf = sm.field(id);
const TFieldref* fr = mf.field();
//solo i campi della maschera di riga che hanno un FIELD vengono salvati, gli altri si arrangino!
if (fr != NULL)
{
fr->write(str, rec_his);
}
id ++;
}
his.rewrite_write();
righe_tot ++;
}
//compatta le righe dello storico, eliminando quelle in esubero
TString query;
query << "USE &HIS";
query << "\nFROM CODTAB=#DAATTR";
query << "\nTO CODTAB=#AATTR";
TISAM_recordset recset(query);
TString80 daattr, aattr;
daattr.format("%s%05d", (const char*)codtab, righe_tot + 1);
aattr.format("%s%05d", (const char*)codtab, 99999);
recset.set_var("#DAATTR", daattr);
recset.set_var("#AATTR", aattr);
//accoppa tutte le righe in esubero dalla tabella &HIS
const long recset_items = recset.items();
for (bool ok = recset.move_first(); ok; ok = recset.move_next())
recset.cursor()->relation()->remove();
//una volta che ha salvato lo sheet deve risultare immacolato!
_sheet_dirty = false;
return true;
}
void TGestione_attrezzature_mask::save_if_dirty()
{
if (_sheet_dirty && yesno_box(TR("Salvare le modifiche ?")))
write();
}
bool TGestione_attrezzature_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
//campi
case F_CODCF:
if (e == fe_modify)
{
//albero magico: selezionando un cliente riempie l'albero con tutte le attrezzature del cliente
TTreelist_field& tf = (TTreelist_field&)field(F_ATTREZZATURE);
TCoffee_tree* ct = (TCoffee_tree*)tf.tree();
if (ct != NULL)
{
ct->set_clifo(atol(o.get()));
tf.win().force_update();
}
}
break;
case F_PROGRESSIVO:
if (e == fe_modify)
{
//albero magico: selezionando un'attrezzatura, si posiziona direttamente sulla giusta posizione nell'albero..
//..(il cliente viene riempito dalla maschera)
TTreelist_field& tf = (TTreelist_field&)field(F_ATTREZZATURE);
TCoffee_tree* ct = (TCoffee_tree*)tf.tree();
if (ct != NULL)
{
ct->set_clifo(get_long(F_CODCF));
const TString& codart = get(F_CODART);
const long progressivo = get_long(F_PROGRESSIVO);
if (ct->select_attr(codart, progressivo))
{
tf.select_current();
send_key(K_SPACE, F_ATTREZZATURE, &o);
}
}
}
break;
case F_ATTREZZATURE:
if (e == fe_modify)
{
TTreelist_field& tf = (TTreelist_field&)field(F_ATTREZZATURE);
TCoffee_tree* ct = (TCoffee_tree*)tf.tree();
if (ct != NULL)
{
TString80 codattr;
ct->get_description(codattr);
//riempie i campi di intestazione maschera
set(F_CODART, codattr.left(5));
set(F_PROGRESSIVO, codattr.mid(5,7));
check_field(F_CODART);
//chiede di salvare le modifiche al cambio attrezzatura
save_if_dirty();
//seleziona sull'albero
ct->select_attr(get(F_CODART), get_long(F_PROGRESSIVO));
//la select_attr fa sapere all'albero matricola e cespite -> si possono mettere sulla maschera)
set(F_MATRICOLA, ct->get_matricola());
set(F_CESPITE, ct->get_cespite());
//riempie lo sheet
fill_sheet_storico(codattr);
}
}
break;
case F_STORICO:
if (e == se_query_modify || e == se_notify_del)
{
_sheet_dirty = true;
}
if (e == se_notify_add)
{
//quando si aggiunge una riga si deve fare il sorting in modo che venga come prima riga in alto
TSheet_field& sf = sfield(o.dlg());
TToken_string& row = sf.row(jolly); //riga corrente appena aggiunta
row.add(TDate(TODAY), sf.cid2index(S_DATA));
row.add(get(F_CODCF), sf.cid2index(S_CODCF));
sf.sort(sort_by_data);
sf.force_update();
sf.post_select(0); //evidenzia la prima riga
}
break;
//bottoni
case DLG_ADD_NEW:
if (e == fe_button)
{
//1) per prima cosa deve controllare che siano pieni i campi chiave della tabella ttrezzature, senno' non puo'..
//...aggiungere una cippa
if (get(F_CODART).empty() || get(F_PROGRESSIVO) <= 0L)
return warning_box(TR("E' necessario compilare articolo e progressivo per aggiungere una nuova attrezzatura!"));
TString80 codtab;
const TString& codart = get(F_CODART);
const long progressivo = get_long(F_PROGRESSIVO);
codtab.format("%-5s%07d", (const char*)codart, progressivo);
//2) controllo effettiva "nuovezza" dell'attrezzatura..
//...se l'utonto tentasse di inserire come nuova un'attrezzatura gi<67> esistente va cazziato!
TModule_table tab_att("&ATT");
tab_att.put("CODTAB", codtab);
const int err = tab_att.read();
if (err == NOERR)
return warning_box(TR("L'attrezzatura con questi articolo e progressivo esiste gia'!"));
//3) invio dati al gestore della tabella &ATT delle attrezzature tramite .ini
TFilename trans_ini;
trans_ini.temp(NULL, "ini");
TString4 filenumber;
filenumber << LF_TABMOD;
//i config vanno chiusi tra {} senno' non si riescono ad usare
{
TConfig ini(trans_ini, "Transaction");
ini.set("Action", "INSERT");
ini.set_paragraph(filenumber);
ini.set("CODTAB", codtab);
ini.set("I0", get(F_CODCF));
ini.set("D0", TDate(TODAY));
TString matricola;
matricola.format("%-5s%-15s", (const char*)get(F_CODART), (const char*)get(F_MATRICOLA));
ini.set("S0", matricola);
ini.set("S1", get(F_CESPITE));
}
//invio del config al gestore della tabella &ATT
TString80 cmd;
cmd << "ha0 -0 &ATT /i" << trans_ini;
TExternal_app app(cmd);
//4) lettura dell'ini di ritorno compilato ed aggiornamento conseguente di tabella e maschera
if (app.run() == NOERR)
{
//4a) setta sulla maschera i valori di ritorno del .ini (riempiti dal gestore di &ATT)
TConfig ini(trans_ini, "Transaction");
if (ini.get("Result") == "OK")
{
ini.set_paragraph(filenumber);
TString80 codtab = ini.get("CODTAB");
codtab.strip("\""); //elimina eventuali " che vengono dall'ini
const long codcf = ini.get_long("I0");
const TDate data_storico = ini.get("D0");
const TString& cespite = ini.get("S1");
const TString& full_matricola = ini.get("S0");
const TString16 matricola = full_matricola.mid(5,15);
//4b) da file ini crea un record nuovo sulla tabella &HIS; se non lo facesse l'albero con le attrezzature non..
//....potrebbe mai vedere la nuova attrezzatura aggiunta; sara' poi l'albero stesso ad occuparsi dello sheet
TModule_table tab_his("&HIS");
TString80 his_codtab = codtab;
his_codtab << "00001"; //l'attrezzatura <20> nuova! deve essere il primo record
tab_his.put("CODTAB", his_codtab);
tab_his.put("I0", codcf);
tab_his.put("D0", data_storico);
tab_his.put("S2", matricola);
tab_his.put("S1", cespite);
int can_write = tab_his.write();
if (can_write != NOERR)
return warning_box(TR("Impossibile aggiungere l'attrezzatura! Risulta gia' presente."));
set(F_CODCF, codcf, true);
set(F_CODART, codtab.left(5), true);
set(F_PROGRESSIVO, codtab.mid(5,7), true);
set(F_MATRICOLA, matricola);
set(F_CESPITE, cespite);
}
}
}
break;
case DLG_SAVEREC:
if (e == fe_button && check_fields())
{
write();
}
break;
case DLG_CANCEL:
if (e == fe_button && jolly == 0) //il jolly=0 significa che si riferisce alla maschera principale!..
{ //..se non ci fosse azzererebbe tutto anche quando si fa annulla sulla maschera di riga!
//nel caso l'utonto clicchi su ANNULLA dopo aver fatto modifiche sara' meglio chiedere conferma se le vuole mantenere
save_if_dirty();
//azzera i campi della maschera
reset();
TTreelist_field& tf = (TTreelist_field&)field(F_ATTREZZATURE);
TCoffee_tree* ct = (TCoffee_tree*)tf.tree();
if (ct != NULL)
{
ct->set_clifo(0L);
tf.win().force_update();
}
return false;
}
break;
case DLG_QUIT:
if (e == fe_button)
{
//nel caso l'utonto clicchi su FINE dopo aver fatto modifiche sara' meglio chiedere conferma se le vuole mantenere
save_if_dirty();
}
break;
default:
break;
}
return true;
}
TGestione_attrezzature_mask::TGestione_attrezzature_mask() : TAutomask("ha3900a")
{
//assegna l'albero del caffe' al campo di tipo albero sulla maschera
TTreelist_field& tf = (TTreelist_field&)field(F_ATTREZZATURE);
TCoffee_tree* ct = new TCoffee_tree;
tf.set_tree(ct);
//se non facesse questa precisazione non potrebbe inserire le righe in alto
TSheet_field& sf_storico = sfield(F_STORICO);
sf_storico.set_append(false);
//inizializza lo "sporcatore" dello sheet
_sheet_dirty = false;
}
//////////////////////////////////////////////
// Applicazione
//////////////////////////////////////////////
class TGestione_attrezzature : public TSkeleton_application
{
virtual void main_loop();
};
void TGestione_attrezzature::main_loop()
{
TGestione_attrezzature_mask mask;
while (mask.run() == K_ENTER)
{
}
}
int ha3900(int argc, char* argv[])
{
TGestione_attrezzature app;
app.run(argc, argv, TR("Gestione storico attrezzature"));
return 0;
}