#include "cg2100.h" #include "cg2102.h" #include "cg2107.h" #include "cg2100e.h" #include "cgsalda3.h" #include #include #include /////////////////////////////////////////////////////////// // TNew_game_mask /////////////////////////////////////////////////////////// class TNew_game_mask : public TAutomask { const TBill& _conto; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TNew_game_mask(const TBill& conto); }; bool TNew_game_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { bool ok = true; switch (o.dlg()) { case 102: // Numero partita if (e == fe_close) { const int anno = get_int(101); // ANNO const TString& part = o.get(); // NUMPART // Controlla partita in memoria ok = !app().partite().exist(_conto, anno, part) || // Non esiste app().partite().partita(_conto, anno, part).last()<=0; // Esiste ma non ha righe if (ok) { const TPartita p(_conto, anno, part); // Controlla partita su disco ok = p.last() <= 0; } if (!ok) error_box(FR("La partita %d/%s esiste già"), anno, (const char*)part); } break; default: break; } return ok; } TNew_game_mask::TNew_game_mask(const TBill& conto) : TAutomask(TR("Nuova partita"), 1, 24, 4), _conto(conto) { add_button_tool(DLG_OK, "", TOOL_OK); add_button_tool(DLG_CANCEL, "", TOOL_CANCEL); const char* flags = TPartita::allineamento_richiesto(_conto.tipo()) == 'R' ? "UR" : "U"; TEdit_field& partita = add_string(102, 0, PR("Partita "), 1, 2, 6, flags); partita.set_field(TFixed_string(PART_NUMPART)); partita.check_type(CHECK_REQUIRED); TReal_field& anno = add_number(101, 0, PR("Anno "), 1, 1, 4, "AU"); anno.set_field(TFixed_string(PART_ANNO)); anno.check_type(CHECK_REQUIRED); set_handlers(); } /////////////////////////////////////////////////////////// // TEasySolder_mask /////////////////////////////////////////////////////////// // Forse andrebbe in libreria! void TEasySolder_mask::set_imp(short id, const TImporto& imp) { TEdit_field& e = efield(id); CHECK(e.size() >= 15, "Campo troppo piccolo per contenere un importo"); if (!imp.is_zero()) { const TCurrency c(imp.valore()); TString80 str; str << c.string(true) << ' ' << imp.sezione(); e.set(str); } else e.reset(); } #define get_row_bool(sheet, row, id) (row).get_char(sheet.cid2index(id))=='X' #define get_row_int(sheet, row, id) (row).get_int(sheet.cid2index(id)) #define get_row_str(sheet, row, id) (row).get(sheet.cid2index(id)) #define get_row_real(sheet, row, id) real((row).get(sheet.cid2index(id))) #define set_row_bool(sheet, row, id, n) (row).add(n ? "X" : "", sheet.cid2index(id)) #define set_row_int(sheet, row, id, n) (row).add(n, sheet.cid2index(id)) #define set_row_str(sheet, row, id, n) (row).add(n, sheet.cid2index(id)) static bool set_row_currency(const TSheet_field& sheet, TToken_string& row, short id, const real& n) { const TMask& m = sheet.sheet_mask(); const TCurrency_field& cf = (const TCurrency_field&)m.field(id); TOperable_field* vf = cf.driver(0); if (vf != NULL && !vf->empty()) // E' un importo in valuta? { const TString& codval = vf->get(); if (is_true_value(codval)) // La valuta e' diversa dall'euro? { if (n.is_zero()) set_row_str(sheet, row, id, ""); else { const TCurrency cur(n, codval); set_row_str(sheet, row, id, cur.get_num().string()); } return true; } } if (n.is_zero()) set_row_str(sheet, row, id, ""); else set_row_str(sheet, row, id, n.string(-1, 2)); return false; } void TEasySolder_mask::save_sheet() { // Memorizza i dati del cambio da salvare sulle righe di partita TValuta valuta; valuta.get(*this, G_VALUTA, G_DATACAMBIO, G_CAMBIO); const TCausale& causale = app().causale(); TSheet_field& s = sfield(G_SHEET); FOR_EACH_SHEET_ROW(s, r, row_ptr) { TToken_string& row = *row_ptr; const int anno = get_row_int(s, row, S_ANNO); const TString8 numpart = get_row_str(s, row, S_PARTITA); const int rigaf = get_row_int(s, row, S_RIGAF); const int nrata = get_row_int(s, row, S_RATA); const bool goodrat = nrata > 0 && nrata < TPartita::UNASSIGNED; int nrigp = get_row_int(s, row, S_RIGAP); const real importo = get_row_real(s, row, S_IMPORTO); const real ritfis = valuta.in_valuta() ? ZERO : get_row_real(s, row, S_RITFIS); const real ritsoc = valuta.in_valuta() ? ZERO : get_row_real(s, row, S_RITSOC); const bool a_saldo = goodrat && get_row_bool(s, row, S_SALDO); const TTipo_pag tipopag = (TTipo_pag)get_row_int(s, row, S_MODOPAG); const TDate datapag = get_row_str(s, row, S_DATAPAG); if (a_saldo || !importo.is_zero() || !ritfis.is_zero() || !ritsoc.is_zero() || nrigp > 0) { TPartita& partita = app().partite().partita(_conto, anno, numpart); if (nrigp <= 0) { TRiga_partite& part = partita.new_row(); // Creazione nuova riga vuota nrigp = part.get_int(PART_NRIGA); // Nuova riga set_row_int(s, row, S_RIGAP, nrigp); part.put(PART_SEZ, calcola_sezione()); } TRiga_partite& part = partita.riga(nrigp); // Riga pagamento // Setta il cambio corrente valuta.put(part); // Copia dati di testata movimento TMask& cm = app().curr_mask(); part.put(PART_NREG, _numreg); // Numero operazione part.put(PART_NUMRIG, _numrig); // Riga su cui ho cliccato part.put(PART_NUMDOC, cm.get(F_NUMDOC)); part.put(PART_DATADOC, cm.get(F_DATADOC)); part.put(PART_DATAREG, cm.get(F_DATAREG)); part.put(PART_DESCR, cm.get(F_DESCR)); part.put(PART_DATAPAG, datapag); part.put(PART_TIPOPAG, tipopag); // Copia dati causale corrente part.put(PART_CODCAUS, causale.codice()); part.put(PART_TIPOMOV, causale.tipomov()); if (causale.iva() != nessuna_iva) { part.put(PART_REG, cm.get(F_CODREG)); part.put(PART_PROTIVA, cm.get(F_PROTIVA)); } TRectype newpag = partita.pagamento(rigaf, nrata, nrigp); newpag.put(PAGSCA_ACCSAL, a_saldo ? 'S' : 'A'); if (valuta.in_valuta()) { newpag.put(PAGSCA_IMPORTOVAL, importo); const real impeur = get_row_str(s, row, S_IMPORTO_EUR); newpag.put(PAGSCA_IMPORTO, impeur); } else { newpag.put(PAGSCA_IMPORTO, importo); newpag.zero(PAGSCA_IMPORTOVAL); newpag.put(PAGSCA_RITENUTE, ritfis); newpag.put(PAGSCA_RITSOC, ritsoc); } if (part.tipo() == tm_nota_credito) { const TBill conto_nullo; conto_nullo.put(newpag, true); // Azzera conto newpag.zero(PAGSCA_CODABIPR); newpag.zero(PAGSCA_CODCABPR); app().notify_edit_pagamento(partita, newpag, valuta, importo.is_zero() ? _numrig : 0); } else { TBill conto_banca; conto_banca.get(*this, G_GRUPPOC, G_CONTOC, G_SOTTOCONTOC); conto_banca.put(newpag, true); newpag.put(PAGSCA_CODABIPR, get(G_ABI)); newpag.put(PAGSCA_CODCABPR, get(G_CAB)); app().notify_edit_pagamento(partita, newpag, valuta, importo.is_zero() ? _numrig : 0); } } } app().cgs().force_update(); } long TEasySolder_mask::handler(WINDOW w, EVENT* ep) { // Ordinamento col click destro sull'intestazione colonna if (ep->type == E_MOUSE_DOWN && ep->v.mouse.button == 1) { short id = DLG_NULL; long rec = -1; FOR_EACH_MASK_SHEET(*this, i, s) { if (s->parent() == w && s->point2cell(ep->v.mouse.where, id, rec) && rec < 0) { const char* st = NULL; switch (id) { case S_DATADOC : case S_NUMDOC : st = "C"; break; // Data+Numero documento case S_IMPORTO : st = "I"; break; // Importo pagamento (o insoluto) case S_MODOPAG : st = "M"; break; // Modalità di pagamento case S_RESIDUO : st = "R"; break; // Residuo rata case S_TOTALE : st = "T"; break; // Totale rata case S_DATASCAD: st = "D"; break; // Data scadenza default: if (id >= S_ANNO && id <= S_RIGAP) st = "P"; break; // Anno+Partita+Riga } if (st && *st) set(G_SORT, st, 0x1); return 0; } } } return TAutomask::handler(w, ep); } static int sort_by_fields(TSheet_field& sheet, int r1, int r2, const short* const ids) { const TToken_string& row1 = sheet.row(r1); const TToken_string& row2 = sheet.row(r2); long diff = 0; for (int i = 0; ids[i]>0 && diff==0; i++) { const int idx = sheet.cid2index(ids[i]); switch (ids[i]) { case S_DATASCAD: case S_DATADOC: { TDate d1; row1.get(idx, d1); TDate d2; row2.get(idx, d2); long n1 = d1.date2ansi(); long n2 = d2.date2ansi(); diff = n1-n2; } break; case S_PARTITA: { TString8 p1; row1.get(idx, p1); TString8 p2; row2.get(idx, p2); diff = p1.compare(p2, -1, true); } break; case S_IMPORTO: case S_RESIDUO: case S_TOTALE: { real n1, n2; row1.get(idx, n1); row2.get(idx, n2); diff = real(n1-n2).sign(); } break; default: { long n1, n2; row1.get(idx, n1); row2.get(idx, n2); diff = n1-n2; } break; } } return diff; } static int sort_by_date(TSheet_field& sheet, int r1, int r2) { // Elenco dei campi da confrontare in ordine di priorita' const short ids[8] = { S_DATASCAD, S_ANNO, S_PARTITA, S_RIGAF, S_RATA, S_RIGAP, DLG_NULL }; return sort_by_fields(sheet, r1, r2, ids); } static int sort_by_game(TSheet_field& sheet, int r1, int r2) { // Elenco dei campi da confrontare in ordine di priorita' const short ids[8] = { S_ANNO, S_PARTITA, S_RIGAF, S_RATA, S_RIGAP, DLG_NULL }; return sort_by_fields(sheet, r1, r2, ids); } static int sort_by_doc(TSheet_field& sheet, int r1, int r2) { // Elenco dei campi da confrontare in ordine di priorita' const short ids[8] = { S_DATADOC, S_NUMDOC, S_ANNO, S_PARTITA, S_RIGAF, S_RATA, S_RIGAP, DLG_NULL }; return sort_by_fields(sheet, r1, r2, ids); } static int sort_by_imp(TSheet_field& sheet, int r1, int r2) { // Elenco dei campi da confrontare in ordine di priorita' const short ids[8] = { S_IMPORTO, S_DATASCAD, S_ANNO, S_PARTITA, S_RIGAF, S_RATA, S_RIGAP, DLG_NULL }; return sort_by_fields(sheet, r1, r2, ids); } static int sort_by_tot(TSheet_field& sheet, int r1, int r2) { // Elenco dei campi da confrontare in ordine di priorita' const short ids[8] = { S_TOTALE, S_DATASCAD, S_ANNO, S_PARTITA, S_RIGAF, S_RATA, S_RIGAP, DLG_NULL }; return sort_by_fields(sheet, r1, r2, ids); } static int sort_by_res(TSheet_field& sheet, int r1, int r2) { // Elenco dei campi da confrontare in ordine di priorita' const short ids[8] = { S_RESIDUO, S_DATASCAD, S_ANNO, S_PARTITA, S_RIGAF, S_RATA, S_RIGAP, DLG_NULL }; return sort_by_fields(sheet, r1, r2, ids); } static int sort_by_moda(TSheet_field& sheet, int r1, int r2) { // Elenco dei campi da confrontare in ordine di priorita' const short ids[8] = { S_MODOPAG, S_DATASCAD, S_ANNO, S_PARTITA, S_RIGAF, S_RATA, S_RIGAP, DLG_NULL }; return sort_by_fields(sheet, r1, r2, ids); } real TEasySolder_mask::val2eur(const real& val) const { real eur; const TMask& mm = app().curr_mask(); const real toteur = mm.get(F_TOTALE); const real totval = mm.get(SK_TOTDOCVAL); if (toteur.is_zero() || totval.is_zero()) { const TValuta valuta(mm, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO); eur = valuta.val2eur(val); } else { eur = val * toteur / totval; eur.round(2); } return eur; } real TEasySolder_mask::eur2val(const real& eur) const { real val; const TMask& mm = app().curr_mask(); const real toteur = mm.get(F_TOTALE); const real totval = mm.get(SK_TOTDOCVAL); if (toteur.is_zero() || totval.is_zero()) { const TValuta valuta(mm, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO); val = valuta.eur2val(eur); } else { val = eur * totval / toteur; val.round(2); } return val; } TImporto TEasySolder_mask::eur2val(const TImporto& imp) const { TImporto eur = imp; eur.valore() = eur2val(imp.valore()); return eur; } bool TEasySolder_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_SAVEREC: if (e == fe_button) { if (!check_fields()) return false; save_sheet(); } break; case G_SORT: if (e == fe_modify) { TSheet_field& s = sfield(G_SHEET); switch (o.get()[0]) { case 'C': s.sort(sort_by_doc); break; case 'I': s.sort(sort_by_imp); break; case 'M': s.sort(sort_by_moda); break; case 'P': s.sort(sort_by_game); break; case 'R': s.sort(sort_by_res); break; case 'T': s.sort(sort_by_tot); break; default : s.sort(sort_by_date); break; } s.force_update(); } break; case G_SHEET: switch (e) { case se_enter: { TSheet_field& s = (TSheet_field&)o; TToken_string& row = s.row(jolly); _anno = get_row_int(s, row, S_ANNO); _numpart = get_row_str(s, row, S_PARTITA); const int rigaf = get_row_int(s, row, S_RIGAF); const int nrata = get_row_int(s, row, S_RATA); const int nrigp = get_row_int(s, row, S_RIGAP); if (_tree->goto_single_game(_anno, _numpart, rigaf, nrata, nrigp)) { TTree_field& tf = tfield(G_PARTITE); tf.select_current(); tf.win().force_update(); reset(G_TUTTE); } } break; case se_query_add: { TNew_game_mask m(_conto); if (m.run() == K_ENTER) { // Memorizzo il codice partita in modo da poterlo mettere nella nuova riga _anno = atoi(m.get(PART_ANNO)); _numpart = m.get(PART_NUMPART); return true; } return false; } break; case se_notify_add: { // Metto nella nuova riga il codice partita memorizzato sopra TSheet_field& sheet = (TSheet_field&)o; TToken_string& row = sheet.row(jolly); set_row_int(sheet, row, S_ANNO, _anno); set_row_str(sheet, row, S_PARTITA, _numpart); set_row_int(sheet, row, S_RIGAF, TPartita::UNASSIGNED); set_row_int(sheet, row, S_RATA, TPartita::UNASSIGNED); sheet.disable_cell(jolly, S_SALDO); } break; case se_notify_modify: aggiorna_residuo(); break; case se_query_del: return false; default: break; } break; case G_CAB: if (e == fe_modify && !o.empty() && is_running()) { TString16 codtab; codtab << get(G_ABI) << get(G_CAB); const TRectype& bnp = cache().get("BNP", codtab); if (!bnp.empty()) { const int g = bnp.get_int("I9"); const int c = bnp.get_int("I10"); const long s = bnp.get_long("I11"); if (g > 0 && c > 0 && s > 0) { set(G_GRUPPOC, g); set(G_CONTOC, c); set(G_SOTTOCONTOC, s, 0x2); // Decodifica descrizione } } } break; case S_SPUNTA: if (e == fe_modify) { TMask& m = o.mask(); TSheet_field& s = sfield(G_SHEET); if (o.get().full()) { const real importo = m.get(S_IMPORTO); if (importo.is_zero()) { real residuo = m.get(S_RESIDUO); if (residuo.is_zero()) { const int anno = m.get_int(S_ANNO); const TString8 num = m.get(S_PARTITA); const int nriga = m.get_int(S_RIGAF); const int nrata = m.get_int(S_RATA); const TPartita& game = app().partite().partita(_conto, anno, num); if (game.esiste(nriga, nrata)) residuo = game.rata(nriga, nrata).residuo(true).valore(); } if (!residuo.is_zero()) { m.set(S_IMPORTO, residuo); if (_tipomov != tm_insoluto && _tipomov != tm_nota_credito) m.set(S_SALDO, true); if (in_valuta()) { const real residuo_eur = val2eur(residuo); m.set(S_IMPORTO_EUR, residuo_eur); } } } } else { m.reset(S_IMPORTO); m.reset(S_IMPORTO_EUR); m.reset(S_SALDO); } if (!m.is_running()) { const int r = s.selected(); s.update_row(r); aggiorna_residuo(); } } break; case S_IMPORTO: case S_IMPORTO_EUR: if (e == fe_modify) { if (in_valuta()) { const short buddy_id = S_IMPORTO + S_IMPORTO_EUR - o.dlg(); // :-) TEdit_field& buddy_imp = o.mask().efield(buddy_id); if (buddy_imp.empty()) { const real imp = o.get(); if (buddy_id == S_IMPORTO_EUR) buddy_imp.set(val2eur(imp).string()); else buddy_imp.set(eur2val(imp).string()); } } if (!o.mask().is_running()) { TSheet_field& s = sfield(G_SHEET); const int r = s.selected(); s.update_row(r); aggiorna_residuo(); } } break; case G_TUTTE: case G_INVALUTA: if (e == fe_modify) { TSolder_tree_flags flags = (TSolder_tree_flags)get_int(G_TUTTE); const TString& codval = get(G_VALUTA); real cambio; if (is_true_value(codval)) { cambio = get_real(G_CAMBIO); if (get_bool(G_INVALUTA)) flags = TSolder_tree_flags(flags | sct_show_val); } _tree->set_root(app().partite(), _conto, _numreg, _numrig, codval, cambio, flags); if ((flags & sct_all_games) == sct_single_game) { TSheet_field& s = sfield(G_SHEET); const int sel = s.selected(); if (sel >= 0 && sel < s.items()) on_field_event(s, se_enter, sel); } else // Partite aperte, chiuse o tutte { if (_tree->goto_root()) { if (_tree->has_rbrother()) _tree->shrink_all(); else _tree->expand_all(); } TTree_field& tfp = tfield(G_PARTITE); tfp.win().force_update(); } } break; case G_PARTITE: if (e == fe_modify) { TToken_string curr; _tree->curr_id(curr); const int level = curr.items(); } break; default: break; } return true; } static int nrigp_pagamento_locale(const TSolder_tree& st) { const TToken_string& curr = *(TToken_string*)st.curr_node(); const int level = curr.items(); if (level >= 3) { const long nreg_mov = st.num_reg(); const int nrig_mov = st.num_rig(); if (level == 3) { const TRiga_scadenze* scad = st.scadenza(); if (scad != NULL) // Vera scadenza { for (int nrigp = scad->last(); nrigp > 0; nrigp = scad->pred(nrigp)) { const TRiga_partite& riga = scad->partita().riga(nrigp); const long nreg_riga = riga.get_long(PART_NREG); const int nrig_riga = riga.get_int(PART_NUMRIG); if (nreg_riga == nreg_mov && nrig_riga == nrig_mov) return nrigp; } } } else if (level == 4) { // const int nrigp = st.pagamento()->get_int(PAGSCA_NRIGP); int nrigp = 0; curr.get(3, nrigp); const TRiga_partite& riga = st.partita()->riga(nrigp); const long nreg_riga = riga.get_long(PART_NREG); const int nrig_riga = riga.get_int(PART_NUMRIG); if (nreg_riga == nreg_mov && nrig_riga == nrig_mov) return nrigp; } } return 0; } static int has_lonely_nc(TPartita& game) { int ncs = 0; const TRecord_array& u = game.unassigned(); for (int i = u.last_row(); i > 0; i = u.pred_row(i)) { const TRiga_partite& r = game.riga(i); if (r.tipo() == tm_nota_credito) { ncs = i; break; } } return ncs; } // Aggiunge una nota di credito non associata a fattura static bool add_lonely_nc(TPartita& game, TSheet_field& sheet, int rigasheet) { int nrigp = has_lonely_nc(game); if (nrigp <= 0) return false; const TRiga_partite& riga = game.riga(nrigp); TToken_string& row = sheet.row(rigasheet); const TCausale& causale = app().causale(); const char expected_section = causale.sezione_clifo() == 'D' ? 'A' : 'D'; TImporto res = game.calcola_saldo(true); res.normalize(expected_section); set_row_currency(sheet, row, S_RESIDUO, res.valore()); TImporto tot = riga.importo(true); tot.normalize(expected_section); set_row_currency(sheet, row, S_TOTALE, tot.valore()); set_row_int(sheet, row, S_ANNO, game.anno()); set_row_str(sheet, row, S_PARTITA, game.numero()); set_row_int(sheet, row, S_RIGAF, TPartita::UNASSIGNED); set_row_int(sheet, row, S_RATA, TPartita::UNASSIGNED); set_row_int(sheet, row, S_RIGAP, 0); // Lasciare 0 e NON mettere assultamente nrigp o la scambia per pagamento! set_row_str(sheet, row, S_DATASCAD, riga.get(PART_DATAPAG)); if (game.in_valuta()) { row.add(game.codice_valuta(), sheet.cid2index(S_VALUTA)); TImporto reseur = riga.importo(false); reseur.normalize(expected_section); set_row_currency(sheet, row, S_RESIDUO_EUR, reseur.valore()); } set_row_str(sheet, row, S_NUMDOC, riga.get(PART_NUMDOC)); set_row_str(sheet, row, S_DATADOC, riga.get(PART_DATADOC)); const int nrow = sheet.items()-1; sheet.disable_cell(nrow, S_SALDO); return true; } // static callback function bool TEasySolder_mask::sheet_rate_filler(TTree& tree, void* jolly, word /* flags */) { const TSolder_tree& st = (const TSolder_tree&)tree; const TToken_string& curr = *(TToken_string*)st.curr_node(); const int level = curr.items(); if (level < 3) return false; int nriga; curr.get(1, nriga); int nrata; curr.get(2, nrata); if (level == 3 && nrata >= TPartita::UNASSIGNED) return false; // Falso nodo dell'albero padre dei non assegnati TPartita& game = *st.partita(); if (!same_values(st.codval(), game.codice_valuta())) return false; // Scadenza in valuta diversa da quella selezionata int nrigp = nrigp_pagamento_locale(st); bool good_rat = level >= 3 && nrata > 0 && nrata < TPartita::UNASSIGNED; bool good_pag = level == 4 && nrigp > 0; const TRiga_scadenze* scad = good_rat ? st.scadenza() : NULL; if (good_rat && scad == NULL) { CHECKD(false, "Rata nulla inattesa ", nrata); // Segnalazione 1867 return false; } TSheet_field& sheet = *(TSheet_field*)jolly; const TCausale& causale = app().causale(); const tipo_movimento tm = causale.tipomov(); const char pag_section = ((TEasySolder_mask&)sheet.mask()).calcola_sezione(); const char rat_section = pag_section == 'D' ? 'A' : 'D'; switch (tm) { case tm_nota_credito: case tm_pagamento: case tm_pagamento_insoluto: if (level == 3) { if (good_rat) { good_rat = nrigp <= 0 && !scad->chiusa() && !scad->get_bool(SCAD_BLOCCATA); /* Commentato in quanto impedisce di saldare le note di credito if (good_rat) { const char expected_section = scad->get_char(SCAD_TIPOCF) == 'C' ? 'D' : 'A'; TImporto res = scad->residuo(true); res.normalize(expected_section); // res.normalize(scad->riga().sezione()); if (res.valore () <= ZERO) // In realtà è chiusa! good_rat = false; } */ } } else good_rat &= good_pag; break; case tm_insoluto: if (level == 3) { if (good_rat && nrigp <= 0) good_rat = !scad->importo_pagato(true).is_zero(); else good_rat = false; } else good_rat &= good_pag; break; default: good_rat = good_pag = false; break; } if (good_rat || good_pag) // Creo una nuova riga solo se necessario { TToken_string& row = sheet.row(-1); row.add(game.codice_valuta(), sheet.cid2index(S_VALUTA)); if (good_rat) { TImporto res; if (tm == tm_insoluto) { res = scad->importo_pagato(true); } else { res = scad->residuo(true); res.normalize(rat_section); } set_row_currency(sheet, row, S_RESIDUO, res.valore()); const TImporto tot = scad->importo(true); set_row_currency(sheet, row, S_TOTALE, tot.valore()); set_row_int(sheet, row, S_ANNO, game.anno()); set_row_str(sheet, row, S_PARTITA, game.numero()); set_row_int(sheet, row, S_RIGAF, nriga); set_row_int(sheet, row, S_RATA, nrata); set_row_str(sheet, row, S_DATASCAD, scad->get(SCAD_DATASCAD)); set_row_str(sheet, row, S_MODOPAG, scad->get(SCAD_TIPOPAG)); // Solo proposta if (game.in_valuta()) { // Calcola il residuo rata utilizzando il cambio della fattura e non quello del pagamento const TImporto reseur = tm == tm_insoluto ? scad->importo_pagato(false) : scad->residuo(false); set_row_currency(sheet, row, S_RESIDUO_EUR, reseur.valore()); } if (nriga > 0 && nriga < TPartita::UNASSIGNED) // Dovrebbe sempre essere vero, ma ... { const TRiga_partite& riga = game.riga(nriga); set_row_str(sheet, row, S_NUMDOC, riga.get(PART_NUMDOC)); set_row_str(sheet, row, S_DATADOC, riga.get(PART_DATADOC)); } // Propone data di pagamento per le RIBA if (!good_pag) { TDate dp(TODAY); if (scad->get_int(SCAD_TIPOPAG) > 1) { const TDate ds = scad->get(SCAD_DATASCAD); if (ds > dp) dp = ds; } set_row_str(sheet, row, S_DATAPAG, dp); } } if (good_pag) { if (!good_rat && nrigp > 1 && has_lonely_nc(game)) add_lonely_nc(game, sheet, sheet.items()-1); const TRiga_partite& rigp = game.riga(nrigp); set_row_int(sheet, row, S_RIGAP, nrigp); set_row_int(sheet, row, S_NREG, rigp.get_long(PART_NREG)); set_row_int(sheet, row, S_NRIG, rigp.get_int(PART_NUMRIG)); const TRectype& pag = *st.pagamento(); const real imp = pag.get_real(PAGSCA_IMPORTO); if (!imp.is_zero()) { set_row_bool(sheet, row, S_SPUNTA, true); if (rigp.in_valuta()) { const real impval = pag.get_real(PAGSCA_IMPORTOVAL); set_row_currency(sheet, row, S_IMPORTO, impval); set_row_currency(sheet, row, S_IMPORTO_EUR, imp); } else set_row_currency(sheet, row, S_IMPORTO, imp); } set_row_str(sheet, row, S_SALDO, (good_rat && pag.get_char(PAGSCA_ACCSAL)=='S') ? "X" : ""); set_row_int(sheet, row, S_MODOPAG, rigp.get_int(PART_TIPOPAG)); set_row_currency(sheet, row, S_RITFIS, pag.get_real(PAGSCA_RITENUTE)); set_row_currency(sheet, row, S_RITSOC, pag.get_real(PAGSCA_RITSOC)); set_row_int(sheet, row, S_ANNO, game.anno()); set_row_str(sheet, row, S_PARTITA, game.numero()); set_row_int(sheet, row, S_RIGAF, nriga); set_row_int(sheet, row, S_RATA, nrata); set_row_str(sheet, row, S_MODOPAG, rigp.get(PART_TIPOPAG)); if (good_rat) { set_row_str(sheet, row, S_DATAPAG, rigp.get(PART_DATAPAG)); } else { set_row_str(sheet, row, S_DATASCAD, rigp.get(PART_DATAPAG)); const int nrow = sheet.items()-1; sheet.disable_cell(nrow, S_SALDO); } } } else { // Nota di credito non assegnata e senza pagamenti n questo movimento if (level == 4 && nriga == TPartita::UNASSIGNED && nrigp == 0 && has_lonely_nc(game)) { const TImporto sld = game.calcola_saldo(true); if (!sld.is_zero()) add_lonely_nc(game, sheet, -1); } } return false; } // Complesso algoritmo per calcolare la sezione di una nuova riga partita char TEasySolder_mask::calcola_sezione() const { const char tipoc = _conto.tipo(); const TCausale& causale = app().causale(); char sezione = causale.sezione_clifo(); // Usa la sezione della causale if (sezione != 'A' && sezione != 'D') // Se non c'e' la sezione bell'e' ch'e' pronta { const tipo_movimento tm = causale.tipomov(); if (tm == tm_fattura || tm == tm_insoluto) // calcola in base al tipo movimento e sezione = (tipoc == 'C') ? 'D' : 'A'; // al tipo cliente/fornitore else sezione = (tipoc == 'C') ? 'A' : 'D'; } // Gestione compensazioni if (tipoc > ' ') // Se il tipo e' C o F { TBill bill; causale.bill(1, bill); // Legge primo conto causale const char tc = bill.tipo(); if (tc > ' ' && tc != tipoc) sezione = (sezione == 'D') ? 'A' : 'D'; // inverti sezione } return sezione; } bool TEasySolder_mask::in_valuta() const { const TString& codval = get(G_VALUTA); return is_true_value(codval); } void TEasySolder_mask::calcola_residuo() { TImporto impriga = app().get_cgs_imp(_numrig-1); // Importo sulla riga contabile set(G_TOTALE, impriga.valore()); TImporto residuo = impriga; TPartite_array& giochi = app().partite(); const TImporto speso = giochi.importo_speso(_numreg, _numrig); residuo -= speso; // Residuo della riga const char sez = calcola_sezione(); // Sezione di riferimento residuo.normalize(sez); const real segno_ritsoc = app().causale().sezione_ritsoc() == sez ? UNO : -UNO; _res_eur = residuo.valore(); set(G_RESIDUO_EUR, _res_eur); const bool in_val = in_valuta(); if (in_val) { // Importo della riga contabile senza differenza cambi TImporto resval = impriga; const TImporto abb_diff = giochi.importo_speso(_numreg, _numrig, false, 0x6); resval -= abb_diff; resval = eur2val(resval); TImporto spesoval = giochi.importo_speso(_numreg, _numrig, true, 0x1); resval -= spesoval; // Residuo della riga resval.normalize(sez); _res_val = resval.valore(); set(G_RESIDUO_VAL, _res_val); } else { _res_val = _res_eur; reset(G_RESIDUO_VAL); } TSheet_field& s = sfield(G_SHEET); _tot_val = _tot_eur = ZERO; FOR_EACH_SHEET_ROW(s, i, row) { if (in_val) { _tot_val += get_row_real(s, *row, S_IMPORTO); _tot_eur += get_row_real(s, *row, S_IMPORTO_EUR); } else { _tot_eur += get_row_real(s, *row, S_IMPORTO); _tot_eur += get_row_real(s, *row, S_RITFIS); _tot_eur += get_row_real(s, *row, S_RITSOC) * segno_ritsoc; _tot_val = _tot_eur; } } } void TEasySolder_mask::aggiorna_residuo() { const TCausale& caus = app().causale(); const real segno_ritsoc = caus.sezione_clifo() == caus.sezione_ritsoc() ? UNO : -UNO; const TSheet_field& s = sfield(G_SHEET); const bool in_val = in_valuta(); real totval, toteur; FOR_EACH_SHEET_ROW(s, i, row) { if (in_val) { totval += get_row_real(s, *row, S_IMPORTO); toteur += get_row_real(s, *row, S_IMPORTO_EUR); } else { toteur += get_row_real(s, *row, S_IMPORTO); // Gestisco le ritenute solo per i movimenti in Euro toteur += get_row_real(s, *row, S_RITFIS); // Ritfis ha sempre la sezione dell'importo toteur += get_row_real(s, *row, S_RITSOC) * segno_ritsoc; // Ritsoc puo' avere segno contrario } } const real reseur = _res_eur + _tot_eur - toteur; set(G_RESIDUO_EUR, reseur); if (in_val) { const real resval = _res_val + _tot_val - totval; set(G_RESIDUO_VAL, resval); } else reset(G_RESIDUO_VAL); } void TEasySolder_mask::fill_sheet() { TSheet_field& s = sfield(G_SHEET); s.destroy(); const TString& codval = get(G_VALUTA); const real cambio = get(G_CAMBIO); s.enable_column(S_SALDO, _tipomov != tm_insoluto && _tipomov != tm_nota_credito); const bool in_val = in_valuta(); s.enable_column(S_IMPORTO_EUR, in_val); s.enable_column(S_RITFIS, !in_val); s.enable_column(S_RITSOC, !in_val); if (_tipomov == tm_insoluto) { s.set_column_header(S_IMPORTO, HR("Importo\nInsoluto")); s.set_column_header(S_RESIDUO, HR("Importo\nPagato")); } else { s.set_column_header(S_IMPORTO, HR("Importo\nPagamento")); s.set_column_header(S_RESIDUO, HR("Residuo\nScadenza")); } s.set_column_justify(S_PARTITA, TPartita::allineamento_richiesto(_conto.tipo()) == 'R'); TSolder_tree_flags flags = sct_open_games; if (_tipomov == tm_insoluto || _tipomov == tm_nota_credito) flags = sct_all_games; _tree->set_root(app().partite(), _conto, _numreg, _numrig, codval, cambio, flags); _tree->scan_depth_first(sheet_rate_filler, &s); on_field_event(lfield(G_SORT), fe_modify, 0); FOR_EACH_SHEET_ROW_BACK(s, r, riga) { if (riga->get_char(0) == 'X') { s.post_select(r); first_focus(G_SHEET); break; } } calcola_residuo(); } void TEasySolder_mask::init(const TBill& conto, long numreg, int numrig) { _conto = conto; _numreg= numreg; _numrig = numrig; _tipomov = app().causale().tipomov(); _changed = false; if (_conto.tipo() > ' ') _conto.set(*this, 0, 0, G_CODCF, G_TIPOCF, G_RAGSOC); else _conto.set(*this, 0, 0, 0, G_TIPOCF, G_RAGSOC); TMask& cm = app().curr_mask(); const TString& codval = cm.get(SK_VALUTA); if (is_true_value(codval)) { set(G_VALUTA, codval); set(G_CAMBIO, cm.get(SK_CAMBIO)); set(G_DATACAMBIO, cm.get(SK_DATACAMBIO)); set(G_INVALUTA, "X"); } else { reset(G_VALUTA); reset(G_CAMBIO); reset(G_DATACAMBIO); reset(G_INVALUTA); } reset(G_TUTTE); TBill controbill; const int riga_i = app().type2pos('I'); if (riga_i >= 0) { TToken_string& row = app().cgs().row(riga_i); controbill.get(row, 2, 0xF); } else app().causale().bill(2, controbill); if (controbill.gruppo() > 0) // con controbill.ok() non presentava assolutamente i conti parziali { controbill.set(*this, G_GRUPPOC, G_CONTOC, G_SOTTOCONTOC, 0, G_DESCONTOC); } else { for (short id = G_ABI; id <= G_DESCONTOC; id++) reset(id); } // Nel caso di nota di credito devo nascondere il conto (fuorviante) for (short id = G_ABI; id <= G_DESCONTOC; id++) show(id, _tipomov != tm_nota_credito); if (_tree == NULL) { _tree = new TSolder_tree; tfield(G_PARTITE).set_tree(_tree); } fill_sheet(); } TEasySolder_mask::TEasySolder_mask(const TBill& conto, long numreg, int numrig) : TAutomask("cg2100e"), _tree(NULL) { init(conto, numreg, numrig); } TEasySolder_mask::~TEasySolder_mask() { if (_tree != NULL) delete _tree; }