#include #include #include #include #include #include #include #include #include #include #include "../mg/anamag.h" #include "../mg/umart.h" #include "condv.h" #include "rcondv.h" #include "ve2.h" #include "ve2700.h" /////////////////////////////////////////////////////////////////////////////// // MASCHERA DI EDIT (aggiorna i listini figghi 'u patre!) /////////////////////////////////////////////////////////////////////////////// class TAggiorna_listini_edit_mask : public TAutomask { TMask* _query_mask; //puntatore alla maschera di query TString8 _curr_grmerc; //iniziale grmerc-sotgrmerc bool _ges_um; //gestione unità di misura del listino padre bool _ask_save; //chiede di salvare al cambio grmerc se effettuati cambiamenti nello sheet protected: //Metodi dello sheet listini figli void fill_children_list(); //riempie lo sheet dei listini figli (costruttore) void fill_ricarichi_children_list(); //aggiunge il ricarico nello sheet dei listini figli (on_field) void save_children_list(); //salva i ricarichi (modificabili) dello sheet dei figli (on_field) //Metodi dello sheet aggiornamento multilistini void set_header_multilistini_sheet(); //compila le intestazioni delle colonne dello sheet multilistino (costruttore) int crea_famiglia_listini(TToken_string& keys_listini) const; //crea la famiglia padre+figli void fill_multilistini_sheet(); //riempie lo sheet multilistino (on_field) void update_sons_prices(); //aggiorna i prezzi dei listini figli (on_field) int find_codart(TSheet_field& sf, const TString& codart, const TString& um) const; //cerca l'articolo (on_field) int find_or_add_codart(TSheet_field& sf, const TString& codart, const TString& um); //cerca l'articolo nello sheet e lo aggiunge se non c'è (on_field) bool one_checked() const; //controlla se nella colonna dei check ce ne è almeno 1 checkato (on_field) void check_all(const bool checked); //checka-dechecka la colonna dei check (on_field) void add_art(); //aggiunge un articolo ai listini (on_field) void kill_priceless_articles(const TString& catven, const TString& codlist, int pos); void save_listini(); //salva tutte le righe listini (padre e figli) così come sono sullo sheet (on_field) real get_price(TSheet_field& sf, const int row, const short dlg_id) const; real get_price(TMask_field& fld) const; void set_price(TSheet_field& sf, const int row, const short dlg_id, real& price); void set_price(TMask_field& fld, real& price); bool arrotonda(const short dlg_id, real& price); void get_correct_grmerc(TString& grmerc, const bool asterisk) const; virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TAggiorna_listini_edit_mask(TMask* query_mask); }; //METODI ON_FIELD //--------------- // metodi per F_LISTINI_FIGLI //metodo per riempire lo sheet dei listini figli con i ricarichi oggi tanto di moda void TAggiorna_listini_edit_mask::fill_ricarichi_children_list() { get_correct_grmerc(_curr_grmerc, false); const TRectype& rec_gmc = cache().get("GMC", _curr_grmerc); TToken_string lista_listini(rec_gmc.get("S1"), ';'); //se trova qualcosa nella lista listini collegati al grmerc... if (lista_listini.full()) { lista_listini.trim(); //se la lista di listini riempie il campo S1, magari continua in S2... if (lista_listini.len() == 70) { lista_listini.add(rec_gmc.get("S2")); lista_listini.trim(); } //cerca se i listini trovati in GMC ci sono anche nello sheet dei figli TSheet_field& sf_righe = sfield(F_LISTINI_FIGLI); const int righe_sheet = sf_righe.items(); FOR_EACH_STR_TOKEN(lista_listini, str) { //controlla se il listino in grmerc (chiave) esiste in una delle righe dello sheet dei figli TToken_string chiave(str, SAFE_PIPE_CHR); TString4 catven = chiave.get(0); catven.trim(); TString4 codlis = chiave.get(1); codlis.trim(); FOR_EACH_SHEET_ROW(sf_righe, i, row) { TString4 sh_catven = row->get(0); sh_catven.trim(); TString4 sh_codlis = row->get(1); sh_codlis.trim(); //se incredibilmente trova il listino di grmerc tra i figli prigionieri nello sheet setta il ricarico if (catven == sh_catven && codlis == sh_codlis) row->add(chiave.get(2), 2); } //FOR_EACH_SHEETT_ROW(... } //FOR_EACH_STR_TOKEN sf_righe.force_update(); } //if(lista_listini.full... } //metodo per il salvataggio dei ricarichi sulla tabella GMC dei gruppi merceologici void TAggiorna_listini_edit_mask::save_children_list() { TString8 grmerc; get_correct_grmerc(grmerc, false); if (grmerc.full()) { //cerca sulla tabella GMC il record corrispondente all'attuale GMC TTable tab_gmc("GMC"); tab_gmc.put("CODTAB", grmerc); int err = tab_gmc.read(); if (err == NOERR) { //prende S1 e, se pieno, anche S2 TToken_string stringona(140, ';'); TString s = tab_gmc.get("S1"); if (s.full()) { stringona.add(s); s = tab_gmc.get("S2"); if (s.full()) stringona.add(s); } //mette tutte le token_stringhine catven|codlis|ricarico in uno string_array, in modo da tener traccia.. //..della loro posizione (ogni elemento dello string_array è una token_stringhina) TString_array ricarichi; FOR_EACH_STR_TOKEN(stringona, str) ricarichi.add(str); //giro su tutti gli elementi dell'array FOR_EACH_ARRAY_ROW(ricarichi, i, row) { TToken_string chiave(*row, SAFE_PIPE_CHR); //separatore broken_pipe TString4 catven = chiave.get(0); catven.trim(); TString4 codlis = chiave.get(1); codlis.trim(); //giro sulle righe dello sheet listini figli TSheet_field& sf_righe = sfield(F_LISTINI_FIGLI); FOR_EACH_SHEET_ROW_BACK(sf_righe, r, riga) { TString4 sh_catven = riga->get(0); sh_catven.trim(); TString4 sh_codlis = riga->get(1); sh_codlis.trim(); //se incredibilmente trova il listino dell'array tra i figli prigionieri nello sheet.. if (catven == sh_catven && codlis == sh_codlis) { const TString& ricarico = riga->get(2); chiave.add(ricarico, 2); //setta il ricarico nella cella dello sheet ricarichi.add(chiave, i); //lo aggiunge all'array dei ricarichi //salva il valore dell'arrotondamento sulla testata del listino corrente dello sheet TLocalisamfile condv(LF_CONDV); condv.put(CONDV_TIPO, 'L'); condv.put(CONDV_CATVEN, sh_catven); condv.put(CONDV_TIPOCF, ""); condv.put(CONDV_CODCF, ""); condv.put(CONDV_COD, sh_codlis); int err = condv.read(); if (err == NOERR) { condv.put(CONDV_ARROTONDA, riga->get(3)); condv.rewrite(); } break; //esce perchè non può fare altro } } //FOR_EACH_SHEET_ROW_BACK... } //FOR_EACH_ARRAY_ROW //adesso deve tornare a scrivere le nuove S1 ed S2 modificate TToken_string s1(70, ';'), s2(70, ';'); FOR_EACH_ARRAY_ROW (ricarichi, r, riga) { TToken_string mini_string(*riga, SAFE_PIPE_CHR); //separatore broken_pipe !!! if (s1.len() + mini_string.len() < 70) s1.add(mini_string); else { if (s2.len() + mini_string.len() < 70) s2.add(mini_string); } } //FOR_EACH_ARRAY_ROW.. //finalmente scrive sulla tabella GMC tab_gmc.put("S1", s1); tab_gmc.put("S2", s2); tab_gmc.rewrite(); } //if(err==NOERR) } //if(grmerc.full()) } //metodi F_MULTILISTINI real TAggiorna_listini_edit_mask::get_price(TMask_field& fld) const { TString16 str_prezzo = fld.get(); if (fld.dlg() == S2_PREZZO) { str_prezzo.strip("."); str_prezzo.replace(',', '.'); } return real(str_prezzo); } //prende il prezzo del padre e sostituisce i '.' con le ',' real TAggiorna_listini_edit_mask::get_price(TSheet_field& sf, const int row, const short dlg_id) const { const int col = sf.cid2index(dlg_id); TString16 str_prezzo = sf.cell(row, col); if (dlg_id == S2_PREZZO) { str_prezzo.strip("."); str_prezzo.replace(',', '.'); } return real(str_prezzo); } bool TAggiorna_listini_edit_mask::arrotonda(const short dlg_id, real& price) { TString str_arr; const bool is_father_list = dlg_id == S2_PREZZO; if (is_father_list) { str_arr = get(F_ARROTONDA); } else { TSheet_field& figli = sfield(F_LISTINI_FIGLI); str_arr = figli.cell(dlg_id - S2_LIST1, figli.cid2index(S1_ARROTONDA)); } str_arr.replace(',', '.'); const real num_arr = abs(real(str_arr)); if (!num_arr.is_zero()) { price /= num_arr; switch (str_arr[0]) { case '+': price.ceil(); break; case '-': price.floor(); break; default : price.round(); break; } price *= num_arr; } else //se non specificato alcun arrotondamento usa quello standard dei prezzi { const TPrice p(price); price = p.get_num(); } return is_father_list; } void TAggiorna_listini_edit_mask::set_price(TSheet_field& sf, const int row, const short dlg_id, real& price) { const bool is_father_list = arrotonda(dlg_id, price); const int prezzo_pos = sf.cid2index(dlg_id); if (is_father_list) sf.row(row).add(price.stringa(0, TCurrency::get_firm_dec(true)), prezzo_pos); else sf.row(row).add(price.string(), prezzo_pos); } void TAggiorna_listini_edit_mask::set_price(TMask_field& fld, real& price) { const bool is_father_list = arrotonda(fld.dlg(), price); if (is_father_list) fld.set(price.stringa(0, TCurrency::get_firm_dec(true))); else fld.set(price.string()); } //cerca nello sheet la coppia codart+um che gli viene passata restituendo la posizione della riga ALTA.. //della coppia di righe sheet interessate (è la riga disabilitata); int TAggiorna_listini_edit_mask::find_codart(TSheet_field& sf, const TString& codart, const TString& codum) const { //cerca la riga tra quelle esistenti const int codart_pos = sf.cid2index(S2_CODRIGA); const int codum_pos = codart_pos + 1; const int sf_items = sf.items(); for (int i = 1; i < sf_items; i += 2) { const char* art = sf.cell(i, codart_pos); if (codart == art) { if (_ges_um) // Controllo anche l'unita' di misura solo se necessario { TString4 um = sf.cell(i - 1, codum_pos); um.trim(); if (codum != um) continue; } return i - 1; } } return -1; } //cerca nello sheet la coppia codart+um che gli viene passata restituendo la posizione della riga ALTA.. //della coppia di righe sheet interessate (è la riga disabilitata); se non trova la coppia articolo+um .. //..aggiunge la coppia di righe int TAggiorna_listini_edit_mask::find_or_add_codart(TSheet_field& sf, const TString& codart, const TString& codum) { //cerca la riga nello sheet int riga = find_codart(sf, codart, codum); if (riga < 0) { const int codart_pos = sf.cid2index(S2_CODRIGA); const int codum_pos = codart_pos + 1; //non trova la riga nel padre -> la aggiunge TToken_string& row_alta = sf.row(-1); sf.disable_cell(sf.items()-1, -1); const TString& descr = cache().get(LF_ANAMAG, codart, ANAMAG_DESCR); row_alta.add(descr, codart_pos); if (_ges_um) row_alta.add(codum, codum_pos); TToken_string& row_bassa = sf.row(-1); row_bassa.add("X"); row_bassa.add(codart, codart_pos); riga = sf.items() - 2; //ritorna la penultima riga (riga alta) } return riga; } int TAggiorna_listini_edit_mask::crea_famiglia_listini(TToken_string& keys_listini) const { keys_listini.separator(';'); TToken_string key; key.add(get(F_FATHCATVEN)); key.add(get(F_FATHCODLIS)); key.trim(); keys_listini.add(key); TSheet_field& sf_figli = sfield(F_LISTINI_FIGLI); FOR_EACH_SHEET_ROW(sf_figli, r, riga) { key.cut(0); key.add(riga->get(0)); key.add(riga->get(1)); key.trim(); keys_listini.add(key); } return keys_listini.items(); } void TAggiorna_listini_edit_mask::get_correct_grmerc(TString& grmerc, const bool asterisk) const { grmerc.format("%-3s%-2s", (const char*)get(F_GRMERC),(const char*)get(F_SOTGRMERC)); grmerc.trim(); //se il grmerc non è completo (solo il primo carattere), ci vuole una ricerca tipo.. //..jolly; vale anche per il sottogrmerc (non pieno con i 3 caratteri) if (asterisk && grmerc.len() < 5) grmerc << "*"; } //riempie lo sheet dei multilistini void TAggiorna_listini_edit_mask::fill_multilistini_sheet() { //popola il double-deck sheet //cerca tutte le righe che appartengono a padre e figli; se una riga appartiene ad un figlio e non al padre.. //..viene aggiunta al padre medesimo (i padri devono sapere tutto dei figli, sennò che genitori sono?) //se invece la riga appartiene al padre e non a uno o più figli questi ultimi saranno lasciati nella.. //..loro ignoranza di tale riga (un padre qualche vantaggio dovrà pur averlo, no?) TToken_string keys_listini(140, ';'); const int componenti_famiglia = crea_famiglia_listini(keys_listini); TString8 grmerc; get_correct_grmerc(grmerc, false); TString msg; msg << TR("Lettura listini ") << grmerc << "..."; TProgind pi(keys_listini.items(), msg, true, true); TSheet_field& sf_multilistini = sfield(F_MULTILISTINI); sf_multilistini.destroy(); const int prezzo_pos = sf_multilistini.cid2index(S2_PREZZO); TToken_string key; FOR_EACH_TOKEN(keys_listini, tok) { if (!pi.addstatus(1)) break; key = tok; TString query; query << "USE RCONDV\n"; query << "SELECT ANAMAG.GRMERC?=#GRMERC\n"; //occhio al '?' Serve per poter avere ricerche jolly query << "JOIN ANAMAG INTO CODART==CODRIGA\n"; query << "FROM TIPO=L CATVEN=#CATVEN COD=#COD TIPORIGA=A\n"; query << "TO TIPO=L CATVEN=#CATVEN COD=#COD TIPORIGA=A\n"; TISAM_recordset recset_rows(query); TString8 grmerc; get_correct_grmerc(grmerc, true); recset_rows.set_var("#GRMERC", grmerc); recset_rows.set_var("#CATVEN", key.get(0)); recset_rows.set_var("#COD", key.get(1)); const long recset_rows_items = recset_rows.items(); //posizione dell'attuale prezzo const int pos = keys_listini.get_pos(key); //per ogni riga del recordset va ad aggiornare lo sheet sulla maschera (aggiunge la riga) for (bool ok = recset_rows.move_first(); ok; ok = recset_rows.move_next()) { //dati riga corrente const TString& codart = recset_rows.get(RCONDV_CODRIGA).as_string(); const TString& um = recset_rows.get(RCONDV_UM).as_string(); real prezzo = recset_rows.get(RCONDV_PREZZO).as_real(); //cerca se esiste o se deve aggiungerla: la find_cor_add_odart restituisce il numero della riga alta.. //..(descrizione/um) del codart in questione (che starà la riga sotto, ovvero riga_alta+1) const int riga_alta = find_or_add_codart(sf_multilistini, codart, um); const int riga_bassa = riga_alta + 1; //mette il prezzo al posto giusto (padre e figlio) if (pos <= 0) //padre { set_price(sf_multilistini, riga_bassa, S2_PREZZO, prezzo); //il padre viene arrotondato al suo arrotondamento (se c'e') //sf_multilistini.row(riga_bassa).add(prezzo.stringa(), prezzo_pos + pos); } else { //nella riga alta visualizza prezzo originale (no arrotondamento) sf_multilistini.row(riga_alta).add(prezzo.string(), prezzo_pos + pos); set_price(sf_multilistini, riga_bassa, S2_PREZZO + pos, prezzo); real fath_prezzo = get_price(sf_multilistini, riga_bassa, S2_PREZZO); //se il figlio ha un prezzo ma il padre no, ricalcola il valore dell'articolo nel padre usando il ricarico if (fath_prezzo.is_zero()) { TSheet_field& listini_figli = sfield(F_LISTINI_FIGLI); const real ricarico = listini_figli.cell(pos - 1, listini_figli.cid2index(S1_RICARICO)); real prezzo_base(prezzo * CENTO / (CENTO + ricarico)); set_price(sf_multilistini, riga_bassa, S2_PREZZO, prezzo_base); } } } //for(bool ok.. } //FOR_EACH_TOKEN.. //aggiorna i prezzi nuovi dei listini figli update_sons_prices(); } //aggiorna i prezzi dei listini figli void TAggiorna_listini_edit_mask::update_sons_prices() { //per ogni articolo, per ogni listino figlio prende il ricarico nello sheet dei figli e lo moltiplica per il prezzo del padre //PrezzoNuovoFiglio = Ricaricofiglio * PrezzoPadre (questo vale per ogni articolo) TSheet_field& sf_figli = sfield(F_LISTINI_FIGLI); TSheet_field& sf_listini = sfield(F_MULTILISTINI); FOR_EACH_SHEET_ROW(sf_figli, r, riga_figlio) { const real ricarico = riga_figlio->get(2); FOR_EACH_SHEET_ROW(sf_listini, i, riga) if (riga->get_char(0) > ' ') //è come dire checked (ignoranti!) { const real old_son_prezzo = get_price(sf_listini, i - 1, S2_LIST1 + r); if (old_son_prezzo > ZERO) { const real fath_prezzo = get_price(sf_listini, i, S2_PREZZO); real son_prezzo = fath_prezzo * (CENTO + ricarico) / CENTO; set_price(sf_listini, i, S2_LIST1 + r, son_prezzo); } } } sf_listini.force_update(); } //controlla sulla colonna delle spunte se almeno una è checkata bool TAggiorna_listini_edit_mask::one_checked() const { TSheet_field& sf_listini = sfield(F_MULTILISTINI); FOR_EACH_SHEET_ROW(sf_listini, i, riga) { if ((i & 1) && riga->get_char(0) > ' ') return true; } return false; } //checka-dechecka la colonna di spunte dello sheet void TAggiorna_listini_edit_mask::check_all(const bool checked) { TSheet_field& sf_listini = sfield(F_MULTILISTINI); FOR_EACH_SHEET_ROW(sf_listini, i, riga) if (i & 1) riga->add(checked ? "X" : "", 0); sf_listini.force_update(); } //aggiunge un articolo ai listini void TAggiorna_listini_edit_mask::add_art() { //si possono aggiungere solo articoli con lo stesso GRMERC selezionato ma non ancora in listino padre, oppure.. //..articoli orfani di grmerc (che però saranno sconsigliati!) //(per adesso solo con l'unità di misura principale;per aggiungere gli articoli con più unità di misura.. //..si rimanda al programma principale di gestione listini ve2500!!) TString query; query << "USE ANAMAG\n"; query << "SELECT ((GRMERC?=#GRMERC)||(GRMERC=\"\"))&&(RCONDV.CODRIGA=\"\")\n"; query << "JOIN RCONDV INTO TIPO=\"L\" CATVEN==#CATVEN COD==#COD TIPORIGA=\"A\" CODRIGA==CODART\n"; query << "JOIN UMART INTO CODART=CODART\n"; TISAM_recordset recset(query); TString8 grmerc, grmerc_filter; get_correct_grmerc(grmerc, false); get_correct_grmerc(grmerc_filter, true); recset.set_var("#GRMERC", grmerc_filter); recset.set_var("#CATVEN", get(F_FATHCATVEN)); recset.set_var("#COD", get(F_FATHCODLIS)); const int recset_items = recset.items(); //crea uno sheet volante con gli articoli aggiungibili TArray_sheet sheet(-1, -1, 78, 20, TR("Articoli aggiungibili"), HR("@1|Codice@20|UM|Prezzo@8R|Gr.Merc|Descrizione@50")); TProgind pi(recset_items, TR("Ricerca articoli aggiungibili..."), true, true); for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { if (!pi.addstatus(1)) break; TToken_string row; //prechecka solo quelli con il corretto grmerc; gli articoli orfani no! const TString& grmerc = recset.get(ANAMAG_GRMERC).as_string(); row.add(grmerc.full() ? "X" : ""); const TString codart = recset.get(ANAMAG_CODART).as_string(); row.add(codart); const TString& um = recset.get("UMART.UM").as_string(); row.add(um); const real prezzo = recset.get("UMART.PREZZO").as_real(); row.add(prezzo.is_zero() ? "" : prezzo.string()); const TString& grm = recset.get(ANAMAG_GRMERC).as_string(); row.add(grm); const TString& descr = recset.get(ANAMAG_DESCR).as_string(); row.add(descr); sheet.add(row); } sheet.rows_array().sort(false); //adesso che ha proposto lo sheet con gli articoli aggiungibili, deve aggiungere effettivamente.. //..quelli checkati if (sheet.run() == K_ENTER) { TSheet_field& sf_listini = sfield(F_MULTILISTINI); const int prezzo_pos = sf_listini.cid2index(S2_PREZZO); TString80 codart; TString4 um; FOR_EACH_CHECKED_ROW(sheet, r, riga) { codart = riga->get(1); um = riga->get(2); um.trim(); const int numriga = find_or_add_codart(sf_listini, codart, um); if (numriga >= 0) { const TPrice prezzo(real(riga->get(3))); sf_listini.row(numriga + 1).add(prezzo.string(true), prezzo_pos); //aggiunge i prezzi sui listini figli (sia riga alta che riga bassa ricaricata) TSheet_field& sf_listini_figli = sfield(F_LISTINI_FIGLI); FOR_EACH_SHEET_ROW(sf_listini_figli, i, son) { sf_listini.row(numriga).add(prezzo.get_num().string(), prezzo_pos + i + 1); const real ricarico = son->get(sf_listini_figli.cid2index(S1_RICARICO)); const TPrice son_prezzo = prezzo.get_num() * (CENTO + ricarico) / CENTO; sf_listini.row(numriga + 1).add(son_prezzo.get_num().string(), prezzo_pos + i + 1); } //aggiorna l'articolo in anagrafica con il grmerc se lui non ce l'ha if (riga->get_char(4) <= ' ') { TLocalisamfile anamag(LF_ANAMAG); anamag.put(ANAMAG_CODART, codart); if (anamag.read() == NOERR) { anamag.put(ANAMAG_GRMERC, grmerc); anamag.rewrite(); } } } //if(numriga>=0... } sf_listini.force_update(); } } void TAggiorna_listini_edit_mask::kill_priceless_articles(const TString& catven, const TString& codlist, int pos) { TSheet_field& sf_listini = sfield(F_MULTILISTINI); TString query; query << "USE RCONDV\n"; query << "SELECT ANAMAG.GRMERC?=#GRMERC\n"; query << "JOIN ANAMAG INTO CODART==CODRIGA\n"; query << "FROM TIPO=L CATVEN=#CATVEN COD=#COD TIPORIGA=A\n"; query << "TO TIPO=L CATVEN=#CATVEN COD=#COD TIPORIGA=A\n"; TISAM_recordset recset_rows(query); TString8 grmerc; get_correct_grmerc(grmerc, true); recset_rows.set_var("#GRMERC", grmerc); recset_rows.set_var("#CATVEN", catven); recset_rows.set_var("#COD", codlist); const long recset_rows_items = recset_rows.items(); TLocalisamfile& file = recset_rows.cursor()->file(); //eliminatore di articoli cancellati dallo sheet for (bool ok = recset_rows.move_first(); ok; ok = recset_rows.move_next()) { //prende codart e um dal record su file rcondv const TString& codart = recset_rows.get(RCONDV_CODRIGA).as_string(); const TString& um = recset_rows.get(RCONDV_UM).as_string(); //cerca sullo sheet la coppia codart+um const int riga_alta = find_codart(sf_listini, codart, um); const real prezzo = riga_alta >= 0 ? get_price(sf_listini, riga_alta + 1, S2_PREZZO + pos) : ZERO; //se non la trova o se il prezzo è 0 elimina la riga dal file if (prezzo.is_zero()) { const int err = file.remove(); if (err != NOERR) { TString80 msg; msg.format(FR("Errore %d in cancellazione dell'articolo %s dal listino %s"), err, (const char*)codart, file.curr().build_key()); xvtil_popup_error(msg); } } } } //salva i listini così come li trova sulle righe dello sheet multilistini void TAggiorna_listini_edit_mask::save_listini() { TSheet_field& sf_listini = sfield(F_MULTILISTINI); const int prezzo_pos = sf_listini.cid2index(S2_PREZZO); TToken_string keys_listini; const int num_listini_da_agg = crea_famiglia_listini(keys_listini); TString8 grmerc; get_correct_grmerc(grmerc, false); TString msg; msg << TR("Registrazione listini ") << grmerc << "..."; TProgind pi(num_listini_da_agg, msg, true, true); TToken_string key; //giro su tutti i listini che compaiono nello sheet; padre e figli //prende le righe di un listino alla volta FOR_EACH_TOKEN(keys_listini, tok) { if (!pi.addstatus(1)) break; key = tok; //assegnamento necessario causa tipo (se usasse tok direttamente non funzionerebbe) const int pos = keys_listini.get_pos(key); const TString4 catven = key.get(0); const TString4 codlist = key.get(1); kill_priceless_articles(catven, codlist, pos); TLocalisamfile file(LF_RCONDV); TRectype key_rec(LF_RCONDV); //alla fine della storia registra tutto lo sheet sul file FOR_EACH_SHEET_ROW(sf_listini, r, riga) if ((r & 1) && (riga->get_char(0) > ' ')) //è come dire riga dispari e checked (ignoranti!) { const real prezzo = get_price(sf_listini, r, S2_PREZZO + pos); if (prezzo > ZERO) { const TString codart = riga->get(1); const TString4 um = _ges_um ? sf_listini.row(r - 1).get(2) : ""; //si costruisce un record con la chiave che trova sullo sheet in modo da poterlo cercare.. //..sul file rcondv key_rec.zero(); key_rec.put(RCONDV_TIPO, "L"); key_rec.put(RCONDV_CATVEN, catven); key_rec.put(RCONDV_COD, codlist); key_rec.put(RCONDV_TIPORIGA, "A"); key_rec.put(RCONDV_CODRIGA, codart); if (_ges_um) key_rec.put(RCONDV_UM, um); //c'e' l'articolo nel listino? file.curr() = key_rec; int err = file.read(); //alla fine della fiera deve salvare su file veramente! //se è in inserimento deve fare un write, se in modifica la rewrite if (err == NOERR) //lo trova già esistente -> aggiorna il prezzo { file.put(RCONDV_PREZZO, prezzo); err = file.rewrite_write(); } else //non lo trova quindi lo aggiunge { if (err == _iskeynotfound) { file.curr() = key_rec; file.put(RCONDV_PREZZO, prezzo); err = file.write_rewrite(); } } //if(err==NOERR.. if (err != NOERR) error_box(FR("Errore %d durante l'aggiornamento dell'articolo %s nel listino %s"), err, (const char*)codart, (const char*)codlist); } } //FOR_EACH_SHEET_ROW... } //FOR_EACH_TOKEN... } bool TAggiorna_listini_edit_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_LISTINI_FIGLI: if (e == se_query_add || e == se_query_del) return false; // Rifiuta aggiunte e cancellazioni di figli break; case F_MULTILISTINI: switch (e) { case se_query_add: send_key(K_SPACE, DLG_NEWREC); // Ridirige l'aggiunta al bottone della toolbar return false; case se_query_del: return false; // Rifiuta cancellazioni di articoli default: break; } break; case F_GRMERC: case F_SOTGRMERC: //una volta selezionati grmerc/sotgrmerc riempie la colonna ricarico dello sheet if (e == fe_modify) { TString8 grmerc; get_correct_grmerc(grmerc, false); if (grmerc != _curr_grmerc && grmerc.full()) { const TSheet_field& sf_listini = sfield(F_MULTILISTINI); if (_ask_save && !sf_listini.empty()) { if (yesno_box(FR("Registrare le modifiche effettuate a %s?"), (const char*)_curr_grmerc)) { // Ripristina vecchio gruppo sulla maschera per salvarlo correttamente set(F_GRMERC, _curr_grmerc.left(3)); set(F_SOTGRMERC, _curr_grmerc.mid(3)); save_listini(); // Mette nuovo gruppo sulla maschera per leggerlo correttamente set(F_GRMERC, grmerc.left(3)); set(F_SOTGRMERC, grmerc.mid(3)); } } fill_ricarichi_children_list(); fill_multilistini_sheet(); _ask_save = false; } } break; case S2_PREZZO: if (e == fe_modify && jolly == 2) { //se il prezzo viene messo a 0 nel listino padre, si prepara ad eliminare l'articolo.. //..come se fosse premuto DLG_USER (vedi DLG_USER qui sotto) real father_price = get_price(o); if (father_price.is_zero()) { TMask& rowmask = o.mask(); rowmask.field(DLG_USER).on_hit(); } else //se invece viene cambiato il prezzo del padre ed i figli hanno tutti i prezzi nulli.. //..(articolo nuovo o resettato), sui prezzi figli viene messo il prezzo del padre { //per prima cosa sistema se stesso (è un padre ignobile!) set_price(o, father_price); //poi i figli TMask& rowmask = o.mask(); //serve la maschera di riga! (sennò funziona solo sullo sheet) real somma_prezzi_figli = ZERO; for (int i = S2_LIST1; i <= S2_LIST10; i++) somma_prezzi_figli += rowmask.get_real(i); if (somma_prezzi_figli.is_zero()) { TSheet_field& sf_listini = sfield(F_LISTINI_FIGLI); const int col_ricarichi = sf_listini.cid2index(S1_RICARICO); for (short i = S2_LIST1; i <= S2_LIST10; i++) { TMask_field& campo = rowmask.efield(i); //se il campo è visibile, allora il listino figlio è tra quelli attivi e lo aggiorna if (campo.shown()) { const real ricarico = sf_listini.cell(i - S2_LIST1, col_ricarichi); real prezzo_figlio = father_price * (CENTO + ricarico) / CENTO; set_price(rowmask.efield(i), prezzo_figlio); } } } } _ask_save = true; } break; case S2_LIST1: case S2_LIST2: case S2_LIST3: case S2_LIST4: case S2_LIST5: case S2_LIST6: case S2_LIST7: case S2_LIST8: case S2_LIST9: case S2_LIST10: if (e == fe_modify && jolly == 2) { real price = get_price(o); set_price(o, price); _ask_save = true; } break; case DLG_USER: if (e == fe_button) { if (yesno_box(TR("Si conferma l'eliminazione di questo articolo da tutti i listini collegati?"))) { TSheet_field& sf_listini = sfield(F_MULTILISTINI); const int selected_riga = sf_listini.selected(); TMask& rowmask = sf_listini.sheet_row_mask(selected_riga); rowmask.reset(-1); // Azzera tutto ma ... rowmask.set(S2_CHECK, "X"); // ... forza spunta della riga } } break; //applica i cambiamenti dovuti ai ricarichi e salva questi ultimi in gmc case DLG_APPLICA: if (e == fe_button) { TSheet_field& sf_listini = sfield(F_MULTILISTINI); if (!sf_listini.empty()) { update_sons_prices(); _ask_save = true; } } break; case DLG_CHECKALL: if (e == fe_button) { check_all(!one_checked()); } break; case DLG_NEWREC: if (e == fe_button) { if (field(F_GRMERC).empty()) return error_box(TR("Per aggiungere articoli è necessario selezionare un gruppo merceologico!")); add_art(); } break; case DLG_SAVEREC: if (e == fe_button) { save_children_list(); save_listini(); } break; default: break; } return true; } //METODI COSTRUTTORE //------------------ // metodi per F_LISTINI_FIGLI //metodo per aggiungere i figli allo sheet dei medesimi void TAggiorna_listini_edit_mask::fill_children_list() { //disabilita se necessario la colonna della categoria di vendita (lo sheet serve comunque dopo!) TSheet_field& sf_righe = sfield(F_LISTINI_FIGLI); sf_righe.destroy(); /*dovrebbe nascondere la colonna catven se non la si usa, ma non funziona la chiamata a XI const bool show_catven_column = ini_get_bool(CONFIG_DITTA, "ve", "GESLISCV"); if (!show_catven_column) sf_righe.show_column(S1_CATVEN, false);*/ //aggiorna sheet con i listini figli TString query; query << "USE CONDV\n"; query << "SELECT (FATHCATVEN=#FATHCATVEN)&&(FATHCOD=#FATHCOD)\n"; query << "FROM TIPO=L\n"; query << "TO TIPO=L\n"; TISAM_recordset recset_figli(query); recset_figli.set_var("#FATHCATVEN", get(F_FATHCATVEN)); recset_figli.set_var("#FATHCOD", get(F_FATHCODLIS)); const int recset_figli_items = recset_figli.items(); const TRectype& rec = recset_figli.cursor()->curr(); //per ogni riga del recordset va ad aggiornare lo sheet sulla maschera (aggiunge la riga) for (bool ok = recset_figli.move_first(); ok; ok = recset_figli.move_next()) { TToken_string& row = sf_righe.row(-1); //riga sheet da riempire const TString& catven = rec.get(CONDV_CATVEN); const TString& codlis = rec.get(CONDV_COD); const TString& arrotonda = rec.get(CONDV_ARROTONDA); const TString& deslis = rec.get(CONDV_DESCR); row.add(catven); row.add(codlis); row.add(""); row.add(arrotonda); row.add(deslis); sf_righe.check_row(sf_righe.items()-1, 3); } sf_righe.force_update(); } // metodi per F_MULTILISTINI //metodo per riempire lo sheet con i dati da aggiornare void TAggiorna_listini_edit_mask::set_header_multilistini_sheet() { //rinomina le colonne dello sheet di aggiornamento come il listino che rappresentano (fighissimo!).. //..secondo la solita catven+codlis; fa sparire le colonne che non servono. Ricordiamo infatti che.. //...si posson avere al massimo 10 figli (controllo demografico sui listini) TSheet_field& sf_multilistini = sfield(F_MULTILISTINI); TMask& row_mask = sf_multilistini.sheet_row_mask(0); TSheet_field& sf_figli = sfield(F_LISTINI_FIGLI); TString column_header; int num_of_columns = 3; //giro su tutte le righe dello sheet dei figli per avere intestazioni da mettere nei campi.. //..dello sheet multilistinico FOR_EACH_SHEET_ROW(sf_figli, r, riga) { column_header.cut(0); column_header << riga->get(0) << " "; column_header.trim(); column_header << riga->get(1); //rinomina intestazione colonna dello sheet multilistinico sf_multilistini.set_column_header(num_of_columns, column_header); //sistema di conseguenza la maschera di riga row_mask.efield(num_of_columns + 101).set_prompt(column_header); num_of_columns ++; } //cancella i figli in eccesso for( ;sf_multilistini.exist_column(num_of_columns); num_of_columns++) { //colonne sheet sf_multilistini.delete_column(num_of_columns); //sistema di conseguenza la maschera di riga row_mask.efield(num_of_columns + 101).hide(); } } TAggiorna_listini_edit_mask::TAggiorna_listini_edit_mask(TMask* query_mask) : TAutomask("ve2700b"), _query_mask(query_mask) { //aggiorna campi listino padre set(F_FATHCATVEN, _query_mask->get(F_FATHCATVEN)); set(F_FATHCODLIS, _query_mask->get(F_FATHCODLIS)); // Determina se vengono gestiti i listini con unità di misura TToken_string chiave; chiave.add("L"); chiave.add(get(F_FATHCATVEN)); chiave.add(""); chiave.add(""); chiave.add(get(F_FATHCODLIS)); const TRectype& rec_padre = cache().get(LF_CONDV, chiave); _ges_um = rec_padre.get_bool(CONDV_GESTUM); _ask_save = false; //popola lo sheet dei listini figli fill_children_list(); //e poi setta le intestazioni dello sheet multilistini set_header_multilistini_sheet(); } /////////////////////////////////////////////////////////////////////////////// // MASCHERA DI QUERY (seleziona il listino padre tra i listini con paternità) /////////////////////////////////////////////////////////////////////////////// class TAggiorna_listini_query_mask : public TAutomask { TArray_sheet* _sheet; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TAggiorna_listini_query_mask(); virtual ~TAggiorna_listini_query_mask(); }; bool TAggiorna_listini_query_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_FATHCATVEN: if (e == fe_button) { TArray_sheet sheet_catven(-1, -1, 78, 10, TR("Categorie di vendita"), HR("Codice|Descrizione@50")); TString4 catven; FOR_EACH_SHEET_ROW(*_sheet, t, riga) { const char* cv = riga->get(0); if (catven != cv) { catven = cv; TToken_string r; r.add(catven); r.add(cache().get("CVE", catven, "S0")); sheet_catven.add(r); } } if (sheet_catven.run() == K_ENTER) { TToken_string& r = sheet_catven.row(-1); o.set(r.get(0)); e = fe_modify; } } if ((e == fe_init || e == fe_modify) && !o.empty()) set(F_FATHDESVEN, cache().get("CVE", o.get(), "S0")); break; case F_FATHCODLIS: if (e == fe_button) { if (_sheet->run() == K_ENTER) { //riempie la maschera di query TToken_string& row = _sheet->row(-1); set(F_FATHCATVEN, row.get(0), true); set(F_FATHCODLIS, row.get(1)); set(F_FATHDESLIS, row.get(2)); send_key(K_SPACE, DLG_OK); } } break; case DLG_OK: if (e == fe_button && efield(F_FATHCODLIS).check()) { //lancia la maschera di edit TAggiorna_listini_edit_mask edit_mask(this); //gli passa la maschera principale edit_mask.run(); } return false; // NON deve uscire dal main loop! default: break; } return true; } TAggiorna_listini_query_mask::TAggiorna_listini_query_mask() : TAutomask("ve2700a") { //in base alla cervellotica configurazione impostata dall'utonto abilita/disabilita campi const bool gesliscv = ini_get_bool(CONFIG_DITTA, "ve", "GESLISCV"); enable(F_FATHCATVEN, gesliscv); //attenzione!!! il campo CATVEN è in chiave 1! per disabilitarlo ci vuole questo trucco! if (!gesliscv) efield(F_FATHCATVEN).reset_key(1); _sheet = new TArray_sheet(-1, -1, 78, 10, TR("Listini padri"), HR("Cat.Ven.|Codice|Descrizione@50")); TString query; query << "USE CONDV\n"; query << "SELECT (FATHCOD!='')&&(BETWEEN(FATHCATVEN,#CATVEN,#CATVEN))\n"; query << "FROM TIPO=L\n"; query << "TO TIPO=L\n"; //ottiene tutti i listini che hanno un padre TISAM_recordset listini_figli(query); listini_figli.set_var("#CATVEN", get(F_FATHCATVEN)); const int listini_figli_items = listini_figli.items(); //adesso deve crearsi la lista dei padri TAssoc_array listini_padri; for (bool ok = listini_figli.move_first(); ok; ok = listini_figli.move_next()) { //quale è il padre del figlio? TToken_string key; key.add(listini_figli.get(CONDV_FATHCATVEN).as_string(), 0); key.add(listini_figli.get(CONDV_FATHCOD).as_string(), 1); //se non esiste già nella lista dei padri deve essere aggiunto! if (!listini_padri.is_key(key)) { //necessita della descrizione del padre TToken_string chiave; chiave.add("L"); chiave.add(key.get(0)); chiave.add(""); chiave.add(""); chiave.add(key.get(1)); const TString& descr_padre = cache().get(LF_CONDV, chiave, CONDV_DESCR); listini_padri.add(key, descr_padre); } } //for(bool ok =... //utilizzando l'assoc_array dei padri propone uno sheet di ricerca dei soli listini che hanno paternità //maschera volante di ricerca (è una display) //riempimento dello sheet FOR_EACH_ASSOC_STRING(listini_padri, obj, key, descr) { TToken_string row; row = key; row.add(descr); _sheet->add(row); } if (_sheet->items() > 0) { _sheet->rows_array().sort(); //riordina le righe attualmente scombinate TToken_string& row = _sheet->row(0); set(F_FATHCATVEN, row.get(0), true); set(F_FATHCODLIS, row.get(1)); set(F_FATHDESLIS, row.get(2)); } } TAggiorna_listini_query_mask::~TAggiorna_listini_query_mask() { delete _sheet; } //////////////////////////////////////////////////////// // APPLICAZIONE //////////////////////////////////////////////////////// class TAggiorna_listini : public TSkeleton_application { protected: virtual bool create(); public: virtual void main_loop(); }; void TAggiorna_listini::main_loop() { TSheet_field::set_line_number_width(0); TAggiorna_listini_query_mask mask; while (mask.run() == K_ENTER); } bool TAggiorna_listini::create() { Tdninst dninst; if (!dninst.can_I_run(true)) return error_box(TR("Programma non autorizzato!")); return TSkeleton_application::create(); } int ve2700(int argc, char* argv[]) { TAggiorna_listini a; a.run(argc, argv, TR("Sincronizzazione listini")); return 0; }