#include #include #include #include #include #include #include #include #include #include #include #include "ve2200.h" #include "ve2300x.h" // include anche il file dei campi della maschera delle righe #include "veconf.h" #include "condv.h" #include "rcondv.h" #include "../mg/umart.h" // nome dell'applicazione di gestione delle righe #define RCONDVEN_APP "ve2 -2 " static void key_hide(TMask & m, short id, int key = 1) { ((TEditable_field &)m.field(id)).reset_key(key); m.hide(id); } static void key_disable(TMask & m, short id, int key = 1) { ((TEditable_field &)m.field(id)).reset_key(key); m.disable(id); } class TCondizioni_vendita: public TRelation_application { TMask *_msk; // maschera principale TRelation *_rel; // relazione principale TString16 _condven; // stringa che indica il tipo di archivio TBit_array _tohide; // vettore degli identificatori di campi che devono essere nascosti bool _codlis_catven; // booleano di abilitazione della categoria di vendita nella chiave dei listini bool _codcon_codcf; // booleano di abilitazioni dei campi TIPOCF e CODCF bool _gest_val, _gest_um, _gest_sca, _gest_so; // booleani per l'abilitazione di valute, unitā di misura, scaglioni e sconti/omaggi virtual bool user_create(); virtual bool user_destroy(); virtual TMask *get_mask(int) { return _msk; } virtual bool changing_mask(int) { return FALSE; } virtual TRelation *get_relation() const { return _rel; } static bool handle_mask(TMask &, KEY); // handler custom della maschera (per il tasto di aggancio alle righe) static bool handle_datacam(TMask_field &, KEY); // handler del campo DATACAM (data cambio) static bool handle_valfin(TMask_field &, KEY); // handler del campo VALFIN (data fine validitā) static bool handle_codsucc(TMask_field &, KEY); // handler del campo CODSUCC (codice successivo) static bool handle_copy(TMask_field &, KEY); // handler del bottone copia virtual void init_query_mode(TMask& m); virtual void init_insert_mode(TMask& m); virtual void init_modify_mode(TMask& m); virtual int read(TMask &); // metodo usato per leggere il record dal file virtual int write(const TMask &); // metodo usato per scrivere il record sul file virtual int rewrite(const TMask &); // metodo usato per aggiornare il record sul file virtual bool remove(); // metodo usato per cancellare il record sul file virtual void mask2ini(const TMask& m, TConfig& ini); public: bool codlis_catven() { return _codlis_catven; } // @cmember Disabilita la verifica del modulo : essendo una anagrafica, va sempre abilitata virtual bool check_autorization() const {return FALSE;} TCondizioni_vendita() {} virtual ~TCondizioni_vendita() {} }; class TMask_copy: public TAutomask { public: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); TMask_copy(const TMask& m, const bool enable_catven); }; bool TMask_copy::on_field_event(TOperable_field& o, TField_event e, long jolly) { return TRUE; } TMask_copy::TMask_copy(const TMask& m, const bool enable_catven) : TAutomask("ve2200c") { enable(F_L_CATVEN, enable_catven); set(F_TIPO,m.get(F_TIPO)); } static TCondizioni_vendita &app() { // funzione che ritorna il riferimento alla classe principale dell'applicazione return (TCondizioni_vendita &)main_app(); } void TCondizioni_vendita::init_query_mode(TMask& m) { m.disable(BTN_RIGHE); m.disable(BTN_COPIA); } void TCondizioni_vendita::init_insert_mode(TMask& m) { init_query_mode(m); } void TCondizioni_vendita::init_modify_mode(TMask& m) { m.enable(BTN_RIGHE); m.enable(BTN_COPIA); } bool TCondizioni_vendita::user_create() { bool gotcha= FALSE; // booleano di avvenuta inizializzazione _condven= "*"; // inizializzazione dell'indicatore del tipo di archivio if (argc() > 2) { TFilename trans = argv(2); if (trans.len() == 1) _condven = trans; else { trans.ltrim(2); if (trans.exist()) { TConfig ini(trans, "52"); _condven = ini.get("TIPO"); } } } if (_condven == "*") { TMask choose("ve2200"); // istanzia la maschera di scelta del tipo di archivio if (choose.run() == K_ENTER) _condven= choose.get(F_TIPOCV); // prende il tipo di archivio dalla maschera } _condven.upper(); // rende la stringa upper-case _msk= new TMask("VE2200X"); TConfig prassid(CONFIG_DITTA, "ve"); // apre il file di configurazione della ditta corrente switch (_condven[0]) { case 'L': { // listini if (prassid.get_bool("GES", NULL, A_LISTINI)) // controlla che l'archivio listini sia abilitato { // eliminazione campi di altri archivi _msk->set_caption("Archivio listini"); key_hide(*_msk, F_C_COD); key_hide(*_msk, F_O_COD); key_hide(*_msk, F_C_TIPOCF); key_hide(*_msk, F_C_CODCF); key_hide(*_msk, F_C_OBBLIG); key_hide(*_msk, F_C_DESCF); set_search_field(F_L_COD); // impostazione del campo di ricerca _msk->set_handler(F_L_CODSUCC, handle_codsucc); // setta l'handler per il campo di codice successivo _codlis_catven= prassid.get_bool("GESLISCV"); // setta il booleano di abilitazione delle categoria di vendita if (!_codlis_catven) key_disable(*_msk, F_L_CATVEN); // disabilita condizionalmente le categorie di vendita _gest_um= prassid.get_bool("GESUM", NULL, A_LISTINI); // setta il booleano di abilitazione delle unitā di misura _gest_sca= prassid.get_bool("GESSCA", NULL, A_LISTINI); // setta il booleano di abilitazione degli scaglioni _gest_so= prassid.get_bool("GESSO", NULL, A_LISTINI); // setta il booleano di abilitazione degli sconti/omaggi gotcha= TRUE; } else error_box("L'archivio Listini non č abilititato"); break; } case 'C': // contratti if (prassid.get_bool("GES", NULL, A_CONTRATTI)) // controlla che l'archivio contratti sia abilitato { // settaggio dei campi da eliminare _msk->set_caption("Archivio contratti"); key_hide(*_msk, F_L_COD); key_hide(*_msk, F_O_COD); key_hide(*_msk, F_L_CATVEN); key_hide(*_msk, F_L_DESVEN); key_hide(*_msk, F_L_CODSUCC); key_hide(*_msk, F_L_DESSUCC); _codcon_codcf= prassid.get_bool("GESCONCC"); // setta il booleano di abilitazione di TIPOCF e CODCF if (!_codcon_codcf) { // disabilita i campi di gestione clienti/fornitori in base al flag. di config. key_disable(*_msk, F_C_TIPOCF); TList_field& l = (TList_field&)_msk->field(F_C_TIPOCF); l.replace_items(" | "," | "); key_disable(*_msk, F_C_CODCF); } set_search_field(F_C_COD); // impostazione del campo di ricerca _gest_um= prassid.get_bool("GESUM", NULL, A_CONTRATTI); // setta il booleano di abilitazione delle unitā di misura _gest_sca= prassid.get_bool("GESSCA", NULL, A_CONTRATTI); // setta il booleano di abilitazione degli scaglioni _gest_so= prassid.get_bool("GESSO", NULL, A_CONTRATTI); // setta il booleano di abilitazione degli sconti/omaggi gotcha= TRUE; } else error_box("L'archivio Contratti non č abilititato"); break; case 'O': // offerte if (prassid.get_bool("GES", NULL, A_OFFERTE)) // controlla che l'archivio offerte sia abilitato { // settaggio dei campi da eliminare _msk->set_caption("Archivio offerte"); key_hide(*_msk, F_L_COD); key_hide(*_msk, F_C_COD); key_hide(*_msk, F_L_CATVEN); key_hide(*_msk, F_C_TIPOCF); key_hide(*_msk, F_C_CODCF); key_hide(*_msk, F_C_DESCF); key_hide(*_msk, F_L_DESVEN); key_hide(*_msk, F_C_OBBLIG); key_hide(*_msk, F_L_CODSUCC); key_hide(*_msk, F_L_DESSUCC); set_search_field(F_O_COD); // impostazione del campo di ricerca _gest_um= prassid.get_bool("GESUM", NULL, A_OFFERTE); // setta il booleano di abilitazione delle unitā di misura _gest_sca= prassid.get_bool("GESSCA", NULL, A_OFFERTE); // setta il booleano di abilitazione degli scaglioni _gest_so= prassid.get_bool("GESSO", NULL, A_OFFERTE); // setta il booleano di abilitazione degli sconti/omaggi gotcha= TRUE; } else error_box("L'archivio Offerte non č abilititato"); break; default: // messaggio di errore se si indica un archivio non valido error_box("Indicare l'archivio sulla linea di comando (L, C o O) oppure selezionarla dalla maschera di partenza"); break; } if (gotcha) { // se č stato selezionato correttamente un archivio completa l'inizializzazione _rel= new TRelation(LF_CONDV); // apre la relazione (un unico file) _msk->set(F_TIPO, _condven); // settaggio del campo di tipo archivio _msk->set_handler(handle_mask); // imposta l'handler generale della maschera _msk->set_handler(F_DATACAM, handle_datacam); // imposta l'handler per il campo della data del cambio _msk->set_handler(F_VALFIN, handle_valfin); // imposta l'handler per il campo di fine validitā _msk->set_handler(BTN_COPIA, handle_copy); // imposta l'handler per il bottone Copia if (!_gest_um) _msk->disable(F_GESTUM); // disabilita condizionalmente il booleano di gestione delle unitā di misura if (!_gest_sca) { _msk->disable(F_GESTSCAGL); // disabilita condizionalmente il booleano di gestione degli scaglioni _msk->disable(F_DECIMALI); // disabilita il numero di decimali significativi in qta limite scaglione } if (!_gest_so) _msk->disable(F_GESTSCO); // disabilita condizionalmente il booleano di gestione degli sconti/omaggi _gest_val= prassid.get_bool("GESVAL"); // legge il booleano di abilitazione delle gastione delle valute if (!_gest_val) { // se la gestione delle valute č disabilitata i campi di gestione vengono disabilitati _msk->disable(F_CODVAL); _msk->disable(F_CAMBIO); _msk->disable(F_DATACAM); } } return gotcha; } bool TCondizioni_vendita::user_destroy() { delete _rel; delete _msk; return TRUE; } bool TCondizioni_vendita::handle_mask(TMask &m, KEY k) { if (k==K_F5) { // se viene premuto F5 o selezionato il tasto "Righe" viene lanciata l'applicazione di editing TString &_condven= app()._condven; // prende l'indicatore del tipo di archivio bool &_codlis_catven= app()._codlis_catven; // prende il booleano di attivazione del campo CATVEN TString appname(RCONDVEN_APP); // istanzia e inizializza la stringa con il nome dell'applicazione da lanciare TString body; // istanzia la stringa contenente il corpo del messaggio (lista di inizializzazione dei campi della maschera) switch (_condven[0]) { case 'L': // listini body << F_R_L_RICERCA << "|"; // appende l'id del campo di ricerca body << F_R_TIPO << "=" << _condven << "|"; // appende il filtro sul tipo body << F_R_L_CATVEN << "=" << ((_codlis_catven)?(m.get(F_L_CATVEN)):("")) << "|"; // appende il filtro sulla categoria di vendita body << F_R_L_COD << "=" << m.get(F_L_COD); // appende il filtro sul campo codice break; case 'C': // contratti body << F_R_C_RICERCA << "|"; // appende l'id del campo di ricerca body << F_R_TIPO << "=" << _condven << "|"; // appende il filtro sul tipo body << F_R_C_TIPOCF << "=" << m.get(F_C_TIPOCF) << "|"; // appende il filtro sul campo tipo cliente/fornitore body << F_R_C_CODCF << "=" << m.get(F_C_CODCF) << "|"; // appende il filtro sul campo codice cliente/fornitore body << F_R_C_COD << "=" << m.get(F_C_COD); // appende il filtro sul campo codice break; case 'O': // offerte body << F_R_O_RICERCA << "|"; // appende l'id del campo di ricerca body << F_R_TIPO << "=" << _condven << "|"; // appende il filtro sul tipo body << F_R_O_COD << "=" << m.get(F_O_COD); // appende il filtro sul campo codice break; } appname << _condven; // aggiunge al lancio dell'applicazione la selezione del tipo di archivio TMessage msg(cmd2name(appname), MSG_FS, (const char *)body); // istanzia il messaggio per l'applicazione msg.send(); // invia il messaggio all'applicazione TExternal_app ve2_2(appname); // istanzia l'applicazione esterna... ve2_2.run(); // ...la lancia e rimane in attesa del suo termine } return TRUE; } bool TCondizioni_vendita::handle_datacam(TMask_field &fld, KEY k) { if (k==K_TAB) { // ad ogni perdita di fuoco viene tentato un accoppiamento tra valuta e data per ottenere il cambio preciso TString datacam(fld.get()); // legge la data di cambio nel campo corrente if (datacam.not_empty()) { TMask &m= fld.mask(); // prende la maschera principale TString codval(m.get(F_CODVAL)); // prende il codice della valuta if (codval.not_empty()) { TTable cam("CAM"); // apre la tabella cambi cam.put("CODTAB", codval << datacam); // riempie la chiave if (cam.read() == NOERR) m.set(F_CAMBIO, cam.get("R10")); // se la lettura riesce il valore del cambio viene posto nel campo CAMBIO della maschera } } } return TRUE; } bool TCondizioni_vendita::handle_valfin(TMask_field &fld, KEY k) { if (k==K_TAB) { if (fld.get().not_empty()) { TMask &m= fld.mask(); // prende la maschera principale if (m.get(F_VALIN).not_empty()) { TDate valfin(fld.get()); // prende la data di fine validitā TDate valin(m.get(F_VALIN)); // prende la data di inizio validitā if (valfinlfile(); // prende il file principale della relazione if (_condven != "C") f.zero("TIPOCF"); // se non si sta lavorando sui contratti il campo TIPOCF deve essere svuotato sul file _rel->write(); // invoca la scrittura della relazione return (_rel->status()); // ritorna lo stato della relazione } int TCondizioni_vendita::rewrite(const TMask &m) { m.autosave(*_rel); // scrive il contenuto della maschera nel record della relazione TLocalisamfile &f= _rel->lfile(); // prende il file principale della relazione if (_condven != "C") f.zero("TIPOCF"); // se non si sta lavorando sui contratti il campo TIPOCF deve essere svuotato sul file _rel->rewrite(); // invoca la riscrittura della relazione return (_rel->status()); // ritorna lo stato della relazione } bool TCondizioni_vendita::remove() { TLocalisamfile &condv= _rel->lfile(); // prende il file della testata dalla relazione principale TLocalisamfile rcondv(LF_RCONDV); // apre il file delle righe per ottenenre il record corrente TRectype delrec(rcondv.curr()); // istanzia il record basato sul file delle righe, da usare come campione delrec.zero(); // svuota il record campione delrec.put(RCONDV_TIPO, _condven); // setta il tipo di archivio delrec.put(RCONDV_COD, condv.get("COD")); // setta il codice della testata if ((_condven=="L") && _codlis_catven) delrec.put(RCONDV_CATVEN, condv.get(CONDV_CATVEN)); // setta la categoria di vendita se č abilitata e siamo nei listini if (_condven=="C") { delrec.put(RCONDV_TIPOCF, condv.get(CONDV_TIPOCF)); // setta i dati del cliente/fornitore se siamo nei contratti delrec.put(RCONDV_CODCF, condv.get(CONDV_CODCF)); } TRelation delrel(LF_RCONDV); // istanzia una relazione sulle righe TCursor delcur(&delrel, "", 1, &delrec, &delrec); // istanzia il cursore di cancellazione sulla relazione delle righe long n= delcur.items(); // legge il numero di elementi del cursore delcur.freeze(); // congela il cursore al suo stato attuale bool proceed= FALSE; // istanzia il booleano di conferma alla cancellazione if (n==1) proceed = yesno_box("Esiste una riga collegata a questa testata: verrā anch'essa cancellata. Procedo?"); // viene richiesta conferma alla cancellazione della riga... if (n>1) proceed = yesno_box("Esistono %ld righe collegate a questa testata: verranno anch'esse cancellate. Procedo?", n); // ...o delle righe if (proceed) { // se si conferma le righe vengono cancellate TLocalisamfile &delfile= delcur.file(); // prende riferimento al file delle righe dal cursore for (delcur=0; delcur.pos()curr(); const int nfields = rec.items(); for (int i = 0; i < nfields; i++) { const char* field_name = rec.fieldname(i); ini.set(field_name, rec.get(field_name)); } } } bool TCondizioni_vendita::handle_copy(TMask_field &b, KEY k) { if (k==K_SPACE) { TMask& msk = b.mask(); //maschera principale TMask_copy m(msk, app().codlis_catven()); // gli passo la maschera del bottone copia (cioé la maschera principale ve2200x) if (m.run()==K_ENTER) { TRelation rel(LF_RCONDV); // creo un relazione sul file delle righe delle condizioni di vendita TRectype& rec = rel.curr(); // creo il record che usa nel filtro; case in base al tipo documentovendita rec.put("TIPO",m.get(F_TIPO)); rel.add(LF_ANAMAG, "CODART==CODRIGA"); TString16 newcode; //var stringa in cui mettere il nuovo codice del listino/contratto/offerta const bool overwrite = m.get_bool(F_OVERWRITE); //deve sovrascrivere le righe doc gia' esistenti? const TString & source = m.get(F_PERC); const bool multiply = source.full(); TExpression e(source); TArray v; const char tipo = m.get(F_TIPO)[0]; for (int i = 0; i < e.numvar(); i ++) { const TString name(e.varname(i)); v.add(new TFieldref(name, 0)); } switch(tipo) { case 'L': rec.put(RCONDV_CATVEN,m.get(F_L_CATVEN)); rec.put(RCONDV_COD,m.get(F_L_COD)); newcode = msk.get(F_L_COD); break; case 'C': rec.put(RCONDV_TIPOCF,m.get(F_C_TIPOCF)); rec.put(RCONDV_CODCF,m.get(F_C_CODCF)); rec.put(RCONDV_COD,m.get(F_C_COD)); newcode = msk.get(F_C_COD); break; case 'O': rec.put(RCONDV_COD,m.get(F_O_COD)); newcode = msk.get(F_O_COD); break; default: break; } if(tipo == 'L' && m.get(F_L_COD).blank()) //genera listino da umart { TRelation rel_umart(LF_UMART); //relazione su umart da cui prendo codici e prezzi TRectype& rec_umart = rel_umart.curr(); TString filtro; const bool gestum = msk.get_bool(F_GESTUM); const bool gestscagl = msk.get_bool(F_GESTSCAGL); rel_umart.add(LF_ANAMAG, "CODART==CODART"); if (!gestum) filtro = "NRIGA==1"; TRectype from(LF_UMART); TRectype to(LF_UMART); const TString & codf = m.get(F_FROMCOD); if (codf.full()) from.put(UMART_CODART, codf); const TString & codt = m.get(F_TOCOD); if (codt.full()) to.put(UMART_CODART, codt); TCursor curs(&rel_umart, filtro, 1, from.empty() ? NULL : &from, to.empty() ? NULL : &to); const long items = curs.items(); // metto in items il numero di elementi del cursore TProgind bar(items,"Scansione articoli", FALSE, TRUE); //barra di avanzamento curs.freeze(); for (curs = 0; curs.pos() < items; ++curs) { bar.addstatus(1); //riempie le righe del nuovo listino generato da umart rec.put(RCONDV_TIPO, 'L'); rec.put(RCONDV_CATVEN, msk.get(F_L_CATVEN)); rec.put(RCONDV_COD, newcode); rec.put(RCONDV_TIPORIGA, 'A'); rec.put(RCONDV_CODRIGA, rec_umart.get(UMART_CODART)); if (gestum) rec.put(RCONDV_UM, rec_umart.get(UMART_UM)); else rec.zero(RCONDV_UM); if (gestscagl) rec.put(RCONDV_NSCAGL, 1); else rec.zero(RCONDV_NSCAGL); real prezzo = rec_umart.get_real(UMART_PREZZO); if (multiply) { FOR_EACH_ARRAY_ITEM(v, j, obj) { const TFieldref * f = (const TFieldref *) obj; e.setvar(j, f->read(rel_umart)); } prezzo *= (CENTO + e.as_real()) / CENTO; } rec.put(RCONDV_PREZZO, prezzo); int err = rel.write(); if (err == _isreinsert && overwrite) rel.rewrite(); } } else { TRectype from(rec); TRectype to(rec); const TString & codf = m.get(F_FROMCOD); if (codf.full()) { from.put(RCONDV_TIPORIGA, "A"); from.put(RCONDV_CODRIGA, codf); } const TString & codt = m.get(F_TOCOD); if (codt.full()) { to.put(RCONDV_TIPORIGA, "A"); to.put(RCONDV_CODRIGA, codt); } TCursor curs(&rel,"",1, &from, &to); //creo anche il cursore della relazione, con chiave 1(codice) e record iniz. e fin. uguali nel filtro const long items = curs.items(); // metto in items il numero di elementi del cursore curs.freeze(); TProgind bar(items,"Scansione righe di origine", FALSE, TRUE); //barra di avanzamento for (curs=0; curs.pos() < items; ++curs) { real prezzo = rec.get_real(RCONDV_PREZZO); if (multiply) { FOR_EACH_ARRAY_ITEM(v, j, obj) { const TFieldref * f = (const TFieldref *) obj; e.setvar(j, f->read(rel)); } prezzo *= (CENTO + e.as_real()) / CENTO; } bar.addstatus(1); rec.put(RCONDV_COD, newcode); rec.put(RCONDV_PREZZO, prezzo); int err = rel.write(); if (err == _isreinsert && overwrite) rel.rewrite(); } } } } return true; } int ve2200(int argc, char* argv[]) { TCondizioni_vendita a; a.run(argc, argv, "Condizioni di vendita"); return 0; }