#include // Serve per DLG_NEWREC #include #include // Colori righe #include "cg2100p.h" // Campi maschere partite e pagamenti #ifdef __EXTRA__ #include "cgsaldac.h" #include "sc0100p.h" #else #include "cg2100.h" // Campi maschere prima nota #include "cg2102.h" // Applicazione di prima nota #endif #include // Archivio causali #include // Archivio clienti/fornitori #include // Archivio movimenti di prima nota /////////////////////////////////////////////////////////// // Definizione Maschera partite /////////////////////////////////////////////////////////// class TGame_mask : public TMask { const TBill _conto; // Conto fisso del cliente/fornitore long _numreg; // Numero movimento contabile int _numrig; // Riga contabile corrente (prima = 1!) TImporto _importo; // Importo su riga contabile TImporto _residuo, _resval; // Residuo della riga contabile int _riga_partite; // Riga corrente delle partite bool _changed; // Flag di modifica partite bool _valfirst; // La colonna della valuta precede le lire TDecoder _causali; // Decodificatore delle causali protected: static bool annopart_handler(TMask_field& f, KEY k); static bool numpart_handler(TMask_field& f, KEY k); static bool partite_notify(TSheet_field& partite, int r, KEY k); static bool scadenze_notify(TSheet_field& partite, int r, KEY k); static bool show_all_handler(TMask_field& f, KEY k); static bool edit_scadenza_handler(TMask_field& f, KEY k); static bool nuovo_handler(TMask_field& f, KEY k); static bool cambio_handler(TMask_field& f, KEY k); void add_importo(TToken_string& s, const TImporto& i, bool val = FALSE, int pos = -1); void add_descrizione(TToken_string& s, const TRiga_partite& riga, int pos = -1); TImporto get_importo(TToken_string& s, int pos) const; TToken_string& add_colored_row(TSheet_field& sheet, char type) const; void fill_partite(); void aggiorna_residuo(); int update_partita(const TRectype& game, const TImporto& s, const TImporto& d, const TImporto& p, const TImporto& i, int prow); int update_partita(const TPartita& game, int prow); int update_partita(const TRectype& game, int prow); void update_saldo_clifo(); int nuova_riga(TPartita& partita, tipo_movimento tm) const; int nuovo_pagamento(TPartita& partita, int nriga, int rata, tipo_movimento tm) const; bool edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp) const; char calcola_sezione(tipo_movimento tm = tm_pagamento) const; long number_distance(const char* key, const char* num) const; bool same_number(const char* key, const char* num) const; void append_conto(TString& s) const; #ifdef __EXTRA__ bool edit_fattura(TPartita& p, int nriga); bool prima_nota(const long nreg); #endif const TRiga_partite* cerca_prima_riga() const; void aggiorna_valuta(const TValuta& val); // void aggiorna_sorelle(const TRiga_partite& part) const; public: TSheet_field& partite() const { return (TSheet_field&)field(P_PARTITE); } TSheet_field& scadenze() const { return (TSheet_field&)field(P_SCADENZE); } const TBill& conto() const { return _conto; } const TImporto& residuo(bool val) const { return val ? _resval : _residuo; } bool changed() const { return _changed; } TGame_mask(const TBill& bill, long numreg, int riga); virtual ~TGame_mask() {} }; /////////////////////////////////////////////////////////// // Maschera pagamenti /////////////////////////////////////////////////////////// class TPay_mask : public TMask { TDate _datadoc; real _da_pagare, _pagabile; const TGame_mask& _parent; tipo_movimento _tipomov; TDecoder _causale; bool _assigned; bool _can_solder; protected: static bool importo_handler(TMask_field& f, KEY k); static bool importolire_handler(TMask_field& f, KEY k); static bool saldo_handler(TMask_field& f, KEY k); static bool datapag_handler(TMask_field& f, KEY k); static bool conto_handler(TMask_field& f, KEY k); static bool descr_handler(TMask_field& f, KEY k); void gioca_cambi(int force = 0x0); static bool sottoconto_handler(TMask_field& f, KEY k); #ifdef __EXTRA__ static bool datareg_handler(TMask_field& f, KEY k); static bool datadoc_handler(TMask_field& f, KEY k); static bool numdoc_handler(TMask_field& f, KEY k); static bool sezione_handler(TMask_field& f, KEY k); #endif public: void set_pag(const TRectype& oldpag, const TRiga_scadenze& scad, const TImporto& importo); void get_pag(TRectype& oldpag, TRectype& somma) const; bool assigned() const { return _assigned; } bool unassigned() const { return !_assigned; } tipo_movimento tipo() const { return _tipomov; } void attiva_valuta(bool on); TPay_mask(const TGame_mask& parent, int mode); virtual ~TPay_mask(); }; #ifdef __EXTRA__ const char* const PAYMASK = "sc0100b"; #else const char* const PAYMASK = "cg2100s"; #endif TPay_mask::TPay_mask(const TGame_mask& parent, int mod) : TMask(PAYMASK), _parent(parent), _causale(LF_CAUSALI, CAU_DESCR) { set_mode(mod); enable(DLG_DELREC, edit_mode()); set_handler(S_SOTTOCONTO, sottoconto_handler); #ifdef __EXTRA__ xvt_statbar_set(mod == MODE_MOD ? "Modifica" : "Inserimento", TRUE); hide(E_CODPAG); hide(E_DESPAG); set_handler(E_DATAREG, datareg_handler); set_handler(E_DATADOC, datadoc_handler); set_handler(E_NUMDOC, numdoc_handler); set_handler(E_SEZIONE, sezione_handler); set_handler(E_TOTALE, TSaldaconto_app::totale_handler); if (app().gestione_valuta()) { show(-3); set_handler(E_TOTDOCVAL, TSaldaconto_app::totval_handler); set_handler(E_VALUTA, TSaldaconto_app::valuta_handler); set_handler(E_DATACAMBIO, TSaldaconto_app::datacambio_handler); set_handler(E_CAMBIO, TSaldaconto_app::cambio_handler); } else hide(-3); hide(S_RESIDUOPAG); hide(-2); // I campi relativi alla contropartita non vengono gestiti hide(E_IMPOSTE); set_handler(E_DESCR, descr_handler); set_handler(S_DESCAGG, descr_handler); const char a = TPartita::allineamento_richiesto(parent.conto().tipo()); field(E_NUMRIF).set_justify(a == 'R'); disable(E_ANNORIF); disable(E_NUMRIF); #endif } TPay_mask::~TPay_mask() { #ifdef __EXTRA__ xvt_statbar_set("Estratto conto", TRUE); #endif } void TPay_mask::attiva_valuta(bool in_valuta) { if (in_valuta) { set_handler(S_IMPORTOVAL, importo_handler); set_handler(S_IMPORTO, importolire_handler); } else set_handler(S_IMPORTO, importo_handler); enable(S_RITENUTE, !in_valuta); // dis/abilita ritenute enable(S_IMPORTOVAL, in_valuta); if (in_valuta) { reset(S_RITENUTE); } else { reset(S_IMPORTOVAL_SCAD); reset(S_IMPORTOVAL); } } void TPay_mask::set_pag(const TRectype& oldpag, const TRiga_scadenze& scad, const TImporto& residuo) { const TPartita& p = scad.partita(); const int nrigp = oldpag.get_int(PAGSCA_NRIGP); const TRiga_partite& sum = p.riga(nrigp); _assigned = oldpag.get_int(PAGSCA_NRIGA) != TPartita::UNASSIGNED; _tipomov = (tipo_movimento)sum.get_int(PART_TIPOMOV); const TRiga_partite& fatt = _assigned ? scad.riga() : sum; TRelation rel(LF_PAGSCA); // Working relation rel.add(LF_PARTITE, "ANNO=ANNO|NUMPART=NUMPART"); rel.curr() = oldpag; rel.curr(LF_PARTITE) = sum; autoload(rel); // Load current record on mask TMask_field& group = field(S_RATA); TString prompt(80); const TBill& k = p.conto(); switch (k.tipo()) { case 'C': prompt << "Cliente"; break; case 'F': prompt << "Fornitore"; break; default : prompt << "Conto " << k.gruppo() << ' ' << k.conto(); break; } prompt << ' ' << k.sottoconto() << ' '; prompt << "Partita:" << p.anno() << ' ' << p.numero() << " Riga:" << oldpag.get_int(PAGSCA_NRIGA) << " Rata:" << oldpag.get_int(PAGSCA_NRATA); if (assigned()) prompt << " del " << scad.get_date(SCAD_DATASCAD).string(); #ifndef __EXTRA__ else prompt << " del " << sum.get_date(PART_DATAPAG).string(); #endif group.set_prompt(prompt); set(S_NUMDOC, fatt.get(PART_NUMDOC)); // Numero documento set(S_DATADOC, fatt.get(PART_DATADOC)); // Data documento set(S_NUMPROT, fatt.get(PART_PROTIVA)); // Protocollo IVA TString desfat = fatt.get(PART_DESCR); // Descrizione fattura if (desfat.empty()) // Se e' vuota ... { desfat = fatt.get(PART_CODCAUS); desfat = _causale.decode(desfat); // ... usa descrizione causale } set(S_DESCR, desfat); bool in_valuta = fatt.in_valuta(); #ifdef __EXTRA__ const bool prima_riga = p.first() == p.last(); if (!in_valuta && prima_riga) in_valuta = app().gestione_valuta(); enable(E_VALUTA, prima_riga); // La valuta puo' essere cambiata solo sulle partite nuove #endif show(-3, in_valuta); // Visualizza campi relativi alla valuta attiva_valuta(in_valuta); // Attiva campi e handlers relativi alla valuta const char sez_fat = fatt.sezione(); set(S_SEZIONE_SCAD, sez_fat == 'A' ? "A" : "D"); // Sezione della riga if (assigned()) { set(S_IMPORTO_SCAD, scad.get(SCAD_IMPORTO)); // Importo della rata if (in_valuta) set(S_IMPORTOVAL_SCAD, scad.get(SCAD_IMPORTOVAL)); // Importo in valuta TImporto res_rat = scad.residuo(in_valuta); res_rat.normalize(sez_fat); _da_pagare = res_rat.valore(); // Calcola residuo in valuta TReal_field& res = (TReal_field&)field(S_RESIDUORATA); res.set_decimals(in_valuta ? 3 : 0); if (get(S_SALDOACC)[0] != 'S') res.set(_da_pagare.string()); } else { hide(S_RESIDUORATA); // Se non assegnato nascondi residuo rata _da_pagare = ZERO; } set_handler(S_SALDOACC, saldo_handler); real oldimp = oldpag.get_real(in_valuta ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO); if (!in_valuta) oldimp += oldpag.get_real(PAGSCA_RITENUTE); // Ricorda l'importo da pagare _da_pagare += oldimp; #ifndef __EXTRA__ _pagabile = _parent.residuo(in_valuta).valore(); TReal_field& resp = (TReal_field&)field(S_RESIDUOPAG); resp.set_decimals(in_valuta ? 3 : 0); resp.set(_pagabile.string()); _pagabile += oldimp; #endif // Il flag di saldo/acconto e' attivo solo se non ci sono acconti, cioe': // pagamento non assegnato o con data documento antecedente quella della fattura _can_solder = _assigned; if (_can_solder) { const tipo_movimento tm = sum.tipo(); _can_solder = !(tm == tm_nota_credito || tm == tm_insoluto); if (_can_solder) { const TDate datasca(fatt.get(PART_DATADOC)); const TDate datapag(sum.get(PART_DATADOC)); _can_solder = datapag >= datasca; } } // Mostra saldo solo se non e' ne' un acconto, ne' una nota di credito enable(S_SALDOACC, _can_solder); #ifdef __EXTRA__ enable(E_SEZIONE, oldpag.get_char(PAGSCA_ACCSAL) != 'S'); #else set_handler(S_GRUPPO, conto_handler); set_handler(S_CONTO, conto_handler); const bool mostra_conto = !sum.is_nota_credito(); show(-2, mostra_conto); // mostra/nasconde conto contropartita #endif // Gestione data-pagamento: non puo' precedere la data del documento _datadoc = sum.get_date(PART_DATADOC); set_handler(S_DATAPAG, datapag_handler); const bool mostra_ritenute = !sum.is_nota_credito(); show(S_RITENUTE, mostra_ritenute); } void TPay_mask::get_pag(TRectype& newpag, TRectype& sum) const { TRelation rel(LF_PAGSCA); // Working relation rel.add(LF_PARTITE, "ANNO=ANNO|NUMPART=NUMPART"); rel.curr() = newpag; rel.curr(LF_PARTITE) = sum; autosave(rel); // Load current record from mask newpag = rel.curr(); sum = rel.curr(LF_PARTITE); } // Riempie i campi valuta a zero in base agli altri void TPay_mask::gioca_cambi(int force) { const real totale = get(S_IMPORTO); const real totval = get(S_IMPORTOVAL); #ifdef __EXTRA__ const TValuta cambio(*this, E_VALUTA, E_DATACAMBIO, E_CAMBIO); #else const TValuta cambio(_parent, P_VALUTA, P_DATACAMBIO, P_CAMBIO); #endif if ( (force == 0x1 || totale.is_zero()) && !(totval.is_zero() || cambio.in_lire()) ) { const real new_totale = cambio.val2lit(totval); if (new_totale != totale) set(S_IMPORTO, new_totale, TRUE); } if ( (force == 0x2 || totval.is_zero()) && !(totale.is_zero() || cambio.in_lire())) { const real new_totval = cambio.lit2val(totale); if (new_totval != totval) set(S_IMPORTOVAL, new_totval, TRUE); } #ifdef __EXTRA__ if ( (force == 0x4 || cambio.in_lire()) && !(totale.is_zero() || totval.is_zero())) { real new_cambio = totale / totval; new_cambio.round(5); if (new_cambio != cambio.cambio()) set(E_CAMBIO, new_cambio, TRUE); } #endif } bool TPay_mask::importo_handler(TMask_field& f, KEY k) { TPay_mask& m = (TPay_mask&)f.mask(); if (k == K_F8) { real imp; #ifdef __EXTRA__ const bool in_valuta = m.field(S_IMPORTOVAL).active(); m._pagabile = m.get_real(in_valuta ? E_TOTDOCVAL : E_TOTALE); if (m._assigned) imp = fnc_min(m._da_pagare, m._pagabile); else imp = m._pagabile; #else if (m.field(S_RESIDUORATA).shown() && m.field(S_RESIDUOPAG).shown()) imp = fnc_min(m._da_pagare, m._pagabile); else imp = m.field(S_RESIDUORATA).shown() ? m._da_pagare : m._pagabile; #endif if (m.field(S_RITENUTE).active()) imp -= real(m.get(S_RITENUTE)); f.set(imp.string()); k = K_TAB; } if (k == K_TAB && (f.focusdirty() || !m.is_running())) { const bool in_valuta = m.field(S_IMPORTOVAL).active(); if (in_valuta) m.gioca_cambi(); real i(f.get()); if (m.field(S_RITENUTE).active()) i += real(m.get(S_RITENUTE)); TMask_field& sa = m.field(S_SALDOACC); TMaskmode mod = (TMaskmode)m.mode(); if (m._can_solder && (mod == NO_MODE || mod == MODE_INS)) { if (i >= m._da_pagare) sa.set("S"); } if (sa.get()[0] != 'S') { real residuo = m._da_pagare; if (m.tipo() == tm_insoluto) residuo += i; else residuo -= i; m.set(S_RESIDUORATA, residuo); } else m.reset(S_RESIDUORATA); const real residuopag(m._pagabile - i); m.set(S_RESIDUOPAG, residuopag); } return TRUE; } bool TPay_mask::importolire_handler(TMask_field& f, KEY k) { TPay_mask& m = (TPay_mask&)f.mask(); if (k == K_F8) { #ifdef __EXTRA__ if (m.unassigned()) f.set(m.get(E_TOTALE)); else #endif m.send_key(k, S_IMPORTOVAL); } if (f.to_check(k)) m.gioca_cambi(); return TRUE; } bool TPay_mask::saldo_handler(TMask_field& f, KEY k) { if (k == K_SPACE) { TMask& m = f.mask(); m.set_mode(MODE_QUERY); TMask_field& imp = m.field(m.field(S_IMPORTOVAL).active() ? S_IMPORTOVAL : S_IMPORTO); imp.set_dirty(); imp.on_hit(); m.set_mode(NO_MODE); } return TRUE; } bool TPay_mask::sottoconto_handler(TMask_field& f, KEY k) { bool ok = TRUE; if (k == K_ENTER && f.mask().insert_mode() && f.get().empty()) ok = f.error_box("Contropartita obbligatoria"); return ok; } bool TPay_mask::datapag_handler(TMask_field& f, KEY k) { if (f.to_check(k)) { const TDate datapag(f.get()); TPay_mask& m = (TPay_mask&)f.mask(); if (datapag < m._datadoc) return f.error_box("La data del pagamento e' inferiore alla data del documento %s", m._datadoc.string()); } return TRUE; } bool TPay_mask::conto_handler(TMask_field& f, KEY k) { if (k == K_TAB && f.focusdirty()) { TMask& m = f.mask(); TBill conto; conto.get(m, S_GRUPPO, S_CONTO, S_SOTTOCONTO); const TString& desc = conto.descrizione(); if (desc.empty()) m.reset(S_SOTTOCONTO); m.set(S_DESCRCONTO, desc); } return TRUE; } /////////////////////////////////////////////////////////// // Maschera gestione nuovo pagamento / fattura /////////////////////////////////////////////////////////// class TNew_mask : public TMask { bool _allow_fatt; protected: static bool tipomov_handler(TMask_field& f, KEY k); public: TNew_mask(char tipocf, bool fatt, bool edit); virtual ~TNew_mask() {} }; bool TNew_mask::tipomov_handler(TMask_field& f, KEY k) { if (k == K_ENTER) { TNew_mask& m = (TNew_mask&)f.mask(); if (!m._allow_fatt && f.get() == "1") return f.error_box("Non e' possibile utilizzare una fattura come pagamento"); } return TRUE; } TNew_mask::TNew_mask(char tipocf, bool fatt, bool edit) : TMask("cg2100n"), _allow_fatt(fatt) { TMask_field& tipomov = field(P_NUOVO); #ifdef __EXTRA__ tipomov.set_handler(tipomov_handler); tipomov.enable(); tipomov.set(_allow_fatt ? "1" : "3"); if (!_allow_fatt) set_caption("Nuovo pagamento"); #else tipomov.disable(); #endif enable(P_ANNO, edit); enable(P_NUMERO, edit); if (edit) first_focus(P_NUMERO); const char a = TPartita::allineamento_richiesto(tipocf); field(P_NUMERO).set_justify(a == 'R'); } /////////////////////////////////////////////////////////// // Maschera partite /////////////////////////////////////////////////////////// void TGame_mask::append_conto(TString& s) const { switch (conto().tipo()) { case 'C': s << "Cliente"; break; case 'F': s << "Fornitore"; break; default: s << "Conto " << conto().gruppo() << ' ' << conto().conto(); break; } s << ' ' << conto().sottoconto(); } TGame_mask::TGame_mask(const TBill& bill, long numreg, int riga) : TMask("cg2100p"), _conto(bill), _numreg(numreg), _numrig(riga), _changed(FALSE), _valfirst(FALSE), _causali(LF_CAUSALI, CAU_DESCR) { TString descr(80); append_conto(descr); descr << ' ' << ((TBill&)_conto).descrizione(); set(P_DESCR, descr); #ifdef __EXTRA__ xvt_statbar_set("Estratto conto", TRUE); disable(-3); // Disabilita gestione valuta hide(P_RESIDUO); hide(P_RESIDUOVAL); #else TValuta val; const TRiga_partite* row = cerca_prima_riga(); if (row != NULL) { val.get(*row); // Legge valuta standard dalla partita set(P_ANNO, row->get(PART_ANNO)); // Propone anno e partita set(P_NUMERO, row->get(PART_NUMPART)); } else { TMask& cm = app().curr_mask(); // Legge valuta dal movimento val.get(cm, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO); if (cm.id2pos(F_ANNORIF) > 0) // Se in testata c'e' l'anno di riferimento { set(P_ANNO, cm.get(F_ANNORIF)); // Propone anno e partita set(P_NUMERO, cm.get(F_NUMRIF)); } } val.set(*this, P_VALUTA, P_DATACAMBIO, P_CAMBIO); enable(-3, val.in_valuta()); #endif set_handler(P_ANNO, annopart_handler); set_handler(P_NUMERO, numpart_handler); set_handler(P_SHOWALL, show_all_handler); set_handler(P_NUOVO, nuovo_handler); set_handler(P_CAMBIO, cambio_handler); TSheet_field& games = partite(); games.set_notify(partite_notify); scadenze().set_notify(scadenze_notify); scadenze().sheet_mask().set_handler(100, edit_scadenza_handler); fill_partite(); // Riempie sheet partite } /////////////////////////////////////////////////////////// // Handlers dei campi e della maschera principale /////////////////////////////////////////////////////////// bool TGame_mask::annopart_handler(TMask_field& f, KEY k) { if (k == K_TAB && f.focusdirty() && f.get().not_empty()) { TMask_field& n = f.mask().field(P_NUMERO); n.set_dirty(); numpart_handler(n, k); } return TRUE; } bool TGame_mask::numpart_handler(TMask_field& f, KEY k) { if (k == K_TAB && f.focusdirty()) { const TGame_mask& m = (const TGame_mask&)f.mask(); const int anno = m.get_int(P_ANNO); // Anno partita da cercare if (anno > 0) { const TString key = f.get(); // Numero partita da cercare int best_match = 0; // Partita piu' somigliante long min_dist = 10000000L; // Livello di somiglianza migliore TSheet_field& sheet = m.partite(); for (int i = 0; i < sheet.items(); i++) { TToken_string& row = sheet.row(i); if (anno == row.get_int(0)) // Se corrisponde l'anno e ... { const long dist = m.number_distance(key, row.get()); if (i == 0 || dist < min_dist) { min_dist = dist; best_match = i; if (dist == 0L) break; } } } sheet.select(best_match); // seleziona la partita } } return TRUE; } bool TGame_mask::show_all_handler(TMask_field& f, KEY k) { TGame_mask& gm = (TGame_mask&)f.mask(); if (k == K_SPACE && gm.is_running()) { gm.fill_partite(); } return TRUE; } bool TGame_mask::cambio_handler(TMask_field& f, KEY k) { if (k == K_TAB && f.focusdirty()) { TGame_mask& gm = (TGame_mask&)f.mask(); const bool needed = app().partite().mov2rig(gm._numreg, gm._numrig) > 0; if (needed && yesno_box("Aggiornare gli importi dei pagamenti?")) { const TValuta val(gm, P_VALUTA, P_DATACAMBIO, P_CAMBIO); gm.aggiorna_valuta(val); } gm.aggiorna_residuo(); } return TRUE; } /////////////////////////////////////////////////////////// // Metodi dei campi e della maschera principale /////////////////////////////////////////////////////////// // Aggiorna il campo con il residuo da spendere sui pagamenti void TGame_mask::aggiorna_residuo() { #ifndef __EXTRA__ _importo = app().get_cgs_imp(_numrig-1); // Importo sulla riga contabile _residuo = _importo; 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); set(P_RESIDUO, _residuo.valore()); const TValuta cambio(*this, P_VALUTA, P_DATACAMBIO, P_CAMBIO); if (cambio.in_valuta()) { // Importo della riga contabile senza differenza cambi _resval = _importo; const TImporto abb_diff = giochi.importo_speso(_numreg, _numrig, FALSE, 0x6); _resval -= abb_diff; cambio.lit2val(_resval); const TImporto spesoval = giochi.importo_speso(_numreg, _numrig, TRUE, 0x1); _resval -= spesoval; // Residuo della riga _resval.normalize(sez); set(P_RESIDUOVAL, _resval.valore()); } #endif } // Scandisce tutte le partite per cercare la prima del movimento corrente const TRiga_partite* TGame_mask::cerca_prima_riga() const { const TRiga_partite* riga = app().partite().mov2rig(_numreg, _numrig); return riga; } void TGame_mask::aggiorna_valuta(const TValuta& val) { TPartite_array& pa = app().partite(); for (TPartita* game = pa.first(); game; game = pa.next()) { for (int r = game->last(); r > 0; r = game->pred(r)) { const TRiga_partite& riga = game->riga(r); for (int s = riga.rate(); s > 0; s--) { const TRiga_scadenze& scad = riga.rata(s); for (int p = scad.last(); p > 0; p = scad.pred(p)) { TRiga_partite& sum = game->riga(p); if (sum.get_long(PART_NREG) == _numreg && sum.get_int(PART_NUMRIG) == _numrig) { TRectype pag(scad.row(p)); real imp(pag.get(PAGSCA_IMPORTOVAL)); val.val2lit(imp); pag.put(PAGSCA_IMPORTO, imp); // Converte in lire l'importo in valuta #ifdef __EXTRA__ game->modifica_pagamento(pag, val, TRUE); #else app().notify_edit_pagamento(*game, pag, val); #endif } } } } } fill_partite(); } /* void TGame_mask::aggiorna_sorelle(const TRiga_partite& part) const { TPartite_array& pa = app().partite(); for (TPartita* game = pa.first(); game; game = pa.next()) { for (int r = game->last(); r > 0; r = game->pred(r)) { TRiga_partite& row = game->riga(r); if (row.get_long(PART_NREG) == _numreg && row.get_int(PART_NUMRIG) == _numrig) { row.put(PART_DESCR, part.get(PART_DESCR)); row.put(PART_DATAPAG, part.get(PART_DATAPAG)); row.put(PART_TIPOPAG, part.get(PART_TIPOPAG)); } } } } */ TToken_string& TGame_mask::add_colored_row(TSheet_field& sheet, char type) const { int r = sheet.insert(-1, FALSE, FALSE); COLOR back, fore; app().type2colors(type, back, fore); sheet.set_back_and_fore_color(back, fore, r); return sheet.row(r); } bool TGame_mask::partite_notify(TSheet_field& partite, int r, KEY k) { TGame_mask& gm = (TGame_mask&)partite.mask(); if (k == K_TAB) { const bool changing_row = gm._riga_partite != r; if (!changing_row) return TRUE; main_app().begin_wait(); gm._riga_partite = r; TSheet_field& sheet = gm.scadenze(); sheet.destroy(-1, FALSE); // Azzera righe TToken_string& row = partite.row(r); const int anno = row.get_int(0); // Anno partita const TString16 num = row.get(); // Numero partita gm.set(P_ANNO, anno); // Aggiorna campi di ricerca gm.set(P_NUMERO, num); TValuta prima_valuta; // Codice prima valuta if (anno > 0) { const TBill& zio = gm.conto(); // Conto cliente/fornitore TPartita* game = app().partite().exist(zio, anno, num); // Cerca la partita tra quelle editate const bool should_delete_game = (game == NULL); // Ricorda di fare delete if (should_delete_game) // Se non c'era ... game = new TPartita(zio, anno, num); // ... creane una temporanea TImporto tot_lit, tot_val; const int lastrow = game->last(); if (lastrow > 0) prima_valuta.get(game->riga(lastrow)); const bool in_valuta = prima_valuta.in_valuta(); for (int ri = game->first(); ri <= lastrow; ri = game->succ(ri)) { const TRiga_partite& riga = game->riga(ri); if (!riga.is_fattura()) continue; TToken_string& riga_fattura = gm.add_colored_row(sheet, 'K'); riga_fattura.add(ri); riga_fattura.add(""); riga_fattura.add(riga.get(PART_DATADOC)); riga_fattura.add(""); // Data scad gm.add_descrizione(riga_fattura, riga); gm.add_importo(riga_fattura, riga.importo(FALSE, 0x1)); if (in_valuta) gm.add_importo(riga_fattura, riga.importo(TRUE, 0x1), TRUE); else riga_fattura.add(""); riga_fattura.add(riga.get(PART_NREG)); riga_fattura.add(riga.get(PART_DATAREG)); riga_fattura.add(riga.get(PART_NUMDOC)); riga_fattura.add(riga.get(PART_PROTIVA)); riga_fattura.add(riga.get(PART_TIPOMOV)); for (int ra = 1; ra <= riga.rate(); ra++) { const TRiga_scadenze& scad = riga.rata(ra); TToken_string& row = gm.add_colored_row(sheet, 'I'); row = riga_fattura; row.add(ra, 1); row.add(scad.get(SCAD_DATASCAD), 3); gm.add_importo(row, scad.importo(FALSE), FALSE, 5); if (in_valuta) gm.add_importo(row, scad.importo(TRUE), TRUE, 6); const TString& descr = scad.get(SCAD_DESCR); if (descr.not_empty()) row.add(descr, 4); const bool blocked = scad.get_bool(SCAD_BLOCCATA); row.add(blocked ? "X" : " ", 13); const int lastp = scad.last(); for (int pa = scad.first(); pa <= lastp; pa = scad.succ(pa)) { const TRectype& pag = scad.row(pa); const TRiga_partite& sum = game->riga(pa); const char sez = sum.sezione(); TToken_string& row = gm.add_colored_row(sheet, ' '); row.add(ri); row.add(ra); row.add(sum.get(PART_DATADOC)); row.add(sum.get(PART_DATAPAG)); gm.add_descrizione(row, sum); const TImporto imp(sez, pag.get_real(PAGSCA_IMPORTO)); if (in_valuta) { gm.add_importo(row, imp); gm.add_importo(row, TImporto(sez, pag.get_real(PAGSCA_IMPORTOVAL)), TRUE); } else { gm.add_importo(row, imp); row.add(""); } row.add(sum.get(PART_NREG)); row.add(sum.get(PART_DATAREG)); row.add(sum.get(PART_NUMDOC)); row.add(""); row.add(sum.get(PART_TIPOMOV)); row.add(pa); // Le ritenute non possono esistere in valuta if (!in_valuta) { const TImporto rit(sez, pag.get_real(PAGSCA_RITENUTE)); if (!rit.is_zero()) { TToken_string& rrit = gm.add_colored_row(sheet, 'R'); rrit.add("Ritenute professionali", 4); gm.add_importo(rrit, rit, FALSE); rrit.add(sum.get(PART_TIPOMOV), 11); } } // Gli abbuoni e le differenze cambio esistono solo se e' a saldo if (pag.get_char(PAGSCA_ACCSAL) == 'S') { const TImporto abb(sez, pag.get_real(PAGSCA_ABBUONI)); if (!abb.is_zero()) { const char tipo_abb = pag.get_char(PAGSCA_PASSATT); TToken_string& rabb = gm.add_colored_row(sheet, tipo_abb); rabb.add("Abbuoni ", 4); rabb << (tipo_abb == 'A' ? "attivi" : "passivi"); if (in_valuta) { TImporto abb_lit = abb; prima_valuta.val2lit(abb_lit); gm.add_importo(rabb, abb_lit, FALSE); gm.add_importo(rabb, abb, TRUE); } else { gm.add_importo(rabb, abb, FALSE); rabb.add(""); } rabb.add(sum.get(PART_TIPOMOV), 11); } // Le differenze cambio possono esistere solo in valuta if (in_valuta) { const TImporto diff(sez, pag.get_real(PAGSCA_DIFFCAM)); if (!diff.is_zero()) { TToken_string& rdiff = gm.add_colored_row(sheet, 'C'); rdiff.add("Differenza cambio", 4); gm.add_importo(rdiff, diff); rdiff.add(sum.get(PART_TIPOMOV), 11); } } } // Il pagamento era a saldo } // Fine ciclo sui pagamenti della rata TToken_string& rsal = gm.add_colored_row(sheet, 'S'); rsal.add("Saldo rata ", 4); rsal << ra; if (!scad.chiusa()) { TImporto sl = scad.residuo(FALSE); gm.add_importo(rsal, sl); tot_lit += sl; if (in_valuta) { sl = scad.residuo(TRUE, 0xB); gm.add_importo(rsal, sl, TRUE); tot_val += sl; } } } } TRecord_array& unas = game->unassigned(); const int lastp = unas.last_row(); for (int pa = unas.first_row(); pa <= lastp; pa = unas.succ_row(pa)) { const TRectype& pag = unas.row(pa); const TRiga_partite& sum = game->riga(pa); const char sez = sum.sezione(); TToken_string& row = gm.add_colored_row(sheet, ' '); row.add(pag.get(PAGSCA_NRIGA)); row.add(pag.get(PAGSCA_NRATA)); row.add(sum.get(PART_DATADOC)); row.add(sum.get(PART_DATAPAG)); gm.add_descrizione(row, sum); TImporto imp(sez, pag.get_real(PAGSCA_IMPORTO)); gm.add_importo(row, imp); tot_lit += imp; const real& impval = pag.get_real(PAGSCA_IMPORTOVAL); if (!impval.is_zero()) { imp.set(sum.sezione(), impval); imp.normalize(); gm.add_importo(row, imp, TRUE); tot_val += imp; } else row.add(""); row.add(sum.get(PART_NREG)); row.add(sum.get(PART_DATAREG)); row.add(sum.get(PART_NUMDOC)); row.add(""); row.add(sum.get(PART_TIPOMOV)); row.add(pa); const TImporto rit(sez, pag.get_real(PAGSCA_RITENUTE)); if (!rit.is_zero()) { TToken_string& row = gm.add_colored_row(sheet, 'R'); row.add("Ritenute professionali", 4); gm.add_importo(row, rit, FALSE); row.add(sum.get(PART_TIPOMOV), 11); tot_lit += rit; } } if (lastrow > 0) { TToken_string& sp = gm.add_colored_row(sheet, 'T'); sp.add("Saldo partita", 4); if (prima_valuta.in_valuta()) sp << ' ' << prima_valuta.codice(); #ifdef __EXTRA__ prima_valuta.set(gm, P_VALUTA, P_DATACAMBIO, P_CAMBIO); #endif gm.add_importo(sp, tot_lit); gm.add_importo(sp, tot_val, TRUE); } if (should_delete_game) delete game; } if (prima_valuta.in_valuta() != gm._valfirst) { sheet.swap_columns(106, 107); // Scambia le colonne dell'importo in lire e in valuta gm._valfirst = !gm._valfirst; } if (sheet.items() > 0) sheet.select(0, TRUE); else sheet.force_update(); main_app().end_wait(); } if (k == K_INS) { gm.send_key(K_CTRL + 'N', 0, &partite); // Simula la pressione del tasto nuovo return FALSE; // Rifiuta l'aggiunta di una riga } return TRUE; } bool TGame_mask::scadenze_notify(TSheet_field& scadenze, int r, KEY k) { if (k == K_INS) { TGame_mask& gm = (TGame_mask&)scadenze.mask(); gm.send_key(K_CTRL + 'N', 0, &scadenze); // Simula la pressione del tasto nuovo return FALSE; // Rifiuta l'aggiunta di una riga } return TRUE; } // Complesso algoritmo per calcolare la sezione di una nuova riga partita char TGame_mask::calcola_sezione(tipo_movimento tm) const { char sezione = ' '; const char tipoc = conto().tipo(); #ifndef __EXTRA__ const TCausale& causale = app().causale(); tm = (tipo_movimento)causale.tipomov(); sezione = causale.sezione(1); // Usa la sezione della causale #endif if (sezione <= ' ') // Se non c'e' la sezione bell'e' ch'e' pronta { 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'; } #ifndef __EXTRA__ // 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'; // scambia segno } #endif return sezione; } int TGame_mask::nuova_riga(TPartita& partita, tipo_movimento tm) const { const int una_riga = partita.last(); // Memorizza una riga valida TRiga_partite& part = partita.new_row(); // Creazione nuova riga vuota const int nriga = part.get_int(PART_NRIGA); // Nuova riga // Copia dati movimento corrente part.put(PART_NREG, _numreg); // Numero operazione part.put(PART_NUMRIG, _numrig); // Riga su cui ho cliccato // Forza il gruppo/conto cliente corretto part.put(PART_GRUPPOCL, conto().gruppo()); part.put(PART_CONTOCL, conto().conto()); part.put(PART_TIPOMOV, (int)tm); if (una_riga > 0) { const char* valuta = partita.riga(una_riga).get(PART_CODVAL); part.put(PART_CODVAL, valuta); } #ifdef __EXTRA__ const TDate oggi(TODAY); const char* s = oggi.string(); part.put(PART_DATADOC, s); part.put(PART_DATAREG, s); #else // Setta il cambio corrente const TValuta valuta(*this, P_VALUTA, P_DATACAMBIO, P_CAMBIO); valuta.put(part); TMask& cm = app().curr_mask(); const TCausale& causale = app().causale(); 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, cm.get(F_DATAREG)); part.put(PART_TIPOPAG, 1); const TRiga_partite* prima = (tm != tm_fattura) ? cerca_prima_riga() : NULL; if (prima != NULL && prima != &part) { part.put(PART_DESCR, prima->get(PART_DESCR)); part.put(PART_DATAPAG, prima->get(PART_DATAPAG)); part.put(PART_TIPOPAG, prima->get(PART_TIPOPAG)); } // Copia dati causale corrente part.put(PART_CODCAUS, causale.codice()); if (causale.iva() != nessuna_iva) { part.put(PART_REG, cm.get(F_CODREG)); part.put(PART_PROTIVA, cm.get(F_PROTIVA)); } #endif const char sezione = calcola_sezione(tm); // Memorizza solo la sezione (importi nulli) part.put(PART_SEZ, sezione); part.put(PART_SEZABB, sezione); part.put(PART_SEZDIFCAM, sezione); return nriga; } int TGame_mask::nuovo_pagamento(TPartita& partita, int nriga, int rata, tipo_movimento tm) const { #ifdef __EXTRA__ const int nrigp = nuova_riga(partita, tm); #else int nrigp = partita.mov2rig(_numreg, _numrig); // Cerca riga partita relativa alla riga rmov if (nrigp <= 0) // Devo creare una nuova riga di partita nrigp = nuova_riga(partita, tm); #endif TRectype& pagamento = partita.pagamento(nriga, rata, nrigp); // Crea nuovo pagamento // Calcola riga causale per la contropartita in base al tipo pagamento int caus = 2; if (nriga != TPartita::UNASSIGNED) { const TRiga_partite& fatt = partita.riga(nriga); const TRiga_scadenze& scad = fatt.rata(rata); const int tp = scad.get_int(SCAD_TIPOPAG); caus = partita.tipopag2causale(tp); TRiga_partite& somma = partita.riga(nrigp); somma.put(PART_TIPOPAG, tp); somma.put(PART_CODVAL, fatt.get(PART_CODVAL)); pagamento.put(PAGSCA_CODABIPR, scad.get(SCAD_CODABIPR)); pagamento.put(PAGSCA_CODCABPR, scad.get(SCAD_CODCABPR)); pagamento.put(PAGSCA_CODABI, scad.get(SCAD_CODABI)); pagamento.put(PAGSCA_CODCAB, scad.get(SCAD_CODCAB)); pagamento.put(PAGSCA_CODAG, scad.get(SCAD_CODAG)); } #ifndef __EXTRA__ const TCausale& causale = app().causale(); TBill contro; causale.bill(caus, contro); // Legge conto contropartita if (caus != 2 && contro.empty()) // Se non specificato ... causale.bill(caus = 2, contro); // ... prende il primo contro.put(pagamento, TRUE); // Scrive conto contropartita #endif return nrigp; } bool TGame_mask::edit_scadenza_handler(TMask_field& f, KEY k) { if (k == K_SPACE) { TMask& m = f.mask(); const int nriga = m.get_int(101); // Numero riga fattura if (nriga == 0) return FALSE; // Ho cliccato su di un saldo (per sbaglio!) TGame_mask& gm = (TGame_mask&)(m.get_sheet()->mask()); const TBill& bill = gm.conto(); // Clifo TSheet_field& sp = gm.partite(); TToken_string& spr = sp.row(sp.selected()); const int anno = spr.get_int(0); // Anno const TString numero = spr.get(); // Numero TPartite_array& giochi = app().partite(); TPartita* was = giochi.exist(bill, anno, numero); // Controlla esistenza nell'array TPartita& game = was ? *was : giochi.partita(bill, anno, numero); long nreg = m.get_long(108); // Numero registrazione const int nrata = m.get_int(102); // Rata selezionata (puo' essere 0) int nrigp = m.get_int(113); // Pagamento selezionato (puo' essere 0) if (nrata != 0 && nrigp == 0) { if (m.get_bool(114)) { if (was == NULL) giochi.destroy(game); return f.error_box("La rata %d e' bloccata.", nrata); } #ifndef __EXTRA__ const TValuta parval(game.riga(nriga)); const TValuta curval(gm, P_VALUTA, P_DATACAMBIO, P_CAMBIO); if (parval != curval) { TString c = parval.codice(); if (c.empty()) c = "lire"; if (was == NULL) giochi.destroy(game); return f.error_box("La fattura deve essere pagata in %s.", (const char*)c); } #endif tipo_movimento tm; #ifdef __EXTRA__ TMask* nm = new TNew_mask(gm.conto().tipo(), FALSE, FALSE); nm->set(P_ANNO, game.anno()); nm->set(P_NUMERO, game.numero()); const KEY k = nm->run(); if (k == K_ENTER) tm = (tipo_movimento)nm->get_int(P_NUOVO); else { if (was == NULL) giochi.destroy(game); return FALSE; } delete nm; #else tm = (tipo_movimento)app().causale().tipomov(); #endif nrigp = gm.nuovo_pagamento(game, nriga, nrata, tm); nreg = gm._numreg; } bool cambiato = FALSE; if (nrigp > 0) // Si vuole editare un pagamento { if (nreg == gm._numreg) { cambiato = gm.edit_pagamento(game, nriga, nrata, nrigp); if (cambiato) { #ifdef __EXTRA__ game.rewrite(); // In extra-contabile salvo subito! #endif } } else { #ifdef __EXTRA__ gm.prima_nota(nreg); if (m.is_running()) m.set_focus(); #else if (was == NULL) giochi.destroy(game); return f.error_box("Modificare il movimento %ld", nreg); #endif } } else { // Si vogliono editare le rate #ifdef __EXTRA__ if (nreg > 0) { gm.prima_nota(nreg); if (m.is_running()) m.set_focus(); } else cambiato = gm.edit_fattura(game, nriga); #else if (nreg != gm._numreg || nrata == 0) { if (nreg == 0) f.error_box("Utilizzare la gestione extra-contabile"); else f.error_box("Modificare il movimento %ld", nreg); if (was == NULL) giochi.destroy(game); return FALSE; } #endif } if (cambiato) { if (m.is_running()) // Se la maschera e' aperta la chiudo m.stop_run(K_FORCE_CLOSE); TSheet_field& ss = gm.scadenze(); const int rs = ss.selected(); // Memorizza la riga corrente const int rt = ss.items(); // Memorizza numero righe correnti gm.fill_partite(); // Aggiorna elenco partite const int rn = ss.items(); // Memorizza nuovo numero righe if (rs < rn) // Se esiste ancora ... { const bool scroll = rn > rt; // Scrolla solo se aggiungo righe ss.select(rs, scroll); // ... riporta la selezione sulla riga corrente } gm._changed = TRUE; } } return TRUE; } bool TGame_mask::nuovo_handler(TMask_field& f, KEY k) { if (k == K_SPACE) { TGame_mask& gm = (TGame_mask&)f.mask(); int anno; TString numero; #ifdef __EXTRA__ const bool allow_fatt = TRUE; #else const bool allow_fatt = FALSE; #endif TMask* new_game = new TNew_mask(gm.conto().tipo(), allow_fatt, TRUE); tipo_movimento tm; #ifndef __EXTRA__ const TMask& cm = app().curr_mask(); tm = (tipo_movimento)app().causale().tipomov(); new_game->set(P_NUOVO, tm); if (tm == tm_nota_credito) { new_game->set(P_ANNO, cm.get(F_ANNORIF)); new_game->set(P_NUMERO, cm.get(F_NUMRIF)); } #endif k = new_game->run(); tm = (tipo_movimento)new_game->get_int(P_NUOVO); anno = new_game->get_int(P_ANNO); numero = new_game->get(P_NUMERO); // Distruzione maschera di richiesta delete new_game; new_game = NULL; if (k == K_ENTER) { // Creazione nuova partita TPartita& game = app().partite().partita(gm.conto(), anno, numero); bool edit = FALSE; // N.B. Le fatture non possone essere editate in modo contabile if (tm != tm_fattura) { const int nriga = TPartita::UNASSIGNED; const int nrata = TPartita::UNASSIGNED; const int nrigp = gm.nuovo_pagamento(game, nriga, nrata, tm); edit = gm.edit_pagamento(game, nriga, nrata, nrigp); #ifdef __EXTRA__ if (edit) game.rewrite(); #endif } #ifdef __EXTRA__ else edit = gm.edit_fattura(game, 0); #endif if (edit) { gm.set(P_ANNO, anno); gm.set(P_NUMERO, numero); gm._changed = TRUE; // Aggiorna sheet partite: aggiunge la nuova partita e lo riordina gm.fill_partite(); } // Sono state apportate modifiche } } return TRUE; } /////////////////////////////////////////////////////////// // Metodi della maschera delle partite /////////////////////////////////////////////////////////// void TGame_mask::add_importo(TToken_string& s, const TImporto& i, bool valuta, int pos) { if (i.is_zero()) s.add("", pos); else { TString80 v; TImporto n(i); n.normalize(); if (valuta) { v = n.valore().string(0, 3); const int sep = v.find('.'); v[sep] = ','; } else v = n.valore().string(0, 0); v << ' ' << n.sezione(); s.add(v, pos); } } void TGame_mask::add_descrizione(TToken_string& s, const TRiga_partite& riga, int pos) { const TString& desc = riga.get(PART_DESCR); if (desc.empty()) { const TString& caus = riga.get(PART_CODCAUS); if (caus.not_empty()) s.add(_causali.decode(caus), pos); else s.add("", pos); } else s.add(desc, pos); } TImporto TGame_mask::get_importo(TToken_string& s, int pos) const { const TFixed_string imp(s.get(pos)); const real i(imp); const char sez = imp.right(1)[0]; return TImporto(sez, i); } int TGame_mask::update_partita(const TRectype& riga, const TImporto& saldo, const TImporto& doc, const TImporto& pag, const TImporto& imp, int prow) { TSheet_field& games = partite(); TToken_string &r = games.row(prow); // Stringa di lavoro per lo sheet if (!riga.empty()) // Esiste veramente { r.cut(0); r.add(riga.get(PART_ANNO)); r.right_just(4); // Mette gli spazi se ce n'e' bisogno r.add(riga.get(PART_NUMPART)); r.add(riga.get(PART_DATADOC)); r.add(riga.get(PART_NUMDOC)); add_importo(r, saldo); add_importo(r, doc); add_importo(r, pag); add_importo(r, imp); r.add(riga.get(PART_DESCR)); } else { r.add("", 4); r.add("", 5); r.add("", 6); r.add("", 7); } if (prow >= 0) { games.force_update(prow); update_saldo_clifo(); games.force_update(games.items()-1); aggiorna_residuo(); } else prow = partite().items()-1; if (prow == 0) { const char all = TPartita::allineamento_richiesto(conto().tipo()); field(P_NUMERO).set_justify(all == 'R'); } return prow; } int TGame_mask::update_partita(const TPartita& part, int prow) { int r = part.prima_fattura(); if (r <= 0) r = part.first(); TImporto saldo, doc, pag, imp; part.calcola_saldo(saldo, doc, pag, imp); return update_partita(part.riga(r), saldo, doc, pag, imp, prow); } int TGame_mask::update_partita(const TRectype& riga, int prow) { TImporto saldo, doc, pag, imp; TRectype rec = riga; const int err = TPartita::read_saldo(rec, saldo, doc, pag, imp); return update_partita(rec, saldo, doc, pag, imp, prow); } void TGame_mask::update_saldo_clifo() { TString_array& s = partite().rows_array(); TImporto sal, doc, pag, imp; for (int i = 0; i < s.items(); i++) { TToken_string& r = s.row(i); if (r.get_int(0) > 0) { sal += get_importo(r, 4); doc += get_importo(r, -1); pag += get_importo(r, -1); imp += get_importo(r, -1); } else break; } TToken_string& r = s.row(s.add("", i)); r.add(""); r.add(""); r.add(TDate(TODAY).string()); r.add(""); add_importo(r, sal); add_importo(r, doc); add_importo(r, pag); add_importo(r, imp); r.add("Saldo "); append_conto(r); COLOR back, fore; app().type2colors('T', back, fore); partite().set_back_and_fore_color(back, fore, i); if (i > 0) // Se ho aggiunto una riga devo decolorare la precedente partite().set_back_and_fore_color(NORMAL_BACK_COLOR, NORMAL_COLOR, i-1); } long TGame_mask::number_distance(const char* k, const char* n) const { TString16 key(k); key.upper(); key.trim(); const int kl = key.len(); TString16 num(n); num.upper(); num.trim(); const int nl = num.len(); long dist = 0; for (int i = kl-1; i >= 0; i--) { const char kc = i < kl ? key[i] : 0; const char nc = i < nl ? num[i] : 0; const long d = abs(kc - nc) * (kl - i) * 32; dist += d; } return dist; } bool TGame_mask::same_number(const char* key, const char* num) const { TString16 k(key); k.upper(); k.trim(); TString16 n(num); n.upper(); n.trim(); return k == n; } void TGame_mask::fill_partite() { const int annorif = get_int(P_ANNO); // Anno corrente const TString numrif = get(P_NUMERO); // Partita corrente const bool all = get(P_SHOWALL).not_empty(); // Visualizza anche partite chiuse TString_array& a = partite().rows_array(); a.destroy(); app().begin_wait(); TPartite_array& giochi = app().partite(); for (TPartita* gioco = giochi.first(); gioco != NULL; gioco = giochi.next()) { // Visualizza solo le partite con almeno una riga! Non posso scaricarle a priori in quanto // potrebbero essere state cancellate proprio ora e quindi devo tenerle cosi' per aggiornare // correttamente gli archivi. if (gioco->ok()) { const TBill& k = gioco->conto(); bool u = (k.tipo() > ' ' && k.sottoconto() == conto().sottoconto()) || k == conto(); if (u && !all && gioco->chiusa() && gioco->mov2rig(_numreg, _numrig) <= 0) u = FALSE; if (u) update_partita(*gioco, -1); } else { // Se la partita e' vuota ... if (!gioco->is_on_file()) // ... e non esiste su file giochi.destroy(*gioco); // posso eliminarla tranquillamente } } TLocalisamfile partita(LF_PARTITE); TRectype& curpar = partita.curr(); curpar.zero(); if (conto().tipo() > ' ') // Ignora gruppo e conto dei clifo { curpar.put(PART_TIPOCF, conto().tipo()); curpar.put(PART_SOTTOCONTO, conto().codclifo()); } else conto().put(curpar); // Scrive completamente i conti normali const TRectype filter(curpar); // Record campione for (int err = partita.read(_isgreat); err == NOERR && curpar == filter; err = partita.read(_isgreat)) { if (!giochi.exist(curpar)) { if (all || curpar.get_bool(PART_CHIUSA) == FALSE) update_partita(curpar, -1); } // Forza lettura partita successiva nella prossima read curpar.put(PART_NRIGA, (int)TPartita::UNASSIGNED); } a.sort(); for (int r = a.items()-1; r > 0; r--) { TToken_string& row = a.row(r); if (annorif == row.get_int(0) && same_number(numrif, row.get(1))) break; } update_saldo_clifo(); partite().force_update(); aggiorna_residuo(); if (a.items() > 1) { _riga_partite = -1; partite().select(r, TRUE); } else { scadenze().destroy(); } app().end_wait(); } bool TGame_mask::edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp) const { TRectype oldpag = p.pagamento(nriga, nrata, nrigp); TRiga_partite& somma = p.riga(nrigp); const bool nuovo = oldpag.get(PAGSCA_ACCSAL) != "S" && oldpag.get_real(PAGSCA_IMPORTO).is_zero() && oldpag.get_real(PAGSCA_RITENUTE).is_zero(); // We must create masks on the heap TPay_mask* pm = new TPay_mask(*this, nuovo ? MODE_INS : MODE_MOD); TPay_mask& m = *pm; if (nriga == TPartita::UNASSIGNED) { TRiga_scadenze& scaden = somma.new_row(); // Crea una rata falsa scaden.put(SCAD_DATASCAD, somma.get(PART_DATADOC)); m.set_pag(oldpag, scaden, _residuo); somma.destroy_rows(); // Distrugge la rata falsa } else { const TRiga_scadenze& scaden = p.rata(nriga, nrata); m.set_pag(oldpag, scaden, _residuo); } if (nuovo) // Inizializza automaticamente l'importo { TMask_field& imp = m.field(S_IMPORTO); imp.set_dirty(); imp.on_key(K_F8); } KEY key = m.run(); if (key == K_DEL) { const bool truly = yesno_box("Confermare l'eliminazione"); if (!truly) key = K_ESC; } if (key == K_ESC && nuovo) key = K_DEL; if (key != K_ESC) { TRectype newpag(oldpag); if (key == K_DEL) { newpag.zero(PAGSCA_ACCSAL); // Non puo' essere un saldo newpag.zero(PAGSCA_IMPORTO); // Azzera importo ... newpag.zero(PAGSCA_IMPORTOVAL); // .. anche in valuta newpag.zero(PAGSCA_RITENUTE); // Azzera ritenute } else { m.get_pag(newpag, somma); } const TValuta val(somma); #ifdef __EXTRA__ p.modifica_pagamento(newpag, val, TRUE); #else if (somma.is_nota_credito()) p.modifica_pagamento(newpag, val, TRUE); else app().notify_edit_pagamento(p, newpag, val); #endif } delete pm; return key != K_ESC; } #ifndef __EXTRA__ /////////////////////////////////////////////////////////// // Edit delle partite /////////////////////////////////////////////////////////// bool TPrimanota_application::edit_partite(const TMask& m, int riga) { const char tipo = m.get(CG_TIPO)[0]; const char rt = m.get(CG_ROWTYPE)[0]; if (rt == 'T' && tipo <= ' ') // Nelle note di credito DEVE essere un clifo return FALSE; const int gruppo = m.get_int(CG_GRUPPO); const int conto = m.get_int(CG_CONTO); const long sottoconto = m.get_long(CG_SOTTOCONTO); TBill b(gruppo, conto, sottoconto, tipo); // Legge il conto della riga selezionata // Esci se il conto della riga cliente non e' valido if (!b.ok() || !b.find()) return m.field(CG_SOTTOCONTO).error_box("Conto assente"); // Aggiorna conto sulla riga contabile b.add_to(cgs().row(riga), 3, 0x0); TMovimentoPN* pn = (TMovimentoPN*)get_relation(); curr_mask().autosave(*pn); // Aggiorna i dati della testata sulle partite partite().update_reg(pn->curr()); // Esecuzione maschera di selezione partite TGame_mask* mask = new TGame_mask(b, pn->curr().get_long(MOV_NUMREG), riga+1); mask->run(); const bool changed = mask->changed(); delete mask; if (changed) { cgs().force_update(); // Aggiornamento righe contabili calcola_saldo(); } return changed; } #endif