#include #include #include #include #include "velib.h" #include "ve2300.h" #include "veconf.h" #define MAX_REAL "9999999999.99999" //mmmhh.. 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_show(TMask & m, short id, int key = 1) { ((TEditable_field &)m.field(id)).set_key(key); m.show(id); } static void key_disable(TMask & m, short id, int key = 1) { ((TEditable_field &)m.field(id)).reset_key(key); m.disable(id); } static void key_enable(TMask & m, short id, int key = 1) { ((TEditable_field &)m.field(id)).set_key(key); m.enable(id); } class TRighe_condizioni_vendita: public TRelation_application { TMask *_msk; // maschera principale TRelation *_rel; // relazione principale TString16 _rcondven; // stringa che indica il tipo di archivio bool _codlis_catven; // booleano di abilitazione del campo CATVEN bool _codcon_codcf; // booleano di abilitazioni dei campi TIPOCF e CODCF bool _um; // booleano di abilitazione locale delle unità di misura bool _gest_um, _gest_sca, _gest_so; // variabili di abilitazione deunità di misura, scaglioni e sconti/omaggi TString16 _codval; // valuta del listino virtual bool user_create(); virtual bool user_destroy(); virtual TMask *get_mask(int) { return _msk; } // punto d'aggancio tra la maschera della rel.app. e la maschera principale dell'applicazione virtual bool changing_mask(int) { return FALSE; } // ritorna il flag di cambio maschera a seconda dei modi di funzionamento, in questa applicazione la maschera è una sola quindi il flag è FALSE virtual bool changing_keys() const { return TRUE; } // ritorna il flag di rigenerazione della lista delle chiavi ad ogni find(), in questa applicazione le chiavi cambiano continuamente quindi il flag è TRUE virtual TRelation *get_relation() const { return _rel; } // punto d'aggancio tra la relazione della rel.app. e la relazione principale dell'applicazione static void hide_and_show_codriga(void); // procedura di abilitazione/disabilitazione dei tre campi CODRIGA (codice riga) static bool handle_tiporiga(TMask_field &, KEY); // handler del campo TIPORIGA (articolo, gruppo merc., ragg. fiscale) static bool handle_cod(TMask_field &, KEY); // handler del campo COD (codice listino, numero contratto, codice offerta) static bool handle_price(TMask_field &, KEY); // handler del prezzo netto e lordo static bool handle_qta(TMask_field &, KEY); // handler della quantita' limite per scaglione static bool handle_sca(TMask_field &, KEY); // handler dello scaglione static void fill_rec(TRectype& r, TMask& m); static real find_prev_qta(TRectype& r); static real find_next_qta(TRectype& r); static const char* look_codiva(char tipo, TString& cod); 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 rimuovere il record sul file void renumber_sca(const TRectype& r); //metodo per rinumerare gli scaglioni public: TRighe_condizioni_vendita() {} virtual ~TRighe_condizioni_vendita() {} }; TRighe_condizioni_vendita &app() { // funzione che ritorna il riferimento alla classe principale dell'applicazione return (TRighe_condizioni_vendita &)main_app(); } bool TRighe_condizioni_vendita::user_create() { bool gotcha= FALSE; // booleano di avvenuta inizializzazione _rcondven= "*"; // inizializzazione dell'indicatore del tipo di archivio if (argc() > 2) { TFilename trans = argv(2); if (trans.len() == 1) _rcondven = trans; else { trans.ltrim(2); if (trans.exist()) { TConfig ini(trans, "53"); _rcondven = ini.get("TIPO"); } } } if (_rcondven == "*") { TMask choose("VE2300"); // istanzia la maschera di scelta del tipo di archivio if (choose.run() == K_ENTER) _rcondven= choose.get(F_TIPORCV); // prende il tipo di archivio dalla maschera } _rcondven.upper(); // rende la stringa upper-case _msk= new TMask("ve2300x"); TConfig prassid(CONFIG_DITTA, "ve"); // apre il file di configurazione della ditta corrente switch (_rcondven[0]) { case 'L': // listini _msk->set_caption("Righe listini"); key_hide(*_msk, F_R_C_TIPOCF); // settaggio dei campi da eliminare... { TList_field& l = (TList_field&)_msk->field(F_R_C_TIPOCF); l.replace_items(" | "," | "); } key_hide(*_msk, F_R_C_CODCF); key_hide(*_msk, F_R_C_COD); _msk->efield(F_R_C_COD).check_type(CHECK_NONE); key_hide(*_msk, F_R_O_COD); _msk->efield(F_R_O_COD).check_type(CHECK_NONE); _msk->hide(F_R_C_DESCF); _msk->hide(F_R_C_DES); _msk->hide(F_R_O_DES); _msk->hide(F_R_C_RICERCA); _msk->hide(F_R_O_RICERCA); // _msk->hide(F_R_CO_CODLOTTO); _msk->hide(F_R_O_ARTES); _codlis_catven= prassid.get_bool("GESLISCV"); // setta il booleano di abilitazione di CATVEN if (!_codlis_catven) key_disable(*_msk, F_R_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 set_search_field(F_R_L_RICERCA); // impostazione del campo di ricerca _msk->set_handler(F_R_L_COD, handle_cod); // impostazione dell'handler sul campo di controllo della testata gotcha= TRUE; break; case 'C': // contratti _msk->set_caption("Righe contratti"); key_hide(*_msk, F_R_L_CATVEN); // settaggio dei campi da eliminare... key_hide(*_msk, F_R_L_COD); _msk->efield(F_R_L_COD).check_type(CHECK_NONE); key_hide(*_msk, F_R_O_COD); _msk->efield(F_R_O_COD).check_type(CHECK_NONE); _msk->hide(F_R_L_DESVEN); _msk->hide(F_R_L_DES); _msk->hide(F_R_O_DES); _msk->hide(F_R_L_RICERCA); _msk->hide(F_R_O_RICERCA); _msk->hide(F_R_O_ARTES); _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_R_C_TIPOCF); TList_field& l = (TList_field&)_msk->field(F_R_C_TIPOCF); l.replace_items(" | "," | "); key_disable(*_msk, F_R_C_CODCF); } _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 set_search_field(F_R_C_RICERCA); // impostazione del campo di ricerca _msk->set_handler(F_R_C_COD, handle_cod); // impostazione dell'handler sul campo di controllo della testata gotcha= TRUE; break; case 'O': // offerte _msk->set_caption("Righe offerte"); key_hide(*_msk, F_R_L_CATVEN); // settaggio dei campi da eliminare... key_hide(*_msk, F_R_C_TIPOCF); { TList_field& l = (TList_field&)_msk->field(F_R_C_TIPOCF); l.replace_items(" | "," | "); } key_hide(*_msk, F_R_C_CODCF); key_hide(*_msk, F_R_L_COD); _msk->efield(F_R_L_COD).check_type(CHECK_NONE); key_hide(*_msk, F_R_C_COD); _msk->efield(F_R_C_COD).check_type(CHECK_NONE); _msk->hide(F_R_C_DESCF); _msk->hide(F_R_L_DESVEN); _msk->hide(F_R_L_DES); _msk->hide(F_R_C_DES); _msk->hide(F_R_L_RICERCA); _msk->hide(F_R_C_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 set_search_field(F_R_O_RICERCA); // impostazione del campo di ricerca _msk->set_handler(F_R_O_COD, handle_cod); // impostazione dell'handler sul campo di controllo della testata gotcha= TRUE; 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_RCONDV); // apre la relazione (un unico file) _msk->set(F_R_TIPO, _rcondven); // settaggio del campo di tipo archivio _msk->set_handler(F_R_TIPORIGA, handle_tiporiga); // impostazione dell'handler sul campo di selezione del tipo della riga _msk->set_handler(F_R_PREZZO, handle_price); // setta l'handler per calcolare il prezzo lordo dal prezzo netto _msk->set_handler(F_R_PREZZO_LORDO, handle_price); // setta l'handler per calcolare il prezzo netto dal prezzo lordo if (_gest_sca) { _msk->set_handler(F_R_QLIM, handle_qta); // setta l'handler per controllare la quantita' limite _msk->set_handler(F_R_NSCAGL, handle_sca); // setta l'handler per controllare la sequenza degli scaglioni } _um= _gest_um; // abilita le unità di misura in base alla configurazione hide_and_show_codriga(); // invoca la procedura di controllo della mutua esclusione dei tre campi CODRIGA } return (gotcha); } bool TRighe_condizioni_vendita::user_destroy() { delete _rel; delete _msk; return TRUE; } void TRighe_condizioni_vendita::hide_and_show_codriga() { TMask *_msk= app()._msk; // prende il puntatore alla maschera principale dell'applicazione if (_msk->query_mode()) { // se la maschera è in modo query procede con i controlli... short id_campi_1[4]= { F_R_CODRIGA_A, F_R_CODRIGA_G, F_R_CODRIGA_S, F_R_CODRIGA_R }; // vettore degli identificatori dei tre campi CODRIGA in mutua esclusione short id_campi_2[4]= { F_R_DESRIGA_A, F_R_DESRIGA_G, F_R_DESRIGA_S, F_R_DESRIGA_R }; // vettore degli identificatori dei tre campi CODRIGA in mutua esclusione char tag_campi[4]= { 'A', 'G', 'S', 'R' }; // vettore dei tag di TIPORIGA per i tre campi CODRIGA in mutua esclusione bool &_um= app()._um; // prende il riferimento al booleano di abilitazione locale delle unità di misura TString &_rcondven= app()._rcondven; // prende il riferimento alla stringa di tipo di archivio char tag_campo= toupper(_msk->get(F_R_TIPORIGA)[0]); // prende il tag del campo da abilitare in TIPORIGA for (int i=0; i<4; i++) { // ciclo sui quattro campi CODRIGA if (tag_campo == tag_campi[i]) { // il campo indicato con il tag viene reso visibile key_show(*_msk, id_campi_1[i]); _msk->show(id_campi_2[i]); } else { // i campi non corrispondenti al tag vengono resi invisibili key_hide(*_msk, id_campi_1[i]); _msk->hide(id_campi_2[i]); } } if (_um && (tag_campo=='A')) { key_enable(*_msk, F_R_UM); } // se la gest. delle u.m. è abilitata, il campo viene attivato se la riga è un articolo... else { key_disable(*_msk, F_R_UM); } // ...altrimenti viene disattivato } } bool TRighe_condizioni_vendita::handle_tiporiga(TMask_field &fld, KEY k) { if (k==K_SPACE) hide_and_show_codriga(); // invoca la procedura di controllo della mutua esclusione dei tre campi CODRIGA return TRUE; } bool TRighe_condizioni_vendita::handle_cod(TMask_field &fld, KEY k) { if ((k==K_TAB) && fld.get().not_empty()) { bool &_gest_um= app()._gest_um; // prende il riferimento al booleano di abilitazione delle unità di misura bool &_gest_so= app()._gest_so; // prende il riferimento al booleano di abilitazione degli sconti/omaggi bool &_gest_sca= app()._gest_sca; // prende il riferimento al booleano di abilitazione degli scaglioni bool &_um= app()._um; // prende il riferimento al booleano di abilitazione locale delle unità di misura TString &_rcondven= app()._rcondven; // prende il riferimento alla stringa di indicazione del tipo di archivio TMask *_msk= app()._msk; // prende il puntatore alla maschera principale dell'applicazione TLocalisamfile condv(LF_CONDV); // apre il file della testata (condizioni di vendita) condv.put("TIPO", _rcondven); // riempie il campo "TIPO" switch (_rcondven[0]) { case 'L': // riempie il resto della chiave dei listini condv.put("CATVEN", _msk->get(F_R_L_CATVEN)); condv.put("COD", _msk->get(F_R_L_COD)); break; case 'C': // riempie il resto della chiave dei contratti condv.put("TIPOCF", _msk->get(F_R_C_TIPOCF)); condv.put("CODCF", _msk->get(F_R_C_CODCF)); condv.put("COD", _msk->get(F_R_C_COD)); break; case 'O': // riempie il resto della chiave delle offerte condv.put("COD", _msk->get(F_R_O_COD)); break; } if (condv.read()==NOERR) { // se la lettura è andata a buon fine abilita/disabilita i campi della maschera in base ai booleani della testata TString valuta(condv.get("CODVAL")); TString seqric(condv.get("SEQRIC")); TToken_string codes, values; const bool imp_lordi = condv.get_bool("IMPLORDI"); app()._codval = valuta; if (_gest_um) _um= condv.get_bool("GESTUM"); // legge lo stato di abilitazione della gestione delle unità di misura _gest_sca &= condv.get_bool("GESTSCAGL"); hide_and_show_codriga(); // lancia la funzione che si occupa di abilitare/disabilitare il campo "unità di misura" if (_gest_sca) { if (_msk->query_mode()) key_enable(*_msk, F_R_NSCAGL); // abilita il campo "numero scaglione" _msk->enable(F_R_QLIM); // abilita il campo "quantità limite scaglione" ((TReal_field&)_msk->field(F_R_QLIM)).set_decimals(condv.get_int("DECIMALI")); // E ne setta il numero di decimals } else { if (_msk->query_mode()) key_disable(*_msk, F_R_NSCAGL); // disabilita il campo "numero scaglione" _msk->disable(F_R_QLIM); // disabilita il campo "quantità limite scaglione" } const bool enable_gift = _gest_so && condv.get_bool("GESTSCO"); _msk->enable(-1,enable_gift); // abilita il gruppo di campi relativi all'omaggio _msk->enable(F_R_UMOM, enable_gift); // abilita il campo "unità di misura art. omaggio" const int mode = _msk->mode(); if (mode == MODE_QUERY || mode == MODE_QUERYINS) // Sostituisce il listbox solo in ricerca... { for (int i = 0; i < 4; i++) switch (seqric[i]) { case 'A' : codes.add("A"); values.add("Articolo"); break; case 'G' : codes.add("G"); values.add("Gruppo merc."); break; case 'S' : codes.add("S"); values.add("Sottogr. merc."); break; case 'R' : codes.add("R"); values.add("Ragg. fiscale"); break; default : break; } TList_field& tiporiga = (TList_field&) _msk->field(F_R_TIPORIGA); tiporiga.replace_items(codes,values); // Sostituisce gli items del list box del tipo riga in base a cio' che e' abilitato in testata } return TRUE; } else { error_box("Non esiste una testata corrispondente alla chiave specificata"); return FALSE; } } else return TRUE; } bool TRighe_condizioni_vendita::handle_price(TMask_field &f, KEY k) { if (f.to_check(k,TRUE)) { TMask& m = f.mask(); TString codiva; TString cod(m.get(F_R_CODRIGA_A)); real netto = 0.0; real lordo = 0.0; const char tiporiga = m.get(F_R_TIPORIGA)[0]; codiva = look_codiva(tiporiga, cod); TCodiceIVA iva(codiva); if (f.dlg() == F_R_PREZZO) { netto = real(m.get(F_R_PREZZO)); lordo = iva.lordo(netto, AUTO_PRICES_DECIMALS, app()._codval); m.set(F_R_PREZZO_LORDO,lordo.string()); } else { lordo = real(m.get(F_R_PREZZO_LORDO)); real prec_lordo = lordo; const real imposta = iva.scorpora(lordo, AUTO_PRICES_DECIMALS, app()._codval); netto = lordo; lordo += imposta; if (lordo != prec_lordo) { warning_box("Scorporando l'iva dal prezzo lordo si e' dovuto\n" "correggere quest'ultimo a causa di arrotondamenti."); m.set(F_R_PREZZO_LORDO,lordo.string()); } m.set(F_R_PREZZO,netto.string()); } } return TRUE; } void TRighe_condizioni_vendita::fill_rec(TRectype &r, TMask& m) { const char c = app()._rcondven[0]; short id = (c == 'C' ? F_R_C_COD : (c == 'L' ? F_R_L_COD : F_R_O_COD)); TString16 tipo(m.get(F_R_TIPO)); TString16 catven(m.get(F_R_L_CATVEN)); TString16 tipocf(m.get(F_R_C_TIPOCF)); TString16 codcf(m.get(F_R_C_CODCF)); // sulla maschera e' una stringa TString16 cod(m.get(id)); TString16 tiporiga(m.get(F_R_TIPORIGA)); TString codriga(m.get(F_R_CODRIGA_A)); TString16 um(m.get(F_R_UM)); int sca = m.get_int(F_R_NSCAGL); r.put("TIPO",tipo);r.put("CATVEN",catven);r.put("TIPOCF",tipocf); r.put("CODCF",codcf);r.put("COD",cod);r.put("TIPORIGA",tiporiga); r.put("CODRIGA",codriga);r.put("UM",um);r.put("NSCAGL",sca); } bool TRighe_condizioni_vendita::handle_qta(TMask_field &f, KEY k) { if (f.to_check(k)) { TMask& m = f.mask(); real qta_prev,qta_next; real current_qta(f.get()); TRectype r1(LF_RCONDV); fill_rec(r1,m); TRectype r2(r1); qta_prev = find_prev_qta(r1); qta_next = find_next_qta(r2); int sca = m.get_int(F_R_NSCAGL); if (sca == 1 && current_qta == 0.0) { f.error_box("La quantita' limite deve essere maggiore di 0"); return FALSE; } if (sca == 9 && current_qta == 0.0) return TRUE; if (qta_next <= current_qta) { f.error_box("La quantita' limite deve essere minore di %s.", (const char*)qta_next.string()); return FALSE; } if (qta_prev >= current_qta) { f.error_box("La quantita' limite deve maggiore di %s.", (const char*)qta_prev.string()); return FALSE; } } return TRUE; } bool TRighe_condizioni_vendita::handle_sca(TMask_field &f, KEY k) { if (f.to_check(k)) { TMask& m = f.mask(); int sca = atoi(f.get()); if (sca == 1) return TRUE; TRectype r(LF_RCONDV); fill_rec(r, m); TLocalisamfile cond(LF_RCONDV); cond.curr() = r; cond.read(); if (cond.bad()) // se non l'ha trovato significa che e' in inserimento { sca--; r.put("NSCAGL",sca); //cerca quello precedente... if (cond.read(r) != NOERR) // se non lo trova segnala l'errore di errata sequenza { f.error_box("Il numero di scaglione immesso non e' in sequenza."); return FALSE; } } } return TRUE; } const char* TRighe_condizioni_vendita::look_codiva(char tipo, TString& cod) { switch (tipo) { case 'A': { TLocalisamfile anamag(LF_ANAMAG); anamag.put("CODART",cod); if (anamag.read() == NOERR) return anamag.get("CODIVA"); break; } case 'G': case 'S': { TTable gmc("GMC"); gmc.put("CODTAB",cod); if (gmc.read() == NOERR) return gmc.get("S7"); break; } case 'R': { TTable rfa("RFA"); rfa.put("CODTAB",cod); if (rfa.read() == NOERR) return rfa.get("S9"); } default : break; } return ""; } real TRighe_condizioni_vendita::find_prev_qta(TRectype& r) { TLocalisamfile f(LF_RCONDV); real qta = 0.0; f.curr() = r; int nscagl = r.get_int("NSCAGL"); f.put("NSCAGL", nscagl-1); if (f.read() == NOERR) qta = f.get_real("QLIM"); return qta; } real TRighe_condizioni_vendita::find_next_qta(TRectype& r) { TLocalisamfile f(LF_RCONDV); real qta(MAX_REAL); f.curr() = r; int nscagl = r.get_int("NSCAGL"); f.put("NSCAGL", nscagl+1); if (f.read() == NOERR) qta = f.get_real("QLIM"); return qta; } int TRighe_condizioni_vendita::write(const TMask &m) { m.autosave(*_rel); // scrive il contenuto della maschera nel record della relazione if (_rcondven != "C") { // se non si sta lavorando sui contratti il campo TIPOCF deve essere svuotato sul file TLocalisamfile &f= _rel->lfile(); // prende il file principale della relazione f.zero("TIPOCF"); // svuota il campo TIPOCF } _rel->write(); // invoca la scrittura della relazione return (_rel->status()); // ritorna lo stato della relazione } int TRighe_condizioni_vendita::rewrite(const TMask &m) { m.autosave(*_rel); // scrive il contenuto della maschera nel record della relazione if (_rcondven != "C") { // se non si sta lavorando sui contratti il campo TIPOCF deve essere svuotato sul file TLocalisamfile &f= _rel->lfile(); // prende il file principale della relazione f.zero("TIPOCF"); // svuota il campo TIPOCF } _rel->rewrite(); // invoca la riscrittura della relazione return (_rel->status()); // ritorna lo stato della relazione } void TRighe_condizioni_vendita::renumber_sca(const TRectype& r) { TRectype from(r); from.zero("NSCAGL"); TRecord_array rec_arr(from,"NSCAGL"); if (rec_arr.read(from) == NOERR) { rec_arr.pack(); rec_arr.rewrite(); } } bool TRighe_condizioni_vendita::remove() { TRectype r(LF_RCONDV); fill_rec(r,*_msk); const bool rt = TRelation_application::remove(); if (_gest_sca) // rinumera gli scaglioni renumber_sca(r); return rt; } int ve2300(int argc, char* argv[]) { TRighe_condizioni_vendita a; a.run(argc, argv, "Righe condizioni vendita "); return 0; }