campo-sirio/lv/lv3100.cpp
luca83 b6b59864dd Patch level : 10.0 patch 4??
Files correlati     : lv3 profioli di lv
Ricompilazione Demo : [ ]
Commento            :
Quando inserisco un buono di ritiro a mano, solo il buono di ritiro e non il buono di consegna  data di consegna prevista me la deve proporre in automatico, la prima con data superiore alla data del buono di ritiro.
Se ne inserisco una a mano di un giorno che non è in consegna (inserisco un martedi e il cliente passa il lunedi e il giovedi (file lvpasplan) e quel giorno non è previsto nel giri  cioè non ho inserito una consegna per quella data (file lvrconsplan)) mi dovrebbe dare una segnalazione di conferma tipo “giorno di prevista consegna non corrispondente al cliente, confermi?”


git-svn-id: svn://10.65.10.50/trunk@19196 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-08-06 15:32:02 +00:00

1310 lines
42 KiB
C++
Executable File
Raw Blame History

#include "../ve/ve0100.h"
#include "../ve/veini.h"
#include "../ve/veuml.h"
#include "../ve/veuml3.h"
#include "../ve/verig.h"
#include "../ve/vepriv.h"
#include "lvlib.h"
#include "lvcondv.h"
#include "lvrcondv.h"
#include "lvrconsplan.h"
#include "../mg/clifogiac.h"
#define FOR_EACH_DOC_ROW_BACK(d, r, row) const TRiga_documento* row = NULL; for (int r = d.rows(); r > 0 && (row = &d[r]) != NULL; r--)
//////////////////////////////////////////
//// CLASSE TGESTIONE_BOLLE_MSK ////
//////////////////////////////////////////
//Definizione della classe della maschera
class TGestione_bolle_msk : public TDocumento_mask
{
long _stcodcf;
long _stcodcont;
protected:
static void arrotonda(const TMask& msk, real& quantita);
static void dettaglio_causale(TSheet_field& ss);
//hanlder di documento:
static bool lv_data_handler(TMask_field& f, KEY k);
static bool lv_contratto_handler(TMask_field& f, KEY k);
static bool lv_dataprco_handler(TMask_field& f, KEY k);
static bool lv_bolla_handler(TMask_field& f, KEY k);
//handler di riga:
static bool lv_ritirato_handler(TMask_field& f, KEY k);
static bool lv_consegnato_handler(TMask_field& f, KEY k);
static bool lv_codart_handler(TMask_field& f, KEY k);
static bool lv_causale_handler(TMask_field& f, KEY k);
static bool lv_codmag_handler(TMask_field& f, KEY k);
static bool lv_datatmp_handler(TMask_field& f, KEY k);
static bool ss_notify(TSheet_field& ss, int r, KEY key);
static bool ss_handler(TMask_field& f, KEY key);
virtual void on_idle();
public:
virtual void user_set_handler( short fieldid, int index);
virtual void user_set_row_handler(TMask& rm, short field, int index);
void reset_var_mask() {_stcodcf = 0; _stcodcont = 0;}
TDate proponi_dataprco() const;
TGestione_bolle_msk(const char* tipodoc);
int _autoselect;
};
////////////////////////////////////
//// CLASSE TGIAC_PER_CLI ////
////////////////////////////////////
//Definizione della classe Giacenza per Cliente
class TGiac_per_cli : public TObject
{
private:
TAssoc_array _odierna; //TAssoc_array che conterr<72> le dotazioni odierne
TAssoc_array _temporanea; //TAssoc_array che conterr<72> le dotazioni temporanee
long _clifo; //variabile che conterr<72> il cliente selezionato
long _cont; //variabile che conterr<72> il contratto selezionato
int _year; //variabile che conterr<72> l'anno documento
long _indsped; //variabile che conterr<72> l'indirizzo di spedizione
protected:
real& giacart_od(const TString& codart); //restituisce un puntatore al valore della dot. od. salvato
real& giacart_tmp(const TString& codart); //restituisce un puntatore al valore valore della dot. temp. salvato
long giac_in_mag(const TString& codart, bool odierna) const; //restituisce il valore salvato nel magazzino
public:
bool preset(const TDocumento& doc); //precarico le variabili globali della classe
bool reset(const TDocumento& doc); //svuota i TAssoc_array e carica cli e cont
bool load_row(const TRiga_documento& rdoc); //popola i TAssoc_array
real giac_att(TRiga_documento& rdoc, bool odierna); //restituisce le quantit<69> attuali di dotazione
TGiac_per_cli(); //costruttore
};
//GIACART_OD: metodo che restituisce un puntatore al real che contiene il valore
//della dotazione odierna per un determinato articolo
real& TGiac_per_cli::giacart_od(const TString& codart)
{
real *giac = (real*)_odierna.objptr(codart);
if (giac == NULL)
{
giac = new real(giac_in_mag(codart, true));
_odierna.add(codart,giac);
}
return *giac;
};
//GIACART_TMP: metodo che restituisce un puntatore al real che contiene il valore
//della dotazione temporanea per un determinato articolo
real& TGiac_per_cli::giacart_tmp(const TString& codart)
{
real *giac = (real*)_temporanea.objptr(codart);
if (giac == NULL)
{
giac = new real(giac_in_mag(codart, false));
_temporanea.add(codart,giac);
}
return *giac;
};
//GIAC_IN_MAG: questo metodo restituisce le quantit<69> presenti sul file 166 (clifogiac)
//restituendo il valore salvato in dotazione odierna se odierna == true,
//oppure il valore salvato in dotazione temporanea se odierna = false
long TGiac_per_cli::giac_in_mag(const TString& codart, bool odierna) const
{
//recupero i valori delle dotazioni odierne e temporanee dal magazzino del cliente
TLocalisamfile magcli(LF_CLIFOGIAC);
magcli.put(CLIFOGIAC_ANNOES, _year);
magcli.put(CLIFOGIAC_TIPOCF, 'C');
magcli.put(CLIFOGIAC_CODCF, _clifo);
magcli.put(CLIFOGIAC_INDSPED, _indsped);
magcli.put(CLIFOGIAC_CODART, codart);
magcli.put(CLIFOGIAC_NRIGA, 1);
//leggo il record corrispondente
if (magcli.read() == NOERR)
return magcli.get_long( odierna ? CLIFOGIAC_DOTOD : CLIFOGIAC_DOTTM);
return 0;
}
//PRESET: metodo che carica la coppia cliente - contratto
bool TGiac_per_cli::preset(const TDocumento& doc)
{
//estraggo i dati di interesse dal documento
_clifo = doc.get_long(DOC_CODCF);
_cont = doc.get_long(DOC_CODCONT);
_year = doc.get_date(DOC_DATADOC).year();
_indsped = doc.get_long(DOC_CODINDSP);
return true;
}
//RESET: metodo che distrugge i due TAssoc_array e carica la coppia cliente - contratto
bool TGiac_per_cli::reset(const TDocumento& doc)
{
preset(doc);
//distruggo i due TAssoc_array
_odierna.destroy();
_temporanea.destroy();
return true;
}
//LOAD_ROW: questo metodo popola e aggiorna i TAssoc_array
bool TGiac_per_cli::load_row(const TRiga_documento& rdoc)
{
//recupero il documento e la sua maschera a partire dalla riga documento
const TDocumento& doc = rdoc.doc();
real vardot;
real vartmp;
//se sul documento leggo o il cliente o il contratto o l'indirizzo di spedizione
//diversi da quelli che avevo salvato vuol dire che ho cambiato uno dei due,
//e quindi le giacenze non vanno pi<70> bene; in tal caso resetto i TAssoc_array e riparto
if (doc.get_long(DOC_CODCF) != _clifo || doc.get_long(DOC_CODCONT) != _cont || doc.get_long(DOC_CODINDSP) != _indsped)
reset(doc);
real& dotazione = giacart_od(rdoc.get(RDOC_CODART));
real& dotmp = giacart_tmp(rdoc.get(RDOC_CODART));
//instanzio una cache sulla tabella delle causali
const TString4 causale = rdoc.get(RDOC_CODAGG1);
const TCausale_lavanderie cau(causale);
//movimento o meno la dotazione temporanea a seconda di cosa prevede la causale
if (cau.is_ritiro())
{
const TCausale_magazzino& rit = cau.causale_ritiro();
const real & ritirato = rdoc.get_real(RDOC_QTAGG1);
int st = rit.sgn(s_dottm);
int so = rit.sgn(s_dotod);
vartmp += real(st) * ritirato;
vardot += real(so) * ritirato;
}
if (cau.is_consegna())
{
const TCausale_magazzino& con = cau.causale_consegna();
const real & consegnato = rdoc.get_real(RDOC_QTA);
int st = con.sgn(s_dottm);
int so = con.sgn(s_dotod);
vartmp += real(st) * consegnato;
vardot += real(so) * consegnato;
}
if (rdoc.get_int(RDOC_MOVMAG) != ZERO)
{
dotmp -= vartmp;
dotazione -= vardot;
}
return true;
}
//GIAC_ATT: questo metodo restituisce il valore della dotazione da scrivere a video in base ai valori
//di consegnato e ritirato; ATTENZIONE: restituisce la dotazione odierna se odierna = true,
//restituisce la dotazione temporanea se odierna = false
real TGiac_per_cli::giac_att(TRiga_documento& rdoc, bool odierna)
{
const TString& codart = rdoc.get(RDOC_CODART);
real giac = odierna ? giacart_od(codart) : giacart_tmp(codart);
real saldo;
//instanzio una cache sulla tabella delle causali
TString4 causale = rdoc.get(RDOC_CODAGG1);
const TCausale_lavanderie cau(causale);
//movimento o meno la dotazione temporanea/odierna a seconda di cosa prevede la causale
if (cau.is_ritiro())
{
const TCausale_magazzino& rit = cau.causale_ritiro();
const int s = rit.sgn(odierna ? s_dotod : s_dottm);
saldo += real(s) * rdoc.get_real(RDOC_QTAGG1);
}
if (cau.is_consegna())
{
const TCausale_magazzino& con = cau.causale_consegna();
const int s = con.sgn(odierna ? s_dotod : s_dottm);
saldo += real(s) * rdoc.get_real(RDOC_QTA);
}
giac += saldo;
return giac;
}
//costruttore
TGiac_per_cli::TGiac_per_cli()
{
//estraggo i dati di interesse dal documento
_clifo = 0;
_cont = 0;
_year = 0;
_indsped = 0;
}
//////////////////////////////////////////
//// CLASSE TGESTIONE_BOLLE_APP ////
//////////////////////////////////////////
// Definizione della classe dell'applicazione motore
class TGestione_bolle_app : public TMotore_application
{
TGiac_per_cli _giac;
protected:
virtual TMask* get_mask( int mode );
virtual int write( const TMask& m );
virtual int rewrite( const TMask& m );
virtual int read ( TMask& m );
virtual void init_insert_mode( TMask& m );
void elimina_vuote( const TMask& m);
virtual const char * query_mask_name() { return "lv3100a"; }
public:
TGiac_per_cli& giacenza();
TGestione_bolle_app() {}
};
inline TGestione_bolle_app& gbapp() { return (TGestione_bolle_app &)main_app(); };
//////////////////////////////////////////
//// CLASSE TGESTIONE_BOLLE_MSK ////
//////////////////////////////////////////
//ARROTONDA: metodo che arrotonda la quantit<69> che gli passo se <20> previsto sul contratto
void TGestione_bolle_msk::arrotonda(const TMask& msk, real& quantita)
{
TConfig* configlv = new TConfig(CONFIG_DITTA,"lv");
int perarr = configlv->get_int("Perarr");
const TString& codart = msk.get(FR_CODART);
//instanzio una cache sulla tabella del magazzino
const TRectype& anamag = cache().get(LF_ANAMAG,codart);
//recupero i dati di interesse dall'anagrafica di magazzino
const long ppconf = anamag.get_long(ANAMAG_PPCONF);
if (ppconf > 0)
{
TDocumento_mask& dmsk = (TDocumento_mask&) msk.get_sheet()->mask();
//recupero dal documento i dati di interesse per recuperare...
//...i dati dalla riga contratto
const long codcf = dmsk.get_long(F_CODCF);
const int indsped = dmsk.get_int(F_CODINDSP);
TDate datadoc = dmsk.get_date(F_DATADOC);
if (!datadoc.ok())
datadoc = TODAY;
const TLaundry_contract cont(codcf, indsped, datadoc);
//leggo la riga del contratto per l'articolo corrente
const TRectype& rcont = cont.row(codart);
//recupero i dati di interesse dalla riga del contratto
if (rcont.get_int(LVRCONDV_CALCCONS) == 1)
{
//calcolo di quanti pezzi sforo
long arr = quantita.integer() % ppconf;
//calcolo quanti pezzi in pi<70> o in meno gli devo dare e aggiorno la quantit<69>
if (arr > ppconf * perarr / 100) //arr <= ppconf*perarr/100 -> formula calcolo congualgio di Tassan
{
arr = ppconf - arr;
quantita += arr;
}
else
quantita -= arr;
}
}
}
//DETTAGLIO_CAUSALE: metodo che setta esplode la causale negli appositi campi
void TGestione_bolle_msk::dettaglio_causale(TSheet_field& ss)
{
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&) ss.mask();
TString4 causale = ss.cell(ss.selected(),ss.cid2index(FR_CODAGG1));
//instanzio una cache sulle causali
const TCausale_lavanderie cau(causale);
//esplodo la causale
dmsk.set(F_LVCODCAU, cau.codice());
dmsk.set(F_LVDESCAU, cau.descr());
}
//PROPONI_DATAPRCO: metodo che propone la prima data di prevista consegna
TDate TGestione_bolle_msk::proponi_dataprco() const
{
const TDate dadata = get(F_DATADOC);
TDate dataprco(0,0,0);
if (dadata.ok())
{
TDate adata = dadata;
adata.addmonth(1);
TString query = "USE LVRCONSPLAN KEY 3\n";
query << "FROM CODCF=" << get(F_CODCF) << " CODCONT=" << get(F_LVCODCONT) << " DTCONS=" << dadata << "\n";
query << "TO CODCF=" << get(F_CODCF) << " CODCONT=" << get(F_LVCODCONT) << " DTCONS=" << adata << "\n";
TISAM_recordset consegne(query);
if (consegne.move_first())
dataprco = consegne.get(LVRCONSPLAN_DTCONS).as_date();
}
return dataprco;
}
////////////////////////////
// HANDLER DI DOCUMENTO //
////////////////////////////
void TGestione_bolle_msk:: on_idle()
{
TDocumento_mask::on_idle();
if (_autoselect >= 0)
{
TSheet_field& s = sfield(F_SHEET);
//per ora 4 fisso perch<63> non sappiamo calcolare la colonna del ritirato
s.set_focus_cell_id(_autoselect, FR_QTAGG1);
_autoselect = -1;
dettaglio_causale(s);
}
}
//magico metodo per settare, al cambio riga dello sheet, il focus sul campo desiderato (il campo in questione <20>..
//..definito nella on_idle(); ricordarsi la set_notify() nel costruttore della maschera senno' viene eseguito l'ss_notify()..
//..standard e non questo qui ridefinito. Allah!
bool TGestione_bolle_msk::ss_notify(TSheet_field& ss, int r, KEY key)
{
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&) ss.mask();
if (key == K_TAB && dmsk._autoselect == -1)
dmsk._autoselect = ss.selected(); //riga per settare il focus
return TDocumento_mask::ss_notify(ss, r, key);
}
//SS_HANDLER: handler che mi peremette di evitare la registrazione in caso di documento
//senza righe valide (cio<69> con quantit<69> diverese da zero)
bool TGestione_bolle_msk::ss_handler(TMask_field& f, KEY key)
{
if ((key == K_ENTER) && f.mask().insert_mode())
{
TSheet_field& ss = (TSheet_field&)f;
bool vuote = true;
if (ss.items() > 0)
vuote = false;
if(!vuote)
{
vuote = true;
FOR_EACH_SHEET_ROW(ss, r, row)
{
if (row->get_int(ss.cid2index(FR_QTA)) != 0 || row->get_int(ss.cid2index(FR_QTAGG1)) != 0)
vuote = false;
}
}
if (!app().is_transaction() && vuote)
return error_box(TR("Il documento e' privo di righe valide e pertanto verr<72> ignorato"));
}
return TDocumento_mask::ss_handler(f, key);
}
//LV_DATA_HANDLER: handler che si occupa di decodificare i campi data in testata
bool TGestione_bolle_msk::lv_data_handler(TMask_field& f, KEY k)
{
bool ok = true;
switch(f.dlg())
{
case F_DATADOC: ok = data_hndl( f, k ); break;
default: break;
}
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&)f.mask();
TDate oggi(TODAY);
TDate primo = oggi;
primo.set_day(1);
if (dmsk.get_date(F_DATADOC) != oggi)
{
oggi = dmsk.get_date(F_DATADOC);
primo = oggi;
primo.set_day(1);
}
//decodifica del giorno della settimana
dmsk.set(F_LVGIORNO, itow(oggi.wday()));
//settimana del mese = settimana(oggi) - settimana(primo del mese) + 1
long tmp = oggi.week() - primo.week() + 1;
TString4 settimana;
settimana << tmp;
dmsk.set(F_LVSETTIMANA, settimana);
return ok;
}
//LV_CONTRATTO_HANDLER: handler che si occupa di riempire il campo contratto in testata
bool TGestione_bolle_msk::lv_contratto_handler(TMask_field& f, KEY k)
{
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&)f.mask();
const long codcf = dmsk.get_long(F_CODCF);
const int indsped = dmsk.get_int(F_CODINDSP);
TDate datadoc = dmsk.get_date(F_DATADOC);
if (!datadoc.ok())
datadoc = TODAY;
const int anno = datadoc.year();
if (codcf <= 0)
return true;
long codcont = lv_find_contract(codcf,indsped,datadoc);
if (codcont <= 0)
{
warning_box(TR("Non ci sono contratti in essere alla data indicata"));
return true;
}
else
{
TString16 tmp;
tmp << codcont;
dmsk.set(F_LVCODCONT, tmp);
const TDate dataprco = dmsk.proponi_dataprco();
if (dataprco.ok() && dmsk.field(F_LVDATAPRCO).empty())
dmsk.set(F_LVDATAPRCO, dataprco);
}
TDocumento& doc = dmsk.doc();
doc.put(DOC_CODCONT, codcont);
return true;
}
//LV_DATAPRCO_HANDLER: handler che si occupa della gestione del campo "data di prevista consegna"
bool TGestione_bolle_msk::lv_dataprco_handler(TMask_field& f, KEY k)
{
//se sto leggendo o generando un buono di ritiro, abilito questo campo
if (k == K_TAB)
{
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&)f.mask();
TDocumento& doc = dmsk.doc();
//se la data viene modificata a mano, controlla se <20> una data di previsto passaggio;
//se non lo <20> chiedi conferma se si desidera mantenre la data indicata manualmente o se
//<2F> meglio riproporre la data di previsto passaggio
if (!f.empty() && f.focusdirty() && doc.get_date("DATAPRCO") != (TDate)f.get())
{
doc.put("DATAPRCO", f.get());
TString query1 = "USE LVRCONSPLAN KEY 3\n";
query1 << "FROM CODCF=" << dmsk.get(F_CODCF) << " CODCONT=\"" << dmsk.get(F_LVCODCONT) << "\" DTCONS=" << f.get() << "\n";
query1 << "TO CODCF=" << dmsk.get(F_CODCF) << " CODCONT=\"" << dmsk.get(F_LVCODCONT) << "\" DTCONS=" << f.get() << "\n";
TISAM_recordset consegne(query1);
if (!consegne.move_first())
{
f.set_focusdirty(false);
if (!yesno_box(TR("Non <20> previsto nessun passaggio per questa data, confermi lo stesso?")))
{
const TDate dataprco = dmsk.proponi_dataprco();
if (dataprco.ok())
{
f.set(dataprco);
doc.put("DATAPRCO", dataprco);
}
}
}
}
}
return true;
}
//LV_BOLLA_HANDLER: handler di bolla, carica le righe contratto sulle bolle, preparando la struttura del documento
bool TGestione_bolle_msk::lv_bolla_handler(TMask_field& f, KEY k)
{
bool ok = true;
switch(f.dlg())
{
case F_CODCF: ok = TDocumento_mask::clifo_handler( f, k ); break;
default: break;
}
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&)f.mask();
if (ok && k == K_TAB && ((dmsk.insert_mode() && f.to_check(k, true)) || f.focusdirty()))
{
f.set_focusdirty(false);
TDocumento& doc = dmsk.doc();
TSheet_field& sheet = dmsk.sfield(F_SHEET);
int nrighe = sheet.items();
const long codcf = dmsk.get_long(F_CODCF);
const int indsped = dmsk.get_int(F_CODINDSP);
TDate datadoc = dmsk.get_date(F_DATADOC);
if (!datadoc.ok())
datadoc = TODAY;
const int anno = datadoc.year();
if (codcf <= 0)
return true;
const long codcont = lv_find_contract(codcf,indsped,datadoc);
if (codcont <= 0)
{
warning_box(TR("Non ci sono contratti in essere alla data indicata"));
return true;
}
else
{
doc.put(DOC_CODCF, codcf);
doc.put(DOC_DATADOC, datadoc);
doc.put(DOC_CODINDSP, indsped);
doc.put(DOC_CODCONT, codcont);
const TDate dataprco = dmsk.proponi_dataprco();
if (dataprco.ok() && dmsk.field(F_LVDATAPRCO).empty())
doc.put("DATAPRCO", dataprco);
}
if (dmsk._stcodcf == codcf && dmsk._stcodcont == codcont && nrighe > 0)
return true;
dmsk.mask2doc();
dmsk._stcodcf = codcf;
dmsk._stcodcont = codcont;
//elimino tutte le righe del documento
doc.destroy_rows();
//tipo riga
const TString& tprig = dmsk.get(F_LBTIPORIGA);
//instanzio una cache sulla tabella dei contratti
const TLaundry_contract tcont(codcf, codcont);
//estraggo i dati di interesse dalla cache
const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino
//instanzio un recordset sulle righe del contratto considerato
TISAM_recordset rcont("USE LVRCONDV\nFROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT");
rcont.set_var("#CODCF",codcf);
rcont.set_var("#CODCONT",codcont);
//leggo dalla configurazione i codici magazzino e deposito standard
TConfig* configlv = new TConfig(CONFIG_DITTA,"lv");
TString8 codmag;
codmag << configlv->get("CODMAG") << configlv->get("CODMAGC");
//per ogni riga estraggo l'articolo, il relativo prezzo e l'eventaule sconto da applicare,
//...riportati in bolla solo se necessario
for (bool ok = rcont.move_first(); ok; ok = rcont.move_next())
{
//creo una nuova riga documento
TRiga_documento& rdoc = doc.new_row(tprig);
//recupero i dati di interesse dalla riga del contratto e li inserisco sullo sheet
const TString80 codart = rcont.get(LVRCONDV_CODART).as_string();
TString4 causale = rcont.get(LVRCONDV_CAUSLAV).as_string();
if (causale.blank() || atoi(causale) == 0)
{
TConfig* configlv = new TConfig(CONFIG_DITTA,"lv");
causale = configlv->get("CAUSLAV");
}
//instanzio una cache sulle anagrafice di magazzino
const TRectype& anamag = cache().get(LF_ANAMAG,codart);
TToken_string key;
key.add(codart);
key.add(1);
const TRectype& umart = cache().get(LF_UMART, key);
rdoc.put(RDOC_CODART,codart);
rdoc.put(RDOC_CODARTMAG,codart);
rdoc.put(RDOC_CHECKED,'X');
rdoc.put(RDOC_DESCR, anamag.get(ANAMAG_DESCR));
rdoc.put(RDOC_UMQTA, umart.get(UMART_UM));
rdoc.put(RDOC_CODAGG1,causale);
rdoc.put(RDOC_CODIVA,anamag.get(ANAMAG_CODIVA));
TString8 codmagold = rdoc.get(RDOC_CODMAG);
if (codmagold.empty())
{
rdoc.put(RDOC_CODMAG, codmag);
rdoc.put(RDOC_CODMAGC, codmag);
}
//gestione campi dotazione odierna e dotazione temporanea
TGiac_per_cli& giac = gbapp().giacenza();
giac.preset(doc);
real dotod = giac.giac_att(rdoc, true);
rdoc.put("DOTOD", dotod);
real dotmp = giac.giac_att(rdoc, false);
rdoc.put("DOTMP", dotmp);
//elaborazione per il prezzo: o lo prendo dalle righe contratto, o dall'anagrafica magazzino
const TString& sconto = rcont.get(LVRCONDV_SCONTPERC).as_string();
rdoc.put(RDOC_SCONTO, sconto);
//controllo da dove devo prendere il prezzo
real prezzo;
if (tplis == 0)
prezzo = rcont.get(LVRCONDV_PREZZO).as_real();
else
prezzo = anamag.get_real(ANAMAG_COSTSTD);
rdoc.put(RDOC_PREZZO, prezzo);
}
dmsk.doc2mask(false);
FOR_EACH_MASK_FIELD(dmsk, i, f)
{
if (f->has_check())
f->check(STARTING_CHECK);
if (f->is_edit())
f->on_hit();
}
dmsk._autoselect = 0;
}
return ok;
}
///////////////////////
// HANDLER DI RIGA //
///////////////////////
//LV_RITIRATO_HANDLER: handler sul campo ritirato, che copia nel campo consegnato
//lo stesso valore eventualmente arrotondato e aggiorna il campo "dotazione odierna" (sempre)
//e il campo "dotazione temporanea" (se la causale <20> giusta)
bool TGestione_bolle_msk::lv_ritirato_handler(TMask_field& f, KEY k)
{
if (f.to_check(k))
{
TMask& msk = f.mask();
real ritirato = f.get();
real dotod = msk.get_real(FR_JOLLY1);
if (ritirato > dotod && f.dirty())
warning_box(TR("ATTENZIONE: stai ritirando un quantitativo maggiore della dotazione!"));
TSheet_field* sheet = msk.get_sheet();
TDocumento_mask& dmask = (TDocumento_mask&)sheet->mask();
TDocumento& doc = dmask.doc();
TRiga_documento& rdoc = dmask.doc()[sheet->selected()+1];
rdoc.put(RDOC_QTAGG1,ritirato);
if (msk.field(FR_QTA).enabled() && msk.field(FR_QTA).empty() && !msk.field(FR_QTA).focusdirty())
{
real consegnato = ritirato;
arrotonda(msk, consegnato);
msk.set(FR_QTA, consegnato, 0x3);
return true;
}
//gestione campi dotazione odierna e dotazione temporanea
TGiac_per_cli& giac = gbapp().giacenza();
dotod = giac.giac_att(rdoc, true);
msk.set(FR_JOLLY1, dotod);
rdoc.put("DOTOD", dotod);
//scrivo la dotazione temporanea solo se esistono le date di dotazione temporanea e questa non <20> scaduta
if (rdoc.get_date("DADATATMP").ok() && rdoc.get_date("ADATATMP").ok() && rdoc.get_date("ADATATMP") >= doc.get_date(DOC_DATADOC))
{
real dotmp = giac.giac_att(rdoc, false);
msk.set(FR_JOLLY2, dotmp);
rdoc.put("DOTMP", dotmp);
}
}
return true;
}
//LV_CONSEGNATO_HANDLER: per adesso <20> solo un segna - posto
bool TGestione_bolle_msk::lv_consegnato_handler(TMask_field& f, KEY k)
{
bool ok = true;
switch(f.dlg())
{
case FR_QTA: ok = qta_handler( f, k ); break;
default: break;
}
if (f.to_check(k))
{
TMask& msk = f.mask();
real consegnato = f.get();
//gestione campi dotazione odierna e dotazione temporanea
TSheet_field* sheet = msk.get_sheet();
TDocumento_mask& dmask = (TDocumento_mask&)sheet->mask();
TDocumento& doc = dmask.doc();
TRiga_documento& rdoc = dmask.doc()[sheet->selected()+1];
rdoc.put(RDOC_QTA, consegnato);
TGiac_per_cli& giac = gbapp().giacenza();
real dotod = giac.giac_att(rdoc, true);
msk.set(FR_JOLLY1, dotod);
rdoc.put("DOTOD", dotod);
//scrivo la dotazione temporanea solo se esistono le date di dotazione temporanea e questa non <20> scaduta
if (rdoc.get_date("DADATATMP").ok() && rdoc.get_date("ADATATMP").ok() && rdoc.get_date("ADATATMP") >= doc.get_date(DOC_DATADOC))
{
real dotmp = giac.giac_att(rdoc, false);
msk.set(FR_JOLLY2, dotmp);
rdoc.put("DOTMP", dotmp);
}
}
return ok;
}
//LV_CODART_HANDLER: handler sul campo codice articolo, che carica la causale relativa all'articolo
//e controlla se l'articolo che si sta inserendo fa parte della dotazione del cliente
bool TGestione_bolle_msk::lv_codart_handler(TMask_field& f, KEY k)
{
bool ok = true;
switch(f.dlg())
{
case FR_CODART: ok = codart_handler( f, k ); break;
default: break;
}
if (ok && (k == K_ENTER || k == K_TAB))
{
TMask& msk = f.mask();
const TString& codart = msk.get(FR_CODART);
if (codart.full())
{
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&) msk.get_sheet()->mask();
TSheet_field* sheet = msk.get_sheet();
TRiga_documento& rdoc = dmsk.doc()[sheet->selected()+1];
rdoc.put(RDOC_CODART, codart);
//recupero dal documento i dati di interesse per recuperare...
//...i dati dalla riga contratto
const long codcf = dmsk.get_long(F_CODCF);
const int indsped = dmsk.get_int(F_CODINDSP);
TDate datadoc = dmsk.get_date(F_DATADOC);
if (!datadoc.ok())
datadoc = TODAY;
const TLaundry_contract cont(codcf, indsped, datadoc);
const TRectype& rcont = cont.row(codart);
//cerco la causale relativa all'articolo; se non la trovo prendo quella standard
TString4 causale = rcont.get(LVRCONDV_CAUSLAV);
if (causale.blank() || atoi(causale) == 0 )
{
TConfig* configlv = new TConfig(CONFIG_DITTA,"lv");
causale = configlv->get("CAUSLAV");
}
if (rdoc.get("DOTOD").empty())
{
//gestione campi dotazione odierna e dotazione temporanea
TGiac_per_cli& giac = gbapp().giacenza();
giac.preset(dmsk.doc());
real dotod = giac.giac_att(rdoc, true);
rdoc.put("DOTOD", dotod);
TString16 tmp;
tmp << dotod;
msk.field(FR_JOLLY1).set(tmp);
}
if (rdoc.get(RDOC_CODAGG1).empty())
msk.set(FR_CODAGG1, causale);
if (k == K_ENTER && rcont.get_int(LVRCONDV_CALCCONS) == 1)
{
TSheet_field* sheet = msk.get_sheet();
TRiga_documento rdoc = dmsk.doc()[sheet->selected()+1];
const real ritor = rdoc.get_real(RDOC_QTAGG4);
const real conor = rdoc.get_real(RDOC_QTAGG3);
const real ritat = msk.get_real(FR_QTAGG1);
const real conat = msk.get_real(FR_QTA);
//instanzio una cache sulle causali
causale = sheet->cell(sheet->selected(),sheet->cid2index(FR_CODAGG1));
const TCausale_lavanderie cau(causale);
if (cau.movcong() && (ritor != ritat || conor != conat))
{
const real congor = rcont.get_real(LVRCONDV_QTACONG);
const real congat = conat - ritat + congor;
rdoc.put(RDOC_QTAGG5, congat); //conguaglio dopo modifica manuale
TLocalisamfile rcondv(LF_LVRCONDV);
rcondv.put(LVRCONDV_CODCF,codcf);
rcondv.put(LVRCONDV_CODCONT,cont.get_int(LVCONDV_CODCONT));
rcondv.put(LVRCONDV_CODART,codart);
if (rcondv.read() == NOERR)
{
rcondv.put(LVRCONDV_QTACONG,congat);
rcondv.rewrite();
}
}
}
//controllo se si vuole aggiungere un eventuale nuovo articolo al contratto
if (cont.get_int(LVCONDV_CODCONT) <= 0)
warning_box(TR("ATTENZIONE: stai generando una bolla per un clinete che non ha nessun contratto in essere"));
else if (k == K_ENTER && f.dirty() && msk.get(FR_CODARTMAG).full() && rcont.empty() &&
yesno_box(TR("L'articolo in esame non fa parte della dotazione standard di questo cliente."
"Si desidera aggiungerla ai contratti?")))
cont.edit();
}
}
return ok;
}
//LV_CAUSALE_HANDLER: handler che abilita e/o disabilita i campi di consegnato e ritirato in base alla causale
//e tenendo conto se l'articolo <20> bloccato o meno
bool TGestione_bolle_msk::lv_causale_handler(TMask_field& f, KEY k)
{
if (f.to_check(k, true))
{
TConfig* configlv = new TConfig(CONFIG_DITTA,"lv");
TString4 codmagdef = configlv->get("CODMAG"); //magazzino
TString4 coddepdef = configlv->get("CODMAGC"); //magazzino del circolante (deposito)
//leggo la causale che ho scritto nella riga corrente dello sheet
TString4 causale = f.get();
if (causale.full())
{
TMask& msk = f.mask();
//leggo il codart che ho scritto nella riga corrente delle sheet
const TString& codart = msk.get(FR_CODART);
//srcrivo nel documento la causale
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&) msk.get_sheet()->mask();
TSheet_field& sheet = dmsk.sfield(F_SHEET);
//esplodo la descrizione della causale
dettaglio_causale(sheet);
TDocumento& doc = dmsk.doc();
TRiga_documento& rdoc = doc[msk.get_sheet()->selected()+1];
TString4 codmag(doc.clifor().vendite().get(CFV_CODMAG));
TString4 coddep(doc.clifor().vendite().get(CFV_CODDEP));
TString4 codmagcoll(codmag);
TString4 coddepcoll(coddep);
rdoc.put(RDOC_CODAGG1, causale);
//recupero i dati di interesse dalla testata per poter trovare il contratto
const long codcf = dmsk.get_long(F_CODCF);
const int indsped = dmsk.get_int(F_CODINDSP);
TDate datadoc = dmsk.get_date(F_DATADOC);
if (!datadoc.ok())
datadoc = TODAY;
//trovo il contratto utlizzato e la riga contratto specifica che mi serve
const TLaundry_contract cont(codcf, indsped, datadoc);
const TRectype& rcont = cont.row(codart);
TCausale_lavanderie cau(causale);
//movimento o meno la dotazione temporanea/odierna a seconda di cosa prevede la causale
int sgn_rit = 0;
int sgn_con = 0;
if (cau.is_ritiro())
{
const TCausale_magazzino& rit = cau.causale_ritiro();
if (codmagcoll.blank() && rit.has_default_mag())
{
codmagcoll = rit.default_mag();
coddepcoll = rit.default_dep();
}
sgn_rit = rit.sgn(s_dottm);
}
if (cau.is_consegna())
{
const TCausale_magazzino& con = cau.causale_consegna();
if (codmag.blank() && con.has_default_mag())
{
codmag = con.default_mag();
coddep = con.default_dep();
}
sgn_con = con.sgn(s_dottm);
}
//setto il valore della dotazione temporanea
TGiac_per_cli& giac = gbapp().giacenza();
giac.preset(doc);
real dotmp = giac.giac_att(rdoc, false);
rdoc.put("DOTMP", dotmp);
TString16 tmp;
tmp << dotmp;
msk.field(FR_JOLLY2).set(tmp);
//setto le date di inizio e fine della dotazione temporanea
TDate dadata = rcont.get_date(LVRCONDV_INDTTMP);
TDate adata = rcont.get_date(LVRCONDV_FIDTTMP);
bool fdotmp = false;
//disabilito i campi di dotazione temporanea se la causale non prevede la loro movimentazione
if (sgn_rit == 0 && sgn_con == 0)
{
msk.field(FR_JOLLY3).disable();
msk.field(FR_JOLLY4).disable();
}
else
{
msk.field(FR_JOLLY3).enable();
msk.field(FR_JOLLY4).enable();
fdotmp = true;
}
if (dadata.ok() || fdotmp)
{
TLocalisamfile rcondv(LF_LVRCONDV);
rcondv.put(LVRCONDV_CODCF,codcf);
rcondv.put(LVRCONDV_CODCONT,cont.get_int(LVCONDV_CODCONT));
rcondv.put(LVRCONDV_CODART,msk.get(FR_CODART));
if (rdoc.get_date("DADATATMP").empty())
{
if (!dadata.ok() && rcondv.read() == NOERR)
{
rcondv.put(LVRCONDV_INDTTMP, datadoc);
rcondv.rewrite();
rdoc.put("DADATATMP", datadoc);
msk.field(FR_JOLLY3).set(datadoc);
}
else
{
rdoc.put("DADATATMP", dadata);
msk.field(FR_JOLLY3).set(dadata);
}
}
if (rdoc.get_date("ADATATMP").empty())
{
if (adata.ok() && adata <= datadoc)
{
rdoc.put("ADATATMP", adata);
msk.field(FR_JOLLY4).set(adata);
}
else
{
//instanzio in TRecordset sui giri
TISAM_recordset giri("USE LVRCONSPLAN KEY 3\nSELECT DTCONS>#DATADOC\nFROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT");
giri.set_var("#DATADOC", datadoc);
giri.set_var("#CODCF", codcf);
giri.set_var("#CODCONT", cont.get_long(LVCONDV_CODCONT));
if (giri.move_first())
{
rdoc.put("ADATATMP", giri.get(LVRCONSPLAN_DTCONS).as_date());
msk.field(FR_JOLLY4).set(giri.get(LVRCONSPLAN_DTCONS).as_date());
if (rcondv.read() == NOERR)
{
rcondv.put(LVRCONDV_FIDTTMP, giri.get(LVRCONSPLAN_DTCONS).as_date());
rcondv.rewrite();
}
}
}
}
}
//abilito o disabilito azzerandolo il campo "Ritirato" a seconda di cosa prevede la causale
if (cau.is_ritiro())
{
msk.field(FR_QTAGG1).enable(true);
if (codmagcoll.blank())
{
codmagcoll = codmagdef;
msk.field(FR_CODMAGC).set(codmagcoll);
}
if (coddepcoll.blank())
{
coddepcoll = coddepdef; //magazzino del circolante
msk.field(FR_CODDEPC).set(coddepcoll);
}
}
else
{
msk.field(FR_QTAGG1).set("");
msk.field(FR_QTAGG1).disable();
}
//abilito o disabilito azzerandolo il campo "Consegnato" a seconda di cosa prevede la causale
//ATTENZIONE: questo campo risulta sempre disabilitato se l'articolo <20> bloccato
if (cau.is_consegna() && rcont.get(LVRCONDV_ARTBLOC).empty())
{
msk.field(FR_QTA).enable(true);
if (codmag.blank())
{
codmag = codmagdef;
msk.field(FR_CODMAG).set(codmag);
}
if (coddep.blank())
{
coddep = coddepdef;
msk.field(FR_CODDEP).set(coddep);
}
}
else
{
msk.field(FR_QTA).set("");
msk.field(FR_QTA).disable();
}
}
}
return true;
}
//LV_CODMAG_HANDLER: handler che limita l'esecuzione
bool TGestione_bolle_msk::lv_codmag_handler(TMask_field& f, KEY k)
{
bool ok = true;
if (f.to_check(k, true))
{
TMask& msk = f.mask();
const TString& causale = msk.get(FR_CAULAV);
if (causale.full())
{
switch(f.dlg())
{
case FR_CODMAG: ok = codmag_handler( f, k ); break;
default: break;
}
}
}
return ok;
}
bool TGestione_bolle_msk::lv_datatmp_handler(TMask_field& f, KEY k)
{
if (k == K_ENTER)
{
TMask& msk = f.mask();
//leggo il codart che ho scritto nella riga corrente dello sheet
const TString& codart = msk.get(FR_CODART);
const TDate& dadata = msk.get_date(FR_JOLLY3);
const TDate& adata = msk.get_date(FR_JOLLY4);
TGestione_bolle_msk& dmsk = (TGestione_bolle_msk&) msk.get_sheet()->mask();
//recupero il documento e modifico le date sulla riga documento
TDocumento& doc = dmsk.doc();
TRiga_documento& rdoc = doc[msk.get_sheet()->selected()+1];
rdoc.put("DADATATMP", dadata);
rdoc.put("ADATATMP", adata);
//recupero i dati di interesse dalla testata per poter trovare il contratto
const long codcf = dmsk.get_long(F_CODCF);
const int indsped = dmsk.get_int(F_CODINDSP);
TDate datadoc = dmsk.get_date(F_DATADOC);
//trovo il contratto utlizzato e la riga contratto specifica che mi serve
const TLaundry_contract cont(codcf, indsped, datadoc);
TLocalisamfile rcondv(LF_LVRCONDV);
rcondv.put(LVRCONDV_CODCF,codcf);
rcondv.put(LVRCONDV_CODCONT,cont.get_int(LVCONDV_CODCONT));
rcondv.put(LVRCONDV_CODART,msk.get(FR_CODART));
if (rcondv.read() == NOERR)
{
rcondv.put(LVRCONDV_INDTTMP, dadata);
rcondv.put(LVRCONDV_FIDTTMP, adata);
rcondv.rewrite();
}
msk.field(FR_JOLLY3).set_focusdirty(false);
msk.field(FR_JOLLY4).set_focusdirty(false);
}
return true;
}
//metodo che setta gli handler sui campi di riga
void TGestione_bolle_msk::user_set_row_handler(TMask& rm, short field, int index)
{
switch(index)
{
case 4101: rm.set_handler(field, lv_ritirato_handler); break;
case 4102: rm.set_handler(field, lv_consegnato_handler); break;
case 4103: rm.set_handler(field, lv_codart_handler); break;
case 4104: rm.set_handler(field, lv_causale_handler); break;
case 4105: rm.set_handler(field, lv_codmag_handler); break;
case 4106: rm.set_handler(field, lv_datatmp_handler); break;
default : TDocumento_mask::user_set_row_handler(rm, field, index); break;
}
}
//metodo che setta l'handler di bolla
void TGestione_bolle_msk::user_set_handler( short fieldid, int index)
{
switch(index)
{
case 4101: set_field_handler(fieldid, lv_data_handler); break;
case 4102: set_field_handler(fieldid, lv_contratto_handler); break;
case 4103: set_field_handler(fieldid, lv_bolla_handler); break;
case 4105: set_field_handler(fieldid, lv_dataprco_handler); break;
default : TDocumento_mask::user_set_handler(fieldid, index); break;
}
}
TGestione_bolle_msk::TGestione_bolle_msk(const char* tipodoc) : TDocumento_mask(tipodoc), _autoselect(-1)
{
TConfig* configlv = new TConfig(CONFIG_DITTA,"lv");
char dtfs = configlv->get_char("Datafissa");
if (dtfs == 'X')
field(F_DATADOC).disable();
sfield(F_SHEET).set_nav_column(FR_QTA, FR_QTAGG1);
sfield(F_SHEET).set_auto_append();
sfield(F_SHEET).set_handler( ss_handler );
sfield(F_SHEET).set_notify( ss_notify );
}
//////////////////////////////////////////
//// CLASSE TGESTIONE_BOLLE_APP ////
//////////////////////////////////////////
//ridefinisco il metodo get_mask delle TMotore_application
TMask* TGestione_bolle_app::get_mask( int mode )
{
if (mode == MODE_INS || mode == MODE_MOD)
{
TString4 tipodoc;
if (mode == MODE_MOD)
tipodoc = get_relation()->curr().get(DOC_TIPODOC); // Lo prendo dalla relazione (Gelai)
else
tipodoc = TMotore_application::get_mask(MODE_QUERY)->get(F_TIPODOC);
if (_doc_masks.objptr(tipodoc) == NULL)
{
TGestione_bolle_msk* m = new TGestione_bolle_msk(tipodoc);
TSheet_field& sheet = m->sfield(F_SHEET);
if (sheet.exist_column(FR_JOLLY1))
{
//setto l'allineamento a destra dei campi incriminati e pure criminali
sheet.set_column_justify(sheet.cid2index(FR_JOLLY1), true);
sheet.set_column_justify(sheet.cid2index(FR_JOLLY2), true);
}
_doc_masks.add(tipodoc, m);
const TTipo_documento& tdoc = m->doc().tipo();
const TString_array& handlers = tdoc.handlers();
FOR_EACH_ARRAY_ROW(handlers, i, row)
{
m->user_set_handler( row->get_int( 0 ), row->get_int( 1 ) );
}
}
}
return TMotore_application::get_mask(mode);
}
void TGestione_bolle_app::elimina_vuote( const TMask& m)
{
TDocumento_mask& mask = (TDocumento_mask&) m;
TDocumento& d = mask.doc();
TSheet_field& sheet = mask.sfield(F_SHEET);
FOR_EACH_DOC_ROW_BACK(d, r, row)
{
if (row->is_articolo() && row->get_int(RDOC_QTA) == 0 && row->get_int(RDOC_QTAGG1) == 0)
{
d.destroy_row(r,true);
}
}
}
//ridefinisco il metodo write delle TMotore_application
int TGestione_bolle_app::write( const TMask& m )
{
elimina_vuote(m);
return TMotore_application::write(m);
}
//ridefinisco il metodo rewrite delle TMotore_application
int TGestione_bolle_app::rewrite( const TMask& m )
{
elimina_vuote(m);
return TMotore_application::rewrite(m);
}
//ridefinisco il metodo read della TMotore_application
int TGestione_bolle_app::read(TMask& m)
{
const int err = TMotore_application::read(m);
TGestione_bolle_msk& mask = (TGestione_bolle_msk&) m;
TDocumento& d = mask.doc();
_giac.reset(d);
FOR_EACH_DOC_ROW_BACK(d, r, row)
_giac.load_row((TRiga_documento&)*row);
if (err == NOERR)
mask._autoselect = 0;
return err;
}
//ridefinisco il metodo init_insert_mode della TMotore_application
void TGestione_bolle_app::init_insert_mode(TMask &m)
{
TGestione_bolle_msk& mask = (TGestione_bolle_msk&) m;
TDocumento& d = mask.doc();
_giac.reset(d);
//se sto leggendo o generando un buono di ritiro, abilito questo campo
bool enable_dataprco = mask.get(F_CODNUM) == ini_get_string(CONFIG_DITTA, "lv", "NUM_RIT(0)") &&
mask.get(F_TIPODOC) == ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_RIT(0)");
mask.field(F_LVDATAPRCO).enable(enable_dataprco);
mask.reset_var_mask();
mask.first_focus(F_CODCF, false);
return TMotore_application::init_insert_mode(m);
}
//metodo che mi restituisce la giac
TGiac_per_cli& TGestione_bolle_app::giacenza()
{
return _giac;
}
int lv3100( int argc, char* argv[])
{
TGestione_bolle_app a;
a.run( argc, argv, TR("Documenti di Trasporto"));
return 0;
}