#include "gv0.h" #include "gv0500a.h" #include "gvlib.h" #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////// // Utilities /////////////////////////////////////////////////////////// // Trasforma un codice tributo in sezione F24 static char trib2sec(const TString& trib) { const TString& sec = cache().get("%TRB", trib, "S6"); return sec[0]; } // Traformazione da codice sheet a codice tributo e viceversa static const short ids[] = { F_ERARIO, F_INPS, 0 }; static const char sec[] = { 'E', 'I', '\0' }; static char sheet2sec(short id) { int i; for (i = 0; ids[i] && ids[i] != id; i++); return sec[i]; } static short sec2sheet(char s) { int i; for (i = 0; sec[i] && sec[i] != s; i++); return ids[i]; } /////////////////////////////////////////////////////////// // TF24_query_mask /////////////////////////////////////////////////////////// class TF24_query_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TF24_query_mask() : TAutomask("gv0500a") {} }; bool TF24_query_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_DISTINTA: if (e == fe_button) { TArray_sheet sheet(-1, -1, 60, 20, TR("Distinte"), HR("F24@6|Progr.|Data@10|Tipo|Codice|ABI@5|CAB@5")); const int tipo = get_int(F_TIPO); TElencoF24_set delega(tipo); // Distinte non inviate const long abi = get_long(F_ABI); const long cab = get_long(F_CAB); const char tipoint = get(F_TIPOINTEST)[0]; const long f24 = atol(o.get()); long sel = 0; for (bool ok = delega.move_first(); ok; ok = delega.move_next()) { const long dist = delega.get(F24_F24).as_int(); bool keep = dist > 0; if (keep && cab > 0) keep = delega.get(F24_ABI).as_int()==abi && delega.get(F24_CAB).as_int()==cab; if (keep && tipoint > ' ') keep = delega.get(F24_TIPOINTEST).as_string()[0] == tipoint; if (keep) { if (dist == f24) sel = sheet.items(); TToken_string row; row << dist; row.add(delega.get(F24_PROGR).as_int()); row.add(delega.get(F24_DATASCAD).as_string()); row.add(delega.get(F24_TIPOINTEST).as_string()); row.add(delega.get(F24_INTEST).as_string()); row.add(delega.get(F24_ABI).as_string()); row.add(delega.get(F24_CAB).as_string()); sheet.add(row); } } if (sel > 0) sheet.select(sel); if (sheet.run() == K_ENTER) { TToken_string& row = sheet.row(); set(F_DISTINTA, row.get_long(0)); set(F_PROGR, row.get_long(1)); send_key(K_AUTO_ENTER, 0); // avessimo da fa na sendekkey dato si che la stop runne nun fuziona } } if (e == fe_modify) { TF24_set delega(atol(o.get())); if (delega.move_first()) set(F_PROGR, delega.get(F24_PROGR).as_int()); } break; case F_PROGR: if (e == fe_button) { // Metodo astuto come un cervo per ottenere le righe F24 non assegnate TRigheF24_set riga(0x1); TArray_sheet sheet(-1, -1, -3, -3, TR("Righe"), HR("@1|Progr.|Trib.|Data@10|Debito@15R|Credito@15R|Tipo|Codice|ABI@5|CAB@5")); const long abi = get_long(F_ABI); const long cab = get_long(F_CAB); const char tipo = get(F_TIPOINTEST)[0]; const long f24 = atol(o.get()); for (bool ok = riga.move_first(); ok; ok = riga.move_next()) { bool keep = true; if (keep && cab > 0) keep = riga.get(F24_ABI).as_int()==abi && riga.get(F24_CAB).as_int()==cab; if (keep && tipo > ' ') keep = riga.get(F24_TIPOINTEST).as_string()[0] == tipo; if (keep) { TToken_string row; row = " "; row.add(riga.get(F24_PROGR).as_int()); row.add(riga.get(F24_TRIBUTO).as_string()); row.add(riga.get(F24_DATASCAD).as_string()); row.add(riga.get(F24_IMPORTODEB).as_string()); row.add(riga.get(F24_IMPORTOCRE).as_string()); row.add(riga.get(F24_TIPOINTEST).as_string()); row.add(riga.get(F24_INTEST).as_string()); row.add(riga.get(F24_ABI).as_string()); row.add(riga.get(F24_CAB).as_string()); sheet.add(row); } } if (sheet.run() == K_ENTER) { TToken_string& row = sheet.row(); set(F_PROGR, row.get_long(1)); set(F_DISTINTA, get_next_f24()); stop_run(K_INS); } } break; default: break; } return true; } /////////////////////////////////////////////////////////// // TF24_mask /////////////////////////////////////////////////////////// class TF24_edit_mask : public TAutomask { private: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); protected: int find_empty_row(TSheet_field& s) const; bool load_row(short id, const TRecordset& riga, int pos) const; void link_tributo(TOperable_field& o); void compute_total(short id, int rows); public: bool add_row(const TRecordset& riga, int pos = -1); void compute_totals(int mode = 0xFF); TF24_edit_mask() : TAutomask("gv0500b") {} }; void TF24_edit_mask::compute_total(short id, int rows) { TSheet_field& s = sfield(id); TMask& m = s.sheet_mask(); const TMask_field* debito = m.find_by_fieldname(F24_IMPORTODEB); const TMask_field* credito = m.find_by_fieldname(F24_IMPORTOCRE); const int posdeb = s.cid2index(debito->dlg()); const int poscre = s.cid2index(credito->dlg()); const bool needs_update = s.items() < rows; real a, b; for (int r = 0; r < rows; r++) { TToken_string& row = s.row(r); a += real(row.get(posdeb)); b += real(row.get(poscre)); } set(id+1, a); set(id+2, b); set(id+3, real(a-b)); if (needs_update) s.force_update(); } void TF24_edit_mask::compute_totals(int mode) { if (mode & 1) compute_total(F_ERARIO, 6); if (mode & 2) compute_total(F_INPS, 4); real saldo; saldo += get_real(F_ERARIO_AB); saldo += get_real(F_INPS_CD); set(F_SALDO, saldo); } void TF24_edit_mask::link_tributo(TOperable_field& o) { TSheet_field& sheet = *o.mask().get_sheet(); const char sez[2] = { sheet2sec(sheet.dlg()), '\0' }; TString query = "USE RIGHEF24 KEY 2 SELECT 4->S6=#SEC"; query << "\nJOIN %TRB INTO CODTAB==TRIBUTO"; query << "\nTO PROGR=999999"; TISAM_recordset delega(query); delega.set_var("#SEC", TVariant(sez)); if (delega.items() > 0) { TCursor_sheet s(delega.cursor(), " |PROGR|TRIBUTO|DATASCAD|IMPORTODEB|IMPORTOCRE|ABI|CAB|TIPOINTEST|INTEST", TR("Righe disponibili"), HR("@1|Progr.|Trib.|Data@10|Debito@15R|Credito@15R|ABI@5|CAB@5|Tipo|Codice"), 0, 1); if (s.run() == K_ENTER) { if (!s.one_checked()) s.check(s.selected()); TISAM_recordset riga("USE RIGHEF24\nFROM PROGR=#RIGA\nTO PROGR=#RIGA"); for (TRecnotype i = 0; i < s.items(); i++) if (s.checked(i)) { const long progr = s.row(i).get_long(1); riga.set_var("#RIGA", TVariant(progr)); if (riga.move_first()) { const int pos = sheet.selected(); add_row(riga, pos); if (o.mask().is_running()) sheet.update_mask(pos); else sheet.force_update(pos); } } } } else warning_box(TR("Non esistono righe F24 compatibili")); } int TF24_edit_mask::find_empty_row(TSheet_field& s) const { int i = 0; for (i = 0; i < 6 && i < s.items(); i++) { const TToken_string& row = s.row(i); if (row.empty_items()) break; } return i; } bool TF24_edit_mask::load_row(short id, const TRecordset& riga, int pos) const { TSheet_field& s = sfield(id); if (pos < 0 || pos >= 6) pos = find_empty_row(s); bool ok = pos >= 0 && pos < 6; if (ok) { TMask& m = s.sheet_mask(); TToken_string& row = s.row(pos); row.cut(0); FOR_EACH_MASK_FIELD(m, i, f) { const TFieldref* fr = f->field(); if (fr != NULL) { const int j = s.cid2index(f->dlg()); row.add(riga.get(fr->name()).as_string(), j); } } } return ok; } bool TF24_edit_mask::add_row(const TRecordset& riga, int pos) { const TString& tributo = riga.get(F24_TRIBUTO).as_string(); const char sec = trib2sec(tributo); const short id = sec2sheet(sec); bool ok = id > 0 && load_row(id, riga, pos); if (!ok) { const long progr = riga.get(F24_PROGR).as_int(); error_box(FR("Impossibile aggiungere la riga %ld (%s) alla delega"), progr, (const char*)tributo); } return ok; } bool TF24_edit_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { bool ok = true; switch (o.dlg()) { case DLG_USER: if (e == fe_button && jolly > 0) link_tributo(o); break; case F_ERARIO: switch (e) { case se_notify_modify: case se_notify_del: compute_totals(0x1); break; case se_query_add: ok = false; break; default: break; } break; case F_INPS: switch (e) { case se_notify_modify: case se_notify_del: compute_totals(0x2); break; case se_query_add: ok = false; break; default: break; } break; case F_CONT: if (e == fe_button) { TLog_report log("Contabilizzazione"); TF24_set d(get_long(F_DISTINTA)); TReport_book book; if (d.contabilizza(log)) o.disable(); book.add(log); book.preview(); } break; default: break; } return ok; } /////////////////////////////////////////////////////////// // TF24_app // TRelation_application molto all'avanguardia // avendo un recorset filtrato come sorgente dati principale. // Notare l'arguta implementazione dei metodi get_filtered_cursor // e get_relation in modo far funzionare bene le ricerche /////////////////////////////////////////////////////////// class TF24_app : public TRelation_application { TPointer_array _progr; TElencoF24_set* _recset; TArray _msk; private: int riscrivi(const TMask& mask); void init_mask(TMask& mask) const; protected: virtual bool user_create(); virtual bool user_destroy(); virtual bool has_filtered_cursor() const { return _recset != NULL; } virtual TCursor& get_filtered_cursor() const { return *_recset->cursor(); } virtual TRelation* get_relation() const { return get_filtered_cursor().relation(); } virtual bool get_next_key(TToken_string& key); virtual bool changing_mask(int mode) { return true; } virtual TMask* get_mask(int mode); virtual void init_query_mode(TMask& m); virtual void init_insert_mode(TMask& m); virtual void init_modify_mode(TMask& m); virtual int read(TMask& m); virtual int write(const TMask& mask); virtual int rewrite(const TMask& mask); virtual bool remove(); }; bool TF24_app::user_create() { _recset = new TElencoF24_set(1); // Elenco di tutti gli F24 da inviare _msk.add(new TF24_query_mask); _msk.add(new TF24_edit_mask); set_search_field(F_DISTINTA); return _recset->cursor() != NULL; } bool TF24_app::user_destroy() { _msk.destroy(); delete _recset; return true; } bool TF24_app::get_next_key(TToken_string& key) { key.cut(0); key.add(F_DISTINTA, 0); key.add(get_next_f24(), 1); return true; } TMask* TF24_app::get_mask(int mode) { const int n = (mode == MODE_QUERY) ? 0 : 1; return (TMask*)_msk.objptr(n); } void TF24_app::init_mask(TMask& mask) const { TF24_edit_mask& m = (TF24_edit_mask&)mask; char ti = m.get(F_TIPOINTEST)[0]; long intest = m.get_long(F_PERSON); TString codfis, ragsoc, key; if (ti == 'C') { key.cut(0) << "C|" << intest; const TRectype& cli = cache().get(LF_CLIFO, key); codfis = cli.get(CLI_COFI); ragsoc = cli.get(CLI_RAGSOC); if (codfis.blank()) codfis = cli.get(CLI_PAIV); } else { if (ti == 'D' || ti <= ' ') { ti = prefix().firm().get(NDT_TIPOA)[0]; intest = prefix().firm().get_long(NDT_CODANAGR); } key.cut(0) << ti << '|' << intest; const TRectype& anag = cache().get(LF_ANAG, key); ragsoc = anag.get(ANA_RAGSOC); codfis = anag.get(ANA_COFI); if (codfis.blank()) codfis = anag.get(ANA_PAIV); } m.set(F_PERSON, intest); m.set(F_COFI, codfis); m.set(F_RAGSOC, ragsoc); const TRelation & rel = *get_relation(); if (main_app().has_module(CGAUT) && m.get(F_DATAVERS).full()) { const bool contabilizzato = rel.curr().get(F24_NUMREG).full(); m.enable(F_CONT, !contabilizzato); } m.compute_totals(); } void TF24_app::init_query_mode(TMask& /*mask*/) { } void TF24_app::init_insert_mode(TMask& mask) { init_mask(mask); const TMask& q = *get_mask(MODE_QUERY); const long progr = q.get_long(F_PROGR); if (progr > 0) { TISAM_recordset riga("USE RIGHEF24\nFROM PROGR=#RIGA\nTO PROGR=#RIGA"); riga.set_var("#RIGA", progr); if (riga.move_first()) { TF24_edit_mask& m = (TF24_edit_mask&)mask; m.add_row(riga); } } } void TF24_app::init_modify_mode(TMask& mask) { init_mask(mask); const bool dainviare = mask.get(F_DATAVERS).blank(); mask.enable(DLG_SAVEREC, dainviare); mask.enable(DLG_DELREC, dainviare); } int TF24_app::read(TMask& mask) { const int err = TRelation_application::read(mask); _progr.destroy(); // Azzera lista delle righe FOR_EACH_MASK_SHEET(mask, i, s) s->destroy(); if (err == NOERR) { TF24_edit_mask& m = (TF24_edit_mask&)mask; TF24_set delega(m.get_long(F_DISTINTA)); for (bool ok = delega.move_first(); ok; ok = delega.move_next()) { if (m.add_row(delega)) { const long p = delega.get(F24_PROGR).as_int(); _progr.add_long(p); // Tengo traccia delle righe lette } } } return err; } int TF24_app::riscrivi(const TMask& mask) { TPointer_array righe; if (mask.sheets() > 0) // dummy test { // Compila la lista di tutte le righe F24 nella distinta corrente FOR_EACH_MASK_SHEET(mask, i, s) { const TMask_field* friga = s->sheet_mask().find_by_fieldname(F24_PROGR); const int pos = s->cid2index(friga->dlg()); FOR_EACH_SHEET_ROW(*s, r, row) { const long progr = row->get_long(pos); if (progr > 0) righe.add_long(progr); } } } TLocalisamfile righef24(LF_RIGHEF24); if (_progr.items() > 0) { // Scollega tutte le righe f24 ora non piu' presenti for (int r = 0; r < _progr.items(); r++) { const long progr = _progr.get_long(r); if (righe.find_long(progr) < 0) // Questa riga c'era prima ma ora non piu' { righef24.put("PROGR", progr); int err = righef24.read(_isequal, _lock); if (err == NOERR) { righef24.zero("F24"); err = righef24.rewrite(); } if (err != NOERR) error_box("Errore %d di scollegamento della riga %ld", err, progr); } } } // Tenta eventuale rinumerazione della distinta if (mask.insert_mode()) { righef24.setkey(2); long f24 = 0; for (f24 = mask.get_long(F_DISTINTA); ; f24++) { righef24.zero(); righef24.put("F24", f24); int err = righef24.read(_isgreat); if (err != NOERR || righef24.get_long("F24") != f24) break; } ((TMask&)mask).set(F_DISTINTA, f24); // Aggiorna numero distinta } // Mi preparo a numerare le eventuali righe nuove long next_progr = get_next_progr_f24(); // Salva le righe F24 nella distinta corrente FOR_EACH_MASK_SHEET(mask, i, s) { // Calcolo le posizioni dei campi importanti nella TToken_string const TMask_field* frig = s->sheet_mask().find_by_fieldname(F24_PROGR); const TMask_field* fdeb = s->sheet_mask().find_by_fieldname(F24_IMPORTODEB); const TMask_field* fcre = s->sheet_mask().find_by_fieldname(F24_IMPORTOCRE); const int pos_pro = s->cid2index(frig->dlg()); // Progressivo const int pos_deb = s->cid2index(fdeb->dlg()); // Debito const int pos_cre = s->cid2index(fcre->dlg()); // Credito // Scandisco le righe dello sheet FOR_EACH_SHEET_ROW(*s, r, row) { const real deb = row->get(pos_deb); const real cre = row->get(pos_cre); const bool is_empty = deb.is_zero() && cre.is_zero(); long progr = row->get_long(pos_pro); int err = NOERR; if (progr <= 0 && !is_empty) // E' una riga nuova con importi validi? { do { progr = next_progr++; righef24.zero(); righef24.put(F24_PROGR, progr); righef24.put(F24_F24, mask.get(F_DISTINTA)); err = righef24.write(); } while (err == _isreinsert); if (err != NOERR) { error_box(FR("Errore %d nell'inserimento righe F24"), err); return err; } row->add(progr, pos_pro); // Aggiorno il progressivo nella riga nuova } if (progr > 0) // E' una riga da aggiornare? { righef24.zero(); righef24.put(F24_PROGR, progr); if (is_empty) { err = righef24.remove(); } else { err = righef24.read(_isequal, _lock); if (err == NOERR) { FOR_EACH_MASK_FIELD(s->sheet_mask(), i, f) { const TFieldref* fr = f->field(); if (fr != NULL) { const int pos = s->cid2index(f->dlg()); righef24.put(fr->name(), row->get(pos)); } } // Metto anche la roba di testata uguale per tutti FOR_EACH_MASK_FIELD(mask, j, g) { const TFieldref* fr = g->field(); if (fr != NULL) righef24.put(fr->name(), g->get()); } err = righef24.rewrite(); } } if (err != NOERR) { error_box(FR("Errore %d nell'aggiornamento righe F24"), err); return err; } } } } _recset->requery(); // Aggiorno la lista delle distinte _progr = righe; // Forse verra' fatto comunque dalla prossima read // Sembra utile non passare in modifica della distinta successiva! TRectype& rec = get_filtered_cursor().curr(); rec.put(F24_F24, mask.get(F_DISTINTA)); rec.zero(F24_PROGR); get_filtered_cursor().read(); return NOERR; } int TF24_app::write(const TMask& mask) { _progr.destroy(); // Precauzione inutile? Chissa'! return riscrivi(mask); } int TF24_app::rewrite(const TMask& mask) { return riscrivi(mask); } // Azzera il campo F24 nelle righe della distinta corrente bool TF24_app::remove() { const long f24 = get_relation()->curr().get_long(F24_F24); TF24_set cur(f24); TRelation& rel = *cur.cursor()->relation(); for (bool ok = cur.move_first(); ok; ok = cur.move_next()) { rel.curr().zero(F24_F24); rel.rewrite(); } return true; } int gv0500(int argc, char* argv[]) { TF24_app app; app.run(argc, argv, "Emissione F24"); return 0; }