#include #include #include #include #include "ca2.h" #include "ca2100a.h" #include "calib01.h" #include "../cg/cglib01.h" #include #include #include "movana.h" #include "rmovana.h" #include "rrip.h" #include "saldana.h" #include "commesse.h" class TMovanal_msk : public TAutomask { TAssoc_array _saldi; bool _use_pdc; short _cms_start; short _cms_end; short _cdc_start; short _cdc_end; protected: virtual bool on_field_event(TOperable_field& o, TField_event fe, long jolly); virtual bool can_be_closed() const; virtual bool on_key(KEY key); const TToken_string& rec2key(const TRectype& rec) const; void aggiorna_saldo_riga(int r); // Lettura movimento contabile TToken_string& get_rip_row(const TRectype& rrip); void split_cg_row(const TRectype& row, const TRecord_array& rrip); void load_cg_row(const TRectype& row); void load_cg_mov(); bool is_ripartible_movcg(); int create_sheet_fields(int lf, int& y, short& dlg, bool required); void create_sheet(); int get_constant_columns(TToken_string& tok) const; public: void reset_saldi(); TImporto& saldo(const TRectype& row); void show_locked_buttons(); bool row2rec(int row, TRectype& rec) const; void row2imp(const TToken_string& row, TImporto& imp) const; bool row2imp(int r, TImporto& imp) const; void imp2row(const TImporto& imp, TToken_string& row) const; TToken_string& rec2row(const TRectype& rec, int i) const; TMovanal_msk(); virtual ~TMovanal_msk() { } }; class TMovanal_app : public TRelation_application { TRelation* _rel; TMovanal_msk* _msk; virtual const char* extra_modules() const { return "cm"; } //deve funzionare anche per le commesse protected: virtual bool user_create(); virtual bool user_destroy(); virtual TMask* get_mask(int); virtual TRelation* get_relation() const; virtual bool get_next_key(TToken_string& key); void write_rows(const TMask& m); void read_rows(const TMask& m); virtual bool protected_record(TRectype& rec); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); virtual int read(TMask& m); virtual void ini2sheet(TConfig& ini, TSheet_field& sheet); virtual void sheet2ini(TSheet_field& sheet,TConfig& ini); virtual void init_query_mode(TMask& m); virtual void init_insert_mode(TMask& m); virtual void init_modify_mode(TMask& m); }; static TMovanal_app& app() { return (TMovanal_app&)main_app(); } /////////////////////////////////////////////////////////// // TMovanal_msk /////////////////////////////////////////////////////////// bool TMovanal_msk::can_be_closed() const { const bool lck = app().is_transaction() && mode() == MODE_INS; return lck ? false : TAutomask::can_be_closed(); } bool TMovanal_msk::on_key(KEY key) { if (key == K_SHIFT + K_F12) { enable(F_BLOCCATO); return true; } return TAutomask::on_key(key); } void TMovanal_msk::show_locked_buttons() { const bool is_trans = app().is_transaction(); const bool modifying = mode() == MODE_MOD; const bool inserting = mode() == MODE_INS; const bool editing = modifying || inserting; const bool unlocked = !(modifying && get_bool(F_BLOCCATO)); show (F_BLOCCATO, modifying); enable(F_BLOCCATO, unlocked); enable(DLG_SAVEREC, unlocked && editing); enable(DLG_DELREC, unlocked && !inserting); enable(DLG_QUIT, !is_trans || !inserting); enable(DLG_CANCEL, !is_trans || !inserting); enable(F_RESET, unlocked && editing); } TToken_string& TMovanal_msk::get_rip_row(const TRectype& rrip) { TSheet_field& sheet = sfield(F_RIGHE); TToken_string keyrip; keyrip.add(rrip.get(RRIP_CODCOSTO)); keyrip.add(rrip.get(RRIP_CODCMS)); keyrip.add(rrip.get(RRIP_CODFASE)); keyrip.add(rrip.get(RRIP_CODCONTO)); TRectype rmov(LF_RMOVANA); const int totrows = sheet.items(); if (totrows > 0) { TToken_string keyrow; for (int i = 0; i < totrows; i++) { row2rec(i, rmov); keyrow.cut(0); keyrow.add(rmov.get(RMOVANA_CODCCOSTO)); keyrow.add(rmov.get(RMOVANA_CODCMS)); keyrow.add(rmov.get(RMOVANA_CODFASE)); keyrow.add(rmov.get(RMOVANA_CODCONTO)); if (keyrow == keyrip) return sheet.row(i); // Ho trovato una riga compatibile } } // Devo creare una riga nuova rmov.zero(); rmov.put(RMOVANA_CODCCOSTO, keyrip.get(0)); rmov.put(RMOVANA_CODCMS, keyrip.get()); rmov.put(RMOVANA_CODFASE, keyrip.get()); rmov.put(RMOVANA_CODCONTO, keyrip.get()); TToken_string& row = rec2row(rmov, -1); return row; } void TMovanal_msk::split_cg_row(const TRectype& row, const TRecord_array& rrip) { // Importo totale da distribuire arrotondato ai decimali della valuta di conto TGeneric_distrib distrib(row.get_real(RMV_IMPORTO), TCurrency::get_firm_dec()); // Calcolo tutte le percentuali da ripartire int i; for (i = 1; i <= rrip.rows(); i++) { const real quota = rrip[i].get_real(RRIP_RIPARTO); distrib.add(quota); } TString80 desc; // Variabile di appoggio per descrizione riga for (i = 1; i <= rrip.rows(); i++) { TToken_string& riga = get_rip_row(rrip[i]); // Cerca o crea la riga cui sommare la quota TImporto impriga; row2imp(riga, impriga); // Legge l'importo della riga const TImporto imp(row.get_char(RMV_SEZIONE), distrib.get()); // Legge la quota da distribuire impriga += imp; impriga.normalize(); // Incrementa l'importo della riga e lo normalizza imp2row(impriga, riga); // Aggiorna la riga riga.get(2, desc); // Legge descrizione riga corrente if (desc.blank()) // Se e' vuota allora ... riga.add(row.get(RMV_DESCR), 2); // ... ci copio la descrizione della riga contabile } } bool TMovanal_msk::is_ripartible_movcg() { bool ok = true; if (!_use_pdc) { const TString& numregcg = get(F_NUMREGCG); TRecord_array cg(numregcg, LF_RMOV); TString query; for (int r = cg.last_row(); r > 0; r--) { const TRectype& row = cg.row(r); const TBill zio(row); if (zio.is_analitico()) { int i; for (i = 3; i > 0; i--) { query = "USE RIP SELECT"; query << " (GRUPPO=" << zio.gruppo() << ')'; // Il gruppo c'e' sempre const int conto = i > 1 ? zio.conto() : 0; // Il conto c'e' per i = 2 o 3 query << "&&(CONTO=" << conto << ')'; if (conto > 0) { const long sotto = i > 2 ? zio.sottoconto() : 0; // Il sottoconto c'e' per i = 3 query << "&&(SOTTOCONTO=" << sotto << ')'; } query << "\nFROM TIPO='I'\nTO TIPO='I'"; TISAM_recordset rs(query); if (rs.items() > 0) // Ho trovato la ripartizione! break; } if (i <= 0) // Non trovato la ripartizione { ok = error_box(FR("Non esiste una ripartizione del conto %d.%d.%ld\n" "presente sulla riga %d del movimento %ld"), zio.gruppo(), zio.conto(), zio.sottoconto(), r, atol(numregcg)); break; } } } } return ok; } void TMovanal_msk::load_cg_row(const TRectype& row) { // Cerco la ripartizione del sottoconto, se non la trovo uso quella del conto o del gruppo TString query; int i; for (i = 3; i > 0; i--) { query = "USE RIP SELECT"; query << " (GRUPPO=" << row.get(RMV_GRUPPO) << ')'; // Il gruppo c'e' sempre const int conto = i > 1 ? row.get_int(RMV_CONTO) : 0; // Il conto c'e' per i = 2 o 3 query << "&&(CONTO=" << conto << ')'; if (conto > 0) { const long sotto = i > 2 ? row.get_long(RMV_SOTTOCONTO) : 0; // Il sottoconto c'e' per i = 3 query << "&&(SOTTOCONTO=" << sotto << ')'; } query << "\nFROM TIPO='I'\nTO TIPO='I'"; TISAM_recordset rs(query); if (rs.items() > 0) // Ho trovato la ripartizione: evviva! { TString16 codice = rs.get("CODICE").as_string(); codice.insert("I|"); TRecord_array rrip(codice, LF_RRIP); // Carico le righe di ripartizione if (rrip.rows() > 0) { split_cg_row(row, rrip); break; } } } if (i == 0) // Non ho trovato nessuno schema di ripartizione valido { // Creo una riga nuova TSheet_field& sheet = sfield(F_RIGHE); TToken_string& riga = sheet.row(-1); const TImporto imp(row.get_char(RMV_SEZIONE), row.get_real(RMV_IMPORTO)); imp2row(imp, riga); // Ci copio l'importo riga.add(row.get(RMV_DESCR), 2); // e la descrizione della riga contabile if (_use_pdc) { TMask_field* f = sheet.sheet_mask().find_by_fieldname(RMOVANA_CODCONTO); const int pos = sheet.cid2index(f->dlg()); TString8 str; str = row.get(RMV_GRUPPO); str.right_just(3, '0'); riga.add(str, pos-2); str = row.get(RMV_CONTO); str.right_just(3, '0'); riga.add(str, pos-1); str = row.get(RMV_SOTTOCONTO); str.right_just(6, '0'); riga.add(str, pos); } } } // A partire dal movimento contabile calcola il totale documento ed eventualmente prepara lo sheet void TMovanal_msk::load_cg_mov() { const TString& numregcg = get(F_NUMREGCG); const TRectype& mov = cache().get(LF_MOV, numregcg); set(F_DATAREG, mov.get(MOV_DATAREG)); if (mode() == MODE_INS) { set(F_DATACOMP, mov.get(MOV_DATACOMP)); set(F_DESCR, mov.get(MOV_DESCR)); } set(F_CODCAUS, mov.get(MOV_CODCAUS), 0x2); set(F_NUMDOC, mov.get(MOV_NUMDOC)); set(F_DATADOC, mov.get(MOV_DATADOC)); set(F_TIPODOC, mov.get(MOV_TIPODOC)); set(F_TIPOCF, mov.get(MOV_TIPO)); set(F_CODCF, mov.get(MOV_CODCF), 0x3); TImporto totdoc; TRecord_array cg(numregcg, LF_RMOV); const bool autoinsert = sfield(F_RIGHE).empty(); for (int i = 1; i <= cg.rows(); i++) { const TRectype& row = cg.row(i); const TBill zio(row); if (zio.is_analitico()) { const TImporto imp(row.get_char(RMV_SEZIONE), row.get_real(RMV_IMPORTO)); totdoc += imp; if (autoinsert) load_cg_row(row); } } set(F_TOTDOC, totdoc.valore()); const char sez[2] = { totdoc.sezione(), '\0' }; set(F_SEZIONE, sez); } int TMovanal_msk::get_constant_columns(TToken_string& tok) const { int n = 0; TSheet_field& sf = sfield(F_RIGHE); const int items = sf.items(); if (items > 0) { TMask& m = sf.sheet_mask(); for (int f = 0; f < m.fields(); f++) { const TMask_field& mf = m.fld(f); const TFieldref* fr = mf.field(); if (fr != NULL && !fr->name().starts_with(RMOVANA_CODCONTO)) { const int i = sf.cid2index(mf.dlg()); if (i >= 2) { const TString campione = sf.row(0).get(i); if (campione.full()) { int j; for (j = items-1; j > 0; j--) { if (campione != sf.row(j).get(i)) break; } if (j == 0) { tok.add(campione, i); n++; } } } } } } return n; } bool TMovanal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { static TString __codcms; switch (o.dlg()) { case F_DATAREG: if ((e == fe_modify || e == fe_close) && !query_mode()) { const TDate datareg = o.get(); const TEsercizi_contabili ec; if (ec.date2esc(datareg) <= 0) return error_box(((TEdit_field&)o).get_warning()); if (e == fe_close && field(F_DATACOMP).empty()) set(F_DATACOMP, datareg); } break; case F_DATACOMP: if ((e == fe_modify || e == fe_close) && !query_mode()) { const TDate datareg = get(F_DATAREG); TDate datacomp = o.get(); if (!datacomp.ok()) datacomp = datareg; if (datacomp > datareg) return error_box(TR("La data di competenza non puo' superare la data di registrazione")); const TEsercizi_contabili ec; const int ae = ec.date2esc(datacomp); if (ae > 0) set(F_ANNOES, ae, 0x1); else return error_box(((TEdit_field&)o).get_warning()); const int ar = ec.date2esc(datareg); const int ap = ec.pred(ar); if (ae != ar && ae != ap) return error_box(FR("La data di competenza deve appartenere all'esercizio in corso o al precedente")); } break; case F_DATAFCOMP: if (e == fe_modify || e == fe_close) { const TDate datacomp = get(F_DATACOMP); const TDate datafcomp = o.get(); if (datafcomp.ok()) { if (datafcomp < datacomp) return error_box(((TEdit_field&)o).get_warning()); } else o.set(datacomp.string()); //se la data fine competenza viene lasciata vuota -> e' uguale alla datacomp } break; case F_RIGHE: if (e == se_enter) { const int r = int(jolly); aggiorna_saldo_riga(r); } if (e == se_query_modify) { TSheet_field & s = sfield(F_RIGHE); const int r = int(jolly); __codcms.cut(0); for (short j = _cms_start; j <= _cms_end; j++) __codcms << s.row(r).get(s.cid2index(j)); } if (e == se_notify_modify) { const int r = int(jolly); TSheet_field & s = sfield(F_RIGHE); TMask & m = s.sheet_mask(); const TRectype & curr = ((TEdit_field &) m.field(_cms_start)).browse()->cursor()->curr(); const TString & codcms = curr.get(COMMESSE_CODCMS); if ((_cms_start > 0)&&(_cdc_start > 0)&&(__codcms != codcms)) { const TString codcosto = curr.get(COMMESSE_CODCOSTO); for (short i = _cdc_start; i <= _cdc_end; i++) { TEdit_field & e = m.efield(i); const TFieldref * f = e.field(); if (f != NULL) { const int from = f->from(); const int to = f->to(); m.set(i, codcosto.sub(from, to), 0x2); s.update_row(r); s.force_update(r); } } } } if (e == fe_close) { const TImporto totdoc(get(F_SEZIONE)[0], get_real(F_TOTDOC)); TImporto totrig; TSheet_field& sf = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sf, i, row) { TImporto imp; row2imp(*row, imp); totrig += imp; //controlli sullo sheet in uscita!! Servono in quanto, anche scrivendo cazzate, l'utente potrebbe.. //..registrare lo stesso il movimento cliccando su FINE e rispondendo SI alla successiva richiesta.. //..di conferma registrazione! if (sf.dirty()) { sf.check_row(i, 1); TMask& rm = sf.sheet_mask(); FOR_EACH_MASK_FIELD(rm, j, fld) { if (fld->has_check() && !fld->check(FINAL_CHECK)) { TString msg; msg << TR("Valore errato nel campo ") << fld->prompt(); return error_box(msg); } } } } if (totrig != totdoc) return error_box(FR("Il totale delle righe e' %s %s, mentre il totale documento e' %s %s"), totrig.valore().string(), totrig.sezione() == 'D' ? TR("Dare") : TR("Avere"), totdoc.valore().string(), totdoc.sezione() == 'D' ? TR("Dare") : TR("Avere")); } break; case S_DARE: case S_AVERE: if (e == fe_modify) { TSheet_field& sf = sfield(F_RIGHE); if (!o.empty()) o.mask().reset(o.dlg() == S_DARE ? S_AVERE : S_DARE); const int r = sfield(F_RIGHE).selected(); sf.update_row(r); aggiorna_saldo_riga(r); } break; case F_NUMREGCG: if (e == fe_init) { const bool vuoto = o.empty(); enable(-5, vuoto); if (!vuoto) load_cg_mov(); } break; case F_BLOCCATO: if (e == fe_modify) { enable(DLG_SAVEREC); // Altrimenti non riesco a registrare la variazione di stato } break; case F_RESET: if (e == fe_button) { if (is_ripartible_movcg()) { TToken_string constants; const int cc = get_constant_columns(constants); TSheet_field& sf = sfield(F_RIGHE); sf.destroy(); load_cg_mov(); if (cc > 0) // Se ci sono colonne costanti le recupera da quelle vecchie salvate { TString campione; FOR_EACH_SHEET_ROW(sf, i, row) { for (int i = constants.items()-1; i > 0; i--) { constants.get(i, campione); if (!campione.blank()) row->add(campione, i); } } } sf.force_update(); } else disable(F_RESET); } break; default: if (e == fe_modify && o.dlg() >= S_CDC1 && o.dlg() <= S_CON4) { TSheet_field& sf = sfield(F_RIGHE); const int r = sf.selected(); sf.update_row(r); aggiorna_saldo_riga(r); } break; } return true; } // Prende dalla riga r dello sheet i dati da scrivere nel record rec dei movimenti analitici bool TMovanal_msk::row2rec(int r, TRectype& rec) const { TSheet_field& sheet = sfield(F_RIGHE); if (r < 0 || r >= sheet.items()) return false; rec.put(RMOVANA_ANNOES, get(F_ANNOES)); rec.put(RMOVANA_DATACOMP, get(F_DATACOMP)); TToken_string& row = sheet.row(r); const real dare = row.get(sheet.cid2index(S_DARE)); const real avere = row.get(); if (dare.is_zero()) { rec.put(RMOVANA_SEZIONE, 'A'); rec.put(RMOVANA_IMPORTO, avere); } else { rec.put(RMOVANA_SEZIONE, 'D'); rec.put(RMOVANA_IMPORTO, dare); } TMask& sm = sheet.sheet_mask(); for (int i = sm.fields()-1; i >= 2; i--) { const TMask_field& mf = sm.fld(i); const TFieldref* fr = mf.field(); if (fr != NULL) { const int idx = sheet.cid2index(mf.dlg()); if (idx < 17) { const char* s = row.get(idx); if (s != NULL) fr->write(s, rec); } } } return true; } void TMovanal_msk::imp2row(const TImporto& imp, TToken_string& row) const { row.add(imp.sezione() == 'D' ? imp.valore().string() : "", 0); row.add(imp.sezione() == 'A' ? imp.valore().string() : "", 1); } TToken_string& TMovanal_msk::rec2row(const TRectype& rec, int r) const { CHECK(rec.num() == LF_RMOVANA, "Bad record type"); TSheet_field& sheet = sfield(F_RIGHE); TMask& sm = sheet.sheet_mask(); TToken_string& row = sheet.row(r); const TImporto imp(rec.get_char(RMOVANA_SEZIONE), rec.get_real(RMOVANA_IMPORTO)); imp2row(imp, row); // Carica tutti gli altri campi dopo le colonne Dare/Avere for (int i = sm.fields()-1; i >= 2; i--) { TMask_field& mf = sm.fld(i); const TFieldref* fr = mf.field(); if (fr != NULL) { const int idx = sheet.cid2index(mf.dlg()); if (idx < 17) row.add(fr->read(rec), idx); } } return row; } void TMovanal_msk::row2imp(const TToken_string& row, TImporto& imp) const { real dare; row.get(0, dare); real avere; row.get(1, avere); if (dare.is_zero()) imp.set('A', avere); else imp.set('D', dare); } bool TMovanal_msk::row2imp(int r, TImporto& imp) const { TSheet_field& sf = sfield(F_RIGHE); if (r >= 0 && r < sf.items()) { const TToken_string& row = sf.row(r); row2imp(row, imp); } else imp.set('D', ZERO); return !imp.is_zero(); } const TToken_string& TMovanal_msk::rec2key(const TRectype& rec) const { TToken_string& key = get_tmp_string(); key = get(F_TIPO); key.add(rec.get(RMOVANA_ANNOES)); key.add(rec.get(RMOVANA_CODCCOSTO)); key.add(rec.get(RMOVANA_CODCMS)); key.add(rec.get(RMOVANA_CODFASE)); key.add(rec.get(RMOVANA_CODCONTO)); return key; } void TMovanal_msk::reset_saldi() { _saldi.destroy(); } TImporto& TMovanal_msk::saldo(const TRectype& rec) { const TToken_string& key = rec2key(rec); TImporto* imp = (TImporto*)_saldi.objptr(key); if (imp == NULL) { const TRectype& saldo = cache().get(LF_SALDANA, key); const char* fld_sez = NULL; const char* fld_val = NULL; switch (get(F_TIPO)[0]) { case 'P': fld_sez = SALDANA_SEZIONEP; fld_val = SALDANA_SALDOP; break; case 'V': fld_sez = SALDANA_SEZIONEV; fld_val = SALDANA_SALDOV; break; default : fld_sez = SALDANA_SEZIONE; fld_val = SALDANA_SALDO; break; } imp = new TImporto(saldo.get_char(fld_sez), saldo.get_real(fld_val)); _saldi.add(key, imp); } return *imp; } void TMovanal_msk::aggiorna_saldo_riga(int r) { TRectype rec(LF_RMOVANA); row2rec(r, rec); const TToken_string& key = rec2key(rec); TImporto sld = saldo(rec); TSheet_field& sheet = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sheet, i, row) { row2rec(i, rec); const TToken_string& k = rec2key(rec); if (k == key) { real dare; row->get(0, dare); real avere; row->get(1, avere); if (dare.is_zero()) sld += TImporto('A', avere); else sld += TImporto('D', dare); } } sld.normalize(); set(F_DARE, sld.sezione() == 'D' ? sld.valore() : ZERO); set(F_AVERE, sld.sezione() == 'A' ? sld.valore() : ZERO); } int TMovanal_msk::create_sheet_fields(int lf, int& y, short& dlg, bool required) { TSheet_field& sf = sfield(F_RIGHE); 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 TString& 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 = RMOVANA_CODCCOSTO; break; case LF_COMMESSE: fieldname = RMOVANA_CODCMS; break; case LF_FASI : fieldname = RMOVANA_CODFASE; break; default : fieldname = RMOVANA_CODCONTO; break; } TFieldref* f = (TFieldref*)fld.field(); f->set_name(fieldname); } fld.check_type(required ? CHECK_REQUIRED : CHECK_NORMAL); TEdit_field& dfld = sm.efield(dlg+50+i); dfld.set_field(EMPTY_STRING); // Toglie campi che fan saltare gli output! } y += h+1; dlg += h; return h; } void TMovanal_msk::create_sheet() { TSheet_field& sf = sfield(F_RIGHE); TMask& sm = sf.sheet_mask(); sm.hide(-1); const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI); TConfig& ini = ca_config(); const bool fsc_req = ini.get_bool("FscRequired"); int y = 3; short dlg = S_CDC1+100; // id del primo campo da generare _cdc_start = _cdc_end = -1; _cms_start = _cms_end = -1; 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 { _cdc_start = dlg; _cdc_end = dlg + ca_multilevel_code_info(LF_CDC).levels()-1; if (fasinfo.parent() == LF_CDC) create_sheet_fields(LF_FASI, y, dlg, fsc_req); else { const bool cdc_req = ini.get_bool("CdcRequired"); create_sheet_fields(LF_CDC, y, dlg, cdc_req); } } else if (level == "CMS") // Crea commessa { _cms_start = dlg; _cms_end = dlg + ca_multilevel_code_info(LF_COMMESSE).levels()-1; if (fasinfo.parent() == LF_COMMESSE) create_sheet_fields(LF_FASI, y, dlg, fsc_req); else { const bool cms_req = ini.get_bool("CmsRequired"); create_sheet_fields(LF_COMMESSE, y, dlg, cms_req); } } } if (fasinfo.levels() > 0 && fasinfo.parent() <= 0) create_sheet_fields(LF_FASI, y, dlg, fsc_req); _use_pdc = ini.get_bool("UsePdcc"); const bool pdc_req = ini.get_bool("PdciRequired"); create_sheet_fields(_use_pdc ? LF_PCON : LF_PCONANA, y, dlg, pdc_req); for (short id = S_CON4+100; id >= S_CDC1+100; 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); } } } TMovanal_msk::TMovanal_msk() : TAutomask("ca2100a") { create_sheet(); } /////////////////////////////////////////////////////////// // TMovanal_app /////////////////////////////////////////////////////////// TMask* TMovanal_app::get_mask(int) { return _msk; } TRelation* TMovanal_app::get_relation() const { return _rel; } bool TMovanal_app::get_next_key(TToken_string& key) { long num = 1; TLocalisamfile movana(LF_MOVANA); if (movana.last() == NOERR) num += movana.get_long(MOVANA_NUMREG); key.format("%d|%ld", F_NUMREG, num); return true; } void TMovanal_app::write_rows(const TMask& m) { TAnal_mov& mov = (TAnal_mov&)_rel->curr(); mov.destroy_rows(); // Scandisce lo sheet e riempie il recarray TSheet_field& sheet = _msk->sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sheet, i, row) { const real dare = row->get(0), avere = row->get(); if (dare.is_zero() && avere.is_zero()) // Scarta righe vuote continue; TRectype& rec = mov.new_row(); // Crea una riga nuova _msk->row2rec(i, rec); } } void TMovanal_app::read_rows(const TMask& m) { const TAnal_mov& mov = (const TAnal_mov&)_rel->curr(); const TRecord_array& a = mov[LF_RMOVANA]; TSheet_field& sheet = m.sfield(F_RIGHE); sheet.destroy(); _msk->reset_saldi(); for (int i = 1; i <= a.rows(); i++) { const TRectype& rec = a.row(i); _msk->rec2row(rec, i-1); TImporto imp; _msk->row2imp(i-1, imp); TImporto& sld = _msk->saldo(rec); sld -= imp; } } bool TMovanal_app::protected_record(TRectype& rec) { return rec.get_bool(MOVANA_BLOCCATO); } int TMovanal_app::write(const TMask& m) { m.autosave(*_rel); write_rows(m); return _rel->write(); } int TMovanal_app::rewrite(const TMask& m) { m.autosave(*_rel); write_rows(m); return _rel->rewrite(); } int TMovanal_app::read(TMask& m) { const int err = TRelation_application::read(m); if (err == NOERR) read_rows(m); return err; } void TMovanal_app::init_query_mode(TMask& m) { ((TMovanal_msk&)m).show_locked_buttons(); } void TMovanal_app::init_insert_mode(TMask& m) { ((TMovanal_msk&)m).show_locked_buttons(); } void TMovanal_app::init_modify_mode(TMask& m) { ((TMovanal_msk&)m).show_locked_buttons(); } void TMovanal_app::ini2sheet(TConfig& ini, TSheet_field& sheet) { TString8 para; para.format("%d,1", LF_RMOVANA); if (ini.set_paragraph(para)) // Esiste la prima riga? { TRectype rec(LF_RMOVANA); // Crea una riga di appoggio sheet.destroy(); // Azzera lo sheet _msk->reset_saldi(); // Azzera i saldi for (int r = 1; ; r++) { para.format("%d,%d", LF_RMOVANA, r); if (!ini.set_paragraph(para)) break; // Riempie il record temporaneo coi dati del .ini rec.zero(); for (int i = 0; i < rec.items(); i++) { const char* field = rec.fieldname(i); const TString& str = ini.get(field); if (str.full()) rec.put(field, str); } _msk->rec2row(rec, r-1); // Riempie la riga dello sheet a partire da record // Aggiorna saldo in base all'importo della riga TImporto imp; _msk->row2imp(r-1, imp); TImporto& sld = _msk->saldo(rec); sld -= imp; } } } void TMovanal_app::sheet2ini(TSheet_field& sheet,TConfig& ini) { TRectype rec(LF_RMOVANA); // Crea una riga di appoggio TString8 para; FOR_EACH_SHEET_ROW(sheet, i, row) { rec.zero(); rec.put(RMOVANA_NUMREG, _msk->get(F_NUMREG)); rec.put(RMOVANA_NUMRIG, i+1); _msk->row2rec(i, rec); para.cut(0) << LF_RMOVANA << ',' << (i+1); ini.set_paragraph(para); for (int i = 0; i < rec.items(); i++) { const char* field = rec.fieldname(i); const TString& str = rec.get(field); if (str.full()) ini.set(field, str); } } } bool TMovanal_app::user_create() { _rel = new TRelation(LF_MOVANA); _rel->file().set_curr(new TAnal_mov); _msk = new TMovanal_msk; return true; } bool TMovanal_app::user_destroy() { delete _msk; _msk = NULL; delete _rel; _rel = NULL; return true; } int ca2100(int argc, char* argv[]) { TMovanal_app app; app.run(argc, argv, "Movimenti analitici"); return 0; }