#include #include #include #include #include #include #include #include "../ca/calib01.h" #include "../ca/calib02.h" #include "../ca/commesse.h" #include "../ca/movana.h" #include "../ca/rmovana.h" #include "../ca/saldana.h" #include "../cg/cglib03.h" #include "../ve/velib.h" #include "../ve/velib04.h" #include "ps1001.h" #include "ps1001300a.h" /////////////////////////////////// // Metodi static di ordinamento /////////////////////////////////// //ordina per numreg/numrig (long+int) oppure per numreg/datacomp/autofcomp/datafcomp static int compare_by_numrig(TSheet_field& s, int r1, int r2) { TToken_string& s1 = s.row(r1); TToken_string& s2 = s.row(r2); //prima guarda il numreg.. const int numreg_pos = s.cid2index(S_NUMREG); const long b11 = s1.get_long(numreg_pos); const long b21 = s2.get_long(numreg_pos); int cmp = b11 - b21; if (cmp == 0) { if (b11 > 0) //..poi il numrig { const int numrig_pos = numreg_pos + 1; const int c11 = s1.get_int(numrig_pos); const int c21 = s2.get_int(numrig_pos); cmp = c11 - c21; } else //..oppure le date se numreg=0 (b11=b12 = 0) { const int datacomp_pos = s.cid2index(S_DATACOMP); const TDate d11 = s1.get(datacomp_pos); const TDate d21 = s2.get(datacomp_pos); cmp = int(d11 - d21); if (cmp == 0) { const int autofcomp_pos = s.cid2index(S_AUTOFCOMP); const char* e11 = s1.get(autofcomp_pos); const char* e21 = s2.get(autofcomp_pos); if (e11 == e21) { const int datafcomp_pos = s.cid2index(S_DATAFCOMP); const TDate f11 = s1.get(datafcomp_pos); const TDate f21 = s2.get(datafcomp_pos); cmp = int(f11 - f21); } } } } return cmp; } //nota: nelle ststic non si possono usare i _pos_quel, perchè sono di maschera //ordina le righe per cms/sede/fase/conto (string+string+string) static int compare_by_fase(TSheet_field & s, int r1, int r2) { TToken_string& s1 = s.row(r1); TToken_string& s2 = s.row(r2); const int tipo_pos = s.cid2index(S_TIPOMOV); const int cms_pos = s.cid2index(S_CMS); const int cdc_pos = s.cid2index(S_CDC); const int fase_pos = s.cid2index(S_FASE); const int conto_pos = s.cid2index(S_CONTO); TToken_string c1; c1.add(s1.get(tipo_pos)); c1.add(s1.get(cms_pos)); c1.add(s1.get(cdc_pos)); c1.add(s1.get(fase_pos)); c1.add(s1.get(conto_pos)); TToken_string c2; c2.add(s2.get(tipo_pos)); c2.add(s2.get(cms_pos)); c2.add(s2.get(cdc_pos)); c2.add(s2.get(fase_pos)); c2.add(s2.get(conto_pos)); int cmp = c1.compare(c2); if (cmp == 0) cmp = compare_by_numrig(s, r1, r2); return cmp; } /////////////////////////////////////////////////////////// // Recordset /////////////////////////////////////////////////////////// static TToken_string _commesse_supporto; class TCommesse_supporto_recordset : public TISAM_recordset { static bool cms_supp_filter(const TRelation* rel); protected: virtual void set_custom_filter(TCursor& cursor) const; public: TCommesse_supporto_recordset(const TString& query, const TToken_string& lista_cms_supp); }; bool TCommesse_supporto_recordset::cms_supp_filter(const TRelation* rel) { const TString& curr_codcms = rel->curr().get(RDOC_CODCMS); return _commesse_supporto.get_pos(curr_codcms) >= 0; } void TCommesse_supporto_recordset::set_custom_filter(TCursor& cursor) const { if (!_commesse_supporto.empty_items()) cursor.set_filterfunction(cms_supp_filter); } TCommesse_supporto_recordset::TCommesse_supporto_recordset(const TString& query, const TToken_string& lista_cms_supp) :TISAM_recordset(query) { _commesse_supporto = lista_cms_supp; } /////////////////////////////////////////////////////////// // TAutomask /////////////////////////////////////////////////////////// class TVariazione_budget_mask : public TAutomask { bool _dirty; bool _exclude_fasi; //posizioni dei vari campi dello sheet: vengono assegnati nel costruttore int _pos_cms, _pos_check, _pos_cdc, _pos_fase, _pos_conto, _pos_datacomp, _pos_autofcomp, _pos_datafcomp, _pos_cosric, _pos_imp, _pos_prev, _pos_mat, _pos_ipg, _pos_descr, _pos_numreg, _pos_numrig, _pos_tipomov; TToken_string _cms_supporto; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void set_status(bool edit); int load(); //(costruttore e on_field) carica i dati per riempire lo sheet long load_rmovana(const TString& cms, const bool include_cms_supp, TSheet_field& sf_righe); //(load()) carica le righe analitiche di preventivo int load_saldana(const TString& cms, const long max_numreg, TSheet_field& sf_righe); //(load()) carica le righe di saldo consuntivo void calcola_impegnato(const TString& cms, const bool include_cms_supp, TSheet_field& sf_righe); //(load()) aggiunge il valore dell'impegnato nella colonna corrispondente TToken_string& add_rmovana(const TRectype& movana, const TRectype& rmovana, TSheet_field& sf_righe); //(load_rmovana()) metodo di basso livello.. //..per caricare fisicamente le righe sullo sheet bool one_checked() const; //(on_field) controlla se nella colonna dei check ce ne è almeno 1 checkato void check_all(const bool checked); //(on_field) checka-dechecka la colonna dei check int find_sister_rows(const int curr_sister, int& first_sister, int& last_sister, const bool by_numreg = false); //(on_field) trova le righe.. //..con la stessa chiave della riga corrente e della chiave selezionata void build_key(int i, TToken_string& key); //(find_sister_rows) crea la chiave cdc/fase/conto della riga con cui cercare le sorelle void build_key_by_numreg(int i, TToken_string& key); //(find_sister_rows) crea la chiave numreg della riga con cui cercare le sorelle void sistema_date_cms(TDate& datainicms, TDate& datafinecms); void trova_cms_supporto(const TString& codcms); //(load(),on_field()) riempie la lista con le commesse di supporto valide int trova_riga_sullo_sheet(TSheet_field& sf_righe, const TString& cms, const TString& cdc, const TString& conto, const TString& fase); void aggiorna_saldi_preventivi(TSheet_field& sf_righe, const int curr_riga); //(load()) crea i saldi preventivi in base agli importi bool save_commessa(); //(save()) salva i cambiamenti di date della commessa esaminata bool save_sheet(); //(save()) salva i cambiamenti nello sheet bool save(); //(on_field) gestisce l'ordine dei salvataggi int modifica_movana(const long numreg, TSheet_field& sf_righe, const int r); //((save_sheet()) gestisce la modifica di movana esistenti int crea_movana(TSheet_field& sf_righe, const int n); //(save_sheet()) gestisce la creazione dei nuovi movana public: TVariazione_budget_mask(); ~TVariazione_budget_mask(); }; TVariazione_budget_mask::TVariazione_budget_mask() : TAutomask ("ps1001300a") { //carica la causale che trova nel ditta.ini TConfig ditta_ini(CONFIG_DITTA, "ps1001"); set(F_CODCAUS, ditta_ini.get("CodCaus"), 0x3); set(F_INCLUDESUPP, ditta_ini.get_bool("InclSupp")); //controlla se può usare le fasi o no, in base alla configurazione analitica di ditta //le fasi devono essere escluse se non sono obbligatorie nella configurazione dei movimenti di analitica! TConfig& caconfig = ca_config(); _exclude_fasi = !caconfig.get_bool("FscRequired"); //se le fasi non vanno considerate -> deve sparire la colonna corrispondente sullo sheet! TSheet_field& sf_righe = sfield(F_RIGHE); _pos_fase = sf_righe.cid2index(S_FASE); if (_exclude_fasi) sf_righe.delete_column(_pos_fase); //setta le posizioni dei campi dello sheet _pos_check = sf_righe.cid2index(S_CHECK); _pos_cms = sf_righe.cid2index(S_CMS); _pos_cdc = sf_righe.cid2index(S_CDC); _pos_conto = sf_righe.cid2index(S_CONTO); _pos_datacomp = sf_righe.cid2index(S_DATACOMP); _pos_autofcomp = sf_righe.cid2index(S_AUTOFCOMP); _pos_datafcomp = sf_righe.cid2index(S_DATAFCOMP); _pos_cosric = sf_righe.cid2index(S_COSRIC); _pos_imp = sf_righe.cid2index(S_IMPORTO); _pos_prev = sf_righe.cid2index(S_PREVENTIVO); _pos_mat = sf_righe.cid2index(S_MATURATO); _pos_ipg = sf_righe.cid2index(S_IMPEGNATO); _pos_descr = sf_righe.cid2index(S_DESCR); _pos_numreg = sf_righe.cid2index(S_NUMREG); _pos_numrig = sf_righe.cid2index(S_NUMRIG); _pos_tipomov = sf_righe.cid2index(S_TIPOMOV); } TVariazione_budget_mask::~TVariazione_budget_mask() { //salva nel ditta.ini la causale sulla maschera TConfig ditta_ini(CONFIG_DITTA, "ps1001"); ditta_ini.set("CodCaus", get(F_CODCAUS)); ditta_ini.set("InclSupp", get_bool(F_INCLUDESUPP)); } //crea la chiave cdc/fase/conto void TVariazione_budget_mask::build_key(int i, TToken_string& key) { TSheet_field& sf_righe = sfield(F_RIGHE); TToken_string& curr_riga = sf_righe.row(i); //chiave della riga sorella originale key.cut(0); key.add(curr_riga.get(_pos_cdc)); key.add(curr_riga.get(_pos_fase)); key.add(curr_riga.get(_pos_conto)); } //crea la chiave numreg/numrig o datacomp/autofcomp/datafcomp void TVariazione_budget_mask::build_key_by_numreg(int i, TToken_string& key) { TSheet_field& sf_righe = sfield(F_RIGHE); TToken_string& curr_riga = sf_righe.row(i); //chiave della riga sorella originale key.cut(0); key.add(curr_riga.get(_pos_numreg)); if (atol(key) == 0) { const TDate datacomp = curr_riga.get(_pos_datacomp); key.add(datacomp.date2ansi()); key.add(curr_riga.get(_pos_autofcomp)); const TDate datafcomp = curr_riga.get(_pos_datafcomp); key.add(datafcomp.date2ansi()); } } //cerca le righe sorelle per chiave cdc/fase/conto o numreg (dipende da by_numreg) int TVariazione_budget_mask::find_sister_rows(const int curr_sister, int& first_sister, int& last_sister, const bool by_numreg) { first_sister = last_sister = curr_sister; TToken_string key; if (by_numreg) build_key_by_numreg(curr_sister, key); else build_key(curr_sister, key); TToken_string key_iesima; for (int i = curr_sister - 1; i >= 0; i--) { if (by_numreg) build_key_by_numreg(i, key_iesima); else build_key(i, key_iesima); if (key == key_iesima) first_sister = i; else break; } TSheet_field& sf_righe = sfield(F_RIGHE); const long items = sf_righe.items(); for (int i = curr_sister + 1; i < items; i++) { if (by_numreg) build_key_by_numreg(i, key_iesima); else build_key(i, key_iesima); if (key == key_iesima) last_sister = i; else break; } return last_sister - first_sister + 1; } void TVariazione_budget_mask::sistema_date_cms(TDate& datainicms, TDate& datafinecms) { datainicms = get_date(F_DATAINICMS); const bool pro = get_bool(F_PROROGATA); if (pro) datafinecms = get_date(F_DATAPRORCMS); if (!pro || !datafinecms.ok()) datafinecms = get_date(F_DATAFINECMS); } void TVariazione_budget_mask::set_status(bool edit) { enable(-3, edit); enable(DLG_CANCEL, edit); enable(DLG_QUIT, !edit); enable(F_CODCMS, !edit); enable(F_DESCRIZ, !edit); xvtil_statbar_set(edit ? TR("Modifica") : TR("Selezione")); } bool TVariazione_budget_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { //maschera case F_CODCMS: if (e == fe_init) set_status(false); if (e == fe_modify) set_status(!o.empty() && load() > 0); break; case F_DATAINICMS: case F_DATAFINECMS: _dirty = true; break; case F_RIGHE: switch (e) { case se_query_add: return field(DLG_CANCEL).enabled(); case se_query_del: return false; case se_notify_add: { const TString& codcms = get(F_CODCMS); TMask& sheet_mask = sfield(F_RIGHE).sheet_mask(); sheet_mask.set(S_CMS, codcms); } break; default: break; } break; //sheet case S_CHECK: if (e == fe_modify) { //se viene checkata una riga deve uncheckare le sue sorelle di chiave TSheet_field& sf_righe = sfield(F_RIGHE); int curr = sf_righe.selected(), first, last; const int sisters = find_sister_rows(curr, first, last); for (int i = first; i <= last; i++) sf_righe.row(i).add(i == curr ? "X" : "", _pos_check); sf_righe.force_update(); } break; case S_DATACOMP: if (e == fe_modify) { TDate datainicms, datafinecms; sistema_date_cms(datainicms, datafinecms); const TDate datacomp = o.get(); if (datacomp < datainicms || (datafinecms.ok() && datacomp > datafinecms)) return o.error_box("La data competenza deve rientrare nella durata della commessa!"); _dirty = true; } break; case S_DATAFCOMP: if (e == fe_modify) { const TDate datafcomp = o.get(); if (datafcomp.ok()) { TDate datainicms, datafinecms; sistema_date_cms(datainicms, datafinecms); if (datafinecms.ok() && datafcomp > datafinecms) return o.error_box("La data fine competenza non può superare la data fine commessa!"); } _dirty = true; } break; case S_IMPORTO: if (e == fe_modify) { //se viene cambiato a mano un importo, deve aggiornare i saldi preventivi TSheet_field& sf_righe = sfield(F_RIGHE); const int curr_riga = sf_righe.selected(); sf_righe.row(curr_riga).add(o.get(), _pos_imp); aggiorna_saldi_preventivi(sf_righe, curr_riga); o.mask().set(S_PREVENTIVO, sf_righe.cell(curr_riga, _pos_prev)); sf_righe.force_update(); _dirty = true; } break; case S_SO: if (e == fe_init) { TMask& m = o.mask(); //maschera di riga const TString& contone = m.get(S_CONTO); m.set(S_GR, contone.left(3)); m.set(S_CO, contone.mid(3,3)); m.set(S_SO, contone.mid(6,6)); } if (e == fe_modify || e == fe_close) { TMask& m = o.mask(); //maschera di riga TString16 contone; contone << m.get(S_GR) << m.get(S_CO) << m.get(S_SO); m.set(S_CONTO, contone); //setta anche il valore di cos/ric TAnal_bill zione(contone, m.get(S_CDC), get(F_CODCMS), m.get(S_FASE)); const int indbillone = zione.indicatore_bilancio(); const char* str_indbillone = indbillone == 3 ? "C" : "R"; m.set(S_COSRIC, str_indbillone); //solo in chiusura di riga ricalcola il saldo consuntivo if (e == fe_close) { const TDate dataini, datafin; //recupera il saldo finale consuntivo! in base alla chiave cms/cdc/fase/conto e lo mette nel campo consuntivo const TSaldanal& saldanal_cons = ca_saldo(zione, dataini, datafin, _saldanal_consuntivo | _saldanal_ultima_imm); TImporto saldo_cons = saldanal_cons._fin; saldo_cons.normalize(indbillone == 3 ? 'D' : 'A'); const real saldo_cons_valore = saldo_cons.valore(); m.set(S_MATURATO, saldo_cons_valore); } } break; //bottoni case DLG_CANCEL: if (e == fe_button && jolly == 0) //jolly serve per specificare che è il DLG_CANCEL della maschera principale { if (_dirty && yesno_box("Salvare le modifiche effettuate?")) { //attenzione! se la save non riesce si deve fermare senza resettare le modifiche! if (!check_fields() || !save()) return false; } sfield(F_RIGHE).destroy(); set_status(false); return false; } break; case DLG_CHECKALL: if (e == fe_button) check_all(!one_checked()); break; case DLG_TODATAINI: if (e == fe_button) { const TString& datainicms = get(F_DATAINICMS); TSheet_field& sf_righe = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sf_righe, i, riga) if (riga->get_char(0) > ' ') //solo le righe checked!! riga->add(datainicms, _pos_datacomp); _dirty = true; sf_righe.force_update(); } break; case DLG_TODATAFIN: if (e == fe_button) { TString datafinecms = get(F_DATAPRORCMS); if (!datafinecms.full()) datafinecms = get(F_DATAFINECMS); TSheet_field& sf_righe = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sf_righe, i, riga) if (riga->get_char(0) > ' ') //solo le righe checked!! riga->add(datafinecms, _pos_datafcomp); _dirty = true; sf_righe.force_update(); } break; case DLG_TOMATURATO: if (e == fe_button) { TSheet_field& sf_righe = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sf_righe, i, riga) if (riga->get_char(0) > ' ') //solo le righe checked!! { //cerca le sorelle della riga int first, last; const int sisters = find_sister_rows(i, first, last); //calcola lo sbilancio tra i saldi maturati e preventivi: il suo scopo sarà quello di modificare gli importi in modo.. //..da azzerare tale sbilancio const real mat = real(riga->get(_pos_mat)); const real prev = real(riga->get(_pos_prev)); real sbilancio = mat - prev; //legge l'importo della riga checkata real imp = real(riga->get(_pos_imp)); //1) se la riga non ha sorelle -> modifica l'importo della riga stessa per azzerare lo sbilancio e stop! //2) se lo sbilancio è > 0 oppure se lo sbilancio è < 0 ma più piccolo dell'importo, basta agire sulla riga stessa.. //..per azzerare lo sbilancio e stop! if (sbilancio >= -imp || sisters == 1) { imp += sbilancio; sbilancio = ZERO; riga->add(imp.string(), _pos_imp); } //3) se invece ci sono sorelle oppure lo sbilancio è < 0 e più grande dell'importo della riga, allora vanno azzerate le.. //..righe sorelle partendo da quella checkata, poi passando all'ultima e risalendo fino a che lo sbilancio non si annulli.. //..Insomma una strage di righe che si azzerano else { riga->add("", _pos_imp); sbilancio += imp; for (int j = last; j >= first && !sbilancio.is_zero(); j--) { imp = sf_righe.cell(j, _pos_imp); if (j == first) { imp += sbilancio; sbilancio = ZERO; sf_righe.row(j).add(imp.string(), _pos_imp); } else { const real k = min(imp, -sbilancio); if (k > ZERO) { imp -= k; sbilancio += k; sf_righe.row(j).add(imp.string(), _pos_imp); } } } } //al termine deve aggiornare la colonna con i preventivi aggiorna_saldi_preventivi(sf_righe, i); } _dirty = true; sf_righe.force_update(); } break; case DLG_SAVEREC: if (e == fe_button && check_fields()) save(); break; default: break; } return true; } /////////////////////////////////// // Metodi della on_field_event /////////////////////////////////// //salva la commessa con le eventuali modifiche effettuate sulle date bool TVariazione_budget_mask::save_commessa() { TLocalisamfile commesse(LF_COMMESSE); commesse.put(COMMESSE_CODCMS, get(F_CODCMS)); int err = commesse.read(_isequal, _lock); if (err == NOERR) { commesse.put(COMMESSE_DATAINIZIO, get(F_DATAINICMS)); commesse.put(COMMESSE_DATAFINE, get(F_DATAFINECMS)); commesse.put(COMMESSE_PROROGA, get_bool(F_PROROGATA)); commesse.put(COMMESSE_DATAPROR, get(F_DATAPRORCMS)); commesse.put(COMMESSE_CHIUSA, get(F_CHIUSA)); //solo la rewrite perchè la commessa ovviamente esiste già err = commesse.rewrite(); } return err == NOERR; } //modifica movana esistente in base alle modifiche sulle righe int TVariazione_budget_mask::modifica_movana(const long numreg, TSheet_field& sf_righe, const int r) { TAnal_mov movana(numreg); int first, last; //prende tutte le sorelle della riga, così da aggiornare un movana alla volta const int sisters = find_sister_rows(r, first, last, true); //giro di controllo sulle date; le righe sheet, eventualmente modificate, devono avere un intervallo date.. //..compatibile con quello del movimento const TDate datacomp = movana.get_date(MOVANA_DATACOMP); const bool autofcomp = movana.get_bool(MOVANA_AUTOFCOMP); TDate datafcomp; if (!autofcomp) { datafcomp = movana.get_date(MOVANA_DATAFCOMP); if (!datafcomp.ok()) datafcomp = datacomp; } //controlla le righe sorelle dello sheet; se le date non rientrano in quelle della testata -> le righe.. //..vanno considerate nuove, e quindi va messo a 0 il loro numreg/numrig bool row_modified = false; for (int i = last; i >= first; i--) { //date testata const TDate r_datacomp = sf_righe.cell(i, _pos_datacomp); const bool r_autofcomp = *sf_righe.cell(i, _pos_autofcomp) > ' '; TDate r_datafcomp; if (!r_autofcomp) { r_datafcomp = sf_righe.cell(i, _pos_datafcomp); if (!r_datafcomp.ok()) r_datafcomp = r_datacomp; } //importo riga: se nullo la riga verrà eliminata in quanto inutile all'umanità const int r_numrig = atoi(sf_righe.cell(i, _pos_numrig)); const real r_importo = sf_righe.cell(i, _pos_imp); //le righe da liberare sono quelle che non rispettano i vincoli sulle date if (r_autofcomp != autofcomp || r_datacomp != datacomp || r_datafcomp != datafcomp || r_importo.is_zero()) { if (!r_importo.is_zero()) { sf_righe.row(i).add("", _pos_numreg); sf_righe.row(i).add("", _pos_numrig); } //elimina la riga dal movana (solo se appartiene al movana, ovvero numrig > 0) if (r_numrig > 0) row_modified |= movana.destroy_row(r_numrig, true); } else //qui invece ci vanno le righe modificate che sono solo da riscrivere (importo e/o descr modificate) { //se la riga non esiste va creata, sennò è proprio lei! TRectype& rmovana = r_numrig > 0 ? movana.body()[r_numrig] : movana.new_row(); //se la riga del movimento è nuova vanno riempiti tutti i campi if (r_numrig <= 0) { rmovana.put(RMOVANA_CODCMS, sf_righe.cell(i, _pos_cms)); if (!_exclude_fasi) rmovana.put(RMOVANA_CODFASE, sf_righe.cell(i, _pos_fase)); rmovana.put(RMOVANA_CODCCOSTO, sf_righe.cell(i, _pos_cdc)); rmovana.put(RMOVANA_CODCONTO, sf_righe.cell(i, _pos_conto)); rmovana.put(RMOVANA_DATACOMP, sf_righe.cell(i, _pos_datacomp)); } //importo const real importo = rmovana.get_real(RMOVANA_IMPORTO); if (importo != r_importo) { rmovana.put(RMOVANA_IMPORTO, r_importo); const char r_sezione = sf_righe.cell(i, _pos_cosric)[0] == 'C' ? 'D' : 'A'; rmovana.put(RMOVANA_SEZIONE, r_sezione); row_modified = true; } //descrizione const char* r_descr = sf_righe.cell(i, _pos_descr); const TString& descr = rmovana.get(RMOVANA_DESCR); if (descr != r_descr) { rmovana.put(RMOVANA_DESCR, r_descr); row_modified = true; } } } //for(int i=last;i<=first;i--)... if (row_modified) { TLocalisamfile file_movana(LF_MOVANA); if (movana.rows() > 0) { movana.update_totdoc(); movana.rewrite(file_movana); } else movana.remove(file_movana); } return last; } //crea un nuovo movana in base alle righe sullo sheet int TVariazione_budget_mask::crea_movana(TSheet_field& sf_righe, const int n) { TAnal_mov new_movana; //trovando numreg=0, le sorelle saranno solo quelle che hanno la stessa chiave datacomp/autofcomp/datafcomp,.. //..in modo da creare movana corretti in termini di date e coerenti con le righe contenute in loro int first, last; const int sisters = find_sister_rows(n, first, last, true); //datacomp/autofcomp/datafcomp vengono presi una volta per tutte le sorelle in quanto sono la chiave della sorellanza const bool r_autofcomp = *sf_righe.cell(n, _pos_autofcomp) > ' '; const TDate r_datacomp = sf_righe.cell(n, _pos_datacomp); TDate r_datafcomp = sf_righe.cell(n, _pos_datafcomp); if (!r_datafcomp.ok() && !r_autofcomp) r_datafcomp = r_datacomp; //riempie la testata del movana const TEsercizi_contabili ec; const int annoes = ec.date2esc(r_datacomp); new_movana.put(MOVANA_ANNOES, annoes); const TDate& datareg = get_date(F_DATAREG); new_movana.put(MOVANA_DATAREG, datareg); new_movana.put(MOVANA_DATACOMP, r_datacomp); new_movana.put(MOVANA_AUTOFCOMP, r_autofcomp); if (!r_autofcomp && r_datafcomp > r_datacomp) new_movana.put(MOVANA_DATAFCOMP, r_datafcomp); const TString& codcaus = get(F_CODCAUS); new_movana.put(MOVANA_CODCAUS, codcaus); TString descr; descr << TR("Preventivo commessa ") << get(F_CODCMS); new_movana.put(MOVANA_DESCR, descr); new_movana.put(MOVANA_TIPOMOV, 'P'); //giro sulle sorelle; ogni riga, se di importo non nullo, va aggiunta al new_movana for (int i = first; i <= last; i++) { const real importo = sf_righe.cell(i, _pos_imp); if (!importo.is_zero()) { //aggiunge la rmovana al movana TRectype& new_rmovana = new_movana.new_row(); //compila la rmovana new_rmovana.put(RMOVANA_ANNOES, annoes); new_rmovana.put(RMOVANA_DATACOMP, r_datacomp); new_rmovana.put(RMOVANA_CODCMS, get(F_CODCMS)); const TString& cdc = sf_righe.cell(i, _pos_cdc); new_rmovana.put(RMOVANA_CODCCOSTO, cdc); if (!_exclude_fasi) { const TString& fase = sf_righe.cell(i, _pos_fase); new_rmovana.put(RMOVANA_CODFASE, fase); } const TString& conto = sf_righe.cell(i, _pos_conto); new_rmovana.put(RMOVANA_CODCONTO, conto); const TString& sezione = sf_righe.cell(i, _pos_cosric); new_rmovana.put(RMOVANA_SEZIONE, sezione == "C" ? 'D' : 'A'); new_rmovana.put(RMOVANA_IMPORTO, importo); const TString& descr = sf_righe.cell(i, _pos_descr); new_rmovana.put(RMOVANA_DESCR, descr); } } //for(int i = last; i >= first; i--)... //alla fine si scrive il nuovo movana solo se ha righe!!! if (new_movana.rows() > 0) { new_movana.update_totdoc(); TLocalisamfile file_movana(LF_MOVANA); new_movana.write(file_movana); } return last; } //salva lo sheet...lasciate ogni speranza voi che entrate! bool TVariazione_budget_mask::save_sheet() { //1) ordina le righe per numreg/numrig TSheet_field& sf_righe = sfield(F_RIGHE); sf_righe.sort(compare_by_numrig); //2) Aggiorna i movana con le righe di loro competenza: registra solo le righe con NUMREG !=0 FOR_EACH_SHEET_ROW(sf_righe, r, riga) { const long numreg = riga->get_long(_pos_numreg); if (numreg > 0) r = modifica_movana(numreg, sf_righe, r); } //FOR_EACH_SHEET_ROW(... //riordina lo sheet per chiave numreg; in questo modo le righe senza numreg vanno all'inizio e vengono.. //..ordinate per datacomp/autofcomp/datafcomp; tali righe, se hanno importo != 0, vengono aggiunte ad.. //..un nuovo movimento analitico che viene creato sul campo! sf_righe.sort(compare_by_numrig); //3)cerca le sorelle per numreg/numrig: righe con NUMREG = 0 FOR_EACH_SHEET_ROW(sf_righe, n, line) { const long numreg = sf_righe.row(n).get_long(_pos_numreg); //l'ultima sort mette in cima allo sheet tutte le righe con numreg=0; quindi alla prima con numreg>0.. //..tanto vale uscire definitivamente if (numreg != 0) break; n = crea_movana(sf_righe, n); } //FOR_EACH_SHEET_ROW(sf_righe,n... //le righe vanno rimesse in ordine di chiave cdc/fase/conto set_status(load() > 0); return true; } bool TVariazione_budget_mask::save() { //salva nel ditta.ini la causale sulla maschera TConfig ditta_ini(CONFIG_DITTA, "ps1001"); ditta_ini.set("CodCaus", get(F_CODCAUS)); //salva le modifiche alle date della commessa e lo sheet if (save_commessa() && save_sheet()) _dirty = false; return true; } //controlla sulla colonna delle spunte se almeno una è checkata bool TVariazione_budget_mask::one_checked() const { TSheet_field& sf_righe = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sf_righe, i, riga) { if (riga->get_char(0) > ' ') return true; } return false; } //checka-dechecka la colonna di spunte dello sheet void TVariazione_budget_mask::check_all(const bool checked) { TSheet_field& sf_righe = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sf_righe, i, riga) { int first, last; find_sister_rows(i, first, last); for (int j = first; j <= last; j++) sf_righe.row(j).add(j == last ? "X" : "", _pos_check); i = last; } sf_righe.force_update(); } //aggiorna la colonna con i saldi preventivi sullo sheet void TVariazione_budget_mask::aggiorna_saldi_preventivi(TSheet_field& sf_righe, const int curr_riga) { int first, last; const int sisters = find_sister_rows(curr_riga, first, last); //calcola il totale degli importi delle righe sorelle in modo da avere il saldo real saldo_prev; for (int j = first; j <= last; j++) { TString80 str_imp = sf_righe.row(j).get(_pos_imp); saldo_prev += real(str_imp); } //mette il saldo in tutte le righe sorelle for (int j = first; j <= last; j++) { TToken_string& row = sf_righe.row(j); row.add(saldo_prev.string(), _pos_prev); } } //in base alla commessa parametro, trova tutte le commesse di supporto void TVariazione_budget_mask::trova_cms_supporto(const TString& codcms) { const TRectype& rec_cms = cache().get(LF_COMMESSE, codcms); const bool is_cms_supporto = rec_cms.get_bool(COMMESSE_APPOGGIO); //comunque la commessa selezionata ci va _cms_supporto = codcms; //tutto il casino vale solo per le commesse normali; se viene selezionata una commessa di supporto.. //..si può agire solo su di lei! if (!is_cms_supporto) { const TDate cms_dataini = rec_cms.get_date(COMMESSE_DATAINIZIO); TDate cms_datafine; const bool pro = rec_cms.get_bool(COMMESSE_PROROGA); if (pro) cms_datafine = rec_cms.get_date(COMMESSE_DATAPROR); if (!pro || !cms_datafine.ok()) cms_datafine = rec_cms.get_date(COMMESSE_DATAFINE); TString query; query << "USE COMMESSE\n"; query << "SELECT ((APPOGGIO=\"X\")&&((NUM(ANSI(DATAINIZIO)<=ANSI(#DATAFINECMS)))&&(NUM(ANSI(DATAFINE)>=ANSI(#DATAINIZIOCMS)))))\n"; TISAM_recordset commesse(query); commesse.set_var("#DATAFINECMS", cms_datafine); commesse.set_var("#DATAINIZIOCMS", cms_dataini); const int items = commesse.items(); for(bool ok = commesse.move_first(); ok; ok = commesse.move_next()) _cms_supporto.add(commesse.get(COMMESSE_CODCMS).as_string()); } //alla fine assegna al campo lista S_CMS della maschera di riga i valori possibili della lista TMask& sheet_mask = sfield(F_RIGHE).sheet_mask(); TList_field& cms_list = sheet_mask.lfield(S_CMS); cms_list.replace_items(_cms_supporto, _cms_supporto); sheet_mask.reset(); } int TVariazione_budget_mask::trova_riga_sullo_sheet(TSheet_field& sf_righe, const TString& cms, const TString& cdc, const TString& conto, const TString& fase) { int index = -1; //cerca una riga con la medesima chiave sullo sheet for (index = sf_righe.items() - 1; index >= 0; index--) { TToken_string& row = sf_righe.row(index); TString80 cod_row = row.get(_pos_cms); cod_row.trim(); if (cms != cod_row) continue; cod_row = row.get(_pos_cdc); cod_row.trim(); if (cdc != cod_row) continue; cod_row = row.get(_pos_conto); cod_row.trim(); if (conto != cod_row) continue; if (!_exclude_fasi) { cod_row = row.get(_pos_fase); cod_row.trim(); if (fase != cod_row) continue; } break; } return index; } TToken_string& TVariazione_budget_mask::add_rmovana(const TRectype& movana, const TRectype& rmovana, TSheet_field& sf_righe) { //chiave iniziale di riga const TString80 cms = rmovana.get(RMOVANA_CODCMS); const TString80 cdc = rmovana.get(RMOVANA_CODCCOSTO); const TString80 conto = rmovana.get(RMOVANA_CODCONTO); TString80 fase = rmovana.get(RMOVANA_CODFASE); int index = -1; if (_exclude_fasi) { fase.cut(0); index = trova_riga_sullo_sheet(sf_righe, cms, cdc, conto, fase); } TToken_string& row = sf_righe.row(index); //Perte comune a un sacco di campi; va fatta comunque //costo o ricavo? all'indbil l'ardua sentenza! TAnal_bill bill(conto, cdc, cms, fase); const int indbil = bill.indicatore_bilancio(); const char* str_indbil = indbil == 3 ? "C" : "R"; row.add(str_indbil, _pos_cosric); //deve creare una riga nuova if (index < 0) { row.add(cms, _pos_cms); row.add(cdc, _pos_cdc); row.add(conto, _pos_conto); if (!_exclude_fasi) row.add(fase, _pos_fase); //date competenza iniziale e finale const TDate datacomp = movana.get_date(MOVANA_DATACOMP); TDate datafcomp = movana.get_date(MOVANA_DATAFCOMP); const bool autofcomp = movana.get_bool(MOVANA_AUTOFCOMP); if (!datafcomp.ok() && !autofcomp) datafcomp = datacomp; row.add(datacomp, _pos_datacomp); row.add(autofcomp ? "X" : "", _pos_autofcomp); //se c'è l'auto fine competenza la cella con la data fine competenza va svuotata.. //..e disabilitata senno' ci va messa e basta if (!autofcomp) row.add(datafcomp, _pos_datafcomp); else sf_righe.disable_cell(sf_righe.items() - 1, _pos_datafcomp); //completa la riga row.add(rmovana.get(RMOVANA_DESCR), _pos_descr); //il numreg lo deve ricordare per le righe di appoggio const long numreg = rmovana.get_long(RMOVANA_NUMREG); row.add(numreg, _pos_numreg); row.add(rmovana.get_int(RMOVANA_NUMRIG), _pos_numrig); const TString& tipomov = movana.get(MOVANA_TIPOMOV); row.add(tipomov, _pos_tipomov); const TDate dataini, datafin; //recupera il saldo finale consuntivo! in base alla chiave cms/cdc/fase/conto e lo mette nel campo consuntivo const TSaldanal& saldanal_cons = ca_saldo(bill, dataini, datafin, _saldanal_consuntivo | _saldanal_ultima_imm); TImporto saldo_cons = saldanal_cons._fin; saldo_cons.normalize(indbil == 3 ? 'D' : 'A'); const real saldo_cons_valore = saldo_cons.valore(); row.add(saldo_cons_valore.string(), _pos_mat); } real valore = rmovana.get_real(RMOVANA_IMPORTO); const char sezione = rmovana.get_char(RMOVANA_SEZIONE); TImporto importo(sezione, valore); importo.normalize(indbil == 3 ? 'D' : 'A'); valore = row.get(_pos_imp); valore += importo.valore(); row.add(valore.string(), _pos_imp); return row; } long TVariazione_budget_mask::load_rmovana(const TString& cms, const bool include_cms_supp, TSheet_field& sf_righe) { TString query; query << "USE RMOVANA KEY 4\n"; query << "SELECT ((MOVANA.TIPOMOV=\"P\")||(MOVANA.TIPOMOV=\"V\"))\n"; query << "JOIN MOVANA INTO NUMREG==NUMREG\n"; query << "FROM CODCMS=#CODCMS\n"; query << "TO CODCMS=#CODCMS\n"; //instanzio un TISAM_recordset sulle rmovana TISAM_recordset recset(query); recset.set_var("#CODCMS", cms); const long recset_items = recset.items(); TProgind pi(recset_items, TR("Caricamento righe..."), true, true); //riempie lo string_array _cms_supporto in base ai parametri della commessa scelta.. //..e al fatto che l'utente lo voglia o meno... if (include_cms_supp) trova_cms_supporto(cms); TAssoc_array numreg_cms; long max_numreg = 0L; //per ogni riga del recordset va ad aggiornare lo sheet sulla maschera (aggiunge la riga) const TRectype& movana = recset.cursor()->curr(LF_MOVANA); const TRectype& rmovana = recset.cursor()->curr(LF_RMOVANA); for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { if (!pi.addstatus(1)) break; TToken_string& row = add_rmovana(movana, rmovana, sf_righe); const char* str_numreg = row.get(_pos_numreg); numreg_cms.add(str_numreg); const long numreg = atol(str_numreg); if (numreg > max_numreg) max_numreg = numreg; } //for(bool ok.move.... //panegirico per trovare le righe delle commesse di supporto //ovviamente ce ne deve essere almeno 1, quindi.. if (_cms_supporto.items() > 1 && include_cms_supp) { FOR_EACH_ASSOC_OBJECT(numreg_cms, obj, key, itm) { TAnal_mov movana(atol(key)); const int righe_movana = movana.rows(); for (int r = 1; r <= righe_movana; r++) { const TRectype& rec_rmovana = movana.body()[r]; const TString& curr_cms = rec_rmovana.get(RMOVANA_CODCMS); if (_cms_supporto.get_pos(curr_cms) > 0) // NON >= o ci metterebbe anche la commessa standard!!!! { TToken_string& row = add_rmovana(movana, rec_rmovana, sf_righe); row.add("S", _pos_tipomov); //è una riga di 'S'upporto } } } } //if (_cms_supporto.items() > 1) //prima di riempire lo sheet a video ordina le righe per tipo/cms/sede/fase/numreg/numrig sf_righe.sort(compare_by_fase); //in base alle righe caricate ricava i saldi preventivi FOR_EACH_SHEET_ROW(sf_righe, i, riga) { //solo le righe a saldo preventivo nullo vanno considerate const TString& str_saldo_prev = riga->get(_pos_prev); if (str_saldo_prev.blank()) aggiorna_saldi_preventivi(sf_righe, i); } return max_numreg; } int TVariazione_budget_mask::load_saldana(const TString& cms, const long max_numreg, TSheet_field& sf_righe) { //caricamento di tutti i saldi consuntivi che riguardano la commessa //chiave 2 per averli ordinati per conto TString query; query << "USE SALDANA KEY 2\n"; query << "SELECT (COMMESSA=#CODCMS)\n"; //instanzio un TISAM_recordset sui saldana TISAM_recordset saldana(query); saldana.set_var("#CODCMS", cms); const long saldana_items = saldana.items(); TProgind pi(saldana_items, TR("Caricamento saldi consuntivi..."), true, true); TAssoc_array chiavi_saldana; TToken_string chiave; //riempie l'assoc_array conto/cdc/cms/fase/saldo for (bool ok = saldana.move_first(); ok; ok = saldana.move_next()) { const TString& conto = saldana.get(SALDANA_CONTO).as_string(); const TString& cdc = saldana.get(SALDANA_COSTO).as_string(); const TString& fase = saldana.get(SALDANA_FASE).as_string(); const real saldop = saldana.get(SALDANA_SALDOP).as_real(); const real saldo = saldana.get(SALDANA_SALDO).as_real(); //solo i record senza saldop vanno considerati!!! Quelli con con saldop != 0 vengono fuori in load_rmovana if (saldop.is_zero() && saldo != ZERO) { chiave.cut(0); chiave.add(conto); chiave.add(cdc); chiave.add(cms); //le fasi vanno aggiunte alla chiave solo se specificato (Adolf rikiesten 20/07/2010) if (!_exclude_fasi) chiave.add(fase); //se non trova la chiave la aggiunge TImporto* s = (TImporto*)chiavi_saldana.objptr(chiave); if (s == NULL) { s = new TImporto; chiavi_saldana.add(chiave, s); } //poi somma il saldo (come importo!) const char sez = saldana.get(SALDANA_SEZIONE).as_string()[0]; TImporto imp_saldo_curr(sez, saldo); *s += imp_saldo_curr; } } //ricava le date da mettere nelle righe generate da saldana e l'eventuale autofcomp TDate datacomp(TODAY), datafcomp(TODAY); bool autofcomp = false; if (max_numreg > 0) { FOR_EACH_SHEET_ROW(sf_righe, r, riga) { const long curr_numreg = riga->get_long(_pos_numreg); if (curr_numreg == max_numreg) { const int curr_numrig = riga->get_int(_pos_numrig); if (curr_numrig > 0) { datacomp = riga->get(_pos_datacomp); datafcomp = riga->get(_pos_datafcomp); autofcomp = riga->get_char(_pos_autofcomp) > ' '; break; } } } } //per ogni riga dell'assoc_array con conto/cdc/cms/fase/saldo va ad aggiornare lo sheet sulla maschera (aggiunge la riga) FOR_EACH_ASSOC_OBJECT(chiavi_saldana, obj, key, itm) { if (!pi.addstatus(1)) break; //estrae l'elemento dell'assoc_array TToken_string key_bill(key); const TString80 conto = key_bill.get(0); const TString80 cdc = key_bill.get(1); const TString80 cms = key_bill.get(2); TString16 fase; if (!_exclude_fasi) fase << key_bill.get(3); TToken_string& row = sf_righe.row(-1); row.add(cms, _pos_cms); row.add(cdc, _pos_cdc); if (!_exclude_fasi) row.add(fase, _pos_fase); row.add(conto, _pos_conto); row.add(datacomp, _pos_datacomp); row.add(autofcomp ? "X" : "", _pos_autofcomp); row.add(datafcomp, _pos_datafcomp); if (autofcomp) sf_righe.disable_cell(sf_righe.items() - 1, _pos_datafcomp); //costo o ricavo? all'indbil l'ardua sentenza! TAnal_bill bill(conto, cdc, cms, fase); const int indbil = bill.indicatore_bilancio(); const char* str_indbil = indbil == 3 ? "C" : "R"; row.add(str_indbil, _pos_cosric); TImporto& saldo_cons = *(TImporto*)itm; saldo_cons.normalize(indbil == 3 ? 'D' : 'A'); const real saldo_cons_valore = saldo_cons.valore(); row.add(saldo_cons_valore.string(), _pos_mat); //aggiunge una descrizione civetta row.add("Riga da saldo", _pos_descr); //ci mette il max_numreg row.add(max_numreg, _pos_numreg); //segna il tipo riga come saldo row.add("P", _pos_tipomov); } //prima di riempire lo sheet a video ordina le righe per tipo/cms/sede/fase/numreg/numrig sf_righe.sort(compare_by_fase); return sf_righe.items(); } void TVariazione_budget_mask::calcola_impegnato(const TString& cms, const bool include_cms_supp, TSheet_field& sf_righe) { //trova tutte le numerazioni di tipo ordine valide in base ai tipi documento ordine (metodo di velib01 preso da ca3883) //solo le numerazioni con almeno un tipo documento ordine interessano TString_array num_ordini, tip_ordini; const int numerazioni_tipo_ordine = numerazioni_ordini(num_ordini, tip_ordini); //le commesse di cui tenere conto sono quella selezionata dall'utente e quelle di supporto; questo elenco di commesse è.. //..già stato riempito ad inizio programma e messo nella token_string _cms_supporto const int commesse_da_controllare = _cms_supporto.items(); //date ed anni degli ordini; sono ammessi ordini di 1 anno prima dell'inizio commessa, ma entro l'anno di fine (non esistono.. //..in genere ordini successivi alla fine della commessa, ma solo fatture e parcelle) const TDate data_inizio_cms = get_date(F_DATAINICMS); const int da_anno = data_inizio_cms.year() - 1; const TDate data_fine_cms = get_date(F_DATAFINECMS); const int a_anno = data_fine_cms.year(); //simpatica progind per intrattenere l'utonto TProgind pi(numerazioni_tipo_ordine, "Calcolo dell'impegnato...", true, true); for (int n = 0; n < numerazioni_tipo_ordine; n++) { //aggiornamento progind intrattenitiva if (!pi.addstatus(1)) break; const TString4 codnum = num_ordini.row(n); //cerca tutte le righe documento che soddisfano i numerosi parametri TString query; query << "USE RDOC"; query << "\nJOIN DOC INTO PROVV==PROVV ANNO==ANNO CODNUM==CODNUM NDOC==NDOC"; //le testate servono per controllo tipo (vedi sotto) query << "\nFROM CODNUM=#CODNUM ANNO=#DAANNO"; query << "\nTO CODNUM=#CODNUM ANNO=#AANNO"; //usando il magico TCommesse_supporto_recordset vengono scartate tutte le righedoc che non hanno commessa corretta,.. //..ovvero le commesse che non appartengono alla lista _cms_supporto TCommesse_supporto_recordset recset(query, _cms_supporto); recset.set_var("#CODNUM", codnum); recset.set_var("#DAANNO", (long)da_anno); recset.set_var("#AANNO", (long)a_anno); const TRecnotype recset_items = recset.items(); //memorizza l'ultimo doc per evitare doppioni in caso di doc con più righe (rielaborerebbe.. //..lo stesso documento tante volte quante sono le sue righe!) TString old_key; TString16 last_conto, last_fase; //contatori interni ad un documento che serve per legare le righe spese% con le righe prestazioni.. TString80 last_cdc; //..distruggono la supersimmetria del programma ma le righe spese% non hanno in genere conti associati //deve controllare che le righe appartengano a documenti di TIPO valido (il filtro è stato sulle numerazioni,.. //..quindi ci potrebbero essere finiti dentro tipi non desiderati) for (bool ok = recset.move_first(); ok; ok = recset.move_next()) //giro sulle varie rdoc... { const TRectype& curr_doc = recset.cursor()->curr(LF_DOC); //controlla se il documento contenente la riga è davvero un ordine ricontrollando il suo tipo nell'array.. //..con i tipi validi; se non lo fosse...ciao ciao rigadocumento! const TString& tipodoc = curr_doc.get(DOC_TIPODOC); if (tip_ordini.find(tipodoc) < 0) continue; //la riga documento non deve risultare contabilizzata! infatti, se lo fosse, i suoi valori apparirebbero.. //..nella sezione delle rmovana (è pressochè impossibile che un ordine venga contabilizzato, ma le vie di.. //..Dinamica sono infinite.. const long numregca = curr_doc.get_long(DOC_NUMREGCA); //se la rigadoc non è stata contabilizzata.. if (numregca == 0) { //magico trucco per non dover ricontabilizzare lo stesso documento tante volte quante sono le righe consecutive const TString curr_key = curr_doc.build_key(); if (curr_key == old_key) continue; else { old_key = curr_key; last_conto.cut(0); last_cdc.cut(0); last_fase.cut(0); } //crea il documento virtuale in memoria; se non è ordine lo saltiamo!!! ole'! TDocumento doc(curr_doc); if (!doc.is_ordine()) continue; //contabilizza l'ordine in finto movimento di analitica in modo da riprodurre il funzionamento.. //..del mitico rendiconto, lo Zeus dei programmi di analitica; in questo modo sistema tutti i problemi.. //..che vengono creati dalle righe di casse profesionali, irap, inps e cazzi simili TContabilizzazione_analitica cont_anal; TAnal_mov finto_movana; cont_anal.elabora(doc, 0L, NULL, false, finto_movana, false); //analizza il finto movana riga x riga const int anal_rows = finto_movana.rows(); for (int j = 1; j <= anal_rows; j++) { const TRectype& riga_finto_movana = finto_movana.body()[j]; //dalla riga analitica estrae i dati che servono per posizionare i valori nello sheet const TString80 rmovana_cms = riga_finto_movana.get(RMOVANA_CODCMS); //la riga è buona solo se ha commessa valida, ovvero quella selezionata o una di supporto if (_cms_supporto.get_pos(rmovana_cms) >= 0) { const TString80 rmovana_cdc = riga_finto_movana.get(RMOVANA_CODCCOSTO); TString16 rmovana_fase = riga_finto_movana.get(RMOVANA_CODFASE); //la fase potrebbe non esserci! if (_exclude_fasi) rmovana_fase.cut(0); TString80 rmovana_conto = riga_finto_movana.get(RMOVANA_CODCONTO); const char rmovana_sez = riga_finto_movana.get_char(RMOVANA_SEZIONE); const real rmovana_valore = riga_finto_movana.get_real(RMOVANA_IMPORTO); //se l'importo è nullo è inutile perdere tempo if (rmovana_valore.is_zero()) continue; //cerca una riga con la medesima chiave sullo sheet int index = trova_riga_sullo_sheet(sf_righe, rmovana_cms, rmovana_cdc, rmovana_conto, rmovana_fase); //se la riga non esiste, siamo in presenza di un caso di solo documento di impegnato (ordine) senza alcun.. //..movimento analitico di preventivo sulla stessa chiave (cms-cdc-conto); quindi provvede ad aggiungere.. //..tale riga allo sheet (ovviamente non c'è, perchè non esistendo movimenti non poteva esserci la riga).. //..mettendola però disabilitata per evitare casini di tipo scrittura sul campo importo!!! (tenterebbe.. //..di creare un rmovana da un rdoc senza alcuna cognizione di causa!! in più non si possono creare rmovana.. //..da rdoc di ordini) if (index < 0 && rmovana_conto.full() && rmovana_cms == _cms_supporto.get(0)) { TToken_string& riga = add_rmovana(finto_movana, riga_finto_movana, sf_righe); riga.add("", _pos_imp); index = sf_righe.items()-1; sf_righe.disable_row(index); } if (index >= 0) { TToken_string& row = sf_righe.row(index); #ifdef DBG if (rmovana_conto == "004001000015") int cazzone = 1; #endif real row_valore_impegnato = row.get(_pos_ipg); row_valore_impegnato += rmovana_valore; row.add(row_valore_impegnato.string(), _pos_ipg); last_conto = rmovana_conto; last_cdc = rmovana_cdc; last_fase = rmovana_fase; } } //if(_cms_supporto.get_pos(rmovana_cms) >= 0) } //for (int j = 1; j <= anal_rows; j++) } //if (numregca == 0)... } //for (bool ok = recset.move_first()... } //for (int n = 0... } int TVariazione_budget_mask::load() { //commessa in esame const TString& cms = get(F_CODCMS); //deve includere anche le righe con commesse di supporto? const bool include_cms_supp = get_bool(F_INCLUDESUPP); //recupero sheet e realtiva mashera di riga TSheet_field& sf_righe = sfield(F_RIGHE); TMask& msk = sf_righe.sheet_mask(); sf_righe.destroy(); //carica le righe dei movimenti preventivi const long max_numreg = load_rmovana(cms, include_cms_supp, sf_righe); //carica le righe dei saldi consuntivi const int righe_saldana = load_saldana(cms, max_numreg, sf_righe); //calcola l'impegnato per ogni riga dello sheet che è stato riempito calcola_impegnato(cms, include_cms_supp, sf_righe); //e poi aggiorna il video! sf_righe.force_update(); //al momento del caricamento NON ci sono state modifiche! _dirty = false; return sf_righe.items(); } /////////////////////////////////////// // TSkeleton_application /////////////////////////////////////// class TVariazione_budget : public TSkeleton_application { protected: virtual bool check_autorization() const { return false; } virtual const char* extra_modules() const { return "ca"; } virtual void main_loop(); }; void TVariazione_budget::main_loop() { TVariazione_budget_mask msk; msk.run(); } int ps1001300 (int argc, char* argv[]) { TVariazione_budget main_app; main_app.run(argc, argv, TR("Gestione budget per commessa")); return true; }