diff --git a/src/lv/f168.trr b/src/lv/f168.trr index 726b02e96..44ee2d919 100755 --- a/src/lv/f168.trr +++ b/src/lv/f168.trr @@ -24,7 +24,7 @@ TIPOCAN|2|1|0|Tipo canone CANFIX|2|1|0|Opzioni per importo canone fisso NOLCICTE|1|1|0|Opzioni per importo % sul valore convenzionale TIPOIMB|2|1|0|Tipo imballo -SSCONS|8|1|0|Spese di spedizione alla consegna +SSCONS|8|1|0|Spese da addebitare alla consegna TIPOSTPRZ|8|1|0|Stampa prezzo in bolla DTLASTFAT|5|8|0|Data ultima fattura ATTFATNODT|8|1|0|Attiva fatturazione indipendentemente dalla data diff --git a/src/lv/lv0400a.uml b/src/lv/lv0400a.uml index 6d738f7d0..801e376c5 100755 --- a/src/lv/lv0400a.uml +++ b/src/lv/lv0400a.uml @@ -586,7 +586,7 @@ END BOOLEAN F_SSCONS BEGIN - PROMPT 2 18 "Spese di spedizione alla consegna" + PROMPT 2 18 "Spese da addebitare alla consegna" FIELD SSCONS END diff --git a/src/lv/lv2400.cpp b/src/lv/lv2400.cpp index 8a8f51212..1ce6585b0 100755 --- a/src/lv/lv2400.cpp +++ b/src/lv/lv2400.cpp @@ -1,1350 +1,1382 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "lvlib.h" -#include "../mg/anamag.h" -#include "../mg/clifogiac.h" -#include "../ve/velib.h" -#include "../ve/rcondv.h" - -#include "doc.h" -#include "lvcondv.h" -#include "lvrcondv.h" -#include "lvrconsplan.h" -#include "rdoc.h" - -#include "lv2400a.h" - - ///////////////////////////////////// - //// TGENERA_DOCUMENTI_MSK //// - ///////////////////////////////////// - -//classe TGenera_documenti_msk -class TGenera_documenti_msk : public TAutomask -{ -public: - virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); - TGenera_documenti_msk (const char* name) : TAutomask(name) {} -}; - -//ON_FIELD_EVENT: questo metodo gestisce i vari eventi che si verificano sui campi della maschera -bool TGenera_documenti_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) -{ - switch (o.dlg()) - { - case F_DTDOC: - if (e == fe_modify) - { - const TDate oggi(TODAY); - if (get_date(F_DTDOC) <= oggi) - { - warning_box(TR("Attenzione: la data documento non può essere nel passato")); - o.reset(); - } - } - break; - default: break; - } - return true; -} - ////////////////////////////////////// - //// TGENERA_DOCUMENTI_APP //// - ////////////////////////////////////// - -//classe TGenera_documenti_app -class TGenera_documenti_app : public TSkeleton_application -{ - TGenera_documenti_msk* _msk; - TAssoc_array _quantita; - TAssoc_array _quantita_ritirata; - TConfig* _configlv; - char _buono; - long _ndoc; - bool _has_gui; - -private: - //Metodi per la generazione dei documenti - bool crea_documento_ritiro(const TISAM_recordset& ritiro, TLog_report& rep, int& numdocgen, TAssoc_array& documenti); - bool crea_documento_plan(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen, TAssoc_array& documenti); - void crea_riga(TToken_string& chiave, const char modpas, const int tplis, const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep); - //Metodi per il recupero di codnum, tpdoc, stato - bool numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; - bool numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; - bool numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; - //Metodi per l'eliminazione dei documenti - void cambia_stato(const char ritoant, const TString_array& docarr); - void elimina_bolle(const long codcli, const long codind, TString_array& docarr); - //Metodi per la scansione dei documenti - int scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen); - void scansione_consegne(const long codcli, const long codind, const TDocumento& docgen); - //Metodo per il calcolo delle quantità in bolla - void calcolo_quantita(const TDocumento& doc, const char ritoant); - //Metodi aggiornare il conguaglio sui contratti - void aggiorna_conguaglio(TRectype& rcondv, const real arr) const; - -protected: - virtual bool create(); - virtual void on_config_change(); - virtual bool destroy(); - -public: - bool transfer(); - virtual void main_loop(); -}; - -//////////////////////////////// -//// Metodi Protected //// -//////////////////////////////// - -//CREATE: metodo costruttore -bool TGenera_documenti_app::create() -{ - open_files(LF_DOC, LF_RIGHEDOC, 0); - _msk = new TGenera_documenti_msk("lv2400a"); - _ndoc = 0; - - _configlv = new TConfig(CONFIG_DITTA,"lv"); - _buono = *TApplication::argv(2); - return TSkeleton_application::create(); -} - -//ON_CONFIG_CHANGE: metodo che aggiorna la variabile TConfig ogni volta -//che faccio un cambiamento al file fisico -void TGenera_documenti_app::on_config_change() -{ - if (_configlv != NULL) - delete _configlv; - _configlv = new TConfig(CONFIG_DITTA,"lv"); -} - -//DESTROY: metodo distruttore -bool TGenera_documenti_app::destroy() -{ - delete _configlv; - delete _msk; - return TApplication::destroy(); -} - -/////////////////////////////////////////////////////// -//// Metodi per la generazione dei documenti //// -/////////////////////////////////////////////////////// - -//CREA_DOCUMENTO_RITIRO: metodo che crea un nuovo documento di trasporto dai dati salvati -bool TGenera_documenti_app::crea_documento_ritiro(const TISAM_recordset& ritiro, TLog_report& rep, int& numdocgen, TAssoc_array& documenti) -{ - //recupero i dati di interesse dalla maschera - const TDate datagen(TODAY); - //per ogni planning recupero i dati di interesse dal planning - const long codcli = ritiro.get(DOC_CODCF).as_int(); - const long codcont = ritiro.get(DOC_CODCONT).as_int(); - const TDate dtcons = ritiro.get("G1:DATAPRCO").as_date(); //che è anche la data documento - const int coditi = int(ritiro.get("CODITI").as_int()); - TString8 codaut = ritiro.get(DOC_CODAG).as_string().right(5); codaut.trim(); - const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons; - const int anno = datadoc.year(); - const long ag_selected = _msk->get_long(F_CODAUT); - - if (ag_selected > 0L && atol(codaut) != ag_selected) - return true; - - //preparo la chiave per la tabella contratti - TToken_string keycont; - keycont.add(codcli); - keycont.add(codcont); - //instanzio una cache sulla tabella dei contratti - const TRectype& tcont = cache().get(LF_LVCONDV,keycont); - //estraggo i dati di interesse dalla cache - const long codind = tcont.get_long(LVCONDV_CODINDSP); //codice dell'indirizzo di spedizione - const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino - //const bool prinbo = tcont.get_bool(LVCONDV_STPRZBOL); //prezzo in bolla - const bool prinbo = true; //sempre a true; verrà gestita a video in futuro (27/10/2009) - - //variabili che conterranno i parametri dei documenti che devo generare... - //...settati dalla funzione numerazione_ddt() - TString4 codnum, tpdoc, statoi, statof; - - //Cerco il tipo documento da generare sul contratto; se non lo trovo lo cerco in configurazione. - //Se non trovo quale documento generare, evito il resto dell'elaborazione - if (tcont.get(LVCONDV_CODNUM).full() && _buono == 'C') - { - codnum = tcont.get(LVCONDV_CODNUM); - tpdoc = tcont.get(LVCONDV_TPDOC); - - //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) - const TString& s2 = cache().get("%TIP",tpdoc,"S2"); - statoi = s2.left(1); - statof = s2.mid(1,1); - } - else if (!numerazione_ddt(codnum, tpdoc, statoi, statof)) - return NOERR; - - //recupero i dati di interesse dal cliente - TToken_string key; - key.add('C'); - key.add(codcli); - const TRectype& clifo = cache().get(LF_CLIFO, key); - const TString4 codpag = clifo.get(CLI_CODPAG); - const long codabi = clifo.get_long(CLI_CODABI); - const long codcab = clifo.get_long(CLI_CODCAB); - const TString80 iban = clifo.get(CLI_IBAN); - - //reupero la cuasale di magazzino di testata - const TString8 causmag = cache().get("%TIP", tpdoc, "S9"); - - //recupero i dati di interesse dal file CFVEN - const TRectype& cfven = cache().get(LF_CFVEN, key); - const long codabipr = cfven.get_long(CFV_CODABIPR); - const long codcabpr = cfven.get_long(CFV_CODCABPR); - const bool ragdoc = cfven.get_bool(CFV_RAGGDOC); - const int codindsp = cfven.get_int(CFV_CODINDSP); - const TString8 codag1 = cfven.get(CFV_CODAG1); - const TString4 codmez = cfven.get(CFV_CODSPMEZZO); - const TString4 codporto = cfven.get(CFV_CODPORTO); - const TString4 codnote1 = cfven.get(CFV_CODNOTESP1); - const TString4 codnote2 = cfven.get(CFV_CODNOTESP2); - const TString4 codnote = cfven.get(CFV_CODNOTE); - const TString8 codvet1 = cfven.get(CFV_CODVETT1); - const TString8 codvet2 = cfven.get(CFV_CODVETT2); - const TString8 codvet3 = cfven.get(CFV_CODVETT3); - const real speseinc = cfven.get_real(CFV_PERCSPINC); - const TString4 catven = cfven.get(CFV_CATVEN); - const bool addbolli = cfven.get_bool(CFV_ADDBOLLI); - const TString8 codlist = cfven.get(CFV_CODLIST); - const TString4 codzona = cfven.get(CFV_CODZONA); - - if(codaut.empty()) - codaut = cfven.get(CFV_CODAG); - - //gestione sconto - TString sconto; - - const char tpgest = ini_get_string(CONFIG_DITTA, "ve", "GESSCO")[0]; - switch(tpgest) - { - case 'P': sconto = cfven.get(CFV_SCONTO); break; //Percentuale su anagrafica cliente - case 'T': sconto = cache().get("%SCC", cfven.get(CFV_CODSCC), "S1"); break; //Gestione tabella sconti - case 'A': //Gestione archivio sconti - { - TConfig ditta(CONFIG_DITTA, "ve"); - - TLocalisamfile sconti(LF_SCONTI); - sconti.put("TIPO", "I"); - - if (ditta.get_bool("SCOKEY", "ve", 1)) - sconti.put("CODCAT", cfven.get(CFV_CATVEN)); - - TString16 cod; - if (ditta.get_bool("SCOKEY", "ve", 2)) - cod.format("%-2s", (const char*)cfven.get(CFV_CODSCC)); - else - cod = " "; - - if (ditta.get_bool("SCOKEY", "ve", 3)) - { - TString8 tmp; - tmp.format("%-2s", (const char*)cfven.get(CFV_CODZONA)); - cod << tmp; - } - else - cod << " "; - - if (ditta.get_bool("SCOKEY", "ve", 4)) - cod << clifo.get(CLI_CODPAG); - - sconti.put("CODART", cod); - - if (sconti.read() == NOERR) - sconto = sconti.get("SCONTO"); - } - break; - case 'N': //sconto non gestito - default: break; - } - - //creo il documento corretto riempiendo i campi che già conosco - TDocumento doc('D', anno, codnum, 0L); - doc.put(DOC_TIPODOC, tpdoc); - doc.put(DOC_DATADOC, datadoc); - doc.put(DOC_TIPOCF, 'C'); - doc.put(DOC_CODCF, codcli); - doc.put(DOC_CODCONT, codcont); - if(codindsp > 0) - doc.put(DOC_CODINDSP, codindsp); - doc.put(DOC_RAGGR, ragdoc); - doc.put(DOC_CODPAG, codpag); - doc.put(DOC_CODABIA, codabi); - doc.put(DOC_CODCABA, codcab); - doc.put(DOC_IBAN, iban); - doc.put(DOC_CODABIP, codabipr); - doc.put(DOC_CODCABP, codcabpr); - doc.put(DOC_CODAG, codaut); - doc.put(DOC_CODAGVIS, codag1); - doc.put(DOC_CODSPMEZZO, codmez); - doc.put(DOC_ZONA, codzona); - doc.put(DOC_CODPORTO, codporto); - doc.put(DOC_CODNOTESP1, codnote1); - doc.put(DOC_CODNOTESP2, codnote2); - doc.put(DOC_CODNOTE, codnote); - doc.put(DOC_CODVETT1, codvet1); - doc.put(DOC_CODVETT2, codvet2); - doc.put(DOC_CODVETT3, codvet3); - doc.put(DOC_CATVEN, catven); - doc.put(DOC_CODLIST, codlist); - doc.put(DOC_CAUSMAG, causmag); - doc.put(DOC_PERCSPINC, speseinc); - doc.put(DOC_ADDBOLLI, addbolli); - doc.put(DOC_SCONTOPERC, sconto); - doc.put(DOC_DATAPART, TDate(TODAY)); - doc.put("DATAGEN", datagen); //data generazione del documento - doc.put("DATAPRCO", dtcons); //data prevista consegna - doc.put("CODITI", coditi); //codice itinerario - - //calcola tutte le quantità riportate sui documenti di ritiro, sui documenti di anticipo - const int numerodoc = scansione_ritiri_anticipi(codcli, dtcons, 'R', doc); - scansione_ritiri_anticipi(codcli, dtcons, 'A', doc); - - int err = 1; - if(numerodoc > 0) - { - FOR_EACH_ASSOC_OBJECT(_quantita,h,key,obj) - { - TToken_string chiave(key); - const TCodice_articolo codart = chiave.get(0); - //preparo la chiave per la tabella righe contratti - TToken_string keyrcont; - keyrcont.add(codcli); - keyrcont.add(codcont); - keyrcont.add(codart); - const TRectype& rcont = cache().get(LF_LVRCONDV, keyrcont); - const TDate dadata = rcont.get_date(LVRCONDV_INDTTMP); - const TDate adata = rcont.get_date(LVRCONDV_FIDTTMP); - - if (dadata.ok() && dtcons >= adata) - crea_riga(chiave, ' ', tplis, true, prinbo, doc, rep); - else - crea_riga(chiave, ' ', tplis, false, prinbo, doc, rep); - } - - if (doc.rows() > 0) - { - TToken_string orderkey; - orderkey.add(RDOC_CODART); - doc.sort_rows(orderkey); - while (err = doc.write() == _isreinsert) - { - const long old_ndoc = doc.get_long(DOC_NDOC); - doc.renum_ndoc(); - const long new_ndoc = doc.get_long(DOC_NDOC); - if (_has_gui) - lv_popup_msg("Attenzione documento numero %ld rinumerato in %ld", old_ndoc, new_ndoc); - } - ++numdocgen; - } - else - doc.remove(); - - //scrivo sul planning il riferimento alla bolla che lo accompagna - if (err == NOERR) - { - //tengo traccia dei documenti che sto generando, per poterli stampare dopo - TDoc_key kdoc(doc.get_int(DOC_ANNO), doc.get(DOC_CODNUM), doc.get_int(DOC_NDOC)); - if (!documenti.is_key(kdoc)) - documenti.add(kdoc, kdoc); - } - } - return err == NOERR; -} - -//CREA_DOCUMENTO_PLAN: metodo che crea un nuovo documento di trasporto dai dati salvati -bool TGenera_documenti_app::crea_documento_plan(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen, TAssoc_array& documenti) -{ - //recupero i dati di interesse dalla maschera - const TDate datagen(TODAY); - - //per ogni planning recupero i dati di interesse dal planning - const long codcli = plan.get(LVRCONSPLAN_CODCF).as_int(); - const long codcont = plan.get(LVRCONSPLAN_CODCONT).as_int(); - const TDate dtcons = plan.get(LVRCONSPLAN_DTCONS).as_date(); //che è anche la data documento - const char modpas = plan.get(LVRCONSPLAN_MODPASS).as_string()[0]; - const int coditi = plan.get(LVRCONSPLAN_CODITI).as_int(); - TString8 codaut = plan.get(LVRCONSPLAN_CODAUT).as_string().right(5); codaut.trim(); - const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons; - const int anno = datadoc.year(); - - //preparo la chiave per la tabella contratti - TToken_string keycont; - keycont.add(codcli); - keycont.add(codcont); - //instanzio una cache sulla tabella dei contratti - const TRectype& tcont = cache().get(LF_LVCONDV,keycont); - //estraggo i dati di interesse dalla cache - const long codind = tcont.get_long(LVCONDV_CODINDSP); //codice dell'indirizzo di spedizione - const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino - //const bool prinbo = tcont.get_bool(LVCONDV_STPRZBOL); //prezzo in bolla - const bool prinbo = true; //sempre a true; verrà gestita a video in futuro (27/10/2009) - - //variabili che conterranno i parametri dei documenti che devo generare... - //...settati dalla funzione numerazione_ddt() - TString4 codnum, tpdoc, statoi, statof; - - //Cerco il tipo documento da generare sul contratto; se non lo trovo lo cerco in configurazione. - //Se non trovo quale documento generare, evito il resto dell'elaborazione - if (tcont.get(LVCONDV_CODNUM).full() && _buono == 'C') - { - codnum = tcont.get(LVCONDV_CODNUM); - tpdoc = tcont.get(LVCONDV_TPDOC); - - //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) - const TString& s2 = cache().get("%TIP",tpdoc,"S2"); - statoi = s2.left(1); - statof = s2.mid(1,1); - } - else if (!numerazione_ddt(codnum, tpdoc, statoi, statof)) - return NOERR; - - if(_ndoc == 0) - { - TString query2; - query2 << "USE DOC\n" - << "FROM PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\"\n" - << "TO PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\""; - TISAM_recordset bolle(query2); - if (bolle.move_last()) - _ndoc = bolle.get(DOC_NDOC).as_int(); - } - - //recupero i dati di interesse dal cliente - TToken_string key; - key.add('C'); - key.add(codcli); - const TRectype& clifo = cache().get(LF_CLIFO, key); - const TString4 codpag = clifo.get(CLI_CODPAG); - const long codabi = clifo.get_long(CLI_CODABI); - const long codcab = clifo.get_long(CLI_CODCAB); - const TString80 iban = clifo.get(CLI_IBAN); - - //reupero la cuasale di magazzino di testata - const TString8 causmag = cache().get("%TIP", tpdoc, "S9"); - - //recupero i dati di interesse dal file CFVEN - const TRectype& cfven = cache().get(LF_CFVEN, key); - const long codabipr = cfven.get_long(CFV_CODABIPR); - const long codcabpr = cfven.get_long(CFV_CODCABPR); - const bool ragdoc = cfven.get_bool(CFV_RAGGDOC); - const int codindsp = cfven.get_int(CFV_CODINDSP); - const TString8 codag1 = cfven.get(CFV_CODAG1); - const TString4 codmez = cfven.get(CFV_CODSPMEZZO); - const TString4 codporto = cfven.get(CFV_CODPORTO); - const TString4 codnote1 = cfven.get(CFV_CODNOTESP1); - const TString4 codnote2 = cfven.get(CFV_CODNOTESP2); - const TString4 codnote = cfven.get(CFV_CODNOTE); - const TString8 codvet1 = cfven.get(CFV_CODVETT1); - const TString8 codvet2 = cfven.get(CFV_CODVETT2); - const TString8 codvet3 = cfven.get(CFV_CODVETT3); - const real speseinc = cfven.get_real(CFV_PERCSPINC); - const TString4 catven = cfven.get(CFV_CATVEN); - const bool addbolli = cfven.get_bool(CFV_ADDBOLLI); - const TString8 codlist = cfven.get(CFV_CODLIST); - const TString4 codzona = cfven.get(CFV_CODZONA); - - if(codaut.empty()) - codaut = cfven.get(CFV_CODAG); - - //gestione sconto - TString sconto; - - const char tpgest = ini_get_string(CONFIG_DITTA, "ve", "GESSCO")[0]; - switch(tpgest) - { - case 'P': sconto = cfven.get(CFV_SCONTO); break; //Percentuale su anagrafica cliente - case 'T': sconto = cache().get("%SCC", cfven.get(CFV_CODSCC), "S1"); break; //Gestione tabella sconti - case 'A': //Gestione archivio sconti - { - TConfig ditta(CONFIG_DITTA, "ve"); - - TLocalisamfile sconti(LF_SCONTI); - sconti.put("TIPO", "I"); - - if(ditta.get_bool("SCOKEY", "ve", 1)) - sconti.put("CODCAT", cfven.get(CFV_CATVEN)); - - TString16 cod; - if(ditta.get_bool("SCOKEY", "ve", 2)) - cod.format("%-2s", (const char*)cfven.get(CFV_CODSCC)); - else - cod = " "; - - if(ditta.get_bool("SCOKEY", "ve", 3)) - { - TString8 tmp; - tmp.format("%-2s", (const char*)cfven.get(CFV_CODZONA)); - cod << tmp; - } - else - cod << " "; - - if(ditta.get_bool("SCOKEY", "ve", 4)) - cod << clifo.get(CLI_CODPAG); - - sconti.put("CODART", cod); - - if (sconti.read() == NOERR) - sconto = sconti.get("SCONTO"); - } - break; - case 'N': //sconto non gestito - default : break; - } - - //creo il documento corretto riempiendo i campi che già conosco - TDocumento doc('D', anno, codnum, ++_ndoc); - doc.put(DOC_TIPODOC, tpdoc); - if(_msk->get_bool(F_DTEMIS)) - doc.put(DOC_DATADOC, _msk->get_date(F_DTDOC)); - else - doc.put(DOC_DATADOC, dtcons); - doc.put(DOC_TIPOCF, 'C'); - doc.put(DOC_CODCF, codcli); - doc.put(DOC_CODCONT, codcont); - if(codindsp > 0) - doc.put(DOC_CODINDSP, codindsp); - doc.put(DOC_RAGGR, ragdoc); - doc.put(DOC_CODPAG, codpag); - doc.put(DOC_CODABIA, codabi); - doc.put(DOC_CODCABA, codcab); - doc.put(DOC_IBAN, iban); - doc.put(DOC_CODABIP, codabipr); - doc.put(DOC_CODCABP, codcabpr); - doc.put(DOC_CODAG, codaut); - doc.put(DOC_CODAGVIS, codag1); - doc.put(DOC_CODSPMEZZO, codmez); - doc.put(DOC_ZONA, codzona); - doc.put(DOC_CODPORTO, codporto); - doc.put(DOC_CODNOTESP1, codnote1); - doc.put(DOC_CODNOTESP2, codnote2); - doc.put(DOC_CODNOTE, codnote); - doc.put(DOC_CODVETT1, codvet1); - doc.put(DOC_CODVETT2, codvet2); - doc.put(DOC_CODVETT3, codvet3); - doc.put(DOC_CATVEN, catven); - doc.put(DOC_CODLIST, codlist); - doc.put(DOC_CAUSMAG, causmag); - doc.put(DOC_PERCSPINC, speseinc); - doc.put(DOC_ADDBOLLI, addbolli); - doc.put(DOC_SCONTOPERC, sconto); - doc.put("DATAGEN", datagen); //data generazione del documento - doc.put("DATAPRCO", dtcons); //data prevista consegna - doc.put("CODITI", coditi); //codice itinerario - - //calcola tutte le quantità riportate sui documenti di ritiro, sui documenti di anticipo - int numerodoc = scansione_ritiri_anticipi(codcli, dtcons, 'R', doc); - scansione_ritiri_anticipi(codcli, dtcons, 'A', doc); - - int err = 1; - if(numerodoc > 0) - { - FOR_EACH_ASSOC_OBJECT(_quantita,h,key,obj) - { - TToken_string chiave(key); - const TString80 codart = chiave.get(0); - //preparo la chiave per la tabella righe contratti - TToken_string keyrcont; - keyrcont.add(codcli); - keyrcont.add(codcont); - keyrcont.add(codart); - const TRectype& rcont = cache().get(LF_LVRCONDV, keyrcont); - const TDate dadata = rcont.get_date(LVRCONDV_INDTTMP); - const TDate adata = rcont.get_date(LVRCONDV_FIDTTMP); - - if (dadata.ok() && dtcons >= adata) - crea_riga(chiave, modpas, tplis, true, prinbo, doc, rep); - else - crea_riga(chiave, modpas, tplis, false, prinbo, doc, rep); - } - - if (doc.rows() > 0) - { - TToken_string orderkey; - orderkey.add(RDOC_CODART); - doc.sort_rows(orderkey); - err = doc.rewrite(); - ++numdocgen; - } - else - doc.remove(); - - //scrivo sul planning il riferimento alla bolla che lo accompagna - if (err == NOERR) - { - TLocalisamfile& f = plan.cursor()->file(); - f.put(LVRCONSPLAN_ANNO, anno); - f.put(LVRCONSPLAN_CODNUM, codnum); - f.put(LVRCONSPLAN_NDOC, _ndoc); - f.rewrite(); - - //tengo traccia dei documenti che sto generando, per poterli stampare dopo - TDoc_key kdoc(doc.get_int(DOC_ANNO), doc.get(DOC_CODNUM), doc.get_int(DOC_NDOC)); - if (!documenti.is_key(kdoc)) - documenti.add(kdoc, kdoc); - } - } - return err == NOERR; -} - -//CREA_RIGA: questa funzione crea una riga merce per una bolla di consegna -void TGenera_documenti_app::crea_riga(TToken_string& chiave, const char modpas, const int tplis, - const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep) -{ - //creo la nuova riga - TString4 tiporiga; - switch (_buono) - { - case 'P': tiporiga = "24"; break; - case 'C': tiporiga = "21"; break; - default: break; - } - - const long codcli = doc.get_long(DOC_CODCF); - const long codcont = doc.get_long(DOC_CODCONT); - const TCodice_articolo codart = chiave.get(0); - const TString4 causale = chiave.get(1); - - //calcolo della quantità che va sulla bolla - - //preparo la chiave per la tabella righe contratti - TLaundry_contract cont(codcli, codcont); - const TRectype& rcont = cont.row(codart); - const bool artbloc = rcont.get_int(LVRCONDV_ARTBLOC) > 0; - - if (artbloc) - return; - - //recupero i dati di interesse dalla riga del contratto - const bool arrot = rcont.get_int(LVRCONDV_CALCCONS) == 1; - - const real conguaglio = rcont.get_real(LVRCONDV_QTACONG); - real& qta = *(real*)_quantita.objptr(chiave); - const real& qta1 = *(real*)_quantita_ritirata.objptr(chiave); - const real przdttmp = rcont.get_real(LVRCONDV_PRZDTTMP); - - //instanzio una cache sulla tabella del magazzino - const TRectype& anamag = cache().get(LF_ANAMAG,codart); - //recupero i dati di interesse dall'anagrafica di magazzino, ma devo evitare divisioni per 0 - const long ppconf = anamag.get_real(ANAMAG_PPCONF) != 0 ? anamag.get_int(ANAMAG_PPCONF) : 1; - TString descrart; - descrart << anamag.get(ANAMAG_DESCR) << anamag.get(ANAMAG_DESCRAGG); - - //recupero i valori delle dotazione temporanea dal magazzino del cliente - TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcli, 0); - //fisso l'anno esercizio - TEsercizi_contabili& esc = esercizi(); - const int last_esc = esc.last(); - - //estraggo il record corrispondente su LF_CLIFOGIAC - const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); - - real dotod = reclav.get_real(CLIFOGIAC_DOTOD); - real dottmp = reclav.get_real(CLIFOGIAC_DOTTM); - - //GESTIONE DOTAZIONE TEMPOARANEA - if (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && dottmp > 0) - { - TRiga_documento& rdoc = doc.new_row(tiporiga); - rdoc.put(RDOC_CODART,codart); - if (descrart.len() > 50) - { - rdoc.put(RDOC_DESCR, descrart.left(50)); - rdoc.put(RDOC_DESCLUNGA, true); - rdoc.put(RDOC_DESCEST, descrart.sub(50)); - } - else - rdoc.put(RDOC_DESCR, descrart); - rdoc.put(RDOC_CODARTMAG,codart); - rdoc.put(RDOC_CHECKED,'X'); - - if (prinbo) - rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); //prezzo - - rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva - - const TCausale_lavanderie caudt(ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT")); - - //se ho ritirato un quantitativo di roba maggiore o uguale alla dotazione temporanea - //allora creo la nuova riga documento e azzero la dottmp; altrimenti preparo la riga - //per la quantità che ho ritirato e tengo traccia della cosa - if (qta >= dottmp) - { - qta -= dottmp; - rdoc.put(RDOC_QTAGG1, dottmp); //quantità ritirata - rdoc.put(RDOC_GENERATA, true); - rdoc.put(RDOC_CODAGG1, caudt.caucol().empty() ? caudt.codice() : caudt.caucol()); - dottmp = 0; - dotod -= dottmp; - TString str; - str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) - << " numero " << doc.get(DOC_NDOC) << " in dotazione è stato ritirato completamente."; - rep.log(1, str); - } - else - { - dottmp -= qta; - dotod -= qta; - rdoc.put(RDOC_QTAGG1, qta); //quantità ritirata - rdoc.put(RDOC_GENERATA, true); - rdoc.put(RDOC_CODAGG1, caudt.caucol().empty() ? caudt.codice() : caudt.caucol()); - TString str; - str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) - << " numero " << doc.get(DOC_NDOC) << " in dotazione temporanea non è stato ritirato completamente." - << " Mancano " << dottmp << "unità"; - rep.log(1, str); - qta = ZERO; - } - - //scrivo il magazzino - - const TCausale_magazzino rit(caudt.causale_ritiro()); - const TCausale_magazzino con(caudt.causale_consegna()); - TString8 magazzino, magazzinoc; - - if (rit.get("S10").full()) - magazzino = rit.get("S10").mid(0,5); - else - magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); - - if (con.get("S10").full()) - magazzinoc = con.get("S10").mid(0,5); - else - magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); - - rdoc.put(RDOC_CODMAG, magazzino); - rdoc.put(RDOC_CODMAGC, magazzinoc); - - //recupero l'unità di misura principale di quest'articolo - TToken_string key; - key.add(codart); - key.add(1); - const TRectype& umart = cache().get(LF_UMART, key); - TString4 um = umart.get(UMART_UM); - rdoc.put(RDOC_UMQTA, um); - - //scrivo gli estremi della dotazione temporanea - rdoc.put("DADATATMP", rcont.get_date(LVRCONDV_INDTTMP)); - rdoc.put("ADATATMP", rcont.get_date(LVRCONDV_FIDTTMP)); - rdoc.dirty_fields(); - } - - if (qta > ZERO || (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && qta == ZERO)) - { - TRiga_documento& rdoc = doc.new_row(tiporiga); - - //causale da mettere sulle righe documento - const TCausale_lavanderie cau(causale); - const TString4 codcau = cau.caucol().empty() ? cau.codice() : cau.caucol(); - rdoc.put(RDOC_CODAGG1, codcau); - - if (cau.is_consegna()) - { - const real quantita_noarr = qta - conguaglio; - real quantita_arr = quantita_noarr > ZERO ? quantita_noarr : ZERO; - //se devo arrotondare - if (quantita_arr > ZERO && arrot) - { - //calcolo di quanti pezzi sforo - long arr = quantita_arr.integer() % ppconf; - //se sforo (arr > 0) allora calcolo quanti pezzi in più gli devo dare e aggiorno la quantità - if (arr > 0) - { - const int perarr = ini_get_int(CONFIG_DITTA, "lv", "Perarr"); - if (arr > ppconf * perarr / 100) //arr <= ppconf*perarr/100 -> formula calcolo conguaglio di Tassan - { - arr = ppconf - arr; - quantita_arr += arr; - } - else - quantita_arr -= arr; - } - } - - //scrivo le quantità - rdoc.put(RDOC_QTA, quantita_arr); //quantità consegnata eventualmente arrotondata - rdoc.put(RDOC_QTAGG2, conguaglio); //conguaglio - rdoc.put(RDOC_QTAGG3, quantita_arr); //copia della quantità consegnata - rdoc.put(RDOC_QTAGG4, quantita_noarr); //quantità che avrei consegnato se non arrotondavo (qta ritirata) - rdoc.put(RDOC_GENERATA, true); - - //aggiorno il conguaglio sulla riga del contratto - //altrimenti se il record di riga contratto è vuoto aggiorno il log - if (!rcont.empty()) - { - aggiorna_conguaglio((TRectype&)rcont, quantita_arr - quantita_noarr); - } - else - { - TString str; - str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) - << " numero " << doc.get(DOC_NDOC) << " per la quantità di " << quantita_arr << " unità" - << " non è presente sul contratto del cliente " << codcli; - rep.log(1, str); - } - } - - //essendo la dot tmp un di cui la quantità ritirata è sempre quella - if (cau.is_ritiro()) - rdoc.put(RDOC_QTAGG1, qta1); //quantità ritirata - - //elaborazione sul prezzo da utilizzare - real prezzo; - - if (rcont.empty()) - { - //PROPONI PREZZO - TToken_string key; - key.add('C'); - key.add(codcli); - 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; - TConfig* configve = new TConfig(CONFIG_DITTA,"ve"); - const char gesliscv = configve->get_char("GESLISCV"); - if (gesliscv != 'X') - 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()) - { - prezzo = 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); - prezzo = umart.get_real(UMART_PREZZO); - if (umart.get(UMART_PREZZO).full()) - trvlst = true; - } - } - else - { - //elaborazione per il prezzo: o lo prendo dalle righe contratto, o dall'anagrafica magazzino - if (tplis == 0) - prezzo = rcont.get_real(LVRCONDV_PREZZO); - else - prezzo = anamag.get_real(ANAMAG_COSTSTD); - } - - rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva - - rdoc.put(RDOC_CODART,codart); - if (descrart.len() > 50) - { - rdoc.put(RDOC_DESCR, descrart.left(50)); - rdoc.put(RDOC_DESCLUNGA, true); - rdoc.put(RDOC_DESCEST, descrart.sub(50)); - } - else - rdoc.put(RDOC_DESCR, descrart); - rdoc.put(RDOC_CODARTMAG,codart); - rdoc.put(RDOC_CHECKED,'X'); - if (prinbo) - { - if (!tmp) - rdoc.put(RDOC_PREZZO, prezzo); - else - rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); - rdoc.put(RDOC_SCONTO,rcont.get(LVRCONDV_SCONTPERC)); //sconto - } - - //recupero l'unità di misura principale di quest'articolo - TToken_string key; - key.add(codart); - key.add(1); - const TRectype& umart = cache().get(LF_UMART, key); - TString4 um = umart.get(UMART_UM); - rdoc.put(RDOC_UMQTA, um); - - //scrivo il magazzino - const TCausale_magazzino rit(cau.causale_ritiro()); - const TCausale_magazzino con(cau.causale_consegna()); - - TString8 magazzino; - TString8 magazzinoc; - - if(rit.get("S10").full()) - magazzino = rit.get("S10").mid(0,5); - else - magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); - - if(con.get("S10").full()) - magazzinoc = con.get("S10").mid(0,5); - else - magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); - - rdoc.put(RDOC_CODMAG, magazzino); - rdoc.put(RDOC_CODMAGC, magazzinoc); - rdoc.dirty_fields(); - } - - if (dottmp == 0) - { - cont.update_row(codart, LVRCONDV_INDTTMP, NULLDATE); - cont.update_row(codart, LVRCONDV_FIDTTMP, NULLDATE); - } -} - - ////////////////////////////////////////////////////////////// - //// Metodi per il recupero di codnum, tpdoc, stato //// - ////////////////////////////////////////////////////////////// - -//NUMERAZIONE_DDT: questa funzione cerca quali sono i codnum e i tpdoc che devo generare -bool TGenera_documenti_app::numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const -{ - //questo switc mi permette di generare con lo stesso programma sia i buoni di prelievo (P) - //che i buoni di consegna (C); la variabile globale _buono viene inizializzata con il valore - //passato come parametro al programma al momento della chiamata da menù - switch (_buono) - { - case 'P': - codnum = _configlv->get("NUM_PRE(0)"); - tpdoc = _configlv->get("TIPODOC_PRE(0)"); - break; - case 'C': - codnum = _configlv->get("NUM_GEN"); - tpdoc = _configlv->get("TIPODOC_GEN"); - break; - default: - break; - } - - //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) - const TString& s2 = cache().get("%TIP",tpdoc,"S2"); - statoi = s2.left(1); - statof = s2.mid(1,1); - - return codnum.full() && tpdoc.full(); -} - -//NUMERAZIONE_DRIT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di ritiro -bool TGenera_documenti_app::numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const -{ - codnum = _configlv->get("NUM_RIT", NULL, cod); - tpdoc = _configlv->get("TIPODOC_RIT", NULL, cod); - - //instanzio una cache sulla tabella tipi documento (cerco lo stato iniziale) - const TString& s2 = cache().get("%TIP",tpdoc,"S2"); - statoi = s2.left(1); - statof = s2.mid(1,1); - - return codnum.full() && tpdoc.full(); -} - -//NUMERAZIONE_DANT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di anticipo -bool TGenera_documenti_app::numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const -{ - codnum = _configlv->get("NUM_ANT", NULL, cod); - tpdoc = _configlv->get("TIPODOC_ANT", NULL, cod); - - //instanzio una cache sulla tabella delle righe contratti (cerco lo stato iniziale) - const TString& s2 = cache().get("%TIP",tpdoc,"S2"); - statoi = s2.left(1); - statof = s2.mid(1,1); - - return codnum.full() && tpdoc.full(); -} - - ////////////////////////////////////////////////////////////// - //// Metodi per la scansione dei documenti //// - ////////////////////////////////////////////////////////////// - -//SCANSIONE_RITIRI_ANTICIPI: questa funzione cerca tutte le bolle di ritiro relative a un certo cliente non ancora evase... -//e, dopo l'elaborazione, gli cambia stato -int TGenera_documenti_app::scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen) -{ - const long aanno = data.year(); - TDate dadata = data; dadata.addmonth(-1); - const long daanno = dadata.year(); - - TString4 codnum; - TString4 tpdoc; - TString4 statoi; - TString4 statof; - bool err = NOERR; - //distinguo se sto scandendo i documenti di ritiro o i documenti di anticipo - switch (ritoant) - { - case 'R': - err = numerazione_drit(0, codnum, tpdoc, statoi, statof); - break; - case 'A': - err = numerazione_dant(0, codnum, tpdoc, statoi, statof); - break; - default: - break; - } - - if (!err) - return err; - - //instanzio un recordset che contiene tutti i documenti di interesse - TString query; - query << "USE DOC " - << "SELECT (TIPOCF=\"C\")&&(BETWEEN(CODCF," << codcli << ',' << codcli << "))&&" - << "(ANSI(G1:DATAPRCO)<=#ADATA)&&" - << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" - << "(STATO=\"" << statoi <<"\")\n" - << "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n" - << "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n"; - - //instanzio un recordset che contiene tutti i documenti di interesse - TISAM_recordset docritiri(query); - docritiri.set_var("#ADATA", data); - - //per ogni documento che trovo, aggiorno la quantità, e poi cambio stato al documento - for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) - { - TDocumento doc(docritiri.cursor()->curr()); //instanzio il documento - calcolo_quantita(doc, ritoant); - doc.put(DOC_STATO,statof); //stato di elaborato - //salvo i riferimenti del documento che sto andando a generare - doc.put("PROVVDG", docgen.get(DOC_PROVV)); - doc.put("ANNODG", docgen.get(DOC_ANNO)); - doc.put("CODNUMDG", docgen.get(DOC_CODNUM)); - doc.put("NDCODG", docgen.get(DOC_NDOC)); - - doc.rewrite(); - } - return docritiri.items(); -} - - ////////////////////////////////////////////////////////////// - //// Metodo per il calcolo delle quantità in bolla //// - ////////////////////////////////////////////////////////////// - -//CALCOLO_QUANTITA: questa funzione scorre tutte le righe documento di una bolla di ritiro, riempiendo un... -//TAssoc_array con le quantità ritirate per ogni articolo, sommando le diverse righe con lo stesso articolo... -//Questa funzione viene richiamata per ogni documento valido individuato dalla SCANSIONE_RITIRI -void TGenera_documenti_app::calcolo_quantita(const TDocumento& doc, const char ritoant) -{ - //scorro le righe documento - FOR_EACH_PHYSICAL_RDOC(doc, i, prdoc) - { - //instanzio la riga corrente - const TRiga_documento& rdoc = *prdoc; - //estraggo i dati di interesse - const TCodice_articolo codart = rdoc.get(RDOC_CODARTMAG); - const TString4 codcau = rdoc.get(RDOC_CODAGG1); - TToken_string key; key.add(codart); key.add(codcau); - const real qtardoc = rdoc.get_real(RDOC_QTAGG1); - //se è una riga che riguarda un articolo e se la quantità su questa riga non è nulla, allora la elaboro - if (codart.full() && !qtardoc.is_zero()) - { - TArticolo& art = rdoc.articolo(); - //leggo se esiste già nel TAssoc_array - real *qta = (real*)_quantita.objptr(key); - real *qta1 = (real*)_quantita_ritirata.objptr(key); - //se non esiste - if (qta == NULL) - { - //per ora memorizzo zero - qta = new real; - _quantita.add(key,qta); - } - if (qta1 == NULL) - { - //per ora memorizzo zero - qta1 = new real; - _quantita_ritirata.add(key,qta1); - } - //aggiorno la quantità convertendola all'unità di misura di base, aggiungendola o sottraendola - //...se si tratta di un ritiro o di un anticipo rispettivamente; nel caso della scansione delle - //...bolle di consegna modificate a mano (caso 'B'), devo modificare la quantità da consegnare - //...tenendo conto delle modifiche manuali - switch (ritoant) - { - case 'R': - *qta += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); - *qta1 += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); - break; - case 'A': - *qta -= art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); - break; - default: - break; - } - } - } - return; -} - - ////////////////////////////////////////////////////////////// - //// Metodi aggiornare il conguaglio sui contratti //// - ////////////////////////////////////////////////////////////// - -//AGGIORNA_CONGUAGLIO: questa funzione aggiorna il parametro conguaglio sulla riga del contratto -void TGenera_documenti_app::aggiorna_conguaglio(TRectype& rcondv, const real arr) const -{ - TLocalisamfile rcont(LF_LVRCONDV); - rcondv.put(LVRCONDV_QTACONG,arr); - rcondv.rewrite(rcont); -} - - //////////////////////////////// - //// Metodi Pubblic //// - //////////////////////////////// - -bool TGenera_documenti_app::transfer() -{ - //leggo i dati dalla maschera - const TDate adata = _msk->get_date(F_DTCONS); - - TDate dadata(TODAY); - if (_msk->get_int(F_TPGEN) == 1) - dadata = adata; - else - ++dadata; - - const int daanno = dadata.year() - 1; - const int aanno = adata.year(); - - const long coditi = _msk->get_long(F_CODITI); - const long codaut = _msk->get_long(F_CODAUT); - - long codcli = _msk->get_long(F_CODCF); - - TLog_report rep(TR("Riepilogo associazioni")); - rep.kill_duplicates(true); - - //preparo un recordset che contiene tutti planning per cui voglio creare i documenti relativi - TString4 codnum, tpdoc, statoi, statof; - numerazione_drit(0, codnum, tpdoc, statoi, statof); - - int numdocgen = 0; - - TAssoc_array documenti; - - if (_msk->get_bool(F_NOTPLAN)) - { - if (_msk->get_int(F_TPGEN) != 1) - dadata.addmonth(-1); - //per ogni data cerco i documenti e per ogni documento cerco i dati del passaggio - TString query; - query << "USE DOC " - << "SELECT (ANSI(G1:DATAPRCO)<=#ADATA)&&" - << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" - << "(STATO=\"" << statoi <<"\")&&"; - query << "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\n" - << "FROM PROVV=\"D\" ANNO=" << dadata.year() << " CODNUM=\"" << codnum << "\"\n" - << "TO PROVV=\"D\" ANNO=" << adata.year() << " CODNUM=\"" << codnum << "\"\n"; - - TISAM_recordset docritiri(query); - docritiri.set_var("#ADATA", adata); - docritiri.set_var("#CODCF", codcli); - - TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso...")); - - for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) - { - _quantita.destroy(); - _quantita_ritirata.destroy(); - crea_documento_ritiro(docritiri, rep, numdocgen, documenti); - if (!pi.add_status()) - break; - } - } - else - { - //TDate d(adata); d.addmonth(-1); - for (dadata; dadata <= adata; ++dadata) - { - //per ogni data cerco i documenti e per ogni documento cerco i dati del passaggio - TString query; - query << "USE DOC " - << "SELECT (ANSI(G1:DATAPRCO)<=#ADATA)&&" - << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" - << "(STATO=\"" << statoi <<"\")&&" - << "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\n" - << "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n" - << "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n"; - - TISAM_recordset docritiri(query); - docritiri.set_var("#ADATA", adata); - docritiri.set_var("#CODCF", codcli); - - TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso...")); - - for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) - { - if (!pi.add_status()) - break; - - if (_msk->field(F_CODCF).empty()) - codcli = docritiri.get(DOC_CODCF).as_int(); - - // instanzio un recordset che contiene tutti i documenti di interesse - TString query = "USE LVRCONSPLAN KEY 2"; - query << " SELECT (CODCF=" << codcli << ")"; - - if (coditi || codaut) - { - if (coditi > 0) - query << "&&(CODITI=" << coditi << ")"; - - if (codaut > 0) - query << "&&(CODAUT=" << codaut << ")"; - } - - query << "\nFROM DTCONS=#DADATA"; - query << "\nTO DTCONS=#ADATA"; - - TISAM_recordset plan(query); - plan.set_var("#DADATA", dadata); - if (_msk->get_int(F_TPGEN) == 0) - plan.set_var("#ADATA", adata); - else - plan.set_var("#ADATA", dadata); - - if (plan.move_first()) - { - _quantita.destroy(); - _quantita_ritirata.destroy(); - crea_documento_plan(plan, rep, numdocgen, documenti); - } - codcli = _msk->get_long(F_CODCF); - } - } - } - - if (_msk->get_bool(F_STAMPA) && documenti.items() > 0) - { - TFilename tmp; - tmp.temp("", "ini"); - - // Ensure that the ofstream is well closed before ve1 call - if (tmp.full()) // dummy test - { - TDoc_key kd(documenti.get_hashobj()->key()); - TString16 chiavedoc; // Parte della chiave comune a tutti i documenti - chiavedoc << kd.provv() << '|' << kd.anno() << '|' << kd.codnum() << '|'; - - ofstream outf(tmp); - outf << "[Transaction]" << endl; // Transaction header - outf << "Action=S" << endl; // 'S'tampa o 'A'nteprima - outf << "Mode=D" << endl; // Definitive (always?) - outf << "NoPrintDlg=X" << endl; // Don't prompt the user with the print dialog - outf << endl; - outf << "[33]" << endl; // Transaction body - long nx = 0; // Document counter - - FOR_EACH_ASSOC_OBJECT(documenti, obj, r, riga) - { - const TDoc_key& kdoc = *(TDoc_key*)riga; - outf << "Doc(" << (nx++) << ")="; - outf << chiavedoc << kdoc.ndoc() << endl; - } - } - - if (tmp.exist()) - { - { - TString cmdline; cmdline << "ve1 -2 -i" << tmp; - TExternal_app app(cmdline); - app.run(); - } - /* Il 6-11-2015 ci siamo accorti che lv1 -3 non esiste (e nella 10.0 non lo chiamava nemmeno) - { - TString cmdline; cmdline << "lv1 -3 -i" << tmp; - TExternal_app app(cmdline); - app.run(); - } - */ - tmp.fremove(); - } - } - - if (_has_gui) - { - if (documenti.items() == 0) - lv_popup_msg(TR("Non è stato possibile generare alcun documento:\nprobabilmente i documenti richiesti esistono già.")); - else - { - if (adata < TDate(TODAY) && _msk->get_int(F_TPGEN) == 0) - lv_popup_msg(TR("Non è stato possibile generare documenti con data prevista consegna nel passato")); - else - { - TReport_book buc; - buc.add(rep); - if (buc.pages() > 0) - buc.preview(); - else - { - TString str; - if (numdocgen > 1) - str << TR("Sono stati generati ") << numdocgen << TR(" buoni."); - else - str << TR("E' stato generato un buono."); - lv_popup_msg(str); - } - } - } - } - - return true; -} - -void TGenera_documenti_app::main_loop() -{ - _has_gui = !(argc() >= 4 && xvt_str_same(argv(3), "-A")); - _msk->set(F_STAMPA, true); - _msk->set(F_NOTPLAN, true); - if (_has_gui) - { - while (_msk->run() == K_ENTER) - { - transfer(); - _msk->set(F_NOTPLAN, true); - } - } - else - { - _msk->set(F_DTCONS, TDate(TODAY)); - _msk->send_key(K_SPACE, DLG_OK); - if (_msk->run() == K_ENTER) - transfer(); - } -} - -int lv2400(int argc, char* argv[]) -{ - TGenera_documenti_app app; - app.run(argc, argv, TR("Generazione documenti")); - return 0; -} +#include +#include +#include +#include +#include +#include +#include + +#include "lvlib.h" +#include "../mg/anamag.h" +#include "../mg/clifogiac.h" +#include "../ve/velib.h" +#include "../ve/rcondv.h" + +#include "doc.h" +#include "lvcondv.h" +#include "lvrcondv.h" +#include "lvrconsplan.h" +#include "rdoc.h" + +#include "lv2400a.h" + + ///////////////////////////////////// + //// TGENERA_DOCUMENTI_MSK //// + ///////////////////////////////////// + +//classe TGenera_documenti_msk +class TGenera_documenti_msk : public TAutomask +{ +public: + virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); + TGenera_documenti_msk (const char* name) : TAutomask(name) {} +}; + +//ON_FIELD_EVENT: questo metodo gestisce i vari eventi che si verificano sui campi della maschera +bool TGenera_documenti_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) +{ + switch (o.dlg()) + { + case F_DTDOC: + if (e == fe_modify) + { + const TDate oggi(TODAY); + if (get_date(F_DTDOC) <= oggi) + { + warning_box(TR("Attenzione: la data documento non può essere nel passato")); + o.reset(); + } + } + break; + default: break; + } + return true; +} + ////////////////////////////////////// + //// TGENERA_DOCUMENTI_APP //// + ////////////////////////////////////// + +//classe TGenera_documenti_app +class TGenera_documenti_app : public TSkeleton_application +{ + TGenera_documenti_msk* _msk; + TAssoc_array _quantita; + TAssoc_array _quantita_ritirata; + TConfig* _configlv; + char _buono; + long _ndoc; + bool _has_gui; + +private: + //Metodi per la generazione dei documenti + bool crea_documento_ritiro(const TISAM_recordset& ritiro, TLog_report& rep, int& numdocgen, TAssoc_array& documenti); + bool crea_documento_plan(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen, TAssoc_array& documenti); + void crea_riga(TToken_string& chiave, const char modpas, const int tplis, const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep); + //Metodi per il recupero di codnum, tpdoc, stato + bool numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; + bool numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; + bool numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; + //Metodi per l'eliminazione dei documenti + void cambia_stato(const char ritoant, const TString_array& docarr); + void elimina_bolle(const long codcli, const long codind, TString_array& docarr); + //Metodi per la scansione dei documenti + int scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen); + void scansione_consegne(const long codcli, const long codind, const TDocumento& docgen); + //Metodo per il calcolo delle quantità in bolla + void calcolo_quantita(const TDocumento& doc, const char ritoant); + //Metodi aggiornare il conguaglio sui contratti + void aggiorna_conguaglio(TRectype& rcondv, const real arr) const; + +protected: + virtual bool create(); + virtual void on_config_change(); + virtual bool destroy(); + +public: + bool transfer(); + virtual void main_loop(); +}; + +//////////////////////////////// +//// Metodi Protected //// +//////////////////////////////// + +//CREATE: metodo costruttore +bool TGenera_documenti_app::create() +{ + open_files(LF_DOC, LF_RIGHEDOC, 0); + _msk = new TGenera_documenti_msk("lv2400a"); + _ndoc = 0; + + _configlv = new TConfig(CONFIG_DITTA,"lv"); + _buono = *TApplication::argv(2); + return TSkeleton_application::create(); +} + +//ON_CONFIG_CHANGE: metodo che aggiorna la variabile TConfig ogni volta +//che faccio un cambiamento al file fisico +void TGenera_documenti_app::on_config_change() +{ + if (_configlv != NULL) + delete _configlv; + _configlv = new TConfig(CONFIG_DITTA,"lv"); +} + +//DESTROY: metodo distruttore +bool TGenera_documenti_app::destroy() +{ + delete _configlv; + delete _msk; + return TApplication::destroy(); +} + +/////////////////////////////////////////////////////// +//// Metodi per la generazione dei documenti //// +/////////////////////////////////////////////////////// + +//CREA_DOCUMENTO_RITIRO: metodo che crea un nuovo documento di trasporto dai dati salvati +bool TGenera_documenti_app::crea_documento_ritiro(const TISAM_recordset& ritiro, TLog_report& rep, int& numdocgen, TAssoc_array& documenti) +{ + //recupero i dati di interesse dalla maschera + const TDate datagen(TODAY); + //per ogni planning recupero i dati di interesse dal planning + const long ndoc = ritiro.get(DOC_NDOC).as_int(); + + if (ndoc > 5132) + int i = 1; + const long codcli = ritiro.get(DOC_CODCF).as_int(); + const long codcont = ritiro.get(DOC_CODCONT).as_int(); + const TDate dtcons = ritiro.get("G1:DATAPRCO").as_date(); //che è anche la data documento + const int coditi = int(ritiro.get("CODITI").as_int()); + TString8 codaut = ritiro.get(DOC_CODAG).as_string().right(5); codaut.trim(); + const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons; + const int anno = datadoc.year(); + const long ag_selected = _msk->get_long(F_CODAUT); + + if (ag_selected > 0L && atol(codaut) != ag_selected) + return true; + + //preparo la chiave per la tabella contratti + TToken_string keycont; + keycont.add(codcli); + keycont.add(codcont); + //instanzio una cache sulla tabella dei contratti + const TRectype& tcont = cache().get(LF_LVCONDV,keycont); + //estraggo i dati di interesse dalla cache + const long codind = tcont.get_long(LVCONDV_CODINDSP); //codice dell'indirizzo di spedizione + const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino + //const bool prinbo = tcont.get_bool(LVCONDV_STPRZBOL); //prezzo in bolla + const bool prinbo = true; //sempre a true; verrà gestita a video in futuro (27/10/2009) + + //variabili che conterranno i parametri dei documenti che devo generare... + //...settati dalla funzione numerazione_ddt() + TString4 codnum, tpdoc, statoi, statof; + + //Cerco il tipo documento da generare sul contratto; se non lo trovo lo cerco in configurazione. + //Se non trovo quale documento generare, evito il resto dell'elaborazione + if (tcont.get(LVCONDV_CODNUM).full() && _buono == 'C') + { + codnum = tcont.get(LVCONDV_CODNUM); + tpdoc = tcont.get(LVCONDV_TPDOC); + + //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) + const TString& s2 = cache().get("%TIP",tpdoc,"S2"); + statoi = s2.left(1); + statof = s2.mid(1,1); + } + else if (!numerazione_ddt(codnum, tpdoc, statoi, statof)) + return NOERR; + + //recupero i dati di interesse dal cliente + TToken_string key; + key.add('C'); + key.add(codcli); + const TRectype& clifo = cache().get(LF_CLIFO, key); + const TString4 codpag = clifo.get(CLI_CODPAG); + const long codabi = clifo.get_long(CLI_CODABI); + const long codcab = clifo.get_long(CLI_CODCAB); + const TString80 iban = clifo.get(CLI_IBAN); + + //reupero la cuasale di magazzino di testata + const TString8 causmag = cache().get("%TIP", tpdoc, "S9"); + + //recupero i dati di interesse dal file CFVEN + const TRectype& cfven = cache().get(LF_CFVEN, key); + const long codabipr = cfven.get_long(CFV_CODABIPR); + const long codcabpr = cfven.get_long(CFV_CODCABPR); + const bool ragdoc = cfven.get_bool(CFV_RAGGDOC); + const int codindsp = cfven.get_int(CFV_CODINDSP); + const TString8 codag1 = cfven.get(CFV_CODAG1); + const TString4 codmez = cfven.get(CFV_CODSPMEZZO); + const TString4 codporto = cfven.get(CFV_CODPORTO); + const TString4 codnote1 = cfven.get(CFV_CODNOTESP1); + const TString4 codnote2 = cfven.get(CFV_CODNOTESP2); + const TString4 codnote = cfven.get(CFV_CODNOTE); + const TString8 codvet1 = cfven.get(CFV_CODVETT1); + const TString8 codvet2 = cfven.get(CFV_CODVETT2); + const TString8 codvet3 = cfven.get(CFV_CODVETT3); + const real speseinc = cfven.get_real(CFV_PERCSPINC); + const TString4 catven = cfven.get(CFV_CATVEN); + const bool addbolli = cfven.get_bool(CFV_ADDBOLLI); + const TString8 codlist = cfven.get(CFV_CODLIST); + const TString4 codzona = cfven.get(CFV_CODZONA); + + if(codaut.empty()) + codaut = cfven.get(CFV_CODAG); + + //gestione sconto + TString sconto; + + const char tpgest = ini_get_string(CONFIG_DITTA, "ve", "GESSCO")[0]; + switch(tpgest) + { + case 'P': sconto = cfven.get(CFV_SCONTO); break; //Percentuale su anagrafica cliente + case 'T': sconto = cache().get("%SCC", cfven.get(CFV_CODSCC), "S1"); break; //Gestione tabella sconti + case 'A': //Gestione archivio sconti + { + TConfig ditta(CONFIG_DITTA, "ve"); + + TLocalisamfile sconti(LF_SCONTI); + sconti.put("TIPO", "I"); + + if (ditta.get_bool("SCOKEY", "ve", 1)) + sconti.put("CODCAT", cfven.get(CFV_CATVEN)); + + TString16 cod; + if (ditta.get_bool("SCOKEY", "ve", 2)) + cod.format("%-2s", (const char*)cfven.get(CFV_CODSCC)); + else + cod = " "; + + if (ditta.get_bool("SCOKEY", "ve", 3)) + { + TString8 tmp; + tmp.format("%-2s", (const char*)cfven.get(CFV_CODZONA)); + cod << tmp; + } + else + cod << " "; + + if (ditta.get_bool("SCOKEY", "ve", 4)) + cod << clifo.get(CLI_CODPAG); + + sconti.put("CODART", cod); + + if (sconti.read() == NOERR) + sconto = sconti.get("SCONTO"); + } + break; + case 'N': //sconto non gestito + default: break; + } + + //creo il documento corretto riempiendo i campi che già conosco + TDocumento doc('D', anno, codnum, 0L); + doc.put(DOC_TIPODOC, tpdoc); + doc.put(DOC_DATADOC, datadoc); + doc.put(DOC_TIPOCF, 'C'); + doc.put(DOC_CODCF, codcli); + doc.put(DOC_CODCONT, codcont); + if(codindsp > 0) + doc.put(DOC_CODINDSP, codindsp); + doc.put(DOC_RAGGR, ragdoc); + doc.put(DOC_CODPAG, codpag); + doc.put(DOC_CODABIA, codabi); + doc.put(DOC_CODCABA, codcab); + doc.put(DOC_IBAN, iban); + doc.put(DOC_CODABIP, codabipr); + doc.put(DOC_CODCABP, codcabpr); + doc.put(DOC_CODAG, codaut); + doc.put(DOC_CODAGVIS, codag1); + doc.put(DOC_CODSPMEZZO, codmez); + doc.put(DOC_ZONA, codzona); + doc.put(DOC_CODPORTO, codporto); + doc.put(DOC_CODNOTESP1, codnote1); + doc.put(DOC_CODNOTESP2, codnote2); + doc.put(DOC_CODNOTE, codnote); + doc.put(DOC_CODVETT1, codvet1); + doc.put(DOC_CODVETT2, codvet2); + doc.put(DOC_CODVETT3, codvet3); + doc.put(DOC_CATVEN, catven); + doc.put(DOC_CODLIST, codlist); + doc.put(DOC_CAUSMAG, causmag); + doc.put(DOC_PERCSPINC, speseinc); + doc.put(DOC_ADDBOLLI, addbolli); + doc.put(DOC_SCONTOPERC, sconto); + doc.put(DOC_DATAPART, TDate(TODAY)); + doc.put("DATAGEN", datagen); //data generazione del documento + doc.put("DATAPRCO", dtcons); //data prevista consegna + doc.put("CODITI", coditi); //codice itinerario + + //calcola tutte le quantità riportate sui documenti di ritiro, sui documenti di anticipo + const int numerodoc = scansione_ritiri_anticipi(codcli, dtcons, 'R', doc); + scansione_ritiri_anticipi(codcli, dtcons, 'A', doc); + + int err = 1; + if(numerodoc > 0) + { + FOR_EACH_ASSOC_OBJECT(_quantita,h,key,obj) + { + TToken_string chiave(key); + const TCodice_articolo codart = chiave.get(0); + //preparo la chiave per la tabella righe contratti + TToken_string keyrcont; + keyrcont.add(codcli); + keyrcont.add(codcont); + keyrcont.add(codart); + const TRectype& rcont = cache().get(LF_LVRCONDV, keyrcont); + const TDate dadata = rcont.get_date(LVRCONDV_INDTTMP); + const TDate adata = rcont.get_date(LVRCONDV_FIDTTMP); + + if (dadata.ok() && dtcons >= adata) + crea_riga(chiave, ' ', tplis, true, prinbo, doc, rep); + else + crea_riga(chiave, ' ', tplis, false, prinbo, doc, rep); + } + + if (doc.rows() > 0) + { + TToken_string orderkey; + orderkey.add(RDOC_CODART); + doc.sort_rows(orderkey); + if (tcont.get_bool(LVCONDV_SSCONS)) + { + char name[8] = "CODSP0"; + TString_array spese; + const TRectype& ven_rec = doc.clifor().vendite(); + for (int i = 1; i <= 4; i++) + { + name[5] = '0' + i; + const TString& s = ven_rec.get(name); + if (s.full()) + spese.add(s); + } + doc.update_spese_aut(spese, false, NULL, true); + } + while (err = doc.write() == _isreinsert) + { + const long old_ndoc = doc.get_long(DOC_NDOC); + doc.renum_ndoc(); + const long new_ndoc = doc.get_long(DOC_NDOC); + if (_has_gui) + lv_popup_msg("Attenzione documento numero %ld rinumerato in %ld", old_ndoc, new_ndoc); + } + ++numdocgen; + } + else + doc.remove(); + + //scrivo sul planning il riferimento alla bolla che lo accompagna + if (err == NOERR) + { + //tengo traccia dei documenti che sto generando, per poterli stampare dopo + TDoc_key kdoc(doc.get_int(DOC_ANNO), doc.get(DOC_CODNUM), doc.get_int(DOC_NDOC)); + if (!documenti.is_key(kdoc)) + documenti.add(kdoc, kdoc); + } + } + return err == NOERR; +} + +//CREA_DOCUMENTO_PLAN: metodo che crea un nuovo documento di trasporto dai dati salvati +bool TGenera_documenti_app::crea_documento_plan(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen, TAssoc_array& documenti) +{ + //recupero i dati di interesse dalla maschera + const TDate datagen(TODAY); + + //per ogni planning recupero i dati di interesse dal planning + const long codcli = plan.get(LVRCONSPLAN_CODCF).as_int(); + const long codcont = plan.get(LVRCONSPLAN_CODCONT).as_int(); + const TDate dtcons = plan.get(LVRCONSPLAN_DTCONS).as_date(); //che è anche la data documento + const char modpas = plan.get(LVRCONSPLAN_MODPASS).as_string()[0]; + const int coditi = plan.get(LVRCONSPLAN_CODITI).as_int(); + TString8 codaut = plan.get(LVRCONSPLAN_CODAUT).as_string().right(5); codaut.trim(); + const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons; + const int anno = datadoc.year(); + + //preparo la chiave per la tabella contratti + TToken_string keycont; + keycont.add(codcli); + keycont.add(codcont); + //instanzio una cache sulla tabella dei contratti + const TRectype& tcont = cache().get(LF_LVCONDV,keycont); + //estraggo i dati di interesse dalla cache + const long codind = tcont.get_long(LVCONDV_CODINDSP); //codice dell'indirizzo di spedizione + const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino + //const bool prinbo = tcont.get_bool(LVCONDV_STPRZBOL); //prezzo in bolla + const bool prinbo = true; //sempre a true; verrà gestita a video in futuro (27/10/2009) + + //variabili che conterranno i parametri dei documenti che devo generare... + //...settati dalla funzione numerazione_ddt() + TString4 codnum, tpdoc, statoi, statof; + + //Cerco il tipo documento da generare sul contratto; se non lo trovo lo cerco in configurazione. + //Se non trovo quale documento generare, evito il resto dell'elaborazione + if (tcont.get(LVCONDV_CODNUM).full() && _buono == 'C') + { + codnum = tcont.get(LVCONDV_CODNUM); + tpdoc = tcont.get(LVCONDV_TPDOC); + + //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) + const TString& s2 = cache().get("%TIP",tpdoc,"S2"); + statoi = s2.left(1); + statof = s2.mid(1,1); + } + else if (!numerazione_ddt(codnum, tpdoc, statoi, statof)) + return NOERR; + + if(_ndoc == 0) + { + TString query2; + query2 << "USE DOC\n" + << "FROM PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\"\n" + << "TO PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\""; + TISAM_recordset bolle(query2); + if (bolle.move_last()) + _ndoc = bolle.get(DOC_NDOC).as_int(); + } + + //recupero i dati di interesse dal cliente + TToken_string key; + key.add('C'); + key.add(codcli); + const TRectype& clifo = cache().get(LF_CLIFO, key); + const TString4 codpag = clifo.get(CLI_CODPAG); + const long codabi = clifo.get_long(CLI_CODABI); + const long codcab = clifo.get_long(CLI_CODCAB); + const TString80 iban = clifo.get(CLI_IBAN); + + //reupero la cuasale di magazzino di testata + const TString8 causmag = cache().get("%TIP", tpdoc, "S9"); + + //recupero i dati di interesse dal file CFVEN + const TRectype& cfven = cache().get(LF_CFVEN, key); + const long codabipr = cfven.get_long(CFV_CODABIPR); + const long codcabpr = cfven.get_long(CFV_CODCABPR); + const bool ragdoc = cfven.get_bool(CFV_RAGGDOC); + const int codindsp = cfven.get_int(CFV_CODINDSP); + const TString8 codag1 = cfven.get(CFV_CODAG1); + const TString4 codmez = cfven.get(CFV_CODSPMEZZO); + const TString4 codporto = cfven.get(CFV_CODPORTO); + const TString4 codnote1 = cfven.get(CFV_CODNOTESP1); + const TString4 codnote2 = cfven.get(CFV_CODNOTESP2); + const TString4 codnote = cfven.get(CFV_CODNOTE); + const TString8 codvet1 = cfven.get(CFV_CODVETT1); + const TString8 codvet2 = cfven.get(CFV_CODVETT2); + const TString8 codvet3 = cfven.get(CFV_CODVETT3); + const real speseinc = cfven.get_real(CFV_PERCSPINC); + const TString4 catven = cfven.get(CFV_CATVEN); + const bool addbolli = cfven.get_bool(CFV_ADDBOLLI); + const TString8 codlist = cfven.get(CFV_CODLIST); + const TString4 codzona = cfven.get(CFV_CODZONA); + + if(codaut.empty()) + codaut = cfven.get(CFV_CODAG); + + //gestione sconto + TString sconto; + + const char tpgest = ini_get_string(CONFIG_DITTA, "ve", "GESSCO")[0]; + switch(tpgest) + { + case 'P': sconto = cfven.get(CFV_SCONTO); break; //Percentuale su anagrafica cliente + case 'T': sconto = cache().get("%SCC", cfven.get(CFV_CODSCC), "S1"); break; //Gestione tabella sconti + case 'A': //Gestione archivio sconti + { + TConfig ditta(CONFIG_DITTA, "ve"); + + TLocalisamfile sconti(LF_SCONTI); + sconti.put("TIPO", "I"); + + if(ditta.get_bool("SCOKEY", "ve", 1)) + sconti.put("CODCAT", cfven.get(CFV_CATVEN)); + + TString16 cod; + if(ditta.get_bool("SCOKEY", "ve", 2)) + cod.format("%-2s", (const char*)cfven.get(CFV_CODSCC)); + else + cod = " "; + + if(ditta.get_bool("SCOKEY", "ve", 3)) + { + TString8 tmp; + tmp.format("%-2s", (const char*)cfven.get(CFV_CODZONA)); + cod << tmp; + } + else + cod << " "; + + if(ditta.get_bool("SCOKEY", "ve", 4)) + cod << clifo.get(CLI_CODPAG); + + sconti.put("CODART", cod); + + if (sconti.read() == NOERR) + sconto = sconti.get("SCONTO"); + } + break; + case 'N': //sconto non gestito + default : break; + } + + //creo il documento corretto riempiendo i campi che già conosco + TDocumento doc('D', anno, codnum, ++_ndoc); + doc.put(DOC_TIPODOC, tpdoc); + if(_msk->get_bool(F_DTEMIS)) + doc.put(DOC_DATADOC, _msk->get_date(F_DTDOC)); + else + doc.put(DOC_DATADOC, dtcons); + doc.put(DOC_TIPOCF, 'C'); + doc.put(DOC_CODCF, codcli); + doc.put(DOC_CODCONT, codcont); + if(codindsp > 0) + doc.put(DOC_CODINDSP, codindsp); + doc.put(DOC_RAGGR, ragdoc); + doc.put(DOC_CODPAG, codpag); + doc.put(DOC_CODABIA, codabi); + doc.put(DOC_CODCABA, codcab); + doc.put(DOC_IBAN, iban); + doc.put(DOC_CODABIP, codabipr); + doc.put(DOC_CODCABP, codcabpr); + doc.put(DOC_CODAG, codaut); + doc.put(DOC_CODAGVIS, codag1); + doc.put(DOC_CODSPMEZZO, codmez); + doc.put(DOC_ZONA, codzona); + doc.put(DOC_CODPORTO, codporto); + doc.put(DOC_CODNOTESP1, codnote1); + doc.put(DOC_CODNOTESP2, codnote2); + doc.put(DOC_CODNOTE, codnote); + doc.put(DOC_CODVETT1, codvet1); + doc.put(DOC_CODVETT2, codvet2); + doc.put(DOC_CODVETT3, codvet3); + doc.put(DOC_CATVEN, catven); + doc.put(DOC_CODLIST, codlist); + doc.put(DOC_CAUSMAG, causmag); + doc.put(DOC_PERCSPINC, speseinc); + doc.put(DOC_ADDBOLLI, addbolli); + doc.put(DOC_SCONTOPERC, sconto); + doc.put("DATAGEN", datagen); //data generazione del documento + doc.put("DATAPRCO", dtcons); //data prevista consegna + doc.put("CODITI", coditi); //codice itinerario + + //calcola tutte le quantità riportate sui documenti di ritiro, sui documenti di anticipo + int numerodoc = scansione_ritiri_anticipi(codcli, dtcons, 'R', doc); + scansione_ritiri_anticipi(codcli, dtcons, 'A', doc); + + int err = 1; + if(numerodoc > 0) + { + FOR_EACH_ASSOC_OBJECT(_quantita,h,key,obj) + { + TToken_string chiave(key); + const TString80 codart = chiave.get(0); + //preparo la chiave per la tabella righe contratti + TToken_string keyrcont; + keyrcont.add(codcli); + keyrcont.add(codcont); + keyrcont.add(codart); + const TRectype& rcont = cache().get(LF_LVRCONDV, keyrcont); + const TDate dadata = rcont.get_date(LVRCONDV_INDTTMP); + const TDate adata = rcont.get_date(LVRCONDV_FIDTTMP); + + if (dadata.ok() && dtcons >= adata) + crea_riga(chiave, modpas, tplis, true, prinbo, doc, rep); + else + crea_riga(chiave, modpas, tplis, false, prinbo, doc, rep); + } + + if (doc.rows() > 0) + { + TToken_string orderkey; + orderkey.add(RDOC_CODART); + doc.sort_rows(orderkey); + if (tcont.get_bool(LVCONDV_SSCONS)) + { + char name[8] = "CODSP0"; + TString_array spese; + const TRectype& ven_rec = doc.clifor().vendite(); + for (int i = 1; i <= 4; i++) + { + name[5] = '0' + i; + const TString& s = ven_rec.get(name); + if (s.full()) + spese.add(s); + } + doc.update_spese_aut(spese, false, NULL, true); + } + err = doc.rewrite(); + ++numdocgen; + } + else + doc.remove(); + + //scrivo sul planning il riferimento alla bolla che lo accompagna + if (err == NOERR) + { + TLocalisamfile& f = plan.cursor()->file(); + f.put(LVRCONSPLAN_ANNO, anno); + f.put(LVRCONSPLAN_CODNUM, codnum); + f.put(LVRCONSPLAN_NDOC, _ndoc); + f.rewrite(); + + //tengo traccia dei documenti che sto generando, per poterli stampare dopo + TDoc_key kdoc(doc.get_int(DOC_ANNO), doc.get(DOC_CODNUM), doc.get_int(DOC_NDOC)); + if (!documenti.is_key(kdoc)) + documenti.add(kdoc, kdoc); + } + } + return err == NOERR; +} + +//CREA_RIGA: questa funzione crea una riga merce per una bolla di consegna +void TGenera_documenti_app::crea_riga(TToken_string& chiave, const char modpas, const int tplis, + const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep) +{ + //creo la nuova riga + TString4 tiporiga; + switch (_buono) + { + case 'P': tiporiga = "24"; break; + case 'C': tiporiga = "21"; break; + default: break; + } + + const long codcli = doc.get_long(DOC_CODCF); + const long codcont = doc.get_long(DOC_CODCONT); + const TCodice_articolo codart = chiave.get(0); + const TString4 causale = chiave.get(1); + + //calcolo della quantità che va sulla bolla + + //preparo la chiave per la tabella righe contratti + TLaundry_contract cont(codcli, codcont); + const TRectype& rcont = cont.row(codart); + const bool artbloc = rcont.get_int(LVRCONDV_ARTBLOC) > 0; + + if (artbloc) + return; + + //recupero i dati di interesse dalla riga del contratto + const bool arrot = rcont.get_int(LVRCONDV_CALCCONS) == 1; + + const real conguaglio = rcont.get_real(LVRCONDV_QTACONG); + real& qta = *(real*)_quantita.objptr(chiave); + const real& qta1 = *(real*)_quantita_ritirata.objptr(chiave); + const real przdttmp = rcont.get_real(LVRCONDV_PRZDTTMP); + + //instanzio una cache sulla tabella del magazzino + const TRectype& anamag = cache().get(LF_ANAMAG,codart); + //recupero i dati di interesse dall'anagrafica di magazzino, ma devo evitare divisioni per 0 + const long ppconf = anamag.get_real(ANAMAG_PPCONF) != 0 ? anamag.get_int(ANAMAG_PPCONF) : 1; + TString descrart; + descrart << anamag.get(ANAMAG_DESCR) << anamag.get(ANAMAG_DESCRAGG); + + //recupero i valori delle dotazione temporanea dal magazzino del cliente + TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcli, 0); + //fisso l'anno esercizio + TEsercizi_contabili& esc = esercizi(); + const int last_esc = esc.last(); + + //estraggo il record corrispondente su LF_CLIFOGIAC + const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); + + real dotod = reclav.get_real(CLIFOGIAC_DOTOD); + real dottmp = reclav.get_real(CLIFOGIAC_DOTTM); + + //GESTIONE DOTAZIONE TEMPOARANEA + if (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && dottmp > 0) + { + TRiga_documento& rdoc = doc.new_row(tiporiga); + rdoc.put(RDOC_CODART,codart); + if (descrart.len() > 50) + { + rdoc.put(RDOC_DESCR, descrart.left(50)); + rdoc.put(RDOC_DESCLUNGA, true); + rdoc.put(RDOC_DESCEST, descrart.sub(50)); + } + else + rdoc.put(RDOC_DESCR, descrart); + rdoc.put(RDOC_CODARTMAG,codart); + rdoc.put(RDOC_CHECKED,'X'); + + if (prinbo) + rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); //prezzo + + rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva + + const TCausale_lavanderie caudt(ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT")); + + //se ho ritirato un quantitativo di roba maggiore o uguale alla dotazione temporanea + //allora creo la nuova riga documento e azzero la dottmp; altrimenti preparo la riga + //per la quantità che ho ritirato e tengo traccia della cosa + if (qta >= dottmp) + { + qta -= dottmp; + rdoc.put(RDOC_QTAGG1, dottmp); //quantità ritirata + rdoc.put(RDOC_GENERATA, true); + rdoc.put(RDOC_CODAGG1, caudt.caucol().empty() ? caudt.codice() : caudt.caucol()); + dottmp = 0; + dotod -= dottmp; + TString str; + str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) + << " numero " << doc.get(DOC_NDOC) << " in dotazione è stato ritirato completamente."; + rep.log(1, str); + } + else + { + dottmp -= qta; + dotod -= qta; + rdoc.put(RDOC_QTAGG1, qta); //quantità ritirata + rdoc.put(RDOC_GENERATA, true); + rdoc.put(RDOC_CODAGG1, caudt.caucol().empty() ? caudt.codice() : caudt.caucol()); + TString str; + str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) + << " numero " << doc.get(DOC_NDOC) << " in dotazione temporanea non è stato ritirato completamente." + << " Mancano " << dottmp << "unità"; + rep.log(1, str); + qta = ZERO; + } + + //scrivo il magazzino + + const TCausale_magazzino rit(caudt.causale_ritiro()); + const TCausale_magazzino con(caudt.causale_consegna()); + TString8 magazzino, magazzinoc; + + if (rit.get("S10").full()) + magazzino = rit.get("S10").mid(0,5); + else + magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); + + if (con.get("S10").full()) + magazzinoc = con.get("S10").mid(0,5); + else + magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); + + rdoc.put(RDOC_CODMAG, magazzino); + rdoc.put(RDOC_CODMAGC, magazzinoc); + + //recupero l'unità di misura principale di quest'articolo + TToken_string key; + key.add(codart); + key.add(1); + const TRectype& umart = cache().get(LF_UMART, key); + TString4 um = umart.get(UMART_UM); + rdoc.put(RDOC_UMQTA, um); + + //scrivo gli estremi della dotazione temporanea + rdoc.put("DADATATMP", rcont.get_date(LVRCONDV_INDTTMP)); + rdoc.put("ADATATMP", rcont.get_date(LVRCONDV_FIDTTMP)); + rdoc.dirty_fields(); + } + + if (qta > ZERO || (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && qta == ZERO)) + { + TRiga_documento& rdoc = doc.new_row(tiporiga); + + //causale da mettere sulle righe documento + const TCausale_lavanderie cau(causale); + const TString4 codcau = cau.caucol().empty() ? cau.codice() : cau.caucol(); + rdoc.put(RDOC_CODAGG1, codcau); + + if (cau.is_consegna()) + { + const real quantita_noarr = qta - conguaglio; + real quantita_arr = quantita_noarr > ZERO ? quantita_noarr : ZERO; + //se devo arrotondare + if (quantita_arr > ZERO && arrot) + { + //calcolo di quanti pezzi sforo + long arr = quantita_arr.integer() % ppconf; + //se sforo (arr > 0) allora calcolo quanti pezzi in più gli devo dare e aggiorno la quantità + if (arr > 0) + { + const int perarr = ini_get_int(CONFIG_DITTA, "lv", "Perarr"); + if (arr > ppconf * perarr / 100) //arr <= ppconf*perarr/100 -> formula calcolo conguaglio di Tassan + { + arr = ppconf - arr; + quantita_arr += arr; + } + else + quantita_arr -= arr; + } + } + + //scrivo le quantità + rdoc.put(RDOC_QTA, quantita_arr); //quantità consegnata eventualmente arrotondata + rdoc.put(RDOC_QTAGG2, conguaglio); //conguaglio + rdoc.put(RDOC_QTAGG3, quantita_arr); //copia della quantità consegnata + rdoc.put(RDOC_QTAGG4, quantita_noarr); //quantità che avrei consegnato se non arrotondavo (qta ritirata) + rdoc.put(RDOC_GENERATA, true); + + //aggiorno il conguaglio sulla riga del contratto + //altrimenti se il record di riga contratto è vuoto aggiorno il log + if (!rcont.empty()) + { + aggiorna_conguaglio((TRectype&)rcont, quantita_arr - quantita_noarr); + } + else + { + TString str; + str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) + << " numero " << doc.get(DOC_NDOC) << " per la quantità di " << quantita_arr << " unità" + << " non è presente sul contratto del cliente " << codcli; + rep.log(1, str); + } + } + + //essendo la dot tmp un di cui la quantità ritirata è sempre quella + if (cau.is_ritiro()) + rdoc.put(RDOC_QTAGG1, qta1); //quantità ritirata + + //elaborazione sul prezzo da utilizzare + real prezzo; + + if (rcont.empty()) + { + //PROPONI PREZZO + TToken_string key; + key.add('C'); + key.add(codcli); + 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; + TConfig* configve = new TConfig(CONFIG_DITTA,"ve"); + const char gesliscv = configve->get_char("GESLISCV"); + if (gesliscv != 'X') + 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()) + { + prezzo = 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); + prezzo = umart.get_real(UMART_PREZZO); + if (umart.get(UMART_PREZZO).full()) + trvlst = true; + } + } + else + { + //elaborazione per il prezzo: o lo prendo dalle righe contratto, o dall'anagrafica magazzino + if (tplis == 0) + prezzo = rcont.get_real(LVRCONDV_PREZZO); + else + prezzo = anamag.get_real(ANAMAG_COSTSTD); + } + + rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva + + rdoc.put(RDOC_CODART,codart); + if (descrart.len() > 50) + { + rdoc.put(RDOC_DESCR, descrart.left(50)); + rdoc.put(RDOC_DESCLUNGA, true); + rdoc.put(RDOC_DESCEST, descrart.sub(50)); + } + else + rdoc.put(RDOC_DESCR, descrart); + rdoc.put(RDOC_CODARTMAG,codart); + rdoc.put(RDOC_CHECKED,'X'); + if (prinbo) + { + if (!tmp) + rdoc.put(RDOC_PREZZO, prezzo); + else + rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); + rdoc.put(RDOC_SCONTO,rcont.get(LVRCONDV_SCONTPERC)); //sconto + } + + //recupero l'unità di misura principale di quest'articolo + TToken_string key; + key.add(codart); + key.add(1); + const TRectype& umart = cache().get(LF_UMART, key); + TString4 um = umart.get(UMART_UM); + rdoc.put(RDOC_UMQTA, um); + + //scrivo il magazzino + const TCausale_magazzino rit(cau.causale_ritiro()); + const TCausale_magazzino con(cau.causale_consegna()); + + TString8 magazzino; + TString8 magazzinoc; + + if(rit.get("S10").full()) + magazzino = rit.get("S10").mid(0,5); + else + magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); + + if(con.get("S10").full()) + magazzinoc = con.get("S10").mid(0,5); + else + magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); + + rdoc.put(RDOC_CODMAG, magazzino); + rdoc.put(RDOC_CODMAGC, magazzinoc); + rdoc.dirty_fields(); + } + + if (dottmp == 0) + { + cont.update_row(codart, LVRCONDV_INDTTMP, NULLDATE); + cont.update_row(codart, LVRCONDV_FIDTTMP, NULLDATE); + } +} + + ////////////////////////////////////////////////////////////// + //// Metodi per il recupero di codnum, tpdoc, stato //// + ////////////////////////////////////////////////////////////// + +//NUMERAZIONE_DDT: questa funzione cerca quali sono i codnum e i tpdoc che devo generare +bool TGenera_documenti_app::numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const +{ + //questo switc mi permette di generare con lo stesso programma sia i buoni di prelievo (P) + //che i buoni di consegna (C); la variabile globale _buono viene inizializzata con il valore + //passato come parametro al programma al momento della chiamata da menù + switch (_buono) + { + case 'P': + codnum = _configlv->get("NUM_PRE(0)"); + tpdoc = _configlv->get("TIPODOC_PRE(0)"); + break; + case 'C': + codnum = _configlv->get("NUM_GEN"); + tpdoc = _configlv->get("TIPODOC_GEN"); + break; + default: + break; + } + + //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) + const TString& s2 = cache().get("%TIP",tpdoc,"S2"); + statoi = s2.left(1); + statof = s2.mid(1,1); + + return codnum.full() && tpdoc.full(); +} + +//NUMERAZIONE_DRIT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di ritiro +bool TGenera_documenti_app::numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const +{ + codnum = _configlv->get("NUM_RIT", NULL, cod); + tpdoc = _configlv->get("TIPODOC_RIT", NULL, cod); + + //instanzio una cache sulla tabella tipi documento (cerco lo stato iniziale) + const TString& s2 = cache().get("%TIP",tpdoc,"S2"); + statoi = s2.left(1); + statof = s2.mid(1,1); + + return codnum.full() && tpdoc.full(); +} + +//NUMERAZIONE_DANT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di anticipo +bool TGenera_documenti_app::numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const +{ + codnum = _configlv->get("NUM_ANT", NULL, cod); + tpdoc = _configlv->get("TIPODOC_ANT", NULL, cod); + + //instanzio una cache sulla tabella delle righe contratti (cerco lo stato iniziale) + const TString& s2 = cache().get("%TIP",tpdoc,"S2"); + statoi = s2.left(1); + statof = s2.mid(1,1); + + return codnum.full() && tpdoc.full(); +} + + ////////////////////////////////////////////////////////////// + //// Metodi per la scansione dei documenti //// + ////////////////////////////////////////////////////////////// + +//SCANSIONE_RITIRI_ANTICIPI: questa funzione cerca tutte le bolle di ritiro relative a un certo cliente non ancora evase... +//e, dopo l'elaborazione, gli cambia stato +int TGenera_documenti_app::scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen) +{ + const long aanno = data.year(); + TDate dadata = data; dadata.addmonth(-1); + const long daanno = dadata.year(); + + TString4 codnum; + TString4 tpdoc; + TString4 statoi; + TString4 statof; + bool err = NOERR; + //distinguo se sto scandendo i documenti di ritiro o i documenti di anticipo + switch (ritoant) + { + case 'R': + err = numerazione_drit(0, codnum, tpdoc, statoi, statof); + break; + case 'A': + err = numerazione_dant(0, codnum, tpdoc, statoi, statof); + break; + default: + break; + } + + if (!err) + return err; + + //instanzio un recordset che contiene tutti i documenti di interesse + TString query; + query << "USE DOC " + << "SELECT (TIPOCF=\"C\")&&(BETWEEN(CODCF," << codcli << ',' << codcli << "))&&" + << "(ANSI(G1:DATAPRCO)<=#ADATA)&&" + << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" + << "(STATO=\"" << statoi <<"\")\n" + << "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n" + << "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n"; + + //instanzio un recordset che contiene tutti i documenti di interesse + TISAM_recordset docritiri(query); + docritiri.set_var("#ADATA", data); + + //per ogni documento che trovo, aggiorno la quantità, e poi cambio stato al documento + for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) + { + TDocumento doc(docritiri.cursor()->curr()); //instanzio il documento + calcolo_quantita(doc, ritoant); + doc.put(DOC_STATO,statof); //stato di elaborato + //salvo i riferimenti del documento che sto andando a generare + doc.put("PROVVDG", docgen.get(DOC_PROVV)); + doc.put("ANNODG", docgen.get(DOC_ANNO)); + doc.put("CODNUMDG", docgen.get(DOC_CODNUM)); + doc.put("NDCODG", docgen.get(DOC_NDOC)); + + doc.rewrite(); + } + return docritiri.items(); +} + + ////////////////////////////////////////////////////////////// + //// Metodo per il calcolo delle quantità in bolla //// + ////////////////////////////////////////////////////////////// + +//CALCOLO_QUANTITA: questa funzione scorre tutte le righe documento di una bolla di ritiro, riempiendo un... +//TAssoc_array con le quantità ritirate per ogni articolo, sommando le diverse righe con lo stesso articolo... +//Questa funzione viene richiamata per ogni documento valido individuato dalla SCANSIONE_RITIRI +void TGenera_documenti_app::calcolo_quantita(const TDocumento& doc, const char ritoant) +{ + //scorro le righe documento + FOR_EACH_PHYSICAL_RDOC(doc, i, prdoc) + { + //instanzio la riga corrente + const TRiga_documento& rdoc = *prdoc; + //estraggo i dati di interesse + const TCodice_articolo codart = rdoc.get(RDOC_CODARTMAG); + const TString4 codcau = rdoc.get(RDOC_CODAGG1); + TToken_string key; key.add(codart); key.add(codcau); + const real qtardoc = rdoc.get_real(RDOC_QTAGG1); + //se è una riga che riguarda un articolo e se la quantità su questa riga non è nulla, allora la elaboro + if (codart.full() && !qtardoc.is_zero()) + { + TArticolo& art = rdoc.articolo(); + //leggo se esiste già nel TAssoc_array + real *qta = (real*)_quantita.objptr(key); + real *qta1 = (real*)_quantita_ritirata.objptr(key); + //se non esiste + if (qta == NULL) + { + //per ora memorizzo zero + qta = new real; + _quantita.add(key,qta); + } + if (qta1 == NULL) + { + //per ora memorizzo zero + qta1 = new real; + _quantita_ritirata.add(key,qta1); + } + //aggiorno la quantità convertendola all'unità di misura di base, aggiungendola o sottraendola + //...se si tratta di un ritiro o di un anticipo rispettivamente; nel caso della scansione delle + //...bolle di consegna modificate a mano (caso 'B'), devo modificare la quantità da consegnare + //...tenendo conto delle modifiche manuali + switch (ritoant) + { + case 'R': + *qta += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); + *qta1 += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); + break; + case 'A': + *qta -= art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); + break; + default: + break; + } + } + } + return; +} + + ////////////////////////////////////////////////////////////// + //// Metodi aggiornare il conguaglio sui contratti //// + ////////////////////////////////////////////////////////////// + +//AGGIORNA_CONGUAGLIO: questa funzione aggiorna il parametro conguaglio sulla riga del contratto +void TGenera_documenti_app::aggiorna_conguaglio(TRectype& rcondv, const real arr) const +{ + TLocalisamfile rcont(LF_LVRCONDV); + rcondv.put(LVRCONDV_QTACONG,arr); + rcondv.rewrite(rcont); +} + + //////////////////////////////// + //// Metodi Pubblic //// + //////////////////////////////// + +bool TGenera_documenti_app::transfer() +{ + //leggo i dati dalla maschera + const TDate adata = _msk->get_date(F_DTCONS); + + TDate dadata(TODAY); + if (_msk->get_int(F_TPGEN) == 1) + dadata = adata; + else + ++dadata; + + const int daanno = dadata.year() - 1; + const int aanno = adata.year(); + + const long coditi = _msk->get_long(F_CODITI); + const long codaut = _msk->get_long(F_CODAUT); + + long codcli = _msk->get_long(F_CODCF); + + TLog_report rep(TR("Riepilogo associazioni")); + rep.kill_duplicates(true); + + //preparo un recordset che contiene tutti planning per cui voglio creare i documenti relativi + TString4 codnum, tpdoc, statoi, statof; + numerazione_drit(0, codnum, tpdoc, statoi, statof); + + int numdocgen = 0; + + TAssoc_array documenti; + + if (_msk->get_bool(F_NOTPLAN)) + { + if (_msk->get_int(F_TPGEN) != 1) + dadata.addmonth(-1); + //per ogni data cerco i documenti e per ogni documento cerco i dati del passaggio + TString query; + query << "USE DOC " + << "SELECT (ANSI(G1:DATAPRCO)<=#ADATA)&&" + << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" + << "(STATO=\"" << statoi <<"\")&&"; + query << "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\n" + << "FROM PROVV=\"D\" ANNO=" << dadata.year() << " CODNUM=\"" << codnum << "\"\n" + << "TO PROVV=\"D\" ANNO=" << adata.year() << " CODNUM=\"" << codnum << "\"\n"; + + TISAM_recordset docritiri(query); + docritiri.set_var("#ADATA", adata); + docritiri.set_var("#CODCF", codcli); + + TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso...")); + + for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) + { + _quantita.destroy(); + _quantita_ritirata.destroy(); + crea_documento_ritiro(docritiri, rep, numdocgen, documenti); + if (!pi.add_status()) + break; + } + } + else + { + //TDate d(adata); d.addmonth(-1); + for (dadata; dadata <= adata; ++dadata) + { + //per ogni data cerco i documenti e per ogni documento cerco i dati del passaggio + TString query; + query << "USE DOC " + << "SELECT (ANSI(G1:DATAPRCO)<=#ADATA)&&" + << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" + << "(STATO=\"" << statoi <<"\")&&" + << "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\n" + << "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n" + << "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n"; + + TISAM_recordset docritiri(query); + docritiri.set_var("#ADATA", adata); + docritiri.set_var("#CODCF", codcli); + + TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso...")); + + for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) + { + if (!pi.add_status()) + break; + + if (_msk->field(F_CODCF).empty()) + codcli = docritiri.get(DOC_CODCF).as_int(); + + // instanzio un recordset che contiene tutti i documenti di interesse + TString query = "USE LVRCONSPLAN KEY 2"; + query << " SELECT (CODCF=" << codcli << ")"; + + if (coditi || codaut) + { + if (coditi > 0) + query << "&&(CODITI=" << coditi << ")"; + + if (codaut > 0) + query << "&&(CODAUT=" << codaut << ")"; + } + + query << "\nFROM DTCONS=#DADATA"; + query << "\nTO DTCONS=#ADATA"; + + TISAM_recordset plan(query); + plan.set_var("#DADATA", dadata); + if (_msk->get_int(F_TPGEN) == 0) + plan.set_var("#ADATA", adata); + else + plan.set_var("#ADATA", dadata); + + if (plan.move_first()) + { + _quantita.destroy(); + _quantita_ritirata.destroy(); + crea_documento_plan(plan, rep, numdocgen, documenti); + } + codcli = _msk->get_long(F_CODCF); + } + } + } + + if (_msk->get_bool(F_STAMPA) && documenti.items() > 0) + { + TFilename tmp; + tmp.temp("", "ini"); + + // Ensure that the ofstream is well closed before ve1 call + if (tmp.full()) // dummy test + { + TDoc_key kd(documenti.get_hashobj()->key()); + TString16 chiavedoc; // Parte della chiave comune a tutti i documenti + chiavedoc << kd.provv() << '|' << kd.anno() << '|' << kd.codnum() << '|'; + + ofstream outf(tmp); + outf << "[Transaction]" << endl; // Transaction header + outf << "Action=S" << endl; // 'S'tampa o 'A'nteprima + outf << "Mode=D" << endl; // Definitive (always?) + outf << "NoPrintDlg=X" << endl; // Don't prompt the user with the print dialog + outf << endl; + outf << "[33]" << endl; // Transaction body + long nx = 0; // Document counter + + FOR_EACH_ASSOC_OBJECT(documenti, obj, r, riga) + { + const TDoc_key& kdoc = *(TDoc_key*)riga; + outf << "Doc(" << (nx++) << ")="; + outf << chiavedoc << kdoc.ndoc() << endl; + } + } + + if (tmp.exist()) + { + { + TString cmdline; cmdline << "ve1 -2 -i" << tmp; + TExternal_app app(cmdline); + app.run(); + } + /* Il 6-11-2015 ci siamo accorti che lv1 -3 non esiste (e nella 10.0 non lo chiamava nemmeno) + { + TString cmdline; cmdline << "lv1 -3 -i" << tmp; + TExternal_app app(cmdline); + app.run(); + } + */ + tmp.fremove(); + } + } + + if (_has_gui) + { + if (documenti.items() == 0) + lv_popup_msg(TR("Non è stato possibile generare alcun documento:\nprobabilmente i documenti richiesti esistono già.")); + else + { + if (adata < TDate(TODAY) && _msk->get_int(F_TPGEN) == 0) + lv_popup_msg(TR("Non è stato possibile generare documenti con data prevista consegna nel passato")); + else + { + TReport_book buc; + buc.add(rep); + if (buc.pages() > 0) + buc.preview(); + else + { + TString str; + if (numdocgen > 1) + str << TR("Sono stati generati ") << numdocgen << TR(" buoni."); + else + str << TR("E' stato generato un buono."); + lv_popup_msg(str); + } + } + } + } + + return true; +} + +void TGenera_documenti_app::main_loop() +{ + _has_gui = !(argc() >= 4 && xvt_str_same(argv(3), "-A")); + _msk->set(F_STAMPA, true); + _msk->set(F_NOTPLAN, true); + if (_has_gui) + { + while (_msk->run() == K_ENTER) + { + transfer(); + _msk->set(F_NOTPLAN, true); + } + } + else + { + _msk->set(F_DTCONS, TDate(TODAY)); + _msk->send_key(K_SPACE, DLG_OK); + if (_msk->run() == K_ENTER) + transfer(); + } +} + +int lv2400(int argc, char* argv[]) +{ + TGenera_documenti_app app; + app.run(argc, argv, TR("Generazione documenti")); + return 0; +} diff --git a/src/lv/lv2600a.uml b/src/lv/lv2600a.uml index cecae774e..5a2a431b3 100755 --- a/src/lv/lv2600a.uml +++ b/src/lv/lv2600a.uml @@ -45,7 +45,7 @@ END STRING F_PATH 255 50 BEGIN PROMPT 10 8 "Cartella " - FLAGS "D" + // FLAGS "D" END SPREADSHEET F_SHEET_NAME 78 -1 diff --git a/src/lv/lv3300.cpp b/src/lv/lv3300.cpp index f7521679c..903133132 100755 --- a/src/lv/lv3300.cpp +++ b/src/lv/lv3300.cpp @@ -1,1490 +1,1529 @@ -#include - -#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" -#include "../ve/rcondv.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_BUONI_MSK //// - ////////////////////////////////////////// - -//Definizione della classe della maschera -class TGestione_buoni_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 set_data_handler(TMask_field& f, KEY k); - static bool set_contratto_handler(TMask_field& f, KEY k); - static bool set_dataprco_handler(TMask_field& f, KEY k); - static bool set_righe_buono_handler(TMask_field& f, KEY k); - - static bool pre_ritirato_handler(TMask_field& f, KEY k); - static bool pre_daconsegnare_handler(TMask_field& f, KEY k); - static bool pre_codart_handler(TMask_field& f, KEY k); - static bool pre_causale_handler(TMask_field& f, KEY k); - static bool pre_codmag_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; - TString8 proponi_autista() const; - TGestione_buoni_msk(const char* tipodoc); - - int _autoselect; - -}; - - ////////////////////////////////////////// - //// CLASSE TGESTIONE_BUONI_APP //// - ////////////////////////////////////////// - -// Definizione della classe dell'applicazione motore -class TGestione_buoni_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_query_mode( TMask& m ); - virtual void init_insert_mode( TMask& m ); - virtual void init_modify_mode( TMask& m ); - - void elimina_vuote( const TMask& m); - void salva_conguaglio( const TMask& m); - void date_dotmp( const TMask& m); - virtual const char * query_mask_name() { return "lv3300a"; } - - -public: - TGiac_per_cli& giacenza(); - TGestione_buoni_app() {} -}; - -inline TGestione_buoni_app& gbapp() { return (TGestione_buoni_app &)main_app(); }; - - ////////////////////////////////////////// - //// CLASSE TGestione_buoni_msk //// - ////////////////////////////////////////// - -//ARROTONDA: metodo che arrotonda la quantità che gli passo se è previsto sul contratto -void TGestione_buoni_msk::arrotonda(const TMask& msk, real& quantita) -{ - int perarr = ini_get_int(CONFIG_DITTA, "lv", "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ù o in meno gli devo dare e aggiorno la quantità - 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_buoni_msk::dettaglio_causale(TSheet_field& ss) -{ - TGestione_buoni_msk& dmsk = (TGestione_buoni_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_buoni_msk::proponi_dataprco() const -{ - TDate dadata = get(F_DATADOC); - TDate dataprco = NULLDATE; - - if (dadata.ok()) - { - TDate adata = dadata; - adata.addmonth(1); - ++dadata; - - TString query = "USE LVRCONSPLAN KEY 3"; - query << "\nFROM CODCF=" << get(F_CODCF) << " CODCONT=" << get(F_LVCODCONT) << " DTCONS=" << dadata; - query << "\nTO CODCF=" << get(F_CODCF) << " CODCONT=" << get(F_LVCODCONT) << " DTCONS=" << adata; - TISAM_recordset consegne(query); - - if (consegne.move_first()) - dataprco = consegne.get(LVRCONSPLAN_DTCONS).as_date(); - } - - return dataprco; -} - -//PROPONI_AUTISTA: metodo che propone l'autista previsto per la data di prevista consegna -TString8 TGestione_buoni_msk::proponi_autista() const -{ - const TDate datadoc = get(F_DATADOC); - const int indsped = get_int(F_CODINDSP); - const long codcf = get_long(F_CODCF); - const long codcont = lv_find_contract(codcf, indsped, datadoc); - - TDate dataprco; - - if (datadoc.ok()) - { - TDate adata = datadoc; - adata.addmonth(1); - - TString query = "USE LVRCONSPLAN KEY 3\n"; - query << "FROM CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=" << datadoc << "\n"; - query << "TO CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=" << adata << "\n"; - TISAM_recordset consegne(query); - - if (consegne.items() >= 2) - { - consegne.move_to(1); - dataprco = consegne.get(LVRCONSPLAN_DTCONS).as_date(); - } - } - - TString query = "USE LVRCONSPLAN KEY 3\n"; - query << "FROM CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=#DADATA\n"; - query << "TO CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=#ADATA\n"; - TISAM_recordset consegne(query); - consegne.set_var("#DADATA", dataprco); - consegne.set_var("#ADATA", dataprco); - consegne.move_first(); - - TString8 codaut = consegne.get(LVRCONSPLAN_CODAUT).as_string().right(5); codaut.trim(); - - if(codaut.empty()) - { - TToken_string key; - key.add('C'); - key.add(codcf); - - const TRectype& cfven = cache().get(LF_CFVEN, key); - codaut = cfven.get(CFV_CODAG); - } - return codaut; - -} - -//////////////////////////// -// HANDLER DI DOCUMENTO // -//////////////////////////// - -void TGestione_buoni_msk:: on_idle() -{ - TDocumento_mask::on_idle(); - if (_autoselect >= 0) - { - TSheet_field& s = sfield(F_SHEET); - if (_autoselect < s.items()) - { - //per ora 4 fisso perchè non sappiamo calcolare la colonna del ritirato - s.set_focus_cell_id(_autoselect, FR_QTAGG1); - dettaglio_causale(s); - } - _autoselect = -1; - } -} - -//magico metodo per settare, al cambio riga dello sheet, il focus sul campo desiderato (il campo in questione è.. -//..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_buoni_msk::ss_notify(TSheet_field& ss, int r, KEY key) -{ - TGestione_buoni_msk& dmsk = (TGestione_buoni_msk&) ss.mask(); - - if (key == K_TAB && dmsk._autoselect < 0 && dmsk.is_running()) - dmsk._autoselect = r; //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è con quantità diverese da zero) -bool TGestione_buoni_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à ignorato")); - } - return TDocumento_mask::ss_handler(f, key); -} - -//SET_DATA_HANDLER: handler che si occupa di decodificare i campi data in testata -bool TGestione_buoni_msk::set_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_buoni_msk& dmsk = (TGestione_buoni_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; -} - -//SET_CONTRATTO_HANDLER: handler che si occupa di riempire il campo contratto in testata -bool TGestione_buoni_msk::set_contratto_handler(TMask_field& f, KEY k) -{ - TGestione_buoni_msk& dmsk = (TGestione_buoni_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.get(F_LVDATAPRCO).empty()) - dmsk.set(F_LVDATAPRCO, dataprco); - - const TString8 autista = dmsk.proponi_autista(); - if (dmsk.field(F_CODAG).empty()) - dmsk.set(F_CODAG, autista); - } - - return true; -} - -//SET_DATAPRCO_HANDLER: handler che si occupa della gestione del campo "data di prevista consegna" -bool TGestione_buoni_msk::set_dataprco_handler(TMask_field& f, KEY k) -{ - //se sto leggendo o generando un buono di ritiro, abilito questo campo - if (k == K_TAB) - { - TGestione_buoni_msk& dmsk = (TGestione_buoni_msk&)f.mask(); - TDocumento& doc = dmsk.doc(); - //se la data viene modificata a mano, controlla se è una data di previsto passaggio; - //se non lo è chiedi conferma se si desidera mantenre la data indicata manualmente o se - //è 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 è 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; -} - -//SET_RIGHE_BUONO_HANDLER: handler di bolla, carica le righe contratto sulle bolle, preparando la struttura del documento -bool TGestione_buoni_msk::set_righe_buono_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_buoni_msk& dmsk = (TGestione_buoni_msk&)f.mask(); - if(dmsk.mode() == MODE_INS) - dmsk.set(F_CODAG, dmsk.proponi_autista()); - - if (ok && k == K_TAB && ((dmsk.insert_mode() && f.to_check(k, true)) || f.focusdirty()) && dmsk.mode() != MODE_MOD) - { - 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.get(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 - TString8 codmag; - codmag << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "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) - causale = ini_get_string(CONFIG_DITTA, "lv", "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); - TString descr; - descr << anamag.get(ANAMAG_DESCR) << anamag.get(ANAMAG_DESCRAGG); - - rdoc.put(RDOC_CODART,codart); - rdoc.put(RDOC_CODARTMAG,codart); - rdoc.put(RDOC_CHECKED,'X'); - if(descr.len() <= 50) - rdoc.put(RDOC_DESCR, descr); - else - { - rdoc.put(RDOC_DESCR, descr.left(50)); - rdoc.put(RDOC_DESCEST, descr.sub(50)); - rdoc.put(RDOC_DESCLUNGA, true); - } - 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()) - { - const TCausale_lavanderie cau(causale); - const TCausale_magazzino rit = cau.causale_ritiro(); - const TCausale_magazzino con = cau.causale_consegna(); - - TString8 magazzino; - TString8 magazzinoc; - - if(rit.get("S10").full()) - magazzino = rit.get("S10").mid(0,5); - else - magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); - - if(con.get("S10").full()) - magazzinoc = con.get("S10").mid(0,5); - else - magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); - - rdoc.put(RDOC_CODMAG, magazzino); - rdoc.put(RDOC_CODMAGC, magazzinoc); - } - - //gestione campi dotazione odierna e dotazione temporanea - TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, indsped); - //fisso l'anno esercizio - TEsercizi_contabili& esc = esercizi(); - const int last_esc = esc.last(); - - //estraggo il record corrispondente su LF_CLIFOGIAC - const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); - real dotod = reclav.get_real(CLIFOGIAC_DOTOD); - real dotmp = reclav.get_real(CLIFOGIAC_DOTTM); - - if(reclav.empty()) - { - TArticolo_lavanderie& artrec1 = cached_article_laundry(codart, 'C', codcf, 0); - const TRecmag_lavanderie& reclav1 = artrec1.find_rec(last_esc); - dotod = reclav1.get_real(CLIFOGIAC_DOTOD); - dotmp = reclav1.get_real(CLIFOGIAC_DOTTM); - } - - rdoc.put("DOTOD", dotod); - 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); - const int righe = doc.physical_rows(); - sheet.destroy( ); - for (int i = 1; i <= righe; i++) - { - TRiga_documento& r = doc[i]; - - doc[i].autoload(sheet); - sheet.check_row(i - 1, 0x3); - } - - FOR_EACH_MASK_FIELD(dmsk, i, f) - { - if (f->has_check()) - f->check(STARTING_CHECK); - if (f->is_edit()) - f->on_hit(); - } - - const int posdacons = sheet.cid2index(FR_QTA); - const int poscons = sheet.cid2index(FR_QTAEVASA); - const int pospacchi = sheet.cid2index(FR_NCOLLI); - const int posdotod = sheet.cid2index(FR_JOLLY1); - const int posdotmp = sheet.cid2index(FR_JOLLY2); - const int posdatmp = sheet.cid2index(FR_JOLLY3); - const int posatmp = sheet.cid2index(FR_JOLLY4); - const int posrif = sheet.cid2index(FR_JOLLY5); - - FOR_EACH_SHEET_ROW(sheet, i, riga) - { - TString rif = riga->get(posrif); - if (riga->get_int(poscons) == riga->get_int(posdacons) && rif.full()) - { - sheet.disable_row(i); - continue; - } - - sheet.disable_cell(i, poscons); - sheet.disable_cell(i, pospacchi); - sheet.disable_cell(i, posdotod); - sheet.disable_cell(i, posdotmp); - sheet.disable_cell(i, posdatmp); - sheet.disable_cell(i, posatmp); - sheet.disable_cell(i, posrif); - } - dmsk.highlight(); - sheet.force_update(); - - - dmsk._autoselect = 0; - } - return ok; -} - -//PRE_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 è giusta) -bool TGestione_buoni_msk::pre_ritirato_handler(TMask_field& f, KEY k) -{ - if (f.to_check(k)) - { - //maschera di riga - TMask& msk = f.mask(); - - //maschera di documento - TSheet_field* sheet = msk.get_sheet(); - TDocumento_mask& dmsk = (TDocumento_mask&)sheet->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; - - //recupero i valori della dotazione iniziale dal magazzino del cliente - TLocalisamfile magcli(LF_CLIFOGIAC); - magcli.put(CLIFOGIAC_ANNOES, datadoc.year()); - magcli.put(CLIFOGIAC_TIPOCF, 'C'); - magcli.put(CLIFOGIAC_CODCF, codcf); - magcli.put(CLIFOGIAC_INDSPED, 0); - magcli.put(CLIFOGIAC_CODART, msk.get(FR_CODART)); - magcli.put(CLIFOGIAC_NRIGA, 1); - - //leggo il record corrispondente - magcli.read(); - long dotin = magcli.get_long(CLIFOGIAC_DOTIN); - - real ritirato = f.get(); - real dotod = magcli.get_long(CLIFOGIAC_DOTOD); //segnalazione Tassan mail 05/04/2011 ore 17:08 - - if (ritirato > dotod && f.dirty() && dotin > 0 && dotod > 0) //accordi da Tassan in data 06/04/2011 - warning_box(TR("ATTENZIONE: si sta ritirando un quantitativo maggiore della dotazione!")); - - - TDocumento& doc = dmsk.doc(); - TRiga_documento& rdoc = dmsk.doc()[sheet->selected()+1]; - - rdoc.put(RDOC_QTAGG1,ritirato); - - if ((k == K_TAB && f.focusdirty()) && 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 è 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; -} - -//PRE_DACONSEGNARE_HANDLER: per adesso è solo un segna - posto -bool TGestione_buoni_msk::pre_daconsegnare_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); - - //gestione campi dotazione odierna e dotazione temporanea - 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 è 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; -} - -//PRE_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_buoni_msk::pre_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_buoni_msk& dmsk = (TGestione_buoni_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; - - 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 ) - causale = ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV"); - - if (rdoc.get("DOTOD").empty()) - { - //gestione campi dotazione odierna e dotazione temporanea - TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, indsped); - //fisso l'anno esercizio - TEsercizi_contabili& esc = esercizi(); - const int last_esc = esc.last(); - - //estraggo il record corrispondente su LF_CLIFOGIAC - const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); - - real dotod = reclav.get_real(CLIFOGIAC_DOTOD); - real dotmp = reclav.get_real(CLIFOGIAC_DOTTM); - - 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) && ini_get_bool(CONFIG_DITTA, "lv", "Aggcong")) - { - const real congor = rcont.get_real(LVRCONDV_QTACONG); - - const real congat = conat - conor - ritat + ritor + congor; - msk.set(FR_QTAGG5, congat); - - 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(); - } - } - } - - if (rcont.empty()) - { - real prezzo; - //PROPONI PREZZO - TToken_string key; - key.add('C'); - key.add(codcf); - 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()) - { - prezzo = 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); - prezzo = umart.get_real(UMART_PREZZO); - if (umart.get(UMART_PREZZO).full()) - trvlst = true; - } - rdoc.put(RDOC_PREZZO, prezzo); - } - - //controllo se si vuole aggiungere un eventuale nuovo articolo al contratto - if (cont.get_int(LVCONDV_CODCONT) <= 0) - { - static clock_t _next_time = 0; - const clock_t curr_time = clock(); - if (curr_time > _next_time) - { - xvt_dm_popup_warning(TR("ATTENZIONE: il cliente non ha nessun contratto in essere")); - _next_time = curr_time + 5 * CLOCKS_PER_SEC; - } - } - 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.add_row(codart); - - //questo pezzo sostituisce il metodo edit - TFilename ininame; ininame.temp(); - { - TConfig ini(ininame, "Transaction"); - ini.set("Action", "LINK"); - TString16 p; p << "168"; - ini.set_paragraph(p); - - ini.set(LVCONDV_CODCF, codcf); - ini.set(LVCONDV_CODCONT, cont.get_int(LVCONDV_CODCONT)); - } - - TString app = "lv0 -3"; - app << " -i" << ininame; - app << " -c" << codart; - - TExternal_app a(app); - ok = a.run() == 0; - } - } - } - return ok; -} - -//PRE_CAUSALE_HANDLER: handler che abilita e/o disabilita i campi di consegnato e ritirato in base alla causale -//e tenendo conto se l'articolo è bloccato o meno -bool TGestione_buoni_msk::pre_causale_handler(TMask_field& f, KEY k) -{ - if (f.to_check(k, true)) - { - TString4 codmagdef = ini_get_string(CONFIG_DITTA, "lv", "CODMAG"); //magazzino - TString4 coddepdef = ini_get_string(CONFIG_DITTA, "lv", "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_buoni_msk& dmsk = (TGestione_buoni_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); - - const TCausale_lavanderie cau(causale); - const TCausale_magazzino rit = cau.causale_ritiro(); - const TCausale_magazzino con = cau.causale_consegna(); - - TString8 magazzino; - TString8 magazzinoc; - - if(rit.get("S10").full()) - magazzino = rit.get("S10").mid(0,5); - else - magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); - - if(con.get("S10").full()) - magazzinoc = con.get("S10").mid(0,5); - else - magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); - - rdoc.put(RDOC_CODMAG, magazzino); - rdoc.put(RDOC_CODMAGC, magazzinoc); - - msk.field(FR_CODAGG1).set(causale); - msk.field(FR_CODMAG).set(magazzino.left(3)); msk.field(FR_CODDEP).set(magazzino.mid(3,2)); - msk.field(FR_CODMAGC).set(magazzinoc.left(3)); msk.field(FR_CODDEPC).set(magazzinoc.mid(3,2)); - - //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); - - //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 - //setto il valore della dotazione temporanea - TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, indsped); - //fisso l'anno esercizio - TEsercizi_contabili& esc = esercizi(); - const int last_esc = esc.last(); - - //estraggo il record corrispondente su LF_CLIFOGIAC - const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); - real dotmp = reclav.get_real(CLIFOGIAC_DOTTM); - - 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 - { - if(adata < datadoc) - { - //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 && !cau.is_reso()) - { - 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 è 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; -} - -//PRE_CODMAG_HANDLER: handler che limita l'esecuzione -bool TGestione_buoni_msk::pre_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; -} - -//metodo che setta gli handler sui campi di riga -void TGestione_buoni_msk::user_set_row_handler(TMask& rm, short field, int index) -{ - switch(index) - { - case 4101: rm.set_handler(field, pre_ritirato_handler); break; - case 4102: rm.set_handler(field, pre_daconsegnare_handler); break; - case 4103: rm.set_handler(field, pre_codart_handler); break; - case 4104: rm.set_handler(field, pre_causale_handler); break; - case 4105: rm.set_handler(field, pre_codmag_handler); break; - default: break; - } -} - -//metodo che setta l'handler di bolla -void TGestione_buoni_msk::user_set_handler( short fieldid, int index) -{ - switch(index) - { - case 4101: set_field_handler(fieldid, set_data_handler); break; - case 4102: set_field_handler(fieldid, set_contratto_handler); break; - case 4103: set_field_handler(fieldid, set_righe_buono_handler); break; - case 4105: set_field_handler(fieldid, set_dataprco_handler); break; - default: /*TDocumento_mask::user_set_handler(fieldid, index);*/ break; - } -} - -TGestione_buoni_msk::TGestione_buoni_msk(const char* tipodoc) : TDocumento_mask(tipodoc), _autoselect(-1) -{ - if (ini_get_bool(CONFIG_DITTA, "lv", "Datafissa")) - 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_buoni_app //// - ////////////////////////////////////////// - -//ridefinisco il metodo get_mask delle TMotore_application -TMask* TGestione_buoni_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_buoni_msk* m = new TGestione_buoni_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 TPointer_array& handlers = tdoc.handlers(); - FOR_EACH_ARRAY_ROW(handlers, i, row) - { - CHECKD(i > DLG_CANCEL, "Invalid handled field ", i); - m->user_set_handler( i, handlers.get_long(i) ); - } - } - } - return TMotore_application::get_mask(mode); -} - -void TGestione_buoni_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_real(RDOC_QTAGG1) == ZERO) - { - d.destroy_row(r,true); - } - } -} - -void TGestione_buoni_app::salva_conguaglio( const TMask& m) -{ - if (ini_get_bool(CONFIG_DITTA, "lv", "Aggcong")) - { - TDocumento_mask& mask = (TDocumento_mask&) m; - TDocumento& d = mask.doc(); - - TSheet_field& sheet = mask.sfield(F_SHEET); - const long codcf = mask.get_long(F_CODCF); - const int indsped = mask.get_int(F_CODINDSP); - TDate datadoc = mask.get_date(F_DATADOC); - - const TLaundry_contract cont(codcf, indsped, datadoc); - const int codcont = cont.get_int(LVCONDV_CODCONT); - - TLocalisamfile rcondv(LF_LVRCONDV); - - FOR_EACH_DOC_ROW_BACK(d, r, row) - { - TRiga_documento& rdoc = (TRiga_documento&)*row; - rcondv.put(LVRCONDV_CODCF,codcf); - rcondv.put(LVRCONDV_CODCONT, codcont); - rcondv.put(LVRCONDV_CODART, rdoc.get(RDOC_CODART)); - if (rcondv.read() == NOERR) - rcondv.put(LVRCONDV_QTACONG, rdoc.get_real(RDOC_QTAGG5)); - const real ritat = rdoc.get_real(RDOC_QTAGG1); - const real conat = rdoc.get_real(RDOC_QTA); - rdoc.put(RDOC_QTAGG4, ritat); - rdoc.put(RDOC_QTAGG3, conat); - } - rcondv.rewrite(); - } -} - -void TGestione_buoni_app::date_dotmp( const TMask& m) -{ - TDocumento_mask& mask = (TDocumento_mask&) m; - TDocumento& d = mask.doc(); - - TSheet_field& sheet = mask.sfield(F_SHEET); - const long codcf = mask.get_long(F_CODCF); - const int indsped = mask.get_int(F_CODINDSP); - TDate datadoc = mask.get_date(F_DATADOC); - - const TLaundry_contract cont(codcf, indsped, datadoc); - const int codcont = cont.get_int(LVCONDV_CODCONT); - - TLocalisamfile rcondv(LF_LVRCONDV); - - FOR_EACH_DOC_ROW_BACK(d, r, row) - { - TRiga_documento& rdoc = (TRiga_documento&)*row; - if(rdoc.get_date("DADATATMP").ok()) - { - bool to_write = false; - - rcondv.put(LVRCONDV_CODCF,codcf); - rcondv.put(LVRCONDV_CODCONT, codcont); - rcondv.put(LVRCONDV_CODART, rdoc.get(RDOC_CODART)); - - const TCausale_lavanderie cau(rdoc.get(RDOC_CODAGG1)); - - if (rcondv.read() == NOERR) - { - const TDate da_data_contr = rcondv.get_date(LVRCONDV_INDTTMP); - const TDate da_data_bolla = rdoc.get_date("DADATATMP"); - - if (da_data_contr > da_data_bolla) - { - rcondv.put(LVRCONDV_INDTTMP, da_data_bolla); - to_write = true; - } - - const TDate a_data_contr = rcondv.get_date(LVRCONDV_FIDTTMP); - const TDate a_data_bolla = rdoc.get_date("ADATATMP"); - - if(a_data_contr < a_data_bolla && !cau.is_reso()) - { - rcondv.put(LVRCONDV_FIDTTMP, a_data_bolla); - to_write = true; - } - if (to_write && cau.is_reso()) - rcondv.rewrite(); - } - } - } -} - -//ridefinisco il metodo write delle TMotore_application -int TGestione_buoni_app::write( const TMask& m ) -{ - elimina_vuote(m); - - salva_conguaglio(m); - - date_dotmp(m); - - return TMotore_application::write(m); -} - -//ridefinisco il metodo rewrite delle TMotore_application -int TGestione_buoni_app::rewrite( const TMask& m ) -{ - elimina_vuote(m); - - salva_conguaglio(m); - - date_dotmp(m); - - return TMotore_application::rewrite(m); -} - -//ridefinisco il metodo read della TMotore_application -int TGestione_buoni_app::read(TMask& m) -{ - m.sfield(F_SHEET).destroy(); - - const int err = TMotore_application::read(m); - - if (err == NOERR) - { - TGestione_buoni_msk& mask = (TGestione_buoni_msk&) m; - TDocumento& d = mask.doc(); - - _giac.reset(d); - FOR_EACH_DOC_ROW_BACK(d, r, row) - { - TRiga_documento& rdoc = (TRiga_documento&)*row; - _giac.load_row(rdoc, true, true); - real dotod = _giac.giac_att(rdoc, true); - real dotmp = _giac.giac_att(rdoc, false); - } - mask.doc2mask(); - mask._autoselect = 0; - - TSheet_field& sheet = mask.sfield(F_SHEET); - FOR_EACH_SHEET_ROW(sheet, i, riga) - { - if (riga->get_int(sheet.cid2index(FR_QTA)) > 0 && riga->get_int(sheet.cid2index(FR_QTAEVASA)) == riga->get_int(sheet.cid2index(FR_QTA))) - { - sheet.disable_row(i); - continue; - } - sheet.disable_cell(i, sheet.cid2index(FR_QTAEVASA)); - sheet.disable_cell(i, sheet.cid2index(FR_NCOLLI)); - sheet.disable_cell(i, sheet.cid2index(FR_JOLLY1)); - sheet.disable_cell(i, sheet.cid2index(FR_JOLLY2)); - sheet.disable_cell(i, sheet.cid2index(FR_JOLLY3)); - sheet.disable_cell(i, sheet.cid2index(FR_JOLLY4)); - sheet.disable_cell(i, sheet.cid2index(FR_JOLLY5)); - } - sheet.force_update(); - } - return err; -} - -//ridefinisco il metodo init_query_mode della TMotore_application -void TGestione_buoni_app::init_query_mode(TMask &m) -{ - /* La data di prevista cosegna NON puo' essere sulla maschera di query! Guy 10-12-2014 - //se sto leggendo o generando un buono di ritiro, abilito questo campo - bool enable_dataprco = m.get(F_CODNUM) == ini_get_string(CONFIG_DITTA, "lv", "NUM_RIT(0)") && - m.get(F_TIPODOC) == ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_RIT(0)"); - - m.enable(F_LVDATAPRCO, enable_dataprco); - */ - return TMotore_application::init_query_mode(m); -} - -//ridefinisco il metodo init_insert_mode della TMotore_application -void TGestione_buoni_app::init_insert_mode(TMask &m) -{ - TGestione_buoni_msk& mask = (TGestione_buoni_msk&)m; - TDocumento& d = mask.doc(); - _giac.reset(d); - - mask.reset_var_mask(); - mask.first_focus(F_CODCF, false); - - return TMotore_application::init_insert_mode(m); -} - -//ridefinisco il metodo init_query_mode della TMotore_application -void TGestione_buoni_app::init_modify_mode(TMask &m) -{ - m.first_focus(F_CODCF, false); - return TMotore_application::init_modify_mode(m); -} - -//metodo che mi restituisce la giac -TGiac_per_cli& TGestione_buoni_app::giacenza() -{ - return _giac; -} - -int lv3300( int argc, char* argv[]) -{ - TGestione_buoni_app a; - - a.run( argc, argv, TR("Buoni di Prelievo")); - return 0; -} +#include + +#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" +#include "../ve/rcondv.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_BUONI_MSK //// + ////////////////////////////////////////// + +//Definizione della classe della maschera +class TGestione_buoni_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 set_data_handler(TMask_field& f, KEY k); + static bool set_contratto_handler(TMask_field& f, KEY k); + static bool set_dataprco_handler(TMask_field& f, KEY k); + static bool set_righe_buono_handler(TMask_field& f, KEY k); + + static bool pre_ritirato_handler(TMask_field& f, KEY k); + static bool pre_daconsegnare_handler(TMask_field& f, KEY k); + static bool pre_codart_handler(TMask_field& f, KEY k); + static bool pre_causale_handler(TMask_field& f, KEY k); + static bool pre_codmag_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; + TString8 proponi_autista() const; + TGestione_buoni_msk(const char* tipodoc); + + int _autoselect; + +}; + + ////////////////////////////////////////// + //// CLASSE TGESTIONE_BUONI_APP //// + ////////////////////////////////////////// + +// Definizione della classe dell'applicazione motore +class TGestione_buoni_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_query_mode( TMask& m ); + virtual void init_insert_mode( TMask& m ); + virtual void init_modify_mode( TMask& m ); + + void elimina_vuote( const TMask& m); + void salva_conguaglio( const TMask& m); + void date_dotmp( const TMask& m); + virtual const char * query_mask_name() { return "lv3300a"; } + + +public: + TGiac_per_cli& giacenza(); + TGestione_buoni_app() {} +}; + +inline TGestione_buoni_app& gbapp() { return (TGestione_buoni_app &)main_app(); }; + + ////////////////////////////////////////// + //// CLASSE TGestione_buoni_msk //// + ////////////////////////////////////////// + +//ARROTONDA: metodo che arrotonda la quantità che gli passo se è previsto sul contratto +void TGestione_buoni_msk::arrotonda(const TMask& msk, real& quantita) +{ + int perarr = ini_get_int(CONFIG_DITTA, "lv", "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ù o in meno gli devo dare e aggiorno la quantità + 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_buoni_msk::dettaglio_causale(TSheet_field& ss) +{ + TGestione_buoni_msk& dmsk = (TGestione_buoni_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_buoni_msk::proponi_dataprco() const +{ + TDate dadata = get(F_DATADOC); + TDate dataprco = NULLDATE; + + if (dadata.ok()) + { + TDate adata = dadata; + adata.addmonth(1); + ++dadata; + + TString query = "USE LVRCONSPLAN KEY 3"; + query << "\nFROM CODCF=" << get(F_CODCF) << " CODCONT=" << get(F_LVCODCONT) << " DTCONS=" << dadata; + query << "\nTO CODCF=" << get(F_CODCF) << " CODCONT=" << get(F_LVCODCONT) << " DTCONS=" << adata; + TISAM_recordset consegne(query); + + if (consegne.move_first()) + dataprco = consegne.get(LVRCONSPLAN_DTCONS).as_date(); + } + + return dataprco; +} + +//PROPONI_AUTISTA: metodo che propone l'autista previsto per la data di prevista consegna +TString8 TGestione_buoni_msk::proponi_autista() const +{ + const TDate datadoc = get(F_DATADOC); + const int indsped = get_int(F_CODINDSP); + const long codcf = get_long(F_CODCF); + const long codcont = lv_find_contract(codcf, indsped, datadoc); + + TDate dataprco; + + if (datadoc.ok()) + { + TDate adata = datadoc; + adata.addmonth(1); + + TString query = "USE LVRCONSPLAN KEY 3\n"; + query << "FROM CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=" << datadoc << "\n"; + query << "TO CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=" << adata << "\n"; + TISAM_recordset consegne(query); + + if (consegne.items() >= 2) + { + consegne.move_to(1); + dataprco = consegne.get(LVRCONSPLAN_DTCONS).as_date(); + } + } + + TString query = "USE LVRCONSPLAN KEY 3\n"; + query << "FROM CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=#DADATA\n"; + query << "TO CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=#ADATA\n"; + TISAM_recordset consegne(query); + consegne.set_var("#DADATA", dataprco); + consegne.set_var("#ADATA", dataprco); + consegne.move_first(); + + TString8 codaut = consegne.get(LVRCONSPLAN_CODAUT).as_string().right(5); codaut.trim(); + + if(codaut.empty()) + { + TToken_string key; + key.add('C'); + key.add(codcf); + + const TRectype& cfven = cache().get(LF_CFVEN, key); + codaut = cfven.get(CFV_CODAG); + } + return codaut; + +} + +//////////////////////////// +// HANDLER DI DOCUMENTO // +//////////////////////////// + +void TGestione_buoni_msk:: on_idle() +{ + TDocumento_mask::on_idle(); + if (_autoselect >= 0) + { + TSheet_field& s = sfield(F_SHEET); + if (_autoselect < s.items()) + { + //per ora 4 fisso perchè non sappiamo calcolare la colonna del ritirato + s.set_focus_cell_id(_autoselect, FR_QTAGG1); + dettaglio_causale(s); + } + _autoselect = -1; + } +} + +//magico metodo per settare, al cambio riga dello sheet, il focus sul campo desiderato (il campo in questione è.. +//..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_buoni_msk::ss_notify(TSheet_field& ss, int r, KEY key) +{ + TGestione_buoni_msk& dmsk = (TGestione_buoni_msk&) ss.mask(); + + if (key == K_TAB && dmsk._autoselect < 0 && dmsk.is_running()) + dmsk._autoselect = r; //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è con quantità diverese da zero) +bool TGestione_buoni_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à ignorato")); + } + return TDocumento_mask::ss_handler(f, key); +} + +//SET_DATA_HANDLER: handler che si occupa di decodificare i campi data in testata +bool TGestione_buoni_msk::set_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_buoni_msk& dmsk = (TGestione_buoni_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; +} + +//SET_CONTRATTO_HANDLER: handler che si occupa di riempire il campo contratto in testata +bool TGestione_buoni_msk::set_contratto_handler(TMask_field& f, KEY k) +{ + TGestione_buoni_msk& dmsk = (TGestione_buoni_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.get(F_LVDATAPRCO).empty()) + dmsk.set(F_LVDATAPRCO, dataprco); + + const TString8 autista = dmsk.proponi_autista(); + if (dmsk.field(F_CODAG).empty()) + dmsk.set(F_CODAG, autista); + } + + return true; +} + +//SET_DATAPRCO_HANDLER: handler che si occupa della gestione del campo "data di prevista consegna" +bool TGestione_buoni_msk::set_dataprco_handler(TMask_field& f, KEY k) +{ + //se sto leggendo o generando un buono di ritiro, abilito questo campo + if (k == K_TAB) + { + TGestione_buoni_msk& dmsk = (TGestione_buoni_msk&)f.mask(); + TDocumento& doc = dmsk.doc(); + //se la data viene modificata a mano, controlla se è una data di previsto passaggio; + //se non lo è chiedi conferma se si desidera mantenre la data indicata manualmente o se + //è 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 è 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; +} + +//SET_RIGHE_BUONO_HANDLER: handler di bolla, carica le righe contratto sulle bolle, preparando la struttura del documento +bool TGestione_buoni_msk::set_righe_buono_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_buoni_msk& dmsk = (TGestione_buoni_msk&)f.mask(); + if(dmsk.mode() == MODE_INS) + dmsk.set(F_CODAG, dmsk.proponi_autista()); + + if (ok && k == K_TAB && ((dmsk.insert_mode() && f.to_check(k, true)) || f.focusdirty()) && dmsk.mode() != MODE_MOD) + { + 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 + { + + const TDate dataprco = dmsk.proponi_dataprco(); + if (dataprco.ok() && dmsk.get(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 + TString8 codmag; + codmag << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "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) + causale = ini_get_string(CONFIG_DITTA, "lv", "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); + TString descr; + descr << anamag.get(ANAMAG_DESCR) << anamag.get(ANAMAG_DESCRAGG); + + rdoc.put(RDOC_CODART,codart); + rdoc.put(RDOC_CODARTMAG,codart); + rdoc.put(RDOC_CHECKED,'X'); + if(descr.len() <= 50) + rdoc.put(RDOC_DESCR, descr); + else + { + rdoc.put(RDOC_DESCR, descr.left(50)); + rdoc.put(RDOC_DESCEST, descr.sub(50)); + rdoc.put(RDOC_DESCLUNGA, true); + } + 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()) + { + const TCausale_lavanderie cau(causale); + const TCausale_magazzino rit = cau.causale_ritiro(); + const TCausale_magazzino con = cau.causale_consegna(); + + TString8 magazzino; + TString8 magazzinoc; + + if(rit.get("S10").full()) + magazzino = rit.get("S10").mid(0,5); + else + magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); + + if(con.get("S10").full()) + magazzinoc = con.get("S10").mid(0,5); + else + magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); + + rdoc.put(RDOC_CODMAG, magazzino); + rdoc.put(RDOC_CODMAGC, magazzinoc); + } + + //gestione campi dotazione odierna e dotazione temporanea + TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, indsped); + //fisso l'anno esercizio + TEsercizi_contabili& esc = esercizi(); + const int last_esc = esc.last(); + + //estraggo il record corrispondente su LF_CLIFOGIAC + const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); + real dotod = reclav.get_real(CLIFOGIAC_DOTOD); + real dotmp = reclav.get_real(CLIFOGIAC_DOTTM); + + if(reclav.empty()) + { + TArticolo_lavanderie& artrec1 = cached_article_laundry(codart, 'C', codcf, 0); + const TRecmag_lavanderie& reclav1 = artrec1.find_rec(last_esc); + dotod = reclav1.get_real(CLIFOGIAC_DOTOD); + dotmp = reclav1.get_real(CLIFOGIAC_DOTTM); + } + + rdoc.put("DOTOD", dotod); + 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); + const int righe = doc.physical_rows(); + sheet.destroy( ); + for (int i = 1; i <= righe; i++) + { + TRiga_documento& r = doc[i]; + + doc[i].autoload(sheet); + sheet.check_row(i - 1, 0x3); + } + + FOR_EACH_MASK_FIELD(dmsk, i, f) + { + if (f->has_check()) + f->check(STARTING_CHECK); + if (f->is_edit()) + f->on_hit(); + } + + const int posdacons = sheet.cid2index(FR_QTA); + const int poscons = sheet.cid2index(FR_QTAEVASA); + const int pospacchi = sheet.cid2index(FR_NCOLLI); + const int posdotod = sheet.cid2index(FR_JOLLY1); + const int posdotmp = sheet.cid2index(FR_JOLLY2); + const int posdatmp = sheet.cid2index(FR_JOLLY3); + const int posatmp = sheet.cid2index(FR_JOLLY4); + const int posrif = sheet.cid2index(FR_JOLLY5); + + FOR_EACH_SHEET_ROW(sheet, i, riga) + { + TString rif = riga->get(posrif); + if (riga->get_int(poscons) == riga->get_int(posdacons) && rif.full()) + { + sheet.disable_row(i); + continue; + } + + sheet.disable_cell(i, poscons); + sheet.disable_cell(i, pospacchi); + sheet.disable_cell(i, posdotod); + sheet.disable_cell(i, posdotmp); + sheet.disable_cell(i, posdatmp); + sheet.disable_cell(i, posatmp); + sheet.disable_cell(i, posrif); + } + dmsk.highlight(); + sheet.force_update(); + + + dmsk._autoselect = 0; + } + return ok; +} + +//PRE_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 è giusta) +bool TGestione_buoni_msk::pre_ritirato_handler(TMask_field& f, KEY k) +{ + if (f.to_check(k)) + { + //maschera di riga + TMask& msk = f.mask(); + + //maschera di documento + TSheet_field* sheet = msk.get_sheet(); + TDocumento_mask& dmsk = (TDocumento_mask&)sheet->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; + + //recupero i valori della dotazione iniziale dal magazzino del cliente + TLocalisamfile magcli(LF_CLIFOGIAC); + magcli.put(CLIFOGIAC_ANNOES, datadoc.year()); + magcli.put(CLIFOGIAC_TIPOCF, 'C'); + magcli.put(CLIFOGIAC_CODCF, codcf); + magcli.put(CLIFOGIAC_INDSPED, 0); + magcli.put(CLIFOGIAC_CODART, msk.get(FR_CODART)); + magcli.put(CLIFOGIAC_NRIGA, 1); + + //leggo il record corrispondente + magcli.read(); + long dotin = magcli.get_long(CLIFOGIAC_DOTIN); + + real ritirato = f.get(); + real dotod = magcli.get_long(CLIFOGIAC_DOTOD); //segnalazione Tassan mail 05/04/2011 ore 17:08 + + if (ritirato > dotod && f.dirty() && dotin > 0 && dotod > 0) //accordi da Tassan in data 06/04/2011 + warning_box(TR("ATTENZIONE: si sta ritirando un quantitativo maggiore della dotazione!")); + + + TDocumento& doc = dmsk.doc(); + TRiga_documento& rdoc = dmsk.doc()[sheet->selected()+1]; + + rdoc.put(RDOC_QTAGG1,ritirato); + + if ((k == K_TAB && f.focusdirty()) && 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 è 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; +} + +//PRE_DACONSEGNARE_HANDLER: per adesso è solo un segna - posto +bool TGestione_buoni_msk::pre_daconsegnare_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); + + //gestione campi dotazione odierna e dotazione temporanea + 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 è 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; +} + +//PRE_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_buoni_msk::pre_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_buoni_msk& dmsk = (TGestione_buoni_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; + + 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 ) + causale = ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV"); + + if (rdoc.get("DOTOD").empty()) + { + //gestione campi dotazione odierna e dotazione temporanea + TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, indsped); + //fisso l'anno esercizio + TEsercizi_contabili& esc = esercizi(); + const int last_esc = esc.last(); + + //estraggo il record corrispondente su LF_CLIFOGIAC + const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); + + real dotod = reclav.get_real(CLIFOGIAC_DOTOD); + real dotmp = reclav.get_real(CLIFOGIAC_DOTTM); + + 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) && ini_get_bool(CONFIG_DITTA, "lv", "Aggcong")) + { + const real congor = rcont.get_real(LVRCONDV_QTACONG); + + const real congat = conat - conor - ritat + ritor + congor; + msk.set(FR_QTAGG5, congat); + + 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(); + } + } + } + + if (rcont.empty()) + { + real prezzo; + //PROPONI PREZZO + TToken_string key; + key.add('C'); + key.add(codcf); + 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()) + { + prezzo = 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); + prezzo = umart.get_real(UMART_PREZZO); + if (umart.get(UMART_PREZZO).full()) + trvlst = true; + } + rdoc.put(RDOC_PREZZO, prezzo); + } + + //controllo se si vuole aggiungere un eventuale nuovo articolo al contratto + if (cont.get_int(LVCONDV_CODCONT) <= 0) + { + static clock_t _next_time = 0; + const clock_t curr_time = clock(); + if (curr_time > _next_time) + { + xvt_dm_popup_warning(TR("ATTENZIONE: il cliente non ha nessun contratto in essere")); + _next_time = curr_time + 5 * CLOCKS_PER_SEC; + } + } + 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.add_row(codart); + + //questo pezzo sostituisce il metodo edit + TFilename ininame; ininame.temp(); + { + TConfig ini(ininame, "Transaction"); + ini.set("Action", "LINK"); + TString16 p; p << "168"; + ini.set_paragraph(p); + + ini.set(LVCONDV_CODCF, codcf); + ini.set(LVCONDV_CODCONT, cont.get_int(LVCONDV_CODCONT)); + } + + TString app = "lv0 -3"; + app << " -i" << ininame; + app << " -c" << codart; + + TExternal_app a(app); + ok = a.run() == 0; + } + } + } + return ok; +} + +//PRE_CAUSALE_HANDLER: handler che abilita e/o disabilita i campi di consegnato e ritirato in base alla causale +//e tenendo conto se l'articolo è bloccato o meno +bool TGestione_buoni_msk::pre_causale_handler(TMask_field& f, KEY k) +{ + if (f.to_check(k, true)) + { + TString4 codmagdef = ini_get_string(CONFIG_DITTA, "lv", "CODMAG"); //magazzino + TString4 coddepdef = ini_get_string(CONFIG_DITTA, "lv", "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_buoni_msk& dmsk = (TGestione_buoni_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); + + const TCausale_lavanderie cau(causale); + const TCausale_magazzino rit = cau.causale_ritiro(); + const TCausale_magazzino con = cau.causale_consegna(); + + TString8 magazzino; + TString8 magazzinoc; + + if(rit.get("S10").full()) + magazzino = rit.get("S10").mid(0,5); + else + magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); + + if(con.get("S10").full()) + magazzinoc = con.get("S10").mid(0,5); + else + magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); + + rdoc.put(RDOC_CODMAG, magazzino); + rdoc.put(RDOC_CODMAGC, magazzinoc); + + msk.field(FR_CODAGG1).set(causale); + msk.field(FR_CODMAG).set(magazzino.left(3)); msk.field(FR_CODDEP).set(magazzino.mid(3,2)); + msk.field(FR_CODMAGC).set(magazzinoc.left(3)); msk.field(FR_CODDEPC).set(magazzinoc.mid(3,2)); + + //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); + + //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 + //setto il valore della dotazione temporanea + TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, indsped); + //fisso l'anno esercizio + TEsercizi_contabili& esc = esercizi(); + const int last_esc = esc.last(); + + //estraggo il record corrispondente su LF_CLIFOGIAC + const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); + real dotmp = reclav.get_real(CLIFOGIAC_DOTTM); + + 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 + { + if(adata < datadoc) + { + //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 && !cau.is_reso()) + { + 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 è 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; +} + +//PRE_CODMAG_HANDLER: handler che limita l'esecuzione +bool TGestione_buoni_msk::pre_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; +} + +//metodo che setta gli handler sui campi di riga +void TGestione_buoni_msk::user_set_row_handler(TMask& rm, short field, int index) +{ + switch(index) + { + case 4101: rm.set_handler(field, pre_ritirato_handler); break; + case 4102: rm.set_handler(field, pre_daconsegnare_handler); break; + case 4103: rm.set_handler(field, pre_codart_handler); break; + case 4104: rm.set_handler(field, pre_causale_handler); break; + case 4105: rm.set_handler(field, pre_codmag_handler); break; + default: break; + } +} + +//metodo che setta l'handler di bolla +void TGestione_buoni_msk::user_set_handler( short fieldid, int index) +{ + switch(index) + { + case 4101: set_field_handler(fieldid, set_data_handler); break; + case 4102: set_field_handler(fieldid, set_contratto_handler); break; + case 4103: set_field_handler(fieldid, set_righe_buono_handler); break; + case 4105: set_field_handler(fieldid, set_dataprco_handler); break; + default: /*TDocumento_mask::user_set_handler(fieldid, index);*/ break; + } +} + +TGestione_buoni_msk::TGestione_buoni_msk(const char* tipodoc) : TDocumento_mask(tipodoc), _autoselect(-1) +{ + if (ini_get_bool(CONFIG_DITTA, "lv", "Datafissa")) + 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_buoni_app //// + ////////////////////////////////////////// + +//ridefinisco il metodo get_mask delle TMotore_application +TMask* TGestione_buoni_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_buoni_msk* m = new TGestione_buoni_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 TPointer_array& handlers = tdoc.handlers(); + FOR_EACH_ARRAY_ROW(handlers, i, row) + { + CHECKD(i > DLG_CANCEL, "Invalid handled field ", i); + m->user_set_handler( i, handlers.get_long(i) ); + } + } + } + return TMotore_application::get_mask(mode); +} + +void TGestione_buoni_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_real(RDOC_QTAGG1) == ZERO) + { + d.destroy_row(r,true); + } + } +} + +void TGestione_buoni_app::salva_conguaglio( const TMask& m) +{ + if (ini_get_bool(CONFIG_DITTA, "lv", "Aggcong")) + { + TDocumento_mask& mask = (TDocumento_mask&) m; + TDocumento& d = mask.doc(); + + TSheet_field& sheet = mask.sfield(F_SHEET); + const long codcf = mask.get_long(F_CODCF); + const int indsped = mask.get_int(F_CODINDSP); + TDate datadoc = mask.get_date(F_DATADOC); + + const TLaundry_contract cont(codcf, indsped, datadoc); + const int codcont = cont.get_int(LVCONDV_CODCONT); + + TLocalisamfile rcondv(LF_LVRCONDV); + + FOR_EACH_DOC_ROW_BACK(d, r, row) + { + TRiga_documento& rdoc = (TRiga_documento&)*row; + rcondv.put(LVRCONDV_CODCF,codcf); + rcondv.put(LVRCONDV_CODCONT, codcont); + rcondv.put(LVRCONDV_CODART, rdoc.get(RDOC_CODART)); + if (rcondv.read() == NOERR) + rcondv.put(LVRCONDV_QTACONG, rdoc.get_real(RDOC_QTAGG5)); + const real ritat = rdoc.get_real(RDOC_QTAGG1); + const real conat = rdoc.get_real(RDOC_QTA); + rdoc.put(RDOC_QTAGG4, ritat); + rdoc.put(RDOC_QTAGG3, conat); + } + rcondv.rewrite(); + } +} + +void TGestione_buoni_app::date_dotmp( const TMask& m) +{ + TDocumento_mask& mask = (TDocumento_mask&) m; + TDocumento& d = mask.doc(); + + TSheet_field& sheet = mask.sfield(F_SHEET); + const long codcf = mask.get_long(F_CODCF); + const int indsped = mask.get_int(F_CODINDSP); + TDate datadoc = mask.get_date(F_DATADOC); + + const TLaundry_contract cont(codcf, indsped, datadoc); + const int codcont = cont.get_int(LVCONDV_CODCONT); + + TLocalisamfile rcondv(LF_LVRCONDV); + + FOR_EACH_DOC_ROW_BACK(d, r, row) + { + TRiga_documento& rdoc = (TRiga_documento&)*row; + if(rdoc.get_date("DADATATMP").ok()) + { + bool to_write = false; + + rcondv.put(LVRCONDV_CODCF,codcf); + rcondv.put(LVRCONDV_CODCONT, codcont); + rcondv.put(LVRCONDV_CODART, rdoc.get(RDOC_CODART)); + + const TCausale_lavanderie cau(rdoc.get(RDOC_CODAGG1)); + + if (rcondv.read() == NOERR) + { + const TDate da_data_contr = rcondv.get_date(LVRCONDV_INDTTMP); + const TDate da_data_bolla = rdoc.get_date("DADATATMP"); + + if (da_data_contr > da_data_bolla) + { + rcondv.put(LVRCONDV_INDTTMP, da_data_bolla); + to_write = true; + } + + const TDate a_data_contr = rcondv.get_date(LVRCONDV_FIDTTMP); + const TDate a_data_bolla = rdoc.get_date("ADATATMP"); + + if(a_data_contr < a_data_bolla && !cau.is_reso()) + { + rcondv.put(LVRCONDV_FIDTTMP, a_data_bolla); + to_write = true; + } + if (to_write && cau.is_reso()) + rcondv.rewrite(); + } + } + } +} + +//ridefinisco il metodo write delle TMotore_application +int TGestione_buoni_app::write( const TMask& m ) +{ + elimina_vuote(m); + + salva_conguaglio(m); + + date_dotmp(m); + + TDocumento& d = doc(); + const long codcf = d.get_long(DOC_CODCF); + const int codcont = d.get_int(DOC_CODCONT); + + const TLaundry_contract tcont(codcf, codcont); + + if (tcont.get_bool(LVCONDV_SSCONS)) + { + char name[8] = "CODSP0"; + TString_array spese; + const TRectype& ven_rec = d.clifor().vendite(); + for (int i = 1; i <= 4; i++) + { + name[5] = '0' + i; + const TString& s = ven_rec.get(name); + if (s.full()) + spese.add(s); + } + d.update_spese_aut(spese, false, NULL, true); + } + + + return TMotore_application::write(m); +} + +//ridefinisco il metodo rewrite delle TMotore_application +int TGestione_buoni_app::rewrite( const TMask& m ) +{ + elimina_vuote(m); + + salva_conguaglio(m); + + date_dotmp(m); + + TDocumento& d = doc(); + const long codcf = d.get_long(DOC_CODCF); + const int codcont = d.get_int(DOC_CODCONT); + + const TLaundry_contract tcont(codcf, codcont); + + if (tcont.get_bool(LVCONDV_SSCONS)) + { + char name[8] = "CODSP0"; + TString_array spese; + const TRectype& ven_rec = d.clifor().vendite(); + for (int i = 1; i <= 4; i++) + { + name[5] = '0' + i; + const TString& s = ven_rec.get(name); + if (s.full()) + spese.add(s); + } + d.update_spese_aut(spese, false, NULL, true); + } + + return TMotore_application::rewrite(m); +} + +//ridefinisco il metodo read della TMotore_application +int TGestione_buoni_app::read(TMask& m) +{ + m.sfield(F_SHEET).destroy(); + + const int err = TMotore_application::read(m); + + if (err == NOERR) + { + TGestione_buoni_msk& mask = (TGestione_buoni_msk&) m; + TDocumento& d = mask.doc(); + + _giac.reset(d); + FOR_EACH_DOC_ROW_BACK(d, r, row) + { + TRiga_documento& rdoc = (TRiga_documento&)*row; + _giac.load_row(rdoc, true, true); + real dotod = _giac.giac_att(rdoc, true); + real dotmp = _giac.giac_att(rdoc, false); + } + mask.doc2mask(); + mask._autoselect = 0; + + TSheet_field& sheet = mask.sfield(F_SHEET); + FOR_EACH_SHEET_ROW(sheet, i, riga) + { + if (riga->get_int(sheet.cid2index(FR_QTA)) > 0 && riga->get_int(sheet.cid2index(FR_QTAEVASA)) == riga->get_int(sheet.cid2index(FR_QTA))) + { + sheet.disable_row(i); + continue; + } + sheet.disable_cell(i, sheet.cid2index(FR_QTAEVASA)); + sheet.disable_cell(i, sheet.cid2index(FR_NCOLLI)); + sheet.disable_cell(i, sheet.cid2index(FR_JOLLY1)); + sheet.disable_cell(i, sheet.cid2index(FR_JOLLY2)); + sheet.disable_cell(i, sheet.cid2index(FR_JOLLY3)); + sheet.disable_cell(i, sheet.cid2index(FR_JOLLY4)); + sheet.disable_cell(i, sheet.cid2index(FR_JOLLY5)); + } + sheet.force_update(); + } + return err; +} + +//ridefinisco il metodo init_query_mode della TMotore_application +void TGestione_buoni_app::init_query_mode(TMask &m) +{ + /* La data di prevista cosegna NON puo' essere sulla maschera di query! Guy 10-12-2014 + //se sto leggendo o generando un buono di ritiro, abilito questo campo + bool enable_dataprco = m.get(F_CODNUM) == ini_get_string(CONFIG_DITTA, "lv", "NUM_RIT(0)") && + m.get(F_TIPODOC) == ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_RIT(0)"); + + m.enable(F_LVDATAPRCO, enable_dataprco); + */ + return TMotore_application::init_query_mode(m); +} + +//ridefinisco il metodo init_insert_mode della TMotore_application +void TGestione_buoni_app::init_insert_mode(TMask &m) +{ + TGestione_buoni_msk& mask = (TGestione_buoni_msk&)m; + TDocumento& d = mask.doc(); + _giac.reset(d); + + mask.reset_var_mask(); + mask.first_focus(F_CODCF, false); + + return TMotore_application::init_insert_mode(m); +} + +//ridefinisco il metodo init_query_mode della TMotore_application +void TGestione_buoni_app::init_modify_mode(TMask &m) +{ + m.first_focus(F_CODCF, false); + return TMotore_application::init_modify_mode(m); +} + +//metodo che mi restituisce la giac +TGiac_per_cli& TGestione_buoni_app::giacenza() +{ + return _giac; +} + +int lv3300( int argc, char* argv[]) +{ + TGestione_buoni_app a; + + a.run( argc, argv, TR("Buoni di Prelievo")); + return 0; +}