diff --git a/cg/cg4300.h b/cg/cg4300.h index e6ebe4713..3806c5f6f 100755 --- a/cg/cg4300.h +++ b/cg/cg4300.h @@ -185,7 +185,7 @@ class TLiquidazione_app : public TPrint_application TArray_sheet* _ditte; wht _what; TBit_array _selected; - int _menu; // 1 = Liquidazione, 2 = Deleghe, 3 = + int _menu; // 1 = Liquidazione, 2 = Deleghe, 3 = Acconti TString _year; // anno di calcolo int _month; // mese da calcolare TDate _date; // data di stampa diff --git a/cg/pagament.cpp b/cg/pagament.cpp index c91d120de..0f7f9c33d 100755 --- a/cg/pagament.cpp +++ b/cg/pagament.cpp @@ -1,1394 +1,1394 @@ -#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_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]; - TDate d = _inizio; - tt.add(r.string(), 1); -} - - -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); - 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); -// TDistrib ds(toshare,0); - - // check percentages & prepare slicer - for (int i = first; i < n_rate(); i++) - { - real p(perc_rata(i)); -// ds.add(p); - r += p; - } - - if (r != real(100.0)) - res |= P_RSUM; - - - if (_inited) - { -// RIMOSSO in quanto con rate uguali non si usa la percentuale, -// per evitare merdaglia -// ds.init(toshare); - // check importi rate consistenti con la percentuale -// for (int i = first; i < n_rate(); i++) -// { -// real r1(tpay_rata(i)); -// real r2(ds.get()); -// if (r1 != r2) -// { res |= P_IMPNC; break; } -// } - - // 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"; -} - -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.integer()) == ZERO)) - 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 / 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")); - _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; - } - - real toslice = _tpr > 1 ? _secndr : _firstr; - - _slicer.init(toslice, TRUE); - - for (int i = 0; i < _rate.items(); i++) - { - TToken_string& t = (TToken_string&)_rate[i]; - 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 - sf.enable_cell(i,1,!paid); // importo - sf.enable_cell(i,2,!paid); // in valuta - sf.enable_cell(i,3,!paid); // percentuale - } - - // 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)); - } - } - - if (_tpr > 3) - { - // disabilita campi da non toccare sulla prima rata - if (_inited) - { - sf.disable_cell(0,1); // importo - sf.disable_cell(0,2); // in valuta - sf.disable_cell(0,3); // percentuale - } - else - { - sf.disable_cell(0,1); // 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) -{ - _fixd[0] = _fixd[1] = _fixd[2] = 0; - if (data != NULL) - _inizio = data; - if (_code.blank() || !read()) - _new = TRUE; +#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_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]; + TDate d = _inizio; + tt.add(r.string(), 1); +} + + +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); + 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); +// TDistrib ds(toshare,0); + + // check percentages & prepare slicer + for (int i = first; i < n_rate(); i++) + { + real p(perc_rata(i)); +// ds.add(p); + r += p; + } + + if (r != real(100.0)) + res |= P_RSUM; + + + if (_inited) + { +// RIMOSSO in quanto con rate uguali non si usa la percentuale, +// per evitare merdaglia +// ds.init(toshare); + // check importi rate consistenti con la percentuale +// for (int i = first; i < n_rate(); i++) +// { +// real r1(tpay_rata(i)); +// real r2(ds.get()); +// if (r1 != r2) +// { res |= P_IMPNC; break; } +// } + + // 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"; +} + +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 interb. 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.integer()) == ZERO)) + 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 / 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")); + _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; + } + + real toslice = _tpr > 1 ? _secndr : _firstr; + + _slicer.init(toslice, TRUE); + + for (int i = 0; i < _rate.items(); i++) + { + TToken_string& t = (TToken_string&)_rate[i]; + 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 + sf.enable_cell(i,1,!paid); // importo + sf.enable_cell(i,2,!paid); // in valuta + sf.enable_cell(i,3,!paid); // percentuale + } + + // 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)); + } + } + + if (_tpr > 3) + { + // disabilita campi da non toccare sulla prima rata + if (_inited) + { + sf.disable_cell(0,1); // importo + sf.disable_cell(0,2); // in valuta + sf.disable_cell(0,3); // percentuale + } + else + { + sf.disable_cell(0,1); // 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) +{ + _fixd[0] = _fixd[1] = _fixd[2] = 0; + if (data != NULL) + _inizio = data; + if (_code.blank() || !read()) + _new = TRUE; } \ No newline at end of file