97729484de
Files correlati : lv0 Ricompilazione Demo : [ ] Commento : E. Contratto 1) Non mi salva il ritiro in dotazione temporanea messo sulle righe del contratto dallelenco righe ma solo se vado nel dettaglio degli articoli 5) Se entro in modifica di un contratto e cambio un codice articolo mi chiede se sono sicuro ma se dico di si non lo aggiorna , se dico di no lo aggiorna. Deve essere il contrario git-svn-id: svn://10.65.10.50/trunk@19624 c028cbd2-c16b-5b4b-a496-9718f37d4682
1091 lines
35 KiB
C++
Executable File
1091 lines
35 KiB
C++
Executable File
#include <automask.h>
|
|
#include <defmask.h>
|
|
#include <execp.h>
|
|
#include <progind.h>
|
|
#include <relapp.h>
|
|
|
|
#include "lvcondv.h"
|
|
#include "lvrcondv.h"
|
|
|
|
#include "lvlib.h"
|
|
#include "../cg/cglib01.h"
|
|
#include "../mg/clifogiac.h"
|
|
#include "../ve/rcondv.h"
|
|
|
|
#include "lv0400.h"
|
|
|
|
//LV_NEW_CONTRACT: metodo generale utilizzato sia nella maschera che nell'applicazione
|
|
//che restituisce il primo codcont libero
|
|
long lv_new_contract(long cliente, int indsped)
|
|
{
|
|
//leggo dalla configurazione se la numerazione dei contratti
|
|
//è sequenziale per ditta o per cliente
|
|
long codcont = 0;
|
|
|
|
if (ini_get_bool(CONFIG_DITTA, "lv", "UniCont")) //se la numerazione è per ditta, cerco in tutto LVCONDV il codcont più grande
|
|
{
|
|
TISAM_recordset recset ("USE LVCONDV");
|
|
for (bool ok=recset.move_first(); ok; ok = recset.move_next())
|
|
{
|
|
const long codice=recset.get("CODCONT").as_int();
|
|
if (codice>codcont)
|
|
codcont=codice;
|
|
}
|
|
}
|
|
else //altrimenti cerco il codcont più grande di un determinato cliente
|
|
{
|
|
TString query;
|
|
query<<"USE LVCONDV\n"
|
|
<<"FROM CODCF=#CLIENTE\n"
|
|
<<"TO CODCF=#CLIENTE\n";
|
|
TISAM_recordset recset (query);
|
|
recset.set_var("#CLIENTE",cliente);
|
|
if (recset.move_last())
|
|
codcont=recset.get("CODCONT").as_int();
|
|
}
|
|
codcont++;
|
|
return codcont;
|
|
}
|
|
|
|
//////////////////////////////
|
|
//// TCONTRATTI_MSK ////
|
|
//////////////////////////////
|
|
|
|
//classe TContratti_msk
|
|
class TContratti_msk: public TAutomask
|
|
{
|
|
long _post_contr;
|
|
TString80 _artrig;
|
|
int _riga;
|
|
|
|
protected:
|
|
bool on_art_select();
|
|
virtual void on_idle();
|
|
virtual bool on_field_event(TOperable_field& o,TField_event e,long jolly);
|
|
|
|
public:
|
|
int get_riga();
|
|
bool set_riga(const int val);
|
|
TContratti_msk();
|
|
};
|
|
|
|
//ON_ART_SELECT: metodo che riempie i campi delle dotazioni e del consegnato sullo sheet e sulla maschera
|
|
//e riporta i dati dello sheet nel dettaglio sulla maschera (sotto lo sheet)
|
|
bool TContratti_msk::on_art_select()
|
|
{
|
|
//dallo sheet identifico la riga selezionata e estraggo i dati di interesse
|
|
TSheet_field& ss = sfield(F_RIGHE);
|
|
TToken_string& row = ss.row(ss.selected());
|
|
const TString80 codart(row.get(ss.cid2index(S_CODART)));
|
|
const long codcf = get_long(F_CODCF);
|
|
const int indsped = get_int(F_INDSPED);
|
|
|
|
//instanzio un TArticolo_lavanderie per poter recuperare i dati di interesse
|
|
TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, indsped);
|
|
|
|
//setto datasc a oggi e fisso l'anno esercizio
|
|
TDate datasc(TODAY);
|
|
const int annoes = esercizi().date2esc(datasc);
|
|
|
|
//estraggo il record corrispondente su LF_CLIFOGIAC
|
|
const TRecmag_lavanderie& reclav = artrec.find_rec(annoes);
|
|
//recupero la maschera di riga
|
|
TMask& rowmask = ss.sheet_mask();
|
|
|
|
if (!ini_get_bool(CONFIG_DITTA, "lv", "Qtamodi"))
|
|
{
|
|
field(F_DOTTMP).disable();
|
|
rowmask.field(S_DOTIN).disable();
|
|
rowmask.field(S_DOTOD).disable();
|
|
rowmask.field(S_DOTTMP).disable();
|
|
}
|
|
|
|
if (rowmask.get(S_UM).blank() && artrec.um().rows() > 0)
|
|
{
|
|
const TString& um = artrec.um()[1].get(UMART_UM);
|
|
rowmask.set(S_UM, um);
|
|
}
|
|
|
|
//se esiste il record su LF_CLIFOGIAC, recupero l'unità di misura dalla riga dello sheet selezionata
|
|
//e setto i campi delle dotazioni e dei consegnati ai valori corretti riportati alla giusta unità di misura
|
|
if (!reclav.empty())
|
|
{
|
|
if (rowmask.get(S_DOTIN).blank())
|
|
{
|
|
//calcolo dotazione iniziale, scritta sia sulla maschera che sullo sheet
|
|
const real dotin = reclav.get_real(CLIFOGIAC_DOTIN);
|
|
rowmask.set(S_DOTIN, dotin);
|
|
//calcolo dotazione odierna, scritta sia sulla maschera che sullo sheet
|
|
const real dotod = reclav.get_real(CLIFOGIAC_DOTOD);
|
|
rowmask.set(S_DOTOD, dotod);
|
|
//calcolo dotazione temporanea, scritta sia sulla maschera che sullo sheet
|
|
const real dottmp = reclav.get_real(CLIFOGIAC_DOTTM);
|
|
rowmask.set(S_DOTTMP, dottmp);
|
|
}
|
|
//calcolo consegnato anno, scritto sia sulla maschera che sullo sheet
|
|
const real consyear = reclav.get_real("CONSANNO");
|
|
rowmask.set(S_CONSANNO, consyear);
|
|
//calcolo consegnato mese, scritto sia sulla maschera che sullo sheet
|
|
const real consmonth = reclav.get_real("CONSMESE");
|
|
rowmask.set(S_CONSMESE, consmonth);
|
|
}
|
|
|
|
//instanzio una cache sull'anagrafica di magazzino
|
|
//per leggere il valore di PPCONF corretto e sempre aggiornato
|
|
const TRectype& anamag = cache().get(LF_ANAMAG, codart);
|
|
int ppconf = anamag.get_int(ANAMAG_PPCONF);
|
|
rowmask.set(S_PPCONF, ppconf);
|
|
row.add(ppconf, ss.cid2index(S_PPCONF));
|
|
|
|
//ciclo i dati di interesse della riga selezionata nel dettaglio
|
|
//sulla maschera principale
|
|
for (short id = F_CODART; id <= F_CODART + 36; id++)
|
|
{
|
|
const int pos = id2pos(id);
|
|
if (pos > 0)
|
|
{
|
|
TMask_field& f = fld(pos);
|
|
const TString& oldval = f.get();
|
|
const char* newval = row.get(ss.cid2index(id - 400));
|
|
if (oldval != newval)
|
|
{
|
|
f.set(newval);
|
|
if (f.is_kind_of(CLASS_LIST_FIELD))
|
|
f.on_hit();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ppconf <= 0)
|
|
{
|
|
set(F_CALCCONS, "0");
|
|
disable(F_CALCCONS);
|
|
rowmask.set(S_CALCCONS, "0");
|
|
rowmask.field(S_CALCCONS).disable();
|
|
rowmask.field(S_CONG).disable();
|
|
}
|
|
else
|
|
{
|
|
enable(F_CALCCONS);
|
|
rowmask.field(S_CALCCONS).enable();
|
|
rowmask.field(S_CONG).enable();
|
|
TToken_string row = ss.row(ss.selected());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//ON_IDLE: ridefinizione del metodo on_idle() delle TAutomask per settare il focus
|
|
//nel posto desiderato
|
|
void TContratti_msk::on_idle()
|
|
{
|
|
TAutomask::on_idle();
|
|
|
|
TSheet_field& s = sfield(F_RIGHE);
|
|
//se riconosco in quale riga devo andare, setto il focus su quella riga
|
|
if (_riga >= 0)
|
|
{
|
|
field(F_RIGHE).set_focus();
|
|
s.set_focus_cell_id(_riga, S_CODART);
|
|
_riga = -1;
|
|
}
|
|
else
|
|
if (_post_contr > 0)
|
|
{
|
|
set(F_CODCONT, _post_contr);
|
|
_post_contr = 0;
|
|
efield(F_CODCONT);
|
|
}
|
|
}
|
|
|
|
//ON_FIELD_EVENT: definizione del metodo che setta i comportamenti dei vari campi della mashera
|
|
bool TContratti_msk::on_field_event(TOperable_field& o,TField_event e,long jolly)
|
|
{
|
|
switch(o.dlg())
|
|
{
|
|
case F_CODCF:
|
|
case F_RICALT:
|
|
//se sono in query_mode e se il campo risulta pieno e modificato,
|
|
//e il codcont vuoto, allora riempio in automatico l'indirizzo di spedizione
|
|
//e propongo il contratto valido nella giornata di oggi
|
|
if (query_mode())
|
|
{
|
|
if (e == fe_modify && !o.empty() && efield(F_CODCONT).empty())
|
|
{
|
|
const long codcf = atol(o.get());
|
|
const int indsped = get_int(F_INDSPED);
|
|
const TDate oggi(TODAY);
|
|
_post_contr = lv_find_contract(codcf, indsped, oggi);
|
|
}
|
|
}
|
|
break;
|
|
case F_RIGHE:
|
|
//se lo sheet ha ricevuto un se_enter, allora aggiorno i campi del dettaglio sulla mashera principale
|
|
if (e == se_enter)
|
|
{
|
|
TSheet_field& ss = (TSheet_field&)o;
|
|
TToken_string& row = ss.row(ss.selected());
|
|
|
|
for (short id = F_CODART; id <= F_CODART+35; id++)
|
|
{
|
|
const int pos=id2pos(id);
|
|
if (pos>0)
|
|
{
|
|
TMask_field& f = fld(pos);
|
|
const TString& oldval = f.get();
|
|
const char* newval = row.get(ss.cid2index(id - 400));
|
|
if (oldval != newval)
|
|
{
|
|
f.set(newval);
|
|
if (f.is_kind_of(CLASS_LIST_FIELD))
|
|
f.on_hit();
|
|
}
|
|
f.set_dirty(false);
|
|
}
|
|
}
|
|
|
|
//questo pezzo serve per gestire enable e disable dei campi in modo corretto
|
|
//senza massage in maschera, sia sullo sheet che sul dettaglio
|
|
TMask& rowmask = ss.sheet_mask();
|
|
if (field(F_PPCONF).empty())
|
|
{
|
|
set(F_CALCCONS, "0");
|
|
disable(F_CALCCONS);
|
|
rowmask.set(S_CALCCONS, "0");
|
|
rowmask.field(S_CALCCONS).disable();
|
|
rowmask.field(S_CONG).disable();
|
|
}
|
|
else
|
|
{
|
|
enable(F_CALCCONS);
|
|
rowmask.field(S_CALCCONS).enable();
|
|
rowmask.field(S_CONG).enable();
|
|
}
|
|
|
|
_artrig = row.get(0); //salvo nella variabile globale il codart della riga selezionata
|
|
}
|
|
//se ho cancellato una riga dello sheet, chiedo conferma che sia effettivamente quello che si vuole fare
|
|
if (e == se_query_del)
|
|
{
|
|
TSheet_field& ss = (TSheet_field&)o;
|
|
TToken_string& row = ss.row(ss.selected());
|
|
const TString codart = row.get(ss.cid2index(S_CODART));
|
|
const long dotin = row.get_long(ss.cid2index(S_DOTIN));
|
|
if (dotin > 0)
|
|
{
|
|
warning_box("Impossibile cancellare l'articolo %s perchè ha una dotazione iniziale non nulla", (const char*) codart);
|
|
return false;
|
|
}
|
|
if (!yesno_box("Si desidera veramente cancellare l'articolo %s",(const char*) codart))
|
|
return false;
|
|
}
|
|
|
|
if (e == se_leave || e == se_notify_modify)
|
|
_artrig.cut(0);
|
|
|
|
break;
|
|
case F_TIPOCAN:
|
|
case F_NOLCICTE:
|
|
{
|
|
//copio il valore del campo in questione della testata su tutte le righe se F_TIPOCAN vale
|
|
//% su valore convenzionale per cliente, altrimente lascio quello che c'è
|
|
const int tipocan = atoi(get(F_TIPOCAN));
|
|
if (e == fe_modify || e == fe_init)
|
|
{
|
|
TSheet_field& ss = sfield(F_RIGHE);
|
|
|
|
//recupero le posizioni dei campi che devo modificare
|
|
const int pos_tipoforf = ss.cid2index(S_TIPOFORF);
|
|
const int pos_nolcic = ss.cid2index(S_NOLCIC);
|
|
const int pos_vcartcli = ss.cid2index(S_VCARTCLI);
|
|
|
|
const char nolcicte = field(F_NOLCICTE).get()[0];
|
|
|
|
if (tipocan == 2)
|
|
{
|
|
FOR_EACH_SHEET_ROW(ss, r, row)
|
|
{
|
|
TToken_string& riga = ss.row(r);
|
|
//scrivo i valori alle posizioni corrette
|
|
riga.add(4, pos_tipoforf);
|
|
riga.add(nolcicte, pos_nolcic);
|
|
riga.add('C', pos_vcartcli);
|
|
//disabilito le celle interessate
|
|
ss.disable_cell(r, pos_tipoforf);
|
|
ss.disable_cell(r, pos_nolcic);
|
|
ss.disable_cell(r, pos_vcartcli);
|
|
}
|
|
field(F_TIPOFORF).disable();
|
|
field(F_NOLCIC).disable();
|
|
}
|
|
else
|
|
{
|
|
FOR_EACH_SHEET_ROW(ss, r, row)
|
|
{
|
|
TToken_string& riga = ss.row(r);
|
|
//abilito le celle alle posizioni corrette
|
|
ss.enable_cell(r, pos_tipoforf);
|
|
ss.enable_cell(r, pos_nolcic);
|
|
ss.enable_cell(r, pos_vcartcli);
|
|
if (riga.get_int(pos_tipoforf) == 4)
|
|
riga.add('A', pos_vcartcli);
|
|
}
|
|
field(F_TIPOFORF).enable();
|
|
field(F_NOLCIC).enable();
|
|
}
|
|
ss.force_update();
|
|
if (ss.items() > 0)
|
|
ss.select(0); // Forza aggiornamento del dettaglio di riga (saponetta)
|
|
}
|
|
}
|
|
break;
|
|
case F_TIPOFORF:
|
|
{
|
|
//se questo campo risulta modificato, lo copio in alto e forzo l'update
|
|
if (e == fe_modify/* || e == fe_init*/)
|
|
{
|
|
TSheet_field& ss = sfield(F_RIGHE);
|
|
const int sel = ss.selected();
|
|
if (sel >= 0)
|
|
{
|
|
TToken_string& riga = ss.row(sel);
|
|
riga.add(o.get(), ss.cid2index(S_TIPOFORF));
|
|
if (ss.mask().get_int(F_TIPOCAN) != 2)
|
|
{
|
|
riga.add('A', ss.cid2index(S_VCARTCLI));
|
|
ss.disable_cell(sel, ss.cid2index(S_VCARTCLI));
|
|
}
|
|
ss.force_update(sel);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case F_RITAUDTTMPRIG:
|
|
{
|
|
//obbligo a settare il flag prima in testata, altrimenti non lo lascio settare per le righe
|
|
if (e == fe_modify || e == fe_init)
|
|
{
|
|
if (o.get()[0] == 'X')
|
|
{
|
|
if (field(F_RITAUDTTMP).get()[0] != 'X')
|
|
{
|
|
warning_box("E' necessario prima attivare il ritiro automatico della dotazione temporanea in testata");
|
|
o.set("");
|
|
}
|
|
}
|
|
|
|
if (e == fe_modify)
|
|
{
|
|
TSheet_field& ss = sfield(F_RIGHE);
|
|
const int sel = ss.selected();
|
|
|
|
if (sel >= 0)
|
|
{
|
|
const int index = ss.cid2index(S_RITAUDTTMP);
|
|
|
|
const char* oldval = ss.row(sel).get(index);
|
|
const TString& newval = o.get();
|
|
if (newval != oldval)
|
|
{
|
|
ss.sheet_mask().set(S_RITAUDTTMP,newval);
|
|
ss.row(sel).add(newval,index);
|
|
ss.force_update(sel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case F_CALCCONS:
|
|
//questo pezzo gestisce in maniera corretta gli enable e disable del campo conguaglio sullo sheet
|
|
if (e == fe_modify)
|
|
{
|
|
TSheet_field& ss = sfield(F_RIGHE);
|
|
const int sel = ss.selected();
|
|
if (sel >= 0)
|
|
{
|
|
TToken_string& riga = ss.row(sel);
|
|
riga.add(o.get(), ss.cid2index(F_CALCCONS));
|
|
if (riga.get_long(ss.cid2index(S_PPCONF)) <= 0)
|
|
ss.disable_cell(sel, ss.cid2index(S_CONG));
|
|
else
|
|
{
|
|
if (atoi(o.get()) == 1)
|
|
ss.enable_cell(sel, ss.cid2index(S_CONG));
|
|
else
|
|
ss.disable_cell(sel, ss.cid2index(S_CONG));
|
|
}
|
|
}
|
|
ss.force_update(sel);
|
|
}
|
|
break;
|
|
case S_CODART:
|
|
if (!o.empty()) //se il campo risulta pieno
|
|
{
|
|
if (e == fe_modify) //e se risulta modificato
|
|
{
|
|
const TString& codart = o.get();
|
|
TSheet_field& ss = sfield(F_RIGHE);
|
|
TMask& m = o.mask(); // maschera di riga!
|
|
|
|
//PROPONI PREZZO
|
|
TToken_string key;
|
|
key.add('C');
|
|
key.add(field(F_CODCF).get());
|
|
const TRectype& cfven = cache().get(LF_CFVEN, key);
|
|
|
|
bool trvlst = false;
|
|
|
|
if (!cfven.empty())
|
|
{
|
|
//se è settata la categoria merceologica, leggo sia il listino che la cat merc, altrimenti solo il listino
|
|
TString8 codlis = cfven.get(CFV_CODLIST);
|
|
TString8 catven;
|
|
if (!ini_get_bool(CONFIG_DITTA,"ve", "GESLISCV"))
|
|
catven = "";
|
|
else
|
|
catven = cfven.get(CFV_CATVEN);
|
|
|
|
//cerco il prezzo sul listino
|
|
key.cut(0);
|
|
key.add('L'); //tipo
|
|
key.add(catven); //catven
|
|
key.add(""); //tipocf
|
|
key.add(""); //codcf
|
|
key.add(codlis); //codlis
|
|
key.add('A'); //tiporiga
|
|
key.add(codart); //codriga
|
|
key.add(""); //um
|
|
key.add(""); //nscagl
|
|
const TRectype& rcondv = cache().get(LF_RCONDV, key);
|
|
|
|
if (!rcondv.empty())
|
|
{
|
|
m.set(S_PREZZOST, rcondv.get_real(RCONDV_PREZZO));
|
|
trvlst = true;
|
|
}
|
|
}
|
|
|
|
//se non ho trovato un listino, o se non c'è un listino impostato
|
|
//propongo come prezzo il valore convenzionale
|
|
if (!trvlst)
|
|
{
|
|
key.cut(0);
|
|
key.add(codart);
|
|
key.add(1);
|
|
const TRectype& umart = cache().get(LF_UMART, key);
|
|
m.set(S_PREZZOST, umart.get_real(UMART_PREZZO));
|
|
if (umart.get(UMART_PREZZO).full())
|
|
trvlst = true;
|
|
}
|
|
|
|
if (!trvlst && insert_mode())
|
|
warning_box(TR("Non è stato trovato nessun prezzo da proporre"));
|
|
|
|
//se ho scritto un articolo diverso da quello che esisteva prima
|
|
//e se si desidera veramente modificarlo, allora permetto la modifica
|
|
//e forzo l'updatre della riga, altrimenti riscrivo l'articolo che c'era prima
|
|
//e lascio tutto invariato
|
|
if (_artrig.full() && codart != _artrig)
|
|
{
|
|
if (yesno_box("Si desidera veramente modificare l'articolo %s",(const char*) _artrig))
|
|
_artrig = codart;
|
|
|
|
else
|
|
{
|
|
m.set(S_CODART, _artrig);
|
|
TToken_string& row = ss.row(ss.selected());
|
|
row.add(_artrig, 0);
|
|
ss.force_update(ss.selected());
|
|
}
|
|
}
|
|
//se all'articolo è associata un'unità di misura, la propongo
|
|
//in automatico e richiamo il metodo ON_ART_SELECT(); altrimenti lo richiamo
|
|
//solo se è arrivato un fe_init al campo
|
|
on_art_select();
|
|
}
|
|
else
|
|
if (e == fe_init)
|
|
on_art_select();
|
|
}
|
|
break;
|
|
case S_CONG:
|
|
case S_DOTIN:
|
|
case S_DOTOD:
|
|
case S_DOTTMP:
|
|
{
|
|
if (e == fe_modify)
|
|
{
|
|
TString str;
|
|
str << "ATTENZIONE: Una quantità risulta modificata a mano; dopo questa operazione i totali dei movimenti"
|
|
<< "di magazzino potrebbero non corrispondere ai numeri qui salvati";
|
|
warning_box(str);
|
|
}
|
|
}
|
|
break;
|
|
case DLG_PLANNING:
|
|
//se viene premuto il bottone "Giri", lancia lv0500 (generatore automatico dei giri)
|
|
if (e == fe_button && edit_mode())
|
|
{
|
|
TRelation_application& app = (TRelation_application&) main_app();
|
|
app.get_relation()->read(_isequal,_unlock);
|
|
TString str;
|
|
str << "lv0 -4 " << get(F_CODCF) << " " << get(F_CODCONT);
|
|
TExternal_app planning(str);
|
|
planning.run();
|
|
app.get_relation()->read(_isequal,_lock);
|
|
}
|
|
break;
|
|
case DLG_NEWREC:
|
|
if (e == fe_button)
|
|
{
|
|
//se sono in edit_mode, forzo l'uscita dal contratto attuale
|
|
if (edit_mode())
|
|
{
|
|
send_key(K_ESC, 0);
|
|
return false;
|
|
}
|
|
|
|
//se sono in query_mode e esiste già un cliente selzionato, allora richiamo il metodo LV_NEW_CONTRACT()
|
|
//e calcolo il primo codcont libero proponendolo in automatico
|
|
if (query_mode())
|
|
{
|
|
const long codcf = get_long(F_CODCF);
|
|
if (codcf > 0)
|
|
{
|
|
const int indsped = get_int(F_INDSPED);
|
|
const long codcont = lv_new_contract(codcf, indsped);
|
|
if (codcont > 0)
|
|
set(F_CODCONT, codcont);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
//se sto modificando un campo con indice > 500 e diverso da F_CAUSLAVDESCRIG
|
|
//allora forzo l'update dello sheet sulla riga selezionata
|
|
if (e == fe_modify && is_running() && o.dlg() > 500/*&& o.dlg() != F_CAUSLAVDESCRIG*/)
|
|
{
|
|
TSheet_field& ss = sfield(F_RIGHE);
|
|
const int sel = ss.selected();
|
|
|
|
if (sel >= 0)
|
|
{
|
|
const short rowid = o.dlg() - 400;
|
|
const int index = ss.cid2index(rowid);
|
|
|
|
const char* oldval = ss.row(sel).get(index);
|
|
const TString& newval = o.get();
|
|
if (newval != oldval)
|
|
{
|
|
ss.sheet_mask().set(rowid,newval);
|
|
ss.row(sel).add(newval,index);
|
|
ss.force_update(sel);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int TContratti_msk::get_riga()
|
|
{
|
|
return _riga;
|
|
}
|
|
|
|
bool TContratti_msk::set_riga(const int val)
|
|
{
|
|
_riga = val;
|
|
return true;
|
|
}
|
|
|
|
//Costruttore; nasconde o mostra il campo F_INDSPED a seconda di cosa è scritto in configurazione
|
|
TContratti_msk::TContratti_msk():TAutomask("lv0400a"), _post_contr(0)
|
|
{
|
|
if (!ini_get_bool(CONFIG_DITTA, "lv", "Useindsp"))
|
|
field(F_INDSPED).hide();
|
|
}
|
|
|
|
//////////////////////////////
|
|
//// TCONTRATTI_APP ////
|
|
//////////////////////////////
|
|
|
|
//classe TContratti_app
|
|
class TContratti_app: public TRelation_application
|
|
{
|
|
TContratti_msk* _msk;
|
|
TRelation* _rel;
|
|
TString80 _codart;
|
|
|
|
private:
|
|
void save_rows(const TMask& m);
|
|
TString build_query(const TMask& m) const;
|
|
int find_art(TSheet_field& s,const TString& art) const;
|
|
|
|
protected:
|
|
virtual TMask* get_mask (int mode) {return _msk; }
|
|
virtual TRelation* get_relation() const {return _rel;}
|
|
|
|
virtual bool user_create();
|
|
virtual bool user_destroy();
|
|
virtual void on_config_change(); //METODO VUOTO
|
|
virtual bool get_next_key(TToken_string& key); //METODO MAI UTILIZZATO?
|
|
virtual int read(TMask& m);
|
|
virtual int write(const TMask& m);
|
|
virtual int rewrite(const TMask& m);
|
|
virtual bool protected_record(TRectype & rec); //METODO MAI UTILIZZATO?
|
|
virtual bool remove();
|
|
virtual void init_query_mode(TMask& m);
|
|
virtual void init_insert_mode(TMask& m);
|
|
virtual void init_modify_mode(TMask& m);
|
|
bool elimina_planning(const long& codcont, const long& codcf) const;
|
|
bool kill_planning (TISAM_recordset& selrighe) const;
|
|
};
|
|
|
|
//SAVE_ROWS: questo metodo salva effettivamente le righe vislualizzate sullo sheet sul file
|
|
//LF_LVRCONDV e aggiorna e/o aggiunge record su LF_CLIFOGIAC
|
|
void TContratti_app::save_rows(const TMask& m)
|
|
{
|
|
//instanzio un TISAM_recordset sulle righe contratto
|
|
TISAM_recordset righeset(build_query(m));
|
|
//instazio un TLocalisamfile partendo dal recordset che ho appena creato
|
|
//(cioè su LF_LVRCONDV)
|
|
TLocalisamfile& file = righeset.cursor()->file();
|
|
|
|
//recupero lo sheet
|
|
TSheet_field& righe = m.sfield(F_RIGHE);
|
|
|
|
//scorro tutte le righe contratto e elimino tutte quelle che non ci sono più sullo sheet
|
|
for (bool ok = righeset.move_first(); ok; ok = righeset.move_next())
|
|
{
|
|
const TString& art = righeset.get("CODART").as_string();
|
|
if (find_art(righe, art) < 0)
|
|
file.remove();
|
|
}
|
|
|
|
//instanzio un TLocalisamfile su LF_CLIFOGIAC
|
|
TLocalisamfile magcli(LF_CLIFOGIAC);
|
|
|
|
//setto alcune variabili di interesse
|
|
const TDate oggi(TODAY);
|
|
const int year = oggi.year();
|
|
const long clifo = m.get_long(F_CODCF);
|
|
const int indsp = m.get_int(F_INDSPED);
|
|
|
|
//recupero la maschera di riga
|
|
TMask& msk = righe.sheet_mask();
|
|
|
|
//per ogni riga dello sheet
|
|
FOR_EACH_SHEET_ROW(righe, r, row)
|
|
{
|
|
file.zero();
|
|
file.put("CODCF",clifo);
|
|
file.put("CODCONT",m.get(F_CODCONT));
|
|
|
|
//per ogni campo della maschera scrivi setta all'interno del record corrente di file
|
|
//il valore di quei campi che hanno un field
|
|
FOR_EACH_MASK_FIELD(msk,i,f)
|
|
{
|
|
const TFieldref* fr = f->field();
|
|
if (fr != NULL)
|
|
{
|
|
const int pos = righe.cid2index(f->dlg());
|
|
fr->write(row->get(pos), file.curr());
|
|
}
|
|
}
|
|
|
|
//leggo il codart
|
|
const TString80 codart = row->get(righe.cid2index(S_CODART));
|
|
if (codart.full())
|
|
{
|
|
file.rewrite_write();
|
|
//se il codart è pieno e le quantità sono modificabili (da configurazione)
|
|
if (ini_get_bool(CONFIG_DITTA, "lv", "Qtamodi"))
|
|
{
|
|
TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', clifo, indsp);
|
|
TRecmag_lavanderie& reclav = (TRecmag_lavanderie&)artrec.find_rec(year);
|
|
|
|
//gestione LF_CLIFOGIAC
|
|
if(reclav.empty())
|
|
{
|
|
reclav.put(CLIFOGIAC_TIPOCF, 'C');
|
|
reclav.put(CLIFOGIAC_CODCF, clifo);
|
|
reclav.put(CLIFOGIAC_ANNOES, year);
|
|
reclav.put(CLIFOGIAC_INDSPED, indsp);
|
|
reclav.put(CLIFOGIAC_CODART, codart);
|
|
reclav.put(CLIFOGIAC_NRIGA, 1);
|
|
}
|
|
|
|
//riscrivo la dotazione iniziale convertita nell'unità di misura principale
|
|
const real dotin = row->get(righe.cid2index(S_DOTIN));
|
|
reclav.put(CLIFOGIAC_DOTIN, dotin);
|
|
|
|
//riscrivo la dotazione odierna convertita nell'unità di misura principale
|
|
const real dotod = row->get(righe.cid2index(S_DOTOD));
|
|
reclav.put(CLIFOGIAC_DOTOD, dotod);
|
|
|
|
//riscrivo la dotazione temporanea convertita nell'unità di misura principale
|
|
const real dottm = row->get(righe.cid2index(S_DOTTMP));
|
|
reclav.put(CLIFOGIAC_DOTTM, dottm);
|
|
|
|
//riscrivo il consegnato anno convertito nell'unità di misura principale
|
|
const real conan = row->get(righe.cid2index(S_CONSANNO));
|
|
reclav.put(CLIFOGIAC_CONSANNO, conan);
|
|
reclav.rewrite_write(magcli);
|
|
}
|
|
}
|
|
} //fine FOR_EACH_ROW
|
|
}
|
|
|
|
//BUILD_QUERY: metodo che crea la query sulle righe contratti
|
|
//recuperando i dati di interesse dalla maschera
|
|
TString TContratti_app:: build_query(const TMask& m) const
|
|
{
|
|
TString query = "";
|
|
query << "USE LVRCONDV\n"
|
|
<< "FROM CODCF=" << m.get(F_CODCF) << " CODCONT=" << m.get(F_CODCONT) << "\n"
|
|
<< "TO CODCF=" << m.get(F_CODCF) << " CODCONT=" << m.get(F_CODCONT);
|
|
return query;
|
|
}
|
|
|
|
//FIND_ART: metodo che restituisce l'indice della riga dello sheet che contiene
|
|
//l'articolo desiderato (-1 se non lo trova)
|
|
int TContratti_app::find_art(TSheet_field& s, const TString& art) const
|
|
{
|
|
int r = -1;
|
|
//scorro le righe dello sheet partendo dall'ultima
|
|
for (r = s.items()-1 ; r>=0 ; r--)
|
|
{
|
|
const char* codart = s.row(r).get(0);
|
|
if (art == codart)
|
|
break;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
//USER_CREATE: metodo che crea TRelation e TContratti_msk solo se si è in un esercizio valido
|
|
//e che setta i comportamenti sulle righe aggiunte agli sheet
|
|
bool TContratti_app:: user_create()
|
|
{
|
|
//se gli sono stati passati più parametri, allora setto la variabile globale _codart...
|
|
//...con il parametro desiderato, se no lo setto a stringa vuota
|
|
if (argc() > 2)
|
|
{
|
|
_codart = argv(3);
|
|
_codart.ltrim(2);
|
|
}
|
|
else
|
|
_codart = "";
|
|
|
|
TDate datasc(TODAY);
|
|
if (esercizi().date2esc(datasc) == 0)
|
|
return error_box("Attenzione non esiste l'esercizio corrispondente al %s", datasc.string());
|
|
|
|
_rel=new TRelation (LF_LVCONDV);
|
|
_msk= new TContratti_msk;
|
|
|
|
_msk->set_riga(-1);
|
|
|
|
TSheet_field& ss = _msk->sfield(F_RIGHE);
|
|
|
|
ss.set_auto_append();
|
|
ss.set_append(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
//USER_DESTROY: metodo che distrugge le variabili globali alla fine dell'esecuzione
|
|
bool TContratti_app:: user_destroy()
|
|
{
|
|
delete _msk;
|
|
delete _rel;
|
|
return true;
|
|
}
|
|
|
|
|
|
//ON_CONFIG_CHANGE: per adesso un semplice segnaposto
|
|
void TContratti_app:: on_config_change()
|
|
{
|
|
}
|
|
|
|
//GET_NEXT_KEY: metodo che restituisce la chiave di ricerca sui contratti prendendo il prossimo codcont libero
|
|
bool TContratti_app:: get_next_key(TToken_string& key)
|
|
{
|
|
const long cliente=_msk->get_long(F_CODCF);
|
|
if (cliente <= 0)
|
|
return false;
|
|
|
|
key.add(F_CODCF);
|
|
key.add(cliente);
|
|
key.add(F_CODCONT);
|
|
|
|
long codcont= lv_new_contract(cliente, _msk->get_int(F_INDSPED));
|
|
key.add(codcont);
|
|
|
|
return true;
|
|
}
|
|
|
|
//READ: ridefinizione del metodo read() delle TRealtion_application
|
|
int TContratti_app::read(TMask& m)
|
|
{
|
|
//eseguo la read() standard
|
|
int err = TRelation_application::read(m);
|
|
//se la read va a buon fine
|
|
if(err == NOERR)
|
|
{
|
|
//instanzio un TISAM_recordset sulle righe contratto
|
|
TISAM_recordset righeset(build_query(m));
|
|
const TRectype& rec = righeset.cursor()->curr();
|
|
|
|
//instanzio un TLcalisamfile su LF_CLIFOGIAC
|
|
TLocalisamfile magcli(LF_CLIFOGIAC);
|
|
//setto alcune variabili di interesse
|
|
const TDate oggi(TODAY);
|
|
const int year = oggi.year();
|
|
const long clifo = m.get_long(F_CODCF);
|
|
const int indsp = m.get_int(F_INDSPED);
|
|
//recupero sheet e realtiva mashera di riga
|
|
TSheet_field& righe = m.sfield(F_RIGHE);
|
|
TMask& msk = righe.sheet_mask();
|
|
righe.destroy();
|
|
|
|
//per ogni riga dello sheet
|
|
int pos = -1;
|
|
for (bool ok = righeset.move_first(); ok; ok = righeset.move_next())
|
|
{
|
|
++pos;
|
|
TToken_string& row = righe.row(-1);
|
|
//per ogni campo della maschera scrivi setta all'interno del record corrente di file
|
|
//il valore di quei campi che hanno un field
|
|
FOR_EACH_MASK_FIELD(msk,i,f)
|
|
{
|
|
const TFieldref*fr=f->field();
|
|
if (fr!= NULL)
|
|
row.add(fr->read(rec),righe.cid2index(f->dlg()));
|
|
}
|
|
|
|
const TString80 codart(row.get(righe.cid2index(S_CODART)));
|
|
|
|
//se non gli ho passato nessun codart, allora dico che voglio dare il focus alla prima riga dello sheet
|
|
//aktrimenti dico che volgio dare il focus alla riga dello sheet che contiene l'articolo che gli ho passato
|
|
if (_codart.empty())
|
|
_msk->set_riga(0);
|
|
else
|
|
if (codart == _codart)
|
|
{
|
|
_msk->set_riga(pos);
|
|
_codart.cut(0);
|
|
}
|
|
|
|
//estraggo il record corrispondente su LF_CLIFOGIAC
|
|
TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', clifo, indsp);
|
|
artrec.find_rec(0); //svuoto la cache a forza
|
|
const TRecmag_lavanderie& reclav = artrec.find_rec(year);
|
|
//lettura dei dati da LF_CLIFOGIAC
|
|
//se esiste il record su LF_CLIFOGIAC, recupero l'unità di misura dalla riga dello sheet selezionata
|
|
//e setto i campi delle dotazioni e dei consegnati ai valori corretti riportati alla giusta unità di misura
|
|
if (!reclav.empty())
|
|
{
|
|
//calcolo dotazione iniziale, scritta sia sulla maschera che sullo sheet
|
|
const real dotin = reclav.get_real(CLIFOGIAC_DOTIN);
|
|
row.add(dotin.stringa(), righe.cid2index(S_DOTIN));
|
|
|
|
//calcolo dotazione odierna, scritta sia sulla maschera che sullo sheet
|
|
const real dotod = reclav.get_real(CLIFOGIAC_DOTOD);
|
|
row.add(dotod.stringa(), righe.cid2index(S_DOTOD));
|
|
//calcolo dotazione temporanea, scritta sia sulla maschera che sullo sheet
|
|
const real dottmp = reclav.get_real(CLIFOGIAC_DOTTM);
|
|
row.add(dottmp.stringa(), righe.cid2index(S_DOTTMP));
|
|
}
|
|
//forzo una check_row
|
|
righe.check_row(righe.items()-1, 3);
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
//WRITE: ridefinizione del metodo write() delle TRelation_application
|
|
int TContratti_app::write(const TMask& m)
|
|
{
|
|
//esegui la write standard
|
|
int err = TRelation_application::write(m);
|
|
//se va a buon fine esegui la save_rows() e ricorda all'utente i passaggi per planning
|
|
if(err == NOERR)
|
|
{
|
|
save_rows(m);
|
|
warning_box(TR("Ricordarsi di inserire i passaggi per planning"));
|
|
}
|
|
return err;
|
|
}
|
|
|
|
//REWRITE: ridefinizione del metodo rewrite() delle TRelation_application
|
|
int TContratti_app::rewrite(const TMask& m)
|
|
{
|
|
//esegui la rewrite standard
|
|
int err = TRelation_application::rewrite(m);
|
|
//se va a buon fine esegui la save_rows()
|
|
if(err == NOERR)
|
|
save_rows(m);
|
|
return err;
|
|
}
|
|
|
|
//PROTECTED_RECORD: metodo che rendo un record non cancellabile
|
|
bool TContratti_app::protected_record(TRectype & rec)
|
|
{
|
|
TLaundry_contract cont(rec);
|
|
return !cont.can_be_deleted();
|
|
}
|
|
|
|
//REMOVE: ridefinizione del metodo remove() delle TRelation_application
|
|
bool TContratti_app::remove()
|
|
{
|
|
//recupero i dati dalla testata del contratto prima di cancellarla
|
|
const TRectype& tcont = get_relation()->curr();
|
|
const int daanno = tcont.get_date(LVCONDV_DATAIN).year();
|
|
const int aanno = TDate(TODAY).year();
|
|
const long clifo = tcont.get_long(LVCONDV_CODCF);
|
|
const long indsp = tcont.get_long(LVCONDV_CODINDSP);
|
|
|
|
//eseguo la remove standard
|
|
bool ok = TRelation_application::remove();
|
|
|
|
//se va a buon fine, elimino anche le righe contratto dal file specifico
|
|
if(ok)
|
|
{
|
|
TISAM_recordset righeset(build_query(*_msk));
|
|
TLocalisamfile& rcont = righeset.cursor()->file();
|
|
|
|
//elimino le giacenze per cliente SOLO se le quantità sono modificabili
|
|
if (ini_get_bool(CONFIG_DITTA, "lv", "Qtamodi"))
|
|
{
|
|
TLocalisamfile magcli(LF_CLIFOGIAC);
|
|
|
|
for (bool ok = righeset.move_first(); ok; ok = righeset.move_next())
|
|
{
|
|
//con questo ciclo elimino tutte le giacenze per cliente dall'anno di inizio validità
|
|
//del contratto all'anno attuale (essendo nel ciclo che scorre le righe contratto
|
|
//elimino tutti gli articoli presenti per quel contratto)
|
|
for (int y = daanno; y <= aanno; y++)
|
|
{
|
|
magcli.put(CLIFOGIAC_ANNOES, y);
|
|
magcli.put(CLIFOGIAC_TIPOCF, 'C');
|
|
magcli.put(CLIFOGIAC_CODCF, clifo);
|
|
magcli.put(CLIFOGIAC_INDSPED, indsp);
|
|
magcli.put(CLIFOGIAC_CODART, righeset.get(LVRCONDV_CODART).as_string());
|
|
magcli.put(CLIFOGIAC_NRIGA, 1);
|
|
magcli.remove();
|
|
}
|
|
}
|
|
rcont.remove();
|
|
}
|
|
//elimino i planning esistenti per quel cliente - contratto
|
|
elimina_planning(_msk->get_long(F_CODCONT),_msk->get_long(F_CODCF));
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
//INIT_QUERY_MODE: ridefinizione del metodo init_query_mode() standard
|
|
void TContratti_app::init_query_mode(TMask& m)
|
|
{
|
|
//abilita il campo F_RAGSOC se il campo F_CODCF è abilitato
|
|
m.field(F_RAGSOC).enable(m.field(F_CODCF).enabled());
|
|
m.reset();
|
|
}
|
|
|
|
//INIT_MODIFY_MODE: ridefinizione del metodo init_modify_mode() standard
|
|
void TContratti_app::init_modify_mode(TMask& m)
|
|
{
|
|
//setto alcune variabili di interesse
|
|
const TDate oggi(TODAY);
|
|
const int year = oggi.year();
|
|
const long clifo = m.get_long(F_CODCF);
|
|
const int indsp = m.get_int(F_INDSPED);
|
|
|
|
//instanzio un TLocaisamfile su LF_CLIFOGIAC
|
|
TLocalisamfile magcli(LF_CLIFOGIAC);
|
|
//recupero lo sheet
|
|
TSheet_field& righe = m.sfield(F_RIGHE);
|
|
|
|
//per ogni riga dello sheet aggiorno le dotazioni su LF_CLIFOGIAC
|
|
//per tutti ????, se il record esiste già
|
|
FOR_EACH_SHEET_ROW(righe,r,row)
|
|
{
|
|
const TString80 codart=row->get(righe.cid2index(S_CODART));
|
|
// righe.disable_cell(r, righe.cid2index(S_CODART));
|
|
// righe.disable_cell(r, righe.cid2index(S_DESCR));
|
|
// righe.disable_cell(r, righe.cid2index(S_UM));
|
|
|
|
for (int y = year + oggi.month() == 12; y >= year; y--)
|
|
{
|
|
magcli.put(CLIFOGIAC_ANNOES, y);
|
|
magcli.put(CLIFOGIAC_TIPOCF, 'C');
|
|
magcli.put(CLIFOGIAC_CODCF, clifo);
|
|
magcli.put(CLIFOGIAC_INDSPED, indsp);
|
|
magcli.put(CLIFOGIAC_CODART, codart);
|
|
|
|
if (magcli.read() == NOERR)
|
|
{
|
|
row->add(magcli.get(CLIFOGIAC_DOTIN), righe.cid2index(S_DOTIN));
|
|
row->add(magcli.get(CLIFOGIAC_DOTOD), righe.cid2index(S_DOTOD));
|
|
row->add(magcli.get(CLIFOGIAC_DOTTM), righe.cid2index(S_DOTTMP));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//INIT_INSERT_MODE: ridefinizione del metodo init_insert_mode() standard
|
|
void TContratti_app::init_insert_mode(TMask& m)
|
|
{
|
|
//se esiste già un contratto in essere alla data odierna per questo cliente,
|
|
//contrassegna quello attuale come "PROPOSTA"
|
|
const long codcf = m.get_long(F_CODCF);
|
|
const long indsp = m.get_int(F_INDSPED);
|
|
const TDate oggi(TODAY);
|
|
const long old_contr = lv_find_contract(codcf, indsp, oggi);
|
|
const long cur_contr = m.get_long(F_CODCONT);
|
|
if (old_contr > 0 && old_contr < cur_contr)
|
|
m.set(F_PROPOSTA, "X");
|
|
}
|
|
|
|
//ELIMINA PLANNING: metodo che prepara il recordset sui planning con le righe da eliminare
|
|
bool TContratti_app::elimina_planning(const long& codcont, const long& codcf) const
|
|
{
|
|
//creo il recordset
|
|
TISAM_recordset selrighe("USE LVRCONSPLAN KEY 3\nFROM CODCF=#CODCF CODCONT=#CODCONT \nTO CODCF=#CODCF CODCONT=#CODCONT");
|
|
//setto le variabili
|
|
selrighe.set_var("#CODCF",codcf);
|
|
selrighe.set_var("#CODCONT",codcont);
|
|
|
|
//richiamo la funzione che effettivamente fa la cancellazione delle righe interessate
|
|
kill_planning(selrighe);
|
|
|
|
return true;
|
|
}
|
|
|
|
//KILL_PLANNING: metodo che effettivamente fa la cancellazione dei planning interessati
|
|
bool TContratti_app::kill_planning (TISAM_recordset& selrighe) const
|
|
{
|
|
//se effettivamente ci sono delle righe da cancellare, allora le cancello
|
|
const int righe = selrighe.items();
|
|
if (righe > 0)
|
|
{
|
|
TProgind pi(righe, TR("Eliminazione planning in corso..."), true, true);
|
|
TLocalisamfile& rplan = selrighe.cursor()->file();
|
|
for (bool ok = selrighe.move_last(); ok; ok = selrighe.move_prev())
|
|
{
|
|
if (!pi.addstatus(1))
|
|
break;
|
|
rplan.remove();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int lv0400(int argc, char* argv[])
|
|
{
|
|
TContratti_app app;
|
|
app.run (argc,argv,TR("Gestione contratti"));
|
|
return 0;
|
|
} |