#include #include #include #include #include #include #include "ce1.h" #include "ce1500a.h" #include "ce2101.h" #include "celib.h" #include "../cg/cglib01.h" #include #include #include #include #include "ammce.h" #include "ammmv.h" #include "cespi.h" #include "movce.h" #include "salce.h" //-------------------------------------------------- // DICHIARAZIONE APPLICAZIONE //-------------------------------------------------- class TMov_qmask; class TMov_emask; class TMovicespi : public TRelation_application { TRelation* _rel; TMov_qmask* _qmask; TMov_emask* _emask; TFilename _prima_nota; private: void kill_mov(const TString& idcespite, const TString& idmov, int lfile); void kill_rett(const TString& id, const TString& idmov); void set_prompt(TMask_field& fld, bool plus); void show_plus_minus(TMask& m); protected: virtual bool changing_mask(int mode) { return TRUE; } virtual TMask* get_mask(int mode); virtual const char* get_next_key(); virtual bool protected_record(TRelation &r); virtual bool user_create(); virtual bool user_destroy(); virtual void init_query_mode(TMask& m); virtual void init_insert_mode(TMask& m); virtual void init_modify_mode(TMask& m); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); virtual bool remove(); public: virtual TRelation* get_relation() const { return _rel; } void calc_residuo(long numreg); void cg_mode(); int init_mask(TMask& m); void save_if_dirty(); }; TMovicespi& app() { return (TMovicespi&)main_app(); } //--------------------------------------------------------- // MASCHERA DI RICERCA (ce1500a) //--------------------------------------------------------- class TMov_qmask : public TAutomask { int _staat; protected: virtual bool can_be_closed() const; virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void on_user_search(TOperable_field& o); virtual void on_firm_change(); int calcola_stato_attivita(); int create_fields(int x, int y, short key_id); public: int stato_attivita() const { return _staat; } TMov_qmask(); }; void TMov_qmask::on_user_search(TOperable_field& o) { TToken_string order, fields, header; const TFieldref* campo = o.field(); //ordinare per campo personalizzato/idcespite/descrizione order.format("%d->%s", LF_CESPI, (const char*)campo->name()); TString prompt = o.prompt(); prompt << "@" << o.size(); //lunghezza del prompt del campo header.add(prompt); order.add(MOVCE_IDMOV); header.add(TR("Movimento@11")); fields = order; fields.add(MOVCE_DESC); header.add(FR("Descrizione@50")); fields.add(MOVCE_IDCESPITE); header.add(TR("Cespite@10")); TString desc_cesp; desc_cesp.format("%d->%s", LF_CESPI, "DESC"); fields.add(desc_cesp); header.add(FR("Descrizione cespite@50")); TRelation rel(LF_MOVCE); rel.add(LF_CESPI, "IDCESPITE==IDCESPITE"); TSorted_cursor cur(&rel, order); TCursor_sheet sht(&cur, fields, TR("Movimenti"), header, 0, 1); if (sht.run() == K_ENTER) { TToken_string& row = sht.row(); set(F_IDMOV, row.get(1), TRUE); stop_run(K_AUTO_ENTER); } } int TMov_qmask::calcola_stato_attivita() { const int ese = get_int(F_ESERCIZIO); const int gru = get_int(F_GRUPPO); const char* spe = get(F_SPECIE); TString16 str; str.format("%04d%02d%-4s", ese, gru, spe); const TRectype& curr_ccb = cache().get("CCB", str); if (curr_ccb.get_bool("B1")) // Bollato stampato _staat = 3; else { TEsercizi_contabili esc; str.format("%04d%02d%-4s", esc.pred(ese), gru, spe); const TRectype& prev_ccb = cache().get("CCB", str); _staat = prev_ccb.get_bool("B1") ? 2 : 1; } ditta_cespiti().set_attivita(ese, gru, spe); return _staat; } bool TMov_qmask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_ESERCIZIO: if ((e == fe_close || e == fe_modify) && efield(F_INIZIO_ES).empty()) return error_box("Inserire un esercizio valido"); case F_GRUPPO: case F_SPECIE: calcola_stato_attivita(); enable(DLG_NEWREC, _staat != 3); break; case F_IMPIANTO: case F_IDCESPITE: if (e == fe_modify) { const TString& ces = get(F_IDCESPITE); const TString& imp = get(F_IMPIANTO); const bool cesok = !real::is_null(ces); const bool impok = !real::is_null(imp); TString80 filter; if (cesok) filter << MOVCE_IDCESPITE << "==\"" << ces << '"'; if (impok) { if (cesok) filter << ")&&("; filter << LF_CESPI << "->" << CESPI_CODIMP << "==\"" << imp << '"'; if (cesok) { filter << ')'; filter.insert("(", 0); } } TEdit_field& m = efield(F_IDMOV); m.browse()->set_filter(filter); } break; case F_NUMREG: if (e == fe_modify) { TEdit_field& m = efield(F_IDMOV); if (!m.empty()) m.on_key(K_TAB); } break; case F_CGROWS: if (e == se_query_add || e == se_query_del) return FALSE; break; case DLG_QUIT: if (e == fe_button) { TMask_field& f = efield(F_TOTRES); if (f.shown() && !f.empty()) return yesno_box(TR("Attenzione: la registrazione contabile non è ancora del tutto evasa:\n" "Si desidera uscire ugualmente?")); } break; case F_USER: case F_USER+1: case F_USER+2: case F_USER+3: case F_USER+4: case F_USER+5: if (e == fe_button) on_user_search(o); break; default: break; } return TRUE; } bool TMov_qmask::can_be_closed() const { TButton_field& f = (TButton_field&)field(DLG_QUIT); return ((TMov_qmask*)this)->on_field_event(f, fe_button, 0); } void TMov_qmask::on_firm_change() { TAutomask::on_firm_change(); ditta_cespiti().init_mask(*this); } TMov_qmask::TMov_qmask() : TAutomask("ce1500a") { first_focus(F_IDMOV); create_fields(1, 9, F_USER); } //metodo per la generazione dei campi di ricerca personalizzati int TMov_qmask::create_fields(int x, int y, short key_id) { TRectype rec_cespi(LF_CESPI); //cicla sui campi user (se ci sono) nel ditta.ini facendoli apparire sulla pagine Personalizz. TConfig config (CONFIG_DITTA, "ce"); int i = 0; //valuta il valore massimo in orizzontale per il prompt, in modo da allineare i campi in verticale int maxprompt = 0; for (i = 0; config.exist("USER", i); i++) { TToken_string riga = config.get("USER", NULL, i); const TString80 prompt = riga.get(1); const int len = prompt.len(); if (len > maxprompt) maxprompt = len; } maxprompt++; for (i = 0; config.exist("USER", i); i++) { TToken_string riga = config.get("USER", NULL, i); //siamo in pagina di ricerca! se il campo non e' di ricerca lo salta! const bool search = riga.get_char(3) == 'X'; if (!search) continue; //tutto il resto lo fa comunque,settandondolo nella page corretta const short kid = key_id+i; //numero del campo come definito nel .h della maschera const TString16 name = riga.get(0); //nome campo TString80 prompt = riga.get(1); prompt.left_just(maxprompt); //prompt sulla maschera const TString80 picture = riga.get(2); //picture del campo(se c'e') //se la lunghezza del campo non e' definita nella picture la prende dal tracciato const int len = picture.blank() ? rec_cespi.length(name) : picture.len(); //chiede al record di che tipo e' il campo chiamato name... const TFieldtypes tipo_campo = rec_cespi.type(name); //..quanto e' lungo...(maniaca!) const int length_campo = rec_cespi.length(name); //...e quanti decimali ha nel caso sia un real int ndec_campo = 0; if (tipo_campo == _realfld) ndec_campo = rec_cespi.ndec(name); //crea finalmente i nuovi campi sulla pagina 1 (Personalizzazioni) switch(tipo_campo) { case _wordfld: add_number (kid, 0, prompt, x, i+y, len, search ? "BU" : "U"); break; case _intfld : case _longfld: add_number (kid, 0, prompt, x, i+y, len, search ? "B" : ""); break; case _intzerofld: case _longzerofld: add_number (kid, 0, prompt, x, i+y, len, search ? "BZ" : "Z"); break; case _realfld: add_number (kid, 0, prompt, x, i+y, len, "", ndec_campo); break; case _datefld: add_date (kid, 0, prompt, x, i+y, search ? "B" : ""); break; case _memofld: add_zoom(kid, 0, prompt, x, i+y, 50); break; default : add_string (kid, 0, prompt, x, i+y, len, search ? "BU" : ""); break; } //deve poter salvare il contenuto nei campi!! (e' il FIELD delle maschere) TEdit_field& efld = efield(kid); efld.set_field(name); //la set_field lo fa } //deve accendere gli handler di questa maschera perche' funzionino set_handlers(); return i; } //--------------------------------------------------------- // MASCHERA DI MODIFICA (ce1500b) //--------------------------------------------------------- class TMov_emask : public TAutomask { int _staat; TCespite _cespite; TString _s5; private: void set_inputability(short id, char flag); void set_inputability(const short* id, char flag); bool test_inputability(const short* id, char flag); void set_fondi_inputability(); real calc_riv(const TRectype& salpro, int tipo) const; bool calc_amm(int tipo); void calc_plus_minus(int tipo, real& plus, real& minus) const; bool cespite_nuovo() const; TCurrency sum_fields(const short* f) const; void super_polish(); protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); virtual bool on_key(KEY k); public: void set_stato_attivita(int s) { _staat = s; } void recalc_amm(); TMov_emask(); }; // Determina se siamo in presenza di un cespite nuovo bool TMov_emask::cespite_nuovo() const { const TDate dtacq = _cespite.get_date(CESPI_DTCOMP); const TDate dtmov(get(F_DTMOV)); return !dtacq.ok() || dtacq >= dtmov; } TCurrency TMov_emask::sum_fields(const short* f) const { TCurrency sum, val; for (int i = 0; f[i] != 0; i++) { get_currency(abs(f[i]), val); if (f[i] > 0) sum += val; else sum -= val; } return sum; } // Toglie tutti i dirty void TMov_emask::super_polish() { for (int f = fields()-1; f >= 0; f--) { TMask_field& c = fld(f); c.set_dirty(FALSE); } } void TMov_emask::set_inputability(short id, char flag) { TMask_field& f = field(id); if (flag=='S' || flag=='O') f.enable(); else { f.reset(); f.disable(); } f.check_type(flag=='O' ? CHECK_REQUIRED : CHECK_NORMAL); } void TMov_emask::set_inputability(const short* id, char flag) { if (flag == 'O') flag = 'S'; for (; *id > 0; id++) set_inputability(*id, flag); } bool TMov_emask::test_inputability(const short* id, char flag) { bool ok = flag != 'O'; if (!ok) { for (int i = 0; id[i] > 0; i++) { if (!field(id[i]).empty()) { ok = TRUE; break; } } } if (!ok) error_box(TR("E' necessario specificare almeno uno dei valori previsti dal tipo movimento")); return ok; } HIDDEN const short doc_ids[] = { F_TPDOC, F_NDOC, F_DTDOC, 0 }; HIDDEN const short riv_ids[] = { F_RIV75, F_RIV83, F_RIV90, F_RIV91, 0 }; HIDDEN const short fis_ids[] = { F_NORMALE, F_ACCELERATO, F_ANTICIPATO, 0 }; HIDDEN const short civ_ids[] = { F_NORMALE2, F_ACCELERATO2, F_ANTICIPATO2, 0 }; HIDDEN const short prv_ids[] = { F_FPRIVATO, F_QPERSEPRIV, 0 }; bool TMov_emask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_CODMOV: if ((e == fe_modify || e == fe_init)) { const TRectype& tpmov = cache().get("%TMC", o.get()); const bool insert_rett = tpmov.get_int("I0") == 2 && insert_mode(); enable(F_IDRET, insert_rett); if (insert_rett) { TString filter; // Filtro su movimenti rettificabili filter << '(' << MOVCE_CODMOV << "=\"" << tpmov.get("S8") << "\")"; filter << "&&(ANSI(" << MOVCE_DTMOV << ")>=" << get_date(F_INIZIO_ES).string(ANSI) << ')'; filter << "&&(ANSI(" << MOVCE_DTMOV << ")<=" << get_date(F_FINE_ES).string(ANSI) << ')'; efield(F_IDRET).browse()->set_filter(filter); } _s5 = tpmov.get("S5"); if (_s5.empty()) _s5.spaces(16); set_inputability(doc_ids, _s5[0]); set_inputability(F_IMPVEN, _s5[2]); set_inputability(F_ELEMENTI, _s5[3]); set_inputability(F_COSTO, _s5[4]); set_inputability(F_VNONAMM, _s5[5]); set_inputability(F_PLUSREIN, _s5[6]); set_inputability(riv_ids, _s5[7]); set_inputability(F_RIVGF, _s5[8]); set_inputability(F_RIVGC, _s5[9]); // Determina segni possibili switch (tpmov.get_char("S7")) { case '+': disable(F_SEGNO); set(F_SEGNO, "+"); break; case '-': disable(F_SEGNO); set(F_SEGNO, "-"); break; default : enable(F_SEGNO); break; } } break; case F_IDRET: if (e == fe_modify) { TString16 ces; if (!o.empty()) { TEdit_field& e = (TEdit_field&)o; ces = e.browse()->cursor()->curr().get(MOVCE_IDCESPITE); TEdit_field& c = efield(F_IDCESPITE); c.set(ces); c.check(); } enable(F_IDCESPITE, ces.empty()); // Dis/abilita codice cespite enable(F_DESC_CES, ces.empty()); // Dis/abilita descrizione cespite } break; case F_IDCESPITE: if (e == fe_init || e == fe_modify || e == fe_close) { const TString& id = o.get(); if (_cespite.get(CESPI_IDCESPITE) != id) _cespite.read(id); enable_page(3, id.not_empty()); if (id.not_empty()) { const TRectype& cat = _cespite.categoria(); set(F_CATEGORIA, _cespite.get(CESPI_CODCAT), TRUE); set(F_DESC_CAT, cat.get("S0"), TRUE); if (e != fe_init && o.enabled()) { const TRectype& tpmov = cache().get("%TMC", get(F_CODMOV)); switch (_cespite.tipo()) { case tc_immateriale: if (!tpmov.get_bool("B1")) return error_box(TR("Movimento non applicabile a beni immateriali")); break; case tc_pluriennale: if (!tpmov.get_bool("B2")) return error_box(TR("Movimento non applicabile a costi pluriennali")); break; default: if (!tpmov.get_bool("B0")) return error_box(TR("Movimento non applicabile a beni materiali")); break; } } } else { reset(F_CATEGORIA); reset(F_DESC_CAT); } const TDate dtcomp = _cespite.get_date(CESPI_DTCOMP); if (dtcomp.ok()) { const TDate dtmov(get(F_DTMOV)); if (dtcomp > dtmov) return error_box(TR("La data di acquisizione del cespite non può precedere quella del movimento")); } } break; case F_DTMOV: if (e == fe_init || e == fe_modify || e == fe_close) { TEdit_field& dd = efield(F_DTDOC); if (dd.required() && dd.empty()) dd.set(o.get()); // Inserimento nuovo cespite da gestione movimenti cespiti // Se il campo cespite e' vuoto e non sono in uscita di programma (sto quindi inserendo un // cespite nuovo..) prendo la data movimento dal file di configurazione ditta.. if (field(F_IDCESPITE).empty() && e != fe_close) { TConfig ini(CONFIG_DITTA,"ce"); ini.set("DataMovimento", o.get()); } // ..se invece sono in uscita di programma (avro' gia' inserito il cespite) la data movimento // sul file di configurazione deve essere svuotata if (e == fe_close) { TConfig ini(CONFIG_DITTA,"ce"); ini.set("DataMovimento", ""); } const TDate dtret(get(F_DTMOV_RET)); if (dtret.ok()) { const TDate dtmov(o.get()); if (dtmov < dtret) return error_box(TR("La data del movimento di rettifica deve seguire la data del movimento rettificato")); } } break; case F_TPDOC: if (e == fe_button) { TArray_sheet sci(3, 3, -3, -3, o.prompt(), HR("Tipo|Descrizione@20")); sci.add(TR("FA|Fattura d'acquisto")); sci.add(TR("FV|Fattura di vendita")); sci.add(TR("NC|Nota di credito")); sci.add(TR("ND|Nota di debito")); if (sci.run() == K_ENTER) { TToken_string& str = sci.row(-1); o.set(str.get(0)); } } if (e == fe_close) return test_inputability(doc_ids, _s5[0]); break; case F_RIV75: if (e == fe_close) return test_inputability(riv_ids, _s5[7]); break; case F_ELEMENTI: if (e == fe_modify || e == fe_close) { if (o.empty() && cespite_nuovo()) return error_box(TR("È necessario inserire il numero di elementi del nuovo cespite")); } break; case F_VNONAMM: if (e == fe_modify || e == fe_close) { TCurrency csto, vnon; get_currency(F_COSTO, csto); get_currency(F_VNONAMM, vnon); if (vnon > csto) return error_box(FR("Il valore non ammortizzabile non puo' superare %s"), csto.string(TRUE)); } break; case F_PLUSREIN: if (e == fe_modify || e == fe_close) { TCurrency csto, vnon, plus; get_currency(F_COSTO, csto); get_currency(F_VNONAMM, vnon); get_currency(F_PLUSREIN, plus); const TCurrency val = csto-vnon; if (plus > val) return error_box(FR("La plusvalenza reinvestita non puo' superare %s"), val.string(TRUE)); } break; case F_NORMALE: if (e == fe_close) { if (!test_inputability(fis_ids, _s5[10])) return FALSE; const short fv[] = { F_COSTO, -F_VNONAMM, F_RIV75, F_RIV83, F_RIV90, F_RIV91, F_RIVGF, 0 }; const short fa[] = { F_NORMALE, F_ACCELERATO, F_ANTICIPATO, F_QPERSE, F_FPRIVATO, F_QPERSEPRIV, 0 }; const TCurrency val_amm = sum_fields(fv); const TCurrency fon_amm = sum_fields(fa); if (fon_amm > val_amm) { TString msg; msg << TR("Il fondo ammortamento fiscale (") << fon_amm.string(TRUE) << ')'; msg << TR("non puo' superare il valore da ammortizzare (") << val_amm.string(TRUE) << ')'; return error_box(msg); } } break; case F_NORMALE2: if (e == fe_close) { if (!test_inputability(civ_ids, _s5[11])) return FALSE; const short fv[] = { F_COSTO, F_RIV75, F_RIV83, F_RIV90, F_RIV91, F_RIVGC, 0 }; const short fa[] = { F_NORMALE2, F_ACCELERATO2, F_ANTICIPATO2, 0 }; const TCurrency val_amm = sum_fields(fv); const TCurrency fon_amm = sum_fields(fa); if (fon_amm > val_amm) { TString msg; msg << TR("Il fondo ammortamento civilistico (") << fon_amm.string(TRUE) << ')'; msg << TR("non puo' superare il valore da ammortizzare (") << val_amm.string(TRUE) << ')'; return error_box(msg); } } break; case S_TIPO: if (e == fe_init || e == fe_modify) calc_amm(atoi(o.get())); break; default: break; } return TRUE; } real TMov_emask::calc_riv(const TRectype& salpro, int tipo) const { const char* riv_ids[] = { SALCE_RIV75, SALCE_RIV83, SALCE_RIV90, SALCE_RIV91, NULL }; real riv; for (int i = 0; riv_ids[i]; i++) riv += salpro.get_real(riv_ids[i]); if (tipo == 1) riv += salpro.get_real(SALCE_RIVGF); if (tipo == 2) riv += salpro.get_real(SALCE_RIVGC); return riv; } void TMov_emask::calc_plus_minus(int tipo, real& plus, real& minus) const { TDitta_cespiti& cce = ditta_cespiti(); TDate inies, fines; cce.esercizio_corrente(inies, fines); const TDate dtlim(get(F_DTMOV)); TRelation rel(LF_MOVCE); TString expr; expr << "IDCESPITE==IDCESPITE|IDMOV==IDMOV|TPAMM==\"" << tipo << '"'; rel.add(LF_AMMMV, expr); TRectype& movsem = rel.curr(); TRectype& ammmv = rel.curr(LF_AMMMV); const TString& idcespite = get(F_IDCESPITE); movsem.put(MOVCE_IDCESPITE, idcespite); TString filtro; filtro << "(ANSI(DTMOV)>=\"" << inies.string(ANSI) << "\")"; filtro << "&&(ANSI(DTMOV)<=\"" << dtlim.string(ANSI) << "\")"; TCursor cur(&rel, filtro, 2, &movsem, &movsem); const long items = cur.items(); plus = minus = ZERO; if (items > 0) // Continua solo se esistono movimenti { cur.freeze(); for (cur = 0L; cur.pos() < items; ++cur) { plus += ammmv.get_real(AMMMV_PLUS); minus += ammmv.get_real(AMMMV_MINUS); } } } bool TMov_emask::calc_amm(int tipo) { const TString& idcespite = _cespite.get(CESPI_IDCESPITE); if (idcespite.empty()) return FALSE; const TDate dtlim(get(F_DTMOV)); _cespite.calc_amm(tipo, dtlim); set(S_DATAMOV, dtlim); const TRectype& s = _cespite.sal_pro(); set(S_ELEMENTI, s.get(SALCE_NUMELE)); set(S_COSTO, s.get_real(SALCE_CSTO)); set(S_VNONAMM, s.get(SALCE_VNONAMM)); set(S_PLUSREIN, s.get(SALCE_PLUSREIN)); set(S_TOTRIV, calc_riv(s, tipo)); real tot_val; tot_val += get_real(S_COSTO); tot_val -= get_real(S_VNONAMM); tot_val -= get_real(S_PLUSREIN); tot_val += get_real(S_TOTRIV); set(S_TOTVAL, tot_val); const TRectype& a = _cespite.amm_pro(); set(S_NORMALE, a.get(AMMCE_QNORP)); set(S_ACCELERATO, a.get(AMMCE_QACCP)); set(S_ANTICIPATO, a.get(AMMCE_QANTP)); set(S_QPERSE, a.get(AMMCE_QPERSEP)); set(S_FPRIVATO, a.get(AMMCE_FPRIVATOP)); set(S_QPERSEP, a.get(AMMCE_QPPRIVATEP)); real tot_fon; tot_fon += get_real(S_NORMALE); tot_fon += get_real(S_ACCELERATO); tot_fon += get_real(S_ANTICIPATO); tot_fon += get_real(S_QPERSE); tot_fon += get_real(S_FPRIVATO); tot_fon += get_real(S_QPERSEP); set(S_TOTFON, tot_fon); const real tot_res = tot_val-tot_fon; set(S_RESIDUO, tot_res); real plus, minus; calc_plus_minus(tipo, plus, minus); set(S_PLUS, plus); set(S_MINUS, minus); return TRUE; } void TMov_emask::set_fondi_inputability() { set_inputability(fis_ids, _s5[10]); set_inputability(civ_ids, _s5[11]); set_inputability(F_QPERSE, _s5[12]); bool should_be_on = _s5[10] == 'S' || _s5[10] == 'O'; // Test preliminare basato su %TMC if (should_be_on) should_be_on = _cespite.get_int(CESPI_USOPROM) > 1; // Test aggiuntivo su uso promiscuo set_inputability(prv_ids, should_be_on ? _s5[10] : ' '); // Dis/abilita fondo privato e quote perse private } void TMov_emask::recalc_amm() { const TDate dtlim(get(F_FINE_ES)); for (int tipo = 1; tipo <= 3; tipo++) _cespite.calc_amm(tipo, dtlim); } bool TMov_emask::on_key(KEY k) { // Try to predict next page! const int old_page = curr_page()+1; int new_page = old_page; switch (k) { case K_CTRL+K_F1: new_page = 1; break; case K_CTRL+K_F2: new_page = 2; break; case K_CTRL+K_F3: new_page = 3; break; case K_CTRL+K_F4: new_page = 4; break; case K_PREV : new_page--; break; case K_NEXT : new_page++; break; default: break; } // If page will change ... if (old_page != new_page) { switch(new_page) { case 3: set_fondi_inputability(); break; case 4: if (dirty() < S_TIPO) { app().save_if_dirty(); super_polish(); } set(S_TIPO, 1, TRUE); break; default: break; } if (old_page == 4) { recalc_amm(); TRelation& rel = *app().get_relation(); if (rel.read() == NOERR) { autoload(rel); super_polish(); } } } return TAutomask::on_key(k); } TMov_emask::TMov_emask() : TAutomask("ce1500b") { } /////////////////////////////////////////////////////////// // Applicazione principale /////////////////////////////////////////////////////////// TMask* TMovicespi::get_mask(int mode) { return mode == MODE_QUERY ? (TMask*)_qmask : (TMask*)_emask; } bool TMovicespi::user_create() { open_files(LF_TAB, LF_TABCOM, LF_PCON, LF_CLIFO, 0); open_files(LF_CESPI, LF_AMMCE, LF_SALCE, LF_MOVCE, LF_MOVAM, LF_AMMMV, 0); _rel = new TRelation(LF_MOVCE); _rel->add(LF_MOVAM, "IDCESPITE==IDCESPITE|IDMOV==IDMOV|TPAMM==1"); _rel->add(LF_MOVAM, "IDCESPITE==IDCESPITE|IDMOV==IDMOV|TPAMM==2", 1, 0, 2); _rel->add(LF_MOVAM, "IDCESPITE==IDCESPITE|IDMOV==IDMOV|TPAMM==3", 1, 0, 3); _rel->write_enable(); _qmask = new TMov_qmask; _emask = new TMov_emask; // Collegamento da prima nota if (argc() > 2 && strncmp(argv(2), "/c", 2) == 0) { _prima_nota = argv(2); _prima_nota.ltrim(2); } else { _prima_nota.cut(0); } return TRUE; } bool TMovicespi::user_destroy() { delete _emask; delete _qmask; delete _rel; return TRUE; } const char* TMovicespi::get_next_key() { real num = 1; TLocalisamfile cespi(LF_MOVCE); if (cespi.last() == NOERR) num += cespi.get_real(MOVCE_IDMOV); return format("%d|%s", F_IDMOV, num.string()); } bool TMovicespi::protected_record(TRelation &r) { bool stampato = r.curr().get_bool(MOVCE_STAMPATO); return stampato; } void TMovicespi::calc_residuo(long numreg) { TSheet_field& s = _qmask->sfield(F_CGROWS); // Mette tutti i residui uguali importi real tot_imp = ZERO; for (int r = s.items()-1; r >= 0; r--) { TToken_string& row = s.row(r); real imp = row.get(0); row.add(imp.string(), 1); tot_imp += imp; } real tot_res = tot_imp; TRelation rel(LF_MOVCE); TString filter; filter << MOV_NUMREG << "==" << numreg; TCursor cur(&rel, filter, 3); const long items = cur.items(); if (items > 0) { cur.freeze(); TRectype& movce = cur.curr(); TAssoc_array ignore; // Prima cerca movimenti con importo identico ... for (cur = 0L; cur.pos() < items; ++cur) { // const char segno = movce.get_char(MOVCE_SEGNO); real imp = movce.get_real(MOVCE_IMPVEN); if (imp.is_zero()) imp = movce.get_real(MOVCE_CSTO); if (imp > ZERO) // Cerca una riga con lo stesso importo { for (int r = 0; r < s.items(); r++) { TToken_string& row = s.row(r); const real res = row.get(1); if (imp == res) { imp = ZERO; row.add(" ", 1); tot_res -= res; ignore.add(movce.get(MOVCE_IDMOV)); break; } } } } // ... poi scala dalle varie righe l'importo fino ad esaurimento for (cur = 0L; cur.pos() < items && tot_res > ZERO; ++cur) { if (ignore.is_key(movce.get(MOVCE_IDMOV))) continue; // const char segno = movce.get_char(MOVCE_SEGNO); real imp = movce.get_real(MOVCE_IMPVEN); if (imp.is_zero()) imp = movce.get_real(MOVCE_CSTO); for (int r = 0; r < s.items() && imp > ZERO; r++) { TToken_string& row = s.row(r); real res = row.get(1); if (res > ZERO) { const real quota = (res > imp) ? imp : res; res -= quota; imp -= quota; row.add(res.string(), 1); tot_res -= quota; } } } } // s.force_update(); _qmask->set(F_TOTIMP, tot_imp); _qmask->set(F_TOTRES, tot_res); } void TMovicespi::set_prompt(TMask_field& fld, bool plus) { TString str = fld.prompt(); if (plus) { if (str[0] != 'P') { str.ltrim(3); str.insert("Pl"); } } else { if (str[0] != 'M') { str.ltrim(2); str.insert("Min"); } } fld.set_prompt(str); } void TMovicespi::show_plus_minus(TMask& m) { TToken_string key; short id_txt = F_PLUSMIN_FIS_TXT; short id_fld = F_PLUSMIN_FIS; for (int tipo = 1; tipo <= 3; tipo++, id_txt+= 2, id_fld+=2) { key = m.get(F_IDCESPITE); key.add(m.get(F_IDMOV)); key.add(tipo); const TRectype& ammmv = cache().get(LF_AMMMV, key); const real plus = ammmv.get_real(AMMMV_PLUS); const real minus = ammmv.get_real(AMMMV_MINUS); const bool on = !plus.is_zero() || !minus.is_zero(); if (on) { if (!plus.is_zero()) { set_prompt(m.field(id_txt), TRUE); m.set(id_fld, plus); } else { set_prompt(m.field(id_txt), FALSE); m.set(id_fld, minus); } } m.show(id_txt, on); m.show(id_fld, on); } } void TMovicespi::cg_mode() { TConfig ini(_prima_nota, "Transaction"); const char action = ini.get("Action")[0]; TString8 para; para.format("%d", LF_MOV); ini.set_paragraph(para); const long numreg = ini.get_long(MOV_NUMREG); _qmask->set(F_NUMREG, numreg); // Al primo inserimento devo impostare anche l'anno _qmask->set(F_ESERCIZIO, ini.get(MOV_ANNOES), TRUE); if (action != 'I' && action != 'M') { _qmask->hide(-8); return; } else _qmask->show(-8); TSheet_field& s = _qmask->sfield(F_CGROWS); for (int i = 1; ; i++) { para.format("%d,%d", LF_RMOV, i); if (ini.set_paragraph(para)) { const int gruppo = ini.get_int(RMV_GRUPPO); const int conto = ini.get_int(RMV_CONTO); const long sottoconto = ini.get_long(RMV_SOTTOCONTO); const TBill zio(gruppo, conto, sottoconto); const int tipo = zio.tipo_cr(); if (tipo == 2 || tipo == 3 || tipo == 4 || tipo == 8) { TToken_string& row = s.row(-1); row = ini.get(RMV_IMPORTO); row.add(""); row.add(zio.string(0x2)); } } else break; } calc_residuo(numreg); } void TMovicespi::init_query_mode(TMask& m) { TDitta_cespiti& dc = ditta_cespiti(); dc.init_mask(m); // Collegamento da prima nota if (_prima_nota.not_empty()) cg_mode(); else m.hide(-8); // Nascondi campi collegamento prima nota } int TMovicespi::init_mask(TMask& m) { TDitta_cespiti& dc = ditta_cespiti(); dc.init_mask(m); const int staat = _qmask->stato_attivita(); _emask->set_stato_attivita(staat); m.enable(DLG_NEWREC, staat != 3); return staat; } void TMovicespi::init_insert_mode(TMask& m) { const int staat = init_mask(m); m.enable(F_IDCESPITE); m.enable(F_DESC_CES); m.enable(DLG_SAVEREC, staat != 3); if (_prima_nota.not_empty()) { m.disable(DLG_QUIT); // Altrimenti non riesco a controllare il residuo TString16 para; para.format("%d", LF_MOV); TConfig ini(_prima_nota, para); const TRectype& cau = cache().get(LF_CAUSALI, ini.get(MOV_CODCAUS)); m.set(F_CODMOV, cau.get(CAU_COLLCESP), TRUE); if (m.field(F_TPDOC).active()) m.set(F_TPDOC, ini.get(MOV_TIPODOC), TRUE); if (m.field(F_NDOC).active()) m.set(F_NDOC, ini.get(MOV_NUMDOC), TRUE); if (m.field(F_DTDOC).active()) m.set(F_DTDOC, ini.get(MOV_DATADOC), TRUE); TString desc = ini.get(MOV_DESCR); desc.strip("\""); if (desc.empty()) desc = cau.get(CAU_DESCR); m.set(F_DESC_MOV, desc, TRUE); TString16 codreg = ini.get(MOV_REG); if (codreg.not_empty()) { codreg.insert(format("%04d", ini.get_int(MOV_ANNOIVA))); const int iva = atoi(cache().get("REG", codreg, "I0")); TSheet_field& s = _qmask->sfield(F_CGROWS); for (int r = 0; r < s.items(); r++) { const real res = s.row(r).get(1); if (res > 0) { m.set(iva==1 ? F_IMPVEN : F_COSTO, res); break; } } } } show_plus_minus(m); } void TMovicespi::init_modify_mode(TMask& m) { const int staat = init_mask(m); TEsercizi_contabili esc; m.disable(F_IDCESPITE); m.disable(F_DESC_CES); const TRectype& rec = get_relation()->curr(); const TDate dtmov = rec.get_date(MOVCE_DTMOV); bool bollato = rec.get_bool(MOVCE_STAMPATO); if (!bollato) // Se proprio non ci fidiamo del flag { const TEsercizio& e = esc[m.get_int(F_ESERCIZIO)]; const TDate dtini = e.inizio(); const TDate dtfin = e.fine(); bollato = (staat == 3 && dtmov <= dtfin) || (staat == 2 && dtmov < dtini); } if (bollato) { m.disable(DLG_SAVEREC); m.disable(DLG_DELREC); TString msg = TR("Movimento già stampato sul Bollato dell'esercizio "); msg << esc.date2esc(dtmov); xvtil_statbar_set(msg); } if (_prima_nota.not_empty()) m.disable(DLG_QUIT); // Altrimenti non riesco a controllare il residuo show_plus_minus(m); } void TMovicespi::kill_mov(const TString& idcespite, const TString& idmov, int lfile) { CHECKD(lfile == LF_MOVAM || lfile == LF_AMMMV, "Invalid file ", lfile); TRelation rel(lfile); TRectype filter(rel.curr()); filter.zero(); filter.put("IDCESPITE", idcespite); filter.put("IDMOV", idmov); TCursor cur(&rel, "", 1, &filter, &filter); const long items = cur.items(); if (items > 0) { cur.freeze(); for (cur = 0L; cur.pos() < items; ++cur) { int err = rel.remove(); if (err != NOERR) { const int tpamm = rel.curr().get_int("TPAMM"); error_box(FR("Errore %d nella cancellazione dell'ammortamento (%d) del movimento %s"), err, tpamm, (const char*)idmov); } } } } void TMovicespi::kill_rett(const TString& id, const TString& idmov) { TRelation rel(LF_MOVCE); // Il cursore delle rettifiche usa la chiave 2: IDCESPITE+IDMOV // Per cui parto a selezionare le possibili rettifiche dal movimento da rettificare ... TRectype fromret(LF_MOVCE); fromret.put(MOVCE_IDCESPITE, id); fromret.put(MOVCE_IDMOV, idmov); // ... in poi TRectype toret(LF_MOVCE); toret.put(MOVCE_IDCESPITE, id); TString filtro; filtro << MOVCE_IDRET << "==" << idmov; // Confronto numerico! TCursor movcur(&rel, filtro, 2, &fromret, &toret); const long items = movcur.items(); if (items > 0) // Se ci sono rettifiche { const TRectype& curr = movcur.curr(); movcur.freeze(); for (movcur = 0L; movcur.pos() < items; ++movcur) { const TString16 idmov = curr.get(MOVCE_IDMOV); if (rel.remove() == NOERR) { kill_mov(id, idmov, LF_MOVAM); kill_mov(id, idmov, LF_AMMMV); } } } } int TMovicespi::write(const TMask& m) { int err = TRelation_application::write(m); if (err == NOERR) _emask->recalc_amm(); return err; } int TMovicespi::rewrite(const TMask& m) { int err = TRelation_application::rewrite(m); if (err == NOERR) _emask->recalc_amm(); return err; } void TMovicespi::save_if_dirty() { if (save(TRUE)) set_mode(MODE_MOD); } bool TMovicespi::remove() { const TRectype& curr = get_relation()->curr(); const TString16 idcespite = curr.get(MOVCE_IDCESPITE); const TString16 idmov = curr.get(MOVCE_IDMOV); kill_mov(idcespite, idmov, LF_MOVAM); kill_mov(idcespite, idmov, LF_AMMMV); kill_rett(idcespite, idmov); TRelation_application::remove(); _emask->recalc_amm(); return TRUE; } int ce1500(int argc, char* argv[]) { TMovicespi mc; mc.run(argc, argv, TR("Movimenti cespiti")); return 0; }