#include #include "pagament.h" #include #include #include #include int TPagamento::_rata_ifield(int n, int f) const { TToken_string& t = (TToken_string&)_rate[n]; return t.get_int(f); } long TPagamento::_rata_lfield(int n, int f) const { TToken_string& t = (TToken_string&)_rate[n]; return t.get_long(f); } real TPagamento::_rata_rfield(int n, int f) const { TToken_string& t = (TToken_string&)_rate[n]; return real(t.get(f)); } TDate TPagamento::_rata_dfield(int n, int f) const { TToken_string& t = (TToken_string&)_rate[n]; return TDate(t.get(f)); } const char* TPagamento::_rata_sfield(int n, int f) const { static char kak[16]; TToken_string& t = (TToken_string&)_rate[n]; const char* k = t.get(f); if (k != NULL) strncpy(kak, k, 16); else kak[0] = '\0'; return kak; } void TPagamento::set_inizio(const TDate& d) { bool dio; _inizio = d; recalc_rate(0, FALSE, NULL, d.string(), NULL, _rdiff, _mcomm, dio); } void TPagamento::set_intervallo_rate(int in) { _dirty = TRUE; _int_rate = in; if (_mcomm && (in % 30) != 0) _mcomm = FALSE; for (int i = 0; i < n_rate(); i++) { TToken_string& ts = rata(i); ts.add(i == 0 ? (scad_rata(0) == 0 ? 0 : in) : in, 0); } } void TPagamento::set_mese_commerciale(bool v, int& sscad) { _dirty = FALSE; if (_mcomm == v) return; if (sscad < 0) sscad = 30; if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1); set_intervallo_rate(sscad); _mcomm = v; } void TPagamento::set_rate_differenziate(int v) { _dirty = FALSE; if (_rdiff ^ v == 2) return; if (v == 2 && (100 % n_rate()) == 0) { int p = 100 / n_rate(); for (int i = _tpr < 4 ? 0 : 1; i < n_rate(); i++) { TToken_string& tt = rata(i); tt.add(p,1); } } _rdiff = (v != 2); _dirty = TRUE; } void TPagamento::set_tipo_prima_rata(int v, int sscad) { _dirty = FALSE; if (_tpr == v) return; if (v < 4 && _tpr > 3) { for (int i = n_rate() - 1; i > 0; i--) { TToken_string& tt = rata(i); tt.add(scad_rata(i-1),0); tt.add(tipo_rata(i-1),2); tt.add(ulc_rata(i-1),5); } _rate.destroy(0); _rate.pack(); } else if ( _tpr < 4 && v > 3) { TToken_string* ttn = new TToken_string(32); ttn->add(0, 0); ttn->add(0, 1); ttn->add(1, 2); ttn->add("", 3); ttn->add("", 4); ttn->add("", 5); _rate.insert(ttn,0); for (int i = 0; i < (n_rate()-1); i++) { TToken_string& tt = rata(i); tt.add(scad_rata(i+1),0); tt.add(tipo_rata(i+1),2); tt.add(ulc_rata(i+1), 5); } } _tpr = v; _dirty = TRUE; } void TPagamento::set_numero_rate(int n, int sscad, int rdiff) { _dirty = FALSE; if (n == 0 || n == n_rate()) return; real p = real(100) / real(n); p.round(2); int nr = n_rate(); int first = _tpr < 4 ? 0 : 1; real sum = 0.0; int i = 0; if (_inited || (!_inited && rdiff == 1)) // se e' inited rdiff e' 2 per forza { real tot = _inited ? (_tpr < 4 ? _firstr : _secndr) : real(100.0); if (n == 1) { if (_inited) set_imprata(first, tot); set_percrata(first, real(100.0)); if (_inited && _tpr > 0 && _tpr < 4) set_imprata(first, tpay_rata(first) + _secndr); i = first + 1; // per rimozione successiva } else { if (nr == first + 1) { // suddividi equamente e riaggiusta la percentuale di conseguenza real div = tot / real(n); real perc = real(100.0)*(div/tot); for (i = first; i < n; i++) { if (i > 0) add_rata(perc, (sscad == -1 ? scad_rata(0) : sscad), tipo_rata(0)); if (_inited) set_imprata (i, div); set_percrata(i, perc); } if (_inited && _tpr > 0 && _tpr < 4) set_imprata(0, tpay_rata(0) + _secndr); } else if (nr > first + 1) { // dalla prima nota e' abilitato solo se rdiff == 2 // e' selezionato UGUALI: devo: lasciare la prima // rata com'e' (a meno che non ce ne sia una sola) e // suddividere il resto dell'importo tra le altre real rfirst = _inited ? tpay_rata(first) : perc_rata(first); if (_inited && _tpr > 0 && _tpr < 4) rfirst -= _secndr; real rest = tot - rfirst; const real div = rest / real(n - 1); real perc = real(100.0)*(div/tot); for (i = first+1; i < n; i++) { if (i >= nr) add_rata(perc, (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad), tipo_rata(nr-1)); if (_inited) set_imprata (i, div); set_percrata(i, perc); } } } } else { for (i = first; sum < real(100.0); i++) { if ((real(100.0) - sum) < p) p = real(100.0) - sum; sum += p; // if necessary add remainder on first one if ((real(100.0) - sum) /* still */ < p) { real prc = perc_rata(first); prc += real(100.0) - sum; TToken_string& rt = rata(first); rt.add(prc.string(),1), sum = 100; } set_rata(i, real(p), i == 0 ? (i < nr ? scad_rata(0) : 0): (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad), (i < nr ? tipo_rata(i) : tipo_rata(nr-1))); } } // erase remaining for (; i < nr; i++) _rate.destroy(i); _rate.pack(); _dirty = TRUE; } void TPagamento::set_cambio(const real& cambio) { if (cambio.sign() <= 0) _cambio = 1.0; else _cambio = cambio; set_round(_cambio == 1.0 ? 0 : 2); const bool in_valuta = _cambio != 1.0; real lit; for (int i = _rate.items()-1; i >= 0; i--) { TToken_string& row = (TToken_string&)_rate[i]; if (in_valuta) { lit = tpay_rata(i) * _cambio; row.add(lit.string(), 7); } else row.add("", 7); } } void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata) { if (mcomm) { int nm = scad / 30; int ny = nm / 12; nm %= 12; int newm = d.month() + nm; if (newm > 12) { newm -= 12; ny++; } bool last = d.is_end_month() && inizio_scadenza() == 'M'; int dy = d.day(); // la palla del febbraio & c. if (rata > 1) { TDate oldd(data_rata(rata-2)); if (oldd.day() > dy) dy = oldd.day(); } d.set_day(1); // il giorno 1 ce l'hanno tutti d.set_month(newm); d.set_year(d.year()+ny); d.set_end_month(); if (!last && dy < d.day()) d.set_day(dy); } else { d += scad; } // riaggiusta se ci sono scadenze fissate if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0) { for (int i = 0; i < 3; i++) { if (_fixd[i] > d.day()) { if (d.last_day(d.month(), d.year()) <= _fixd[i]) d.set_day(_fixd[i]); else d.set_end_month(); break; } } if (i == 3) { if (_fixd[0] > 0 && _fixd[0] < d.day()) { d.set_day(_fixd[0]); d.set_month(d.month() == 12 ? 1 : d.month() + 1); } } } } void TPagamento::set_default_type(int type, bool change_existing) { _def_tpr = type; if (change_existing) { for (int i = 0; i < n_rate(); i++) { TToken_string& tt = rata(i); tt.add(type, 2); } _dirty = TRUE; } } void TPagamento::set_default_ulc(const char* ulc, bool change_existing) { _def_ulc = ulc; if (change_existing) { for (int i = 0; i < n_rate(); i++) { TToken_string& tt = rata(i); tt.add(ulc, 5); } _dirty = TRUE; } } void TPagamento::remove_rata(int i) { // non fa nessun ricalcolo, si limita ad impacchettare se // necessario _rate.destroy(i); _rate.pack(); _dirty = TRUE; } TToken_string& TPagamento::add_rata(real perc, int day, int type, const char* ulc) { TToken_string* tt = new TToken_string(64); tt->add(day); // scadenza tt->add(perc.string()); // percentuale tt->add(type); // tipo tt->add(""); // data tt->add(""); // importo tt->add(ulc); // ulc _rate.add(tt); _dirty = TRUE; return *tt; } TToken_string& TPagamento::set_rata (int index, real perc, int day, int type, const char* ulc, const char* imp, const char* data) { TToken_string* tt = (TToken_string*)_rate.objptr(index); const bool nwr = (tt == NULL); if (nwr) tt = new TToken_string(64); tt->add(day,0); // scadenza tt->add(perc.string(),1); // percentuale tt->add(type,2); // tipo tt->add(data == NULL ? "" : data, 3); tt->add(imp == NULL ? "" : imp, 4); tt->add(ulc == NULL ? "" : ulc, 5); if (imp && *imp > ' ' && _cambio != 1.0) { real implit(imp); implit *= _cambio; implit.round(); tt->add(implit.string(), 7); } if (!nwr) { if (index > _rate.items()) { error_box("Rate non contigue"); delete tt; } } else { _rate.add(tt,index); _dirty = TRUE; } return *tt; } void TPagamento::set_imprata(int i, const real& r) { TToken_string& tt = (TToken_string&)_rate[i]; TDate d = _inizio; for (int n = 0; n <= i; n++) next_scad(d, scad_rata(n), _mcomm, n); tt.add((const char*)d, 3); tt.add(r.string(), 4); if (_cambio != 1.0) { const real lit = r * _cambio; tt.add(lit.string(), 7); } else tt.add("", 7); } void TPagamento::set_percrata(int i, real r) { TToken_string& tt = (TToken_string&)_rate[i]; tt.add(r.string(), 1); } real TPagamento::recalc_percrata(int i) { real hm(_tpr < 4 ? _firstr : _secndr); if (i == 0 && _tpr > 0 && _tpr < 4) hm -= _secndr; real perc = tpay_rata(i) * 100.0 / hm; perc.round(2); set_percrata(i, perc); return perc; } TToken_string& TPagamento::set_rata(int index, const real& howmuch, const real& quanto, const TDate& date, int type,const char* ulc, bool pagato) { // calcola percentuali e scadenze a partire dagli importi TToken_string* tt = (TToken_string*)_rate.objptr(index); const int first = _tpr < 4 ? 0 : 1; const bool nwr = (tt == NULL); // nuova rata if (nwr) tt = new TToken_string(64); const TDate oldd = index > 0 ? data_rata(index -1) : _inizio; const long day = date - oldd; const real toshare(_tpr < 4 ? _firstr : _secndr); real hm = howmuch; if (index == first && _tpr > 0 && _tpr < 4) hm -= _secndr; real perc = (_tpr > 3 && index == 0) ? ZERO : hm/toshare; perc *= real(100.0); perc.round(2); tt->cut(0); tt->add(day); // 0 - scadenza tt->add(perc.string()); // 1 - percentuale tt->add(type); // 2 - tipo tt->add(date.string()); // 3 - data tt->add(howmuch.string()); // 4 - importo tt->add(ulc); // 5 - ulc(era?) tt->add(pagato ? "X" : " "); // 6 - pagata tt->add(quanto.string()); // 7 - Importo in lire if (!nwr) { if (index > _rate.items()) { error_box("Rate non contigue"); delete tt; } } else { _rate.add(tt, index); _dirty = TRUE; } return *tt; } word TPagamento::validate() const { word res = 0x0000; real r(0.0); int first = _tpr < 4 ? 0 : 1; real toshare(_tpr < 4 ? _firstr : _secndr); // check percentages & prepare slicer for (int i = first; i < n_rate(); i++) r += perc_rata(i); r.round(1); if (r != real(100.0)) res |= P_RSUM; if (_inited) { real tot; for (int i = 0; i < n_rate(); i++) tot += tpay_rata(i); if (tot != _firstr+_secndr) res |= P_TOTNC; // check errori date scadenze (se istanziate) TDate d(data_rata(0)); if (d < _inizio) res |= P_INIZIO; for (i = 1; i < n_rate(); i++) { if (data_rata(i) <= d) { res |= P_SCAD; break; } d = data_rata(i); } } return res; } void TPagamento::strerr(word err, TString& s) { s = "Errore:"; if (err & P_RSUM) s << "\n Le percentuali non sommano a 100"; if (err & P_IMPNC) s << "\n Le percentuali sono inconsistenti con gli importi"; if (err & P_SCAD) s << "\n Le scadenze non sono consecutive"; if (err & P_INIZIO) s << "\n La prima rata e' antecedente alla data movimento"; if (err & P_NEG) s << "\n L'importo dato e' inferiore al minimo possibile"; if (err & P_TROP) s << "\n L'importo dato e' superiore al massimo possibile"; if (err & P_TOTNC) s << "\n La somma degli importi e' diversa dal totale del pagamento"; } const char* TPagamento::desc_tpr() const { const char* o; switch (_tpr) { case 0: o = "Totale su tutte le rate"; break; case 1: o = "Tutte le imposte su 1a"; break; case 2: o = "Tutte le spese su 1a"; break; case 3: o = "Imposte + spese su 1a"; break; case 4: o = "Spese + merce su 1a"; break; case 5: o = "Merce + imposte su 1a"; break; case 6: o = "Tutta la merce su 1a"; break; default: o = ""; break; } return o; } const char* TPagamento::desc_tipo(int i) const { const char* o; switch (i) { case 1: o = "Rimessa diretta o contanti"; break; case 2: o = "Tratta"; break; case 3: o = "Ricevuta bancaria"; break; case 4: o = "Cessione"; break; case 5: o = "Paghero'"; break; case 6: o = "Lettera di credito"; break; case 7: o = "Tratta accettata"; break; case 8: o = "Rapporti interban. diretti"; break; case 9: o = "Bonifici"; break; default: o = "Altro pagamento"; break; } return o; } word TPagamento::recalc_rate(int row, bool is_perc_modified, const char* new_value, const char* scad, const char* typ, int rdiff, bool mcomm, bool& need_recalc) // ricalcola le rate sulla base di parametri modificati sulla riga row // parametri: tutti i const char* possono essere NULL, il che vuol dire // che i dati corrispondenti non sono stati modificati; // se new_value non e' NULL puo' essere la percentuale (e // allora is_perc_modified e' TRUE) o l'importo. Non e' // possibile modificare entrambi; se succede viene data // priorita' alla percentuale. { CHECK(!(!is_perc_modified && new_value != NULL && !_inited), "A'stronzo! E famme 'na pippa! Me dai n'importo che nun ce sta? Ma Vaffanculo!"); if (_rate.items() == 0) return P_OK; real rsum(0.0), newv(0.0), rmax(0.0); int oldtype = tipo_rata(0); int oldscad = scad_rata(0); TDate lastdate = data_rata(0); int first = _tpr < 4 ? 0 : 1; TString_array srate(_rate); // rate come erano if (srate.items() > 1) { // calcola defaults per tipo pagamento e scadenza // nel caso di rate nuove oldscad = scad_rata(1); if (_mcomm) { int mesi = oldscad / 30; if (mesi == 0) mesi = 1; oldscad = 30 * mesi; } } if (oldscad <= 0) oldscad = 30; if (oldtype <= 0) oldtype = 1; if (new_value != NULL) { newv = new_value; rmax = is_perc_modified ? real(100.0) : (_tpr < 4 ? _firstr : _secndr); if (newv > rmax) return P_RSUM; } bool exhausted = FALSE; for (int i = first; i < srate.items(); i++) { if (i == row) { if (typ != NULL) { for (int k = 0; k < srate.items(); k++) { // deve farlo per tutte dalla 1 in poi se rdiff == 2, // soltanto per row diversamente if ((rdiff == 2 && row > 0 && k > 0) || k == row) { TToken_string& tt = rata(k); TToken_string& ss = (TToken_string&)srate[k]; tt.add(typ,2); ss.add(typ,2); need_recalc = TRUE; // no error is possible } } } if (scad != NULL) { // if !_inited scad e' il n. giorni, se no e' la rata if (_inited) { TToken_string& tt = rata(row); TToken_string& ss = (TToken_string&)srate[row]; lastdate = scad; // controlla errore sulla data scadenza if (i > 0) { oldscad = (int)(lastdate - data_rata(i-1)); if (oldscad <= 0l) return P_SCAD; } else if (lastdate < _inizio) return P_INIZIO; tt.add(scad,3); ss.add(scad,3); // ricalcola rate successive: se si vuole modificarne solo una // ci si fotte e si disabilita il ricalcolo TDate ddd (lastdate); for (int j = row+1; j < srate.items(); j++) { TToken_string& tt = rata(j); TToken_string& ss = (TToken_string&)srate[j]; next_scad(ddd,scad_rata(j),mcomm,j); tt.add(ddd.string(),3); ss.add(ddd.string(),3); need_recalc = TRUE; } } else { // nulla di speciale visto che si memorizza la derivata int sc = atoi(scad); for (int i = 0; i < row; i ++) sc -= scad_rata(i); if (sc < 0 || (row > 0 && sc == 0)) return P_SCAD; if (_mcomm && (sc % 30) != 0) _mcomm = FALSE; TToken_string& tt = rata(row); TToken_string& ss = (TToken_string&)srate[row]; tt.add(sc,0); ss.add(sc,0); need_recalc = TRUE; } } // here's the bell if (new_value != NULL) { if (newv == ZERO || (rsum+newv) > rmax) return P_RSUM; // did not sforate rsum += newv; TToken_string& rt = rata(row); // setta nuovo valore e ricalcola cio' che ne consegue if (is_perc_modified) rt.add(new_value,1); else rt.add(new_value,4); // riaggiusta le rate rimanenti real remainder(0.0); remainder = rmax - rsum; if (!(exhausted = (remainder == real(0.0)))) { // se inited e scelto UGUALI (2) occorre dividere in N e // aggiungere il resto sulla 1a rata // controlla se rdiff e' compatibile con // i dati e se e' il caso riaggiusta if (rdiff == 3 && (remainder % newv) != 0.0) rdiff = 2; // *** 10/8/95: se uguali e non e' multiplo intero lo teniamo cosi' e poi // *** aggiungiamo alla prima rata utile // if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) // rdiff = 1; // *** 5/9/85: UGUALI (2) significa la seguente menata: se c'e' una sola rata // *** uguale al totale importo, come prima; diversamente, la prima rata // *** va mantenuta uguale comunque sia, e occorre ridefinire le restanti in // *** modo che siano uguali. In questo caso deve far fede il NUMERO di RATE // *** indicato, che in prima nota non c'e' e va quindi inserito (porcoddio). // si registrano rate UGUALI soltanto se specificato UGUALI // il che non e' sorprendente, ma coi tempi che corrono... _rdiff = (rdiff == 1 || rdiff == 3 || rdiff == 4); // procedi if (rdiff == 1) { // cancella tutte le rate successive, aggiungi un'unica rata // con il resto dell'importo if (row < (srate.items()-1)) { TToken_string& trt = rata(row+1); trt.add(remainder.string(), is_perc_modified ? 1 : 4); for(int j = row+2; j < srate.items(); j++) _rate.destroy(j); } else { // l'importante e' esagerare for(int j = row+1; j < srate.items(); j++) _rate.destroy(j); TToken_string& trt = add_rata(is_perc_modified ? remainder : (real) 0.0, oldscad, oldtype); if (!is_perc_modified) trt.add(remainder.string(),4); if (_inited) { TDate dd = data_rata(row); next_scad(dd,oldscad,mcomm,row); trt.add(dd.string(),3); } } } else // rate non differenziate (dall'inizio o da row) { // ripartisci l'importo nel numero necessario di rate per // mantenere costante il valore real sum(0.0); if (_inited) lastdate = data_rata(rdiff == 2 ? first : row); TDate dd(lastdate); int type = oldtype; int nscd = oldscad; const int frs = (rdiff == 3 || rdiff == 4) ? row+1 : first; const real mx = (rdiff == 3 || rdiff == 4) ? remainder : rmax; // cancelliamo tutto, va' for (int j = srate.items()-1; j >= frs; j--) _rate.destroy(j); const int n = srate.items(); // questo rimane per forza costante if (rdiff == 2 && n > 1) { // HERE real tot = is_perc_modified ? real(100.0) : (_tpr < 4 ? _firstr : _secndr); real delta = is_perc_modified ? ZERO : ((_tpr > 0 && _tpr) < 4 ? _secndr : ZERO); real nimp(new_value); // se ho modificato la prima, divido il resto nelle successive // lasciando costante il numero rate if (row == first) { if (!delta.is_zero()) nimp -= delta; // inferiore al minimo if (nimp.sign() < 0) { _rate = srate; return P_NEG; } real remainder = tot - nimp; real div = remainder / real(n - 1); div.round(is_perc_modified ? 2 : _round); nimp = tot - (div * real(n-1)); for (int k = first; k < n; k++) { TToken_string& trt = (TToken_string&)srate[k]; if (_inited) dd = trt.get(3); type = atoi(trt.get(2)); nscd = k == 0 ? 0 : atoi(trt.get(0)); if (type == 0) type = 1; if (k > 0 && nscd == 0) nscd = oldscad; if (_inited && dd == lastdate && k > 0) next_scad(dd,nscd,mcomm,k); set_rata(k, is_perc_modified ? (k == first ? nimp : div) : ZERO, nscd, type, NULL, NULL, _inited ? dd.string() : NULL); if (!is_perc_modified) set_imprata (k, k == first ? (nimp + delta) : div); } } else { // se ho modificato la seconda o oltre, faccio tutte uguali dalla // seconda in poi; la prima resta com'e' se possibile, mentre se // c'e' un resto glielo sommo. // Dunque: prendo la prima, calcolo il resto, divido per quella nuova, // se resto lo sommo alla prima, e faccio quante rate servono TToken_string& trt = (TToken_string&)srate[first]; real rfirst(is_perc_modified ? trt.get(1) : trt.get(4)); if (!delta.is_zero()) rfirst -= delta; real rest = tot - rfirst; real div = rest / nimp; if (div < real(1.0)) { _rate = srate; return P_TROP; } int nr = (int)div.integer() + (_tpr > 4 ? 2 : 1); real reminder = rest - (nimp * real(nr -1)); rfirst += reminder; for (int k = first; k < nr; k++) { nscd = oldscad; type = _def_tpr; TString16 ulc(_def_ulc); if (srate.items() > k) { TToken_string& trt = (TToken_string&)srate[k]; if (_inited) dd = trt.get(3); type = atoi(trt.get(2)); nscd = atoi(trt.get(0)); ulc = trt.get(5); } if (type == 0) type = 1; if (_inited && dd == lastdate && k > 0) next_scad(dd,nscd,mcomm,k); set_rata(k, is_perc_modified ? (k == first ? rfirst : nimp) : ZERO, nscd, type, ulc); if (!is_perc_modified) set_imprata (k, k == first ? (rfirst + delta) : nimp); } } } else if (rdiff != 4) for (j = frs; sum < mx; j++) { // se c'e' la vecchia rata si tengono i parametri // altrimenti si calcolano if (j < srate.items()) { TToken_string& trt = (TToken_string&)srate[j]; if (_inited) dd = trt.get(3); type = atoi(trt.get(2)); nscd = j == 0 ? 0 : atoi(trt.get(0)); if (type == 0) type = 1; if (j > 0 && nscd == 0) nscd = oldscad; if (_inited && dd == lastdate && j > 0) next_scad(dd,nscd,mcomm,j); } else if (_inited) { if (dd <= botime) dd = lastdate; next_scad(dd,nscd,mcomm,j); } else nscd = _int_rate; TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, nscd, type); if (_inited) ttr.add(dd.string(), 3); if (!is_perc_modified) { ttr.add(newv.string(),4); } if ((mx - sum) < newv) { // add remainder on first rate newv += (mx - sum); if (!is_perc_modified) set_imprata(frs, newv); else { TToken_string& t = rata(frs); t.add(newv.string(), 1); } remove_rata(j); break; } // } sum += newv; } else // rdiff == 4; uguali finche' possibile { bool basta = FALSE; for (j = frs; ; j++) { // ultima rata puo' differire dalle precedenti if (mx - sum <= newv) { newv = mx - sum; basta = TRUE; } // se c'e' la vecchia rata si tengono i parametri // altrimenti si calcolano if (j < srate.items()) { TToken_string& trt = (TToken_string&)srate[j]; if (_inited) dd = trt.get(3); type = atoi(trt.get(2)); nscd = j == 0 ? 0 : atoi(trt.get(0)); if (type == 0) type = 1; if (j > 0 && nscd == 0) nscd = oldscad; if (_inited && dd == lastdate && j > 0) next_scad(dd,nscd,mcomm,j); } else if (_inited) next_scad(dd,nscd,mcomm,j); TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, nscd, type); if (_inited) ttr.add(dd.string(), 3); if (!is_perc_modified) ttr.add(newv.string(),4); if (basta) break; sum += newv; } } } } else // exhausted { for(int j = row+1; j < srate.items(); j++) _rate.destroy(j); } if (_inited) { // ricalcola il valore secondario (non modificato) real toshare(100.0); if (is_perc_modified) toshare = (_tpr < 4 ? _firstr : _secndr); TDistrib dt(toshare, is_perc_modified ? _round : 3); for (int j = first; j < _rate.items(); j++) { real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); // togli pezxo di troppo if (!is_perc_modified && j == first && _tpr > 0 && _tpr < 4) rvl -= _secndr; real zpx = rvl/rmax; // percentuale dt.add(zpx); } for (j = first; j < _rate.items(); j++) { real rfirst(0.0); TToken_string& tr = rata(j); real rvl = dt.get(); if (j == first) { rfirst = rvl; if (rdiff == 2) { real reminder = toshare - rfirst; real rdiv = reminder.is_zero() ? real(0.0) : (reminder / real(_rate.items() - (1+first))); rdiv.round( is_perc_modified ? _round : 2); rfirst += reminder - (rdiv * real(_rate.items() - (1+first))); rvl = rdiv; } } if (is_perc_modified && j == first && _tpr > 0 && _tpr < 4) rfirst += _secndr; tr.add((j == first ? rfirst.string() : rvl.string()), is_perc_modified ? 4 : 1); if (_cambio != 1.0) { real implit(tpay_rata(j)); implit *= _cambio; implit.round(); tr.add(implit.string(), 7); } } // se e' il caso aggiungi l'importo fisso sulla prima rata // if (_inited && _tpr > 0 && _tpr < 4) // { // TToken_string& tr = rata(0); // real tot = tpay_rata(0) + _secndr; // tr.add(tot.string(), 4); // } } need_recalc = TRUE; return P_OK; } // new_value != NULL } else // i != row modified { if (rdiff == 2) continue; if (i > 0 && !((perc_rata(i-1) == perc_rata(i)))) { if (rdiff == 2) rdiff = 1; _rdiff = FALSE; } if (is_perc_modified) rsum += perc_rata(i); else rsum += tpay_rata(i); lastdate = data_rata(i); oldtype = tipo_rata(i); oldscad = scad_rata(i); if (_inited && i > 0) { if (data_rata(i) <= data_rata(i-1)) return P_SCAD; } else if (lastdate < _inizio) return P_INIZIO; } } return P_OK; } bool TPagamento::read(TTable* t, TTable* r) { // puo' chiamarla chiunque bool istnew = FALSE; if (t == NULL) { t = new TTable("%CPG"); istnew = TRUE; } t->zero(); t->put("CODTAB", _code); if (t->read() != NOERR) return FALSE; _slicer.init(real(0.0), TRUE); _rate.destroy(); // set everything _rdiff = t->get_bool("B1"); _mcomm = t->get_bool("B0"); _tpr = atoi(t->get("S3")); _inscad = *((const char*)(t->get("S1"))); _code = t->get("CODTAB"); _name = t->get("S0"); _fixd[0] = t->get_int("I0"); _fixd[1] = t->get_int("I1"); _fixd[2] = t->get_int("I2"); // TBI aggiusta _inizio secondo INSCAD; vedi mese commerciale etc. if (_inscad == 'M') { if (_mcomm) _inizio.set_month(_inizio.month() == 2 ? 28 : 30); else _inizio.set_end_month(); } else if (_inscad == 'F' && _mcomm && _inizio.month() == 31) _inizio.set_month(30); // leggi rate e scadenze bool isrnew = FALSE; if (r == NULL) { r = new TTable("%RPG"); isrnew = TRUE; } TString16 s; for (int i = 0; ;i++) { r->zero(); s.format("%s%3d",(const char*)_code, i); r->put("CODTAB", (const char*)s); if (r->read() != NOERR) break; TToken_string* tt = new TToken_string(16); tt->add((const char*)(r->get("I0"))); // scadenza tt->add((const char*)(r->get("R0"))); // percentuale tt->add((const char*)(r->get("I1"))); // tipo // data e importo TDate d = _inizio; next_scad(d,(int)(r->get_long("I0")),_mcomm,i); tt->add((const char*)d); tt->add(""); tt->add(r->get("S1")); // ulteriore classificazione _slicer.add((real)r->get("R0")); _rate.add(tt); } if (istnew) delete t; if (isrnew) delete r; return TRUE; } int TPagamento::write(TTable& r) { // Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una // relapp, che ha scritto il file principale TString16 s; int err = NOERR; for (int i = 0; err == NOERR && i < n_rate(); i++) { r.zero(); s.format("%s%3d",(const char*)_code, i); r.put("CODTAB", s); r.put("I0", (long)scad_rata(i)); r.put("R0", perc_rata(i).string()); r.put("I1", (long)tipo_rata(i)); r.put("S1", ulc_rata(i)); err = r.write(); } return err; } int TPagamento::rewrite(TTable& r) { TString16 s; int err = NOERR; for (int i = 0; err == NOERR && i < n_rate(); i++) { r.zero(); s.format("%s%3d",(const char*)_code, i); r.put("CODTAB", s); bool was = (r.read() == NOERR); r.zero(); s.format("%s%3d",(const char*)_code, i); r.put("CODTAB", (const char*)s); r.put("I0", (long)scad_rata(i)); r.put("R0", perc_rata(i).string()); r.put("I1", (long)tipo_rata(i)); r.put("S1", ulc_rata(i)); err = (was ? r.rewrite() : r.write()); } // erase possible rates > current n. rates for (;err == NOERR;i++) { r.zero(); s.format("%s%3d",(const char*)_code, i); r.put("CODTAB", (const char*)s); if (r.read() == NOERR) err = r.remove(); else break; } return err; } int TPagamento::remove(TTable& r) { TString s(16); int err = NOERR; for (int i = 0 ; err == NOERR; i++) { r.zero(); s.format("%s%3d",(const char*)_code, i); r.put("CODTAB", (const char*)s); if (r.read() == NOERR) err = r.remove(); else break; } return err; } void TPagamento::set_rate_auto() { // vedi rate esistenti e tipo prima rata // deve fare riferimento ad un tipo pagamento esistente // e sensato int first = 0; real toslice = _firstr; if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1)) return; if (_tpr > 3) // ripartisci _firstr su tutte le rate { first = 1; toslice = _secndr; } _slicer.init(toslice); if (_tpr > 3) // prima rata obbligatoria set_imprata(0, _firstr); // se rate uguali dividi l'importo totale per il numero di rate real r1(0.0), ro(0.0); if (!_rdiff) { int rut = _tpr > 3 ? n_rate() - 1 : n_rate(); // usa la percentuale per la prima rata r1 = (toslice * perc_rata(first))/real(100.0); r1.round(_round); real reminder = toslice - r1; if (!reminder.is_zero()) { ro = reminder/real(rut-1); ro.trunc(_round); r1 = (toslice - (ro*real(rut-1))); } } for (int i = first; i < n_rate(); i++) // setta le fette e le date di scadenza set_imprata(i, _rdiff ? _slicer.get() : (i == first ? r1 : ro)); // se e' nei primi tre casi, si somma l'importo da non dividere alla // prima rata if (_tpr > 0 && _tpr < 4) set_imprata(0, tpay_rata(0) + _secndr); } void TPagamento::set_total(const real& imponibile, const real& imposta, const real& spese) { _imponibile = imponibile; _imposta = imposta; _spese = spese; _inited = TRUE; // istanzia _firstr e _secndr a seconda di _tpr switch(_tpr) { case 0: _firstr = _imponibile + _imposta + _spese; _secndr = 0.0; break; case 1: _secndr = _imposta; _firstr = _imponibile + _spese; break; case 2: _secndr = _spese; _firstr = _imposta + _imponibile; break; case 3: _secndr = _imposta + _spese; _firstr = _imponibile; break; case 4: _firstr = _spese + _imponibile; _secndr = _imposta; break; case 5: _firstr = _imponibile + _imposta; _secndr = _spese; break; case 6: _firstr = _imponibile; _secndr = _imposta + _spese; break; } const real toslice = _tpr > 1 ? _secndr : _firstr; _slicer.init(toslice, TRUE); const int first = _tpr > 3 ? 1 : 0; for (int i = first; i < _rate.items(); i++) { TToken_string& t = (TToken_string&)_rate[i]; const real rr(t.get(1)); _slicer.add(rr); } } void TPagamento::set_sheet(TSheet_field& sf, int sscad) { if (_inited && _rate.items() > 0) { const bool in_valuta = _cambio != 1.0; // si istanzia uno sheet di primanota for (int i = 0; i < n_rate(); i++) { TToken_string& ts = sf.row(i); ts.add((const char*)data_rata(i), 0); // 0 - Data scadenza if (in_valuta) { ts.add(tlit_rata(i).string(), 1); // 1 - Importo in lire ts.add(tpay_rata(i).string(), 2); // 2 - Importo in valuta } else { ts.add(tpay_rata(i).string(), 1); // 1 - Importo ts.add("", 2); } ts.add(perc_rata(i).string(), 3); // 3 - Percentuale ts.add(tipo_rata(i), 4); // 4 - Tipo rata ts.add(desc_tipo(tipo_rata(i)), 5); // 5 - Descrizione tipo rata // 6,7,8,9 - Banche const bool paid = ratapagata(i); ts.add(paid ? "X" : "", 10); // 10 - Pagaya } // destroy remaining while (sf.items() > i) sf.destroy(sf.items()-1); sf.enable_column(2, in_valuta); } else if (_rate.items() > 0) // not inited: set edit sheet { sf.destroy(); for (int i = 0, scr = 0; i < n_rate(); i++) { TToken_string& s = sf.row(-1); scr += scad_rata(i); s.add(scr); s.add(perc_rata(i).string()); s.add(tipo_rata(i)); s.add(desc_tipo(tipo_rata(i))); s.add(ulc_rata(i)); } } else // new: set with 1 or 2 rates according to tpr { if (_tpr > 3) add_rata(ZERO, sscad == -1 ? 0 : sscad, _def_tpr, _def_ulc); add_rata(real(100.0), sscad == -1 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc); _dirty = TRUE; for (int i = 0, scr = 0; i < n_rate(); i++) { TToken_string& s = sf.row(-1); scr += scad_rata(i); s.add(scr); s.add(perc_rata(i).string()); s.add(tipo_rata(i)); s.add(desc_tipo(tipo_rata(i))); s.add(ulc_rata(i)); } } const bool abilita = _tpr <= 3; // disabilita campi da non toccare sulla prima rata if (_inited) { sf.enable_cell(0, 1, abilita); // importo sf.enable_cell(0, 2, abilita); // in valuta sf.enable_cell(0, 3, abilita); // percentuale } else { sf.enable_cell(0, 1, abilita); // percentuale } sf.force_update(); } TPagamento::TPagamento(const char* codtab, const char* data) : _slicer(0.0,0), _new(FALSE), _imponibile(0.0), _imposta(0.0), _spese(0.0), _cambio(1.0), _code(codtab), _dirty(FALSE), _inited(FALSE), _def_tpr(1), _def_ulc(""), _round(0), _int_rate(30), _tpr(0) { _fixd[0] = _fixd[1] = _fixd[2] = 0; if (data != NULL && *data) _inizio = data; else _inizio = TDate(TODAY); if (_code.blank() || !read()) _new = TRUE; }