#include #include #include #include #include "ca0800a.h" #include "calib01.h" #include "fasi.h" #include "rip.h" #include "rrip.h" /////////////////////////////////////////////////////////// // TRiparti_msk /////////////////////////////////////////////////////////// class TRiparti_msk : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); int create_sheet_fields(int lf, int& y, short& dlg); void genera_righe_fasi(); void create_sheet(); public: TRiparti_msk(); }; void TRiparti_msk::genera_righe_fasi() { //data una commessa in ingresso, la si vuole ripartire sulle sue fasi TString80 commessa; for (short id = F_CODCMS_1; id2pos(id) > 0; id++) commessa << get(id); if (commessa.full()) { //sheet della maschera da riempire TSheet_field& sheet = sfield(F_SHEET); sheet.destroy(); //quali sono le fasi legate a 'sto cavolo di commessa? TISAM_recordset fasi("USE FASI\nFROM CODCMSFAS=#COMMESSA\nTO CODCMSFAS=#COMMESSA"); fasi.set_var("#COMMESSA", TVariant(commessa)); TToken_string wts; for (bool ok = fasi.move_first(); ok; ok = fasi.move_next()) { wts = " "; wts.add(commessa); wts.add(fasi.get(FASI_CODFASE).as_string()); sheet.row(-1) = wts; } sheet.force_update(); //scrive le righe effettivamente } //if(commessa.full()... } bool TRiparti_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { //gestione tipo di ripartizioni possibili //0 = percentuale; 1 = in base al peso economico della commessa; 2 = per parti (modello cocktail) case F_TIPORIP: if (e == fe_init || e == fe_modify) { TSheet_field& sf = sfield(F_SHEET); TMask& sm = sf.sheet_mask(); const int t = atoi(o.get()); switch (t) { case 0: //percentuale { sm.hide(201); sm.show(101); sm.enable(101); sf.enable_column(0); set(F_TOTRIP, CENTO); disable(F_TOTRIP); show(F_SOMMA); show(F_DIFFERENZA); } break; case 1: //peso economico della commessa (non viene specificato nulla, la ripartizione avviene in base ai saldi) { sm.show(101); sm.disable(101); //necessario per non avere 2 campi abilitati e nascosti nella stessa posizione (dà errore) sm.hide(201); sf.enable_column(0, false); disable(F_TOTRIP); hide(F_TOTRIP); hide(F_SOMMA); hide(F_DIFFERENZA); } break; case 2: //parti { sm.hide(101); sm.show(201); sm.enable(201); sf.enable_column(0); enable(F_TOTRIP); show(F_SOMMA); show(F_DIFFERENZA); } break; } sf.force_update(); } break; case F_SHEET: if (e == fe_init || (e == se_leave && o.dirty())) { TSheet_field& sf = sfield(F_SHEET); real tot; FOR_EACH_SHEET_ROW(sf, i, row) tot += real(row->get(0)); const int t = atoi(get(F_TIPORIP)); tot.round(5); set(F_SOMMA, tot); real diff = get_real(F_TOTRIP); if (diff != ZERO) diff -= tot; set(F_DIFFERENZA, diff); } break; case F_GENFASI: if (e == fe_init) { bool accendimi = insert_mode(); if (accendimi) { const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI); accendimi = fasinfo.parent() == LF_COMMESSE; } o.show(accendimi); } if (e == fe_button) genera_righe_fasi(); break; default: break; } return true; } int TRiparti_msk::create_sheet_fields(int lf, int& y, short& dlg) { TSheet_field& sf = sfield(F_SHEET); TMask& sm = sf.sheet_mask(); const int h = ca_create_fields(sm, 0, lf, 1, y, dlg, dlg+50); for (int i = 0; i < h; i++) { TEdit_field& fld = sm.efield(dlg+i); int logic = lf; if (logic == LF_FASI) { const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI); if (fasinfo.parent() != 0) { const TMultilevel_code_info& parinfo = ca_multilevel_code_info(fasinfo.parent()); if (i < parinfo.levels()) logic = fasinfo.parent(); } } if (logic == LF_PCON) { const TFieldref* f = fld.field(); const TString16 fieldname = f->name(); if (fieldname == "GRUPPO") fld.set_field("CODCONTO[1,3]"); else if (fieldname == "CONTO") fld.set_field("CODCONTO[4,6]"); else if (fieldname == "SOTTOCONTO") fld.set_field("CODCONTO[7,12]"); } else { const char* fieldname = NULL; switch(logic) { case LF_CDC : fieldname = RRIP_CODCOSTO; break; case LF_COMMESSE: fieldname = RRIP_CODCMS; break; case LF_FASI : fieldname = RRIP_CODFASE; break; default : fieldname = RRIP_CODCONTO; break; } TFieldref* f = (TFieldref*)fld.field(); f->set_name(fieldname); } } y += h+1; dlg += h; return h; } void TRiparti_msk::create_sheet() { TSheet_field& sf = sfield(F_SHEET); TMask& sm = sf.sheet_mask(); sm.hide(-1); const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI); TConfig& ini = ca_config(); int y = 1; short dlg = 202; for (int i = 0; i < 2; i++) { const TString& level = ini.get("Level", NULL, i+1); // Legge il livello 1 o 2 if (level == "CDC") // Crea centro di costo { if (fasinfo.parent() == LF_CDC) create_sheet_fields(LF_FASI, y, dlg); else create_sheet_fields(LF_CDC, y, dlg); } else if (level == "CMS") // Crea commessa { if (fasinfo.parent() == LF_COMMESSE) create_sheet_fields(LF_FASI, y, dlg); else create_sheet_fields(LF_COMMESSE, y, dlg); } } if (fasinfo.levels() > 0 && fasinfo.parent() <= 0) create_sheet_fields(LF_FASI, y, dlg); const bool use_pdc = ini.get_bool("UsePdcc"); create_sheet_fields(use_pdc ? LF_PCON : LF_PCONANA, y, dlg); for (short id = 217; id >= 202; id--) { const int pos = sm.id2pos(id); if (pos >= 0) { TMask_field& f = sm.fld(pos); const int size = f.size(); const TString& prompt = f.prompt(); sf.set_column_header(id, prompt); sf.set_column_justify(id, f.is_kind_of(CLASS_REAL_FIELD)); sf.set_column_width(id, (max(3+size, prompt.len()+1)) * CHARX); } else { sf.delete_column(id); } } } TRiparti_msk::TRiparti_msk() : TAutomask("ca0800a") { TConfig& ini = ca_config(); // Crea gli eventuali campi per commessa e centro di costo const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI); int y = 12; for (int i = 0; i < 2; i++) { const char* prompt = NULL; int h = 0; const TString& level = ini.get("Level", NULL, i+1); // Legge il livello 1 o 2 if (level == "CDC") // Crea centro di costo { h = ca_create_fields(*this, 0, LF_CDC, 2, y, F_CODCDC_1, F_DESCDC_1); prompt = TR("@bCentro di costo"); } else if (level == "CMS") // Crea commessa { if (fasinfo.parent() == LF_COMMESSE) { h = ca_create_fields(*this, 0, LF_FASI, 2, y, F_CODCMS_1, F_DESCMS_1); prompt = TR("@bCommessa/Fase"); const TMultilevel_code_info& cmsinfo = ca_multilevel_code_info(LF_COMMESSE); const int cmslevels = cmsinfo.levels(); for (int j = 0; j < cmslevels; j++) { TEdit_field& cfld = efield(F_CODCMS_1+j); const TFieldref& fr = cmsinfo.fieldref(j); TString80 str = RIP_CODCMS; if (cmslevels > 1) str.format("%s[%d,%d]", RIP_CODCMS, fr.from()+1, fr.to()); cfld.set_field(str); } } else { h = ca_create_fields(*this, 0, LF_COMMESSE, 2, y, F_CODCMS_1, F_DESCMS_1); prompt = TR("@bCommessa"); } } else if (level == "FSC" && fasinfo.parent() <= 0) { h = ca_create_fields(*this, 0, LF_FASI, 2, y, F_CODCMS_1, F_DESCMS_1); prompt = TR("@bFase"); } if (prompt != NULL) // Crea groupbox { const int last = fields()-1; for (int j = 0; j < 2*h; j++) fld(last-j).set_group(2); h += 2; TGroup_field& grp = add_groupbox(F_LEVEL_1+i, 0, prompt, 1, y-1, 78, h); grp.set_group(2); y += h; } } create_sheet(); } /////////////////////////////////////////////////////////// // TRiparti_app /////////////////////////////////////////////////////////// class TRiparti_app : public TRelation_application { TRelation* _rel; TRiparti_msk* _msk; const TString& somma_campi(TToken_string& row, int first, bool pdc = false) const; void write_rows(); void spezza_campo(const TString& str, TToken_string& row, int first) const; void read_rows(); protected: virtual const char * extra_modules() const {return "cm";} //funziona anche con autorizzazione CM virtual bool user_create(); virtual bool user_destroy(); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); virtual int read(TMask& m); virtual bool get_next_key(TToken_string& key); virtual TRelation* get_relation() const { return _rel; } virtual TMask* get_mask(int) { return _msk; } }; const TString& TRiparti_app::somma_campi(TToken_string& row, int first, bool pdc) const { TSheet_field& sheet = _msk->sfield(F_SHEET); TMask& m = sheet.sheet_mask(); const short id = 201 + first; TString& str = get_tmp_string(20); for (int i = 0; i < 4; i++) { TString80 token = row.get(first+i); if (m.id2pos(id+i) < 0) break; const TEdit_field& fld = m.efield(id+i); if (pdc) token.right_just(fld.size(), '0'); else token.left_just(fld.size()); str << token; } return str; } void TRiparti_app::spezza_campo(const TString& str, TToken_string& row, int first) const { TSheet_field& sheet = _msk->sfield(F_SHEET); TMask& m = sheet.sheet_mask(); TString80 token; const short id = 201 + first; int start = 0; for (int i = 0; i < 4; i++) { if (m.id2pos(id+i) < 0) break; const TEdit_field& fld = m.efield(id+i); const int len = fld.size(); token = str.mid(start, len); token.trim(); row.add(token, first+i); start += len; } } void TRiparti_app::write_rows() { real diff = _msk->get_real(F_TOTRIP); const bool has_tot = _msk->get_int(F_TIPORIP) != 1 && diff != ZERO; TRectype* key = new TRectype(LF_RRIP); const char tipo = _msk->get(F_TIPO)[0]; key->put("TIPO", tipo); key->put("CODICE", _msk->get(tipo == 'B' ? F_CODICE_B : F_CODICE_I)); TRecord_array a(LF_RRIP, "NRIGA"); a.set_key(key); TSheet_field& sheet = _msk->sfield(F_SHEET); TMask& sm = sheet.sheet_mask(); FOR_EACH_SHEET_ROW(sheet, i, row) { TRectype& rec = a.row(i+1, true); // Crea una riga nuova for (int i = sm.fields()-1; i >= 0; i--) { TMask_field& mf = sm.fld(i); if (mf.field() != NULL) { const int idx = sheet.cid2index(mf.dlg()); if (idx < 17) mf.field()->write(row->get(idx), rec); } } if ( has_tot) diff -= rec.get_real(RRIP_RIPARTO); } if (has_tot && _msk->get_real(F_DIFFERENZA) != ZERO) if (yesno_box(FR("Il totale da ripartire differisce di %s\ndal totale delle righe devo aggiungere la differenza all'ultima riga"), abs(diff).stringa())) a[a.last_row()].add(RRIP_RIPARTO, diff); else { TRectype & rec = a.row(-1, true); rec.put(RRIP_RIPARTO, diff); } a.rewrite(); } void TRiparti_app::read_rows() { const char tipo = _msk->get(F_TIPO)[0]; TToken_string key; key << tipo << '|' << _msk->get(tipo == 'B' ? F_CODICE_B : F_CODICE_I); TRecord_array a(key, LF_RRIP); TSheet_field& sheet = _msk->sfield(F_SHEET); TMask& sm = sheet.sheet_mask(); sheet.destroy(); for (int i = 1; i <= a.rows(); i++) { TToken_string& row = sheet.row(i-1); const TRectype& rec = a.row(i); for (int i = sm.fields()-1; i >= 0; i--) { TMask_field& mf = sm.fld(i); if (mf.field() != NULL) { const int idx = sheet.cid2index(mf.dlg()); if (idx < 17) row.add(mf.field()->read(rec), idx); } } } } bool TRiparti_app::get_next_key(TToken_string& key) { long num = 1; const char tipo = _msk->get(F_TIPO)[0]; TString query; query << "USE RIP\nFROM TIPO=" << tipo << "\nTO TIPO=" << tipo; TISAM_recordset rip_recset(query); const long items = rip_recset.items(); if (rip_recset.move_last()) num += rip_recset.get(RIP_CODICE).as_int(); //la scelta del campo della maschera su cui scrivere dipende dal tipo di ripartizione scelta nel radiobutton dei tipi long codice = F_CODICE_I; if (tipo == 'B') codice = F_CODICE_B; key.format("%d|%c|%d|%ld", F_TIPO, tipo, codice, num); return true; } int TRiparti_app::write(const TMask& m) { write_rows(); return TRelation_application::write(m); } int TRiparti_app::rewrite(const TMask& m) { write_rows(); return TRelation_application::rewrite(m); } int TRiparti_app::read(TMask& m) { const int err = TRelation_application::read(m); if (err == NOERR) read_rows(); return err; } bool TRiparti_app::user_create() { _rel = new TRelation(LF_RIP); _msk = new TRiparti_msk; return true; } bool TRiparti_app::user_destroy() { delete _rel; delete _msk; return true; } int ca0800(int argc, char* argv[]) { TRiparti_app a; a.run(argc, argv, TR("Tabella di ripartizione")); return 0; }