From 8444247f6a8727d466aa99807d994e7bbf29ccb9 Mon Sep 17 00:00:00 2001 From: villa Date: Fri, 11 Aug 1995 09:02:40 +0000 Subject: [PATCH] Nuovi metodi calcolo pagamento git-svn-id: svn://10.65.10.50/trunk@1700 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- cg/pagament.cpp | 2969 ++++++++++++++++++++++++----------------------- cg/pagament.h | 13 +- 2 files changed, 1517 insertions(+), 1465 deletions(-) diff --git a/cg/pagament.cpp b/cg/pagament.cpp index ef90de5d9..00be71abb 100755 --- a/cg/pagament.cpp +++ b/cg/pagament.cpp @@ -1,1462 +1,1509 @@ -#include - -#include "pagament.h" - -#include -#include - -int TPagamento::_rata_ifield(int n, int f) const -{ - TToken_string& t = (TToken_string&)_rate[n]; - return t.get_int(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[6]; - TToken_string& t = (TToken_string&)_rate[n]; - strcpy(kak,t.get(f)); - return kak; -} - - -bool TPagamento::ratapagata(int n) -{ - TToken_string& t = (TToken_string&)_rate[n]; - return t.items() > 6; -} - - - -void TPagamento::set_intervallo_rate(int in) -{ - _dirty = TRUE; - 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" : format("%d",in)) - : format("%d",in), 0); - } -} - -void TPagamento::set_mese_commerciale(bool v, int& sscad) -{ - _dirty = FALSE; - if (_mcomm == v) return; - if (sscad == -1) 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.add(NULL,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) -{ - _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; - - for (int 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.add(NULL,i); - _rate.pack(); - - _dirty = TRUE; -} - - -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 la minchia 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.add(NULL,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(16); - tt->add(day); // scadenza - tt->add(perc.string()); // percentuale - tt->add(type); // tipo - tt->add(""); - tt->add(""); - tt->add(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(16); - - 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 (!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, 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); -} - -TToken_string& TPagamento::set_rata(int index, const real& howmuch, - 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 bool nwr = (tt == NULL); // nuova rata - - if (nwr) tt = new TToken_string(16); - - TDate oldd = index > 0 ? data_rata(index -1) : _inizio; - int day = date - oldd; - real toshare(_tpr < 4 ? _firstr : _secndr); - real perc = (_tpr > 3 && index == 0) ? ZERO : howmuch/toshare; - perc *= real(100.0); - perc.round(2); - - tt->add(day,0); // scadenza - tt->add(perc.string(),1); // percentuale - tt->add(type,2); // tipo - tt->add(date.string(),3); - tt->add(howmuch.string(),4); - tt->add(ulc,5); - if (pagato) tt->add("X",6); - - 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) - { - 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"; -} - -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; - } - 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 interbancari diretti"; break; - case 9: o = "Bonifici"; break; - case 10: 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; - TArray 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 (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) - { - TToken_string& tt = rata(row); - TToken_string& ss = (TToken_string&)srate[row]; - tt.add(typ,2); - ss.add(typ,2); - // 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)))) - { - // controlla se rdiff e' compatibile con - // i dati e se e' il caso riaggiusta - if (rdiff == 3 && !((remainder % newv.integer()) == ZERO)) - rdiff = 2; - if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) - rdiff = 1; - _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.add(NULL,j); - } - else - { - // l'importante e' esagerare - for(int j = row+1; j < srate.items(); j++) - _rate.add(NULL,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; - - int frs = (rdiff == 3 || rdiff == 4) ? row+1 : first; - real mx = (rdiff == 3 || rdiff == 4) ? remainder : rmax; - - // cancelliamo tutto, va' - for (int j = frs; j < srate.items(); j++) - _rate.add(NULL,j); - - 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); - } - - 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); - 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.add(NULL,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,0); - - for (int j = first; j < _rate.items(); j++) - { - real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); - real zpx = rvl/rmax; // percentuale - dt.add(zpx); - } - for (j = first; j < _rate.items(); j++) - { - TToken_string& tr = rata(j); - real rvl = dt.get(); - tr.add(rvl.string(), is_perc_modified ? 4 : 1); - } - } - - need_recalc = TRUE; - return P_OK; - } // new_value != NULL - } - else // i != row modified - { - 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; - - // set everything - _rdiff = t->get_bool("B1"); - _mcomm = t->get_bool("B0"); - _tpr = *((const char*)(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; - } - TString s(16); - - 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 - - TString s(16); 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", (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 = r.write(); - } - return err; -} - -int TPagamento::rewrite(TTable& r) -{ - TString s(16); 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", (const char*)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 > 1) // ripartisci _firstr su tutte le rate - { - first = 1; - toslice = _secndr; - } - - _slicer.init(toslice); - - if (_tpr > 3) - // prima rata obbligatoria - set_imprata(0, _firstr); - - for (int i = first; i < n_rate(); i++) - // setta le fette e le date di scadenza - set_imprata(i, _slicer.get()); -} - - - -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: - _firstr = _imposta; - _secndr = _imponibile + _spese; - break; - case 2: - _firstr = _spese; - _secndr = _imposta + _imponibile; - break; - case 3: - _firstr = _imposta + _spese; - _secndr = _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) -{ - sf.destroy(-1); - if (_inited && _rate.items() > 0) - { - // si istanzia uno sheet di primanota - for (int i = 0; i < n_rate(); i++) - { - TToken_string& ts = sf.row(-1); - // istanzia, o stronzo - ts.add((const char*)data_rata(i)); - ts.add(perc_rata(i).string()); - ts.add(tpay_rata(i).string()); - ts.add(tipo_rata(i)); - ts.add(desc_tipo(tipo_rata(i))); - if (ratapagata(i)) - { - sf.disable_cell(1,1); // percentuale - sf.disable_cell(1,2); // importo - } - } - } - else if (_rate.items() > 0) // not inited: set edit sheet - { - 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); // percentuale - sf.disable_cell(0,2); // importo - } - 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), _code(codtab), _dirty(FALSE), _inited(FALSE), -_def_tpr(1), _def_ulc("") -{ - _fixd[0] = _fixd[1] = _fixd[2] = 0; - if (data != NULL) - _inizio = data; - if (_code.blank() || !read()) - _new = TRUE; -// if (_new && data != NULL) error_box("Modalita' pagamento inesistente"); -} - - -/////////////////////////////////////////////////////////// -// TTree_rectype -/////////////////////////////////////////////////////////// - -TTree_rectype::TTree_rectype(const TRectype& testa, const TRectype& riga, const char* num) - : TRectype(testa), _recarr(riga, num) -{ -} - -TTree_rectype::TTree_rectype(int testa, int riga, const char* num) - : TRectype(testa), _recarr(riga, num) -{ -} - -TTree_rectype::TTree_rectype(const TTree_rectype& t) - : TRectype(t), _recarr(t._recarr) -{ -} - - -TObject* TTree_rectype::dup() const -{ - TTree_rectype* r = new TTree_rectype(*this); - return r; -} - -void TTree_rectype::copy_key_to_row(TRectype& row) const -{ - const int numkey = 0; // Memento! Gli indici delle chiavi partono da zero! - RecDes* recd = rec_des(); // Descrizione del record della testata - - row.zero(); - for (int i = 0; i < recd->Ky[numkey].NkFields; i++) - { - const KeyDes& kd = recd->Ky[numkey]; - const int nf = kd.FieldSeq[i] % MaxFields; - const RecFieldDes& rf = recd->Fd[nf]; - const char* name = rf.Name; - const TString& val = get(name); - row.put(name, val); - } -} - -int TTree_rectype::fill_array() -{ - TRectype* row = (TRectype*)_recarr.key().dup(); - copy_key_to_row(*row); - const int err = _recarr.read(row); - return err; -} - - -int TTree_rectype::read(TBaseisamfile& f, word op) -{ - int err = TRectype::read(f, op); - if (err == NOERR) - fill_array(); - else - _recarr.destroy_rows(); - return err; -} - -int TTree_rectype::next(TBaseisamfile& f) -{ - int err = TRectype::next(f); - if (err == NOERR) - fill_array(); - else - _recarr.destroy_rows(); - return err; -} - -int TTree_rectype::write(TBaseisamfile& f) const -{ - int err = TRectype::write(f); - if (err == NOERR) - err = _recarr.write(); - return err; -} - -int TTree_rectype::rewrite(TBaseisamfile& f) const -{ - int err = TRectype::rewrite(f); - if (err == NOERR) - err = _recarr.rewrite(); - return err; -} - -int TTree_rectype::remove(TBaseisamfile& f) -{ - int err = TRectype::remove(f); - if (err == NOERR) - err = _recarr.remove(); - return err; -} - -/////////////////////////////////////////////////////////// -// TRiga_scadenze -/////////////////////////////////////////////////////////// - -TRiga_scadenze::TRiga_scadenze() - : TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP") -{ - zero(); -} - -/////////////////////////////////////////////////////////// -// TRiga_partite -/////////////////////////////////////////////////////////// - -TRiga_partite::TRiga_partite() - : TTree_rectype(LF_PARTITE, LF_SCADENZE, "NRATA") -{ - zero(); -} - -TRiga_partite::TRiga_partite(const TRiga_partite& r) - : TTree_rectype(r) -{} - - -int TRiga_partite::read(TBaseisamfile& f, word op) -{ - int err = TRectype::read(f, op); - if (err == NOERR && get_int(PART_TIPOMOV) == 1) - { - TRiga_scadenze* s = new TRiga_scadenze; - copy_key_to_row(*s); - err = _recarr.read(s); // Deve esistere almento una scadenza -#ifdef DBG - if (err != NOERR) - yesnofatal_box("Riga di partite senza nessuna scadenza"); -#endif - } - else - _recarr.destroy_rows(); - return err; -} - -TObject* TRiga_partite::dup() const -{ - return new TRiga_partite(*this); -} - -int TRiga_partite::add_rata(const TRectype& r) -{ - return 1; -} - -int TRiga_partite::ultimo_pagamento(int r) const -{ - const TRiga_scadenze& s = rata(r); - return s.rows_array().last_row(); -} - -// Controlla se la rata r e' stata completamente pagata -bool TRiga_partite::rata_pagata(int r) const -{ - const TRiga_scadenze& scad = rata(r); - real importo(scad.get(SCAD_IMPORTO)); - importo -= scad.get_real(SCAD_IMPORTOPAG); - const bool pagata = importo.is_zero(); - return pagata; -} - - -/////////////////////////////////////////////////////////// -// TPartita -/////////////////////////////////////////////////////////// - -TPartita::TPartita(const TBill& clifo, int anno, const char* num) - : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP") -{ - read(clifo, anno, num); -} - -int TPartita::add_riga(const TRiga_partite& r) -{ - CHECK(r.num() == LF_PARTITE, "Tipo record errato"); - - const char sez = r.get_char(PART_SEZ); - const real val = r.get_real(PART_IMPORTO); - const TImporto imp(sez, val); - - TImporto grow(imp); - const int n = r.get_int(PART_NRIGA); - CHECK(n > 0, "Numero riga nullo"); - if (n <= _part.last_row()) - { - const TRectype& oldrow = riga(n); - const char osez = oldrow.get_char(PART_SEZ); - const real oval = oldrow.get_real(PART_IMPORTO); - const TImporto old(osez, oval); - grow -= old; - } - - return _part.add_row(r); -} - -void TPartita::remove_riga(TRiga_partite& z) -{ - z.zero(PART_IMPORTO); - add_riga(z); - _part.destroy_row(z, TRUE); -} - -// Costruisce le righe della partita -bool TPartita::read(const TBill& clifo, int anno, const char* num) -{ - TRiga_partite* partita = new TRiga_partite; // Record campione della partita - partita->put(PART_TIPOCF, clifo.tipo()); // Tipo clifo - if (clifo.tipo() <= ' ') - { - partita->put(PART_GRUPPO, clifo.gruppo()); // Scrivi gruppo e conto solamente - partita->put(PART_CONTO, clifo.conto()); // nei conti normali (no clifo) - } - partita->put(PART_SOTTOCONTO, clifo.sottoconto()); // Sottoconto o codice clifo - partita->put(PART_ANNO, anno); // Anno partita - partita->put(PART_NUMPART, num); // Numero partita - _part.read(partita); - - TRectype unas(LF_PAGSCA); // Record campione pagamenti non assegnati - unas.zero(); - unas.put(PART_TIPOCF, partita->get(PART_TIPOCF)); // Copia chiave partite - unas.put(PART_GRUPPO, partita->get(PART_GRUPPO)); - unas.put(PART_CONTO, partita->get(PART_CONTO)); - unas.put(PART_SOTTOCONTO, partita->get(PART_SOTTOCONTO)); - unas.put(PART_ANNO, partita->get(PART_ANNO)); - unas.put(PART_NUMPART, partita->get(PART_NUMPART)); - unas.put(PART_NRIGA, 9999); // Numeri magici di non assegamento - unas.put(SCAD_NRATA, 9999); - _unassigned.read(unas); - - return ok(); -} - -bool TPartita::reread() -{ - TBill zio; - conto(zio); - const int year = anno(); - const TString16 num = numero(); - return read(zio, year, num); -} - -bool TPartita::write(bool re) -{ - const bool ok = _part.write(re); - return ok; -} - - -TImporto TPartita::importo_speso(long nreg, int numrig) const -{ - TImporto imp; - - for (int r = _part.last_row(); r > 0; r--) - { - const TRectype& pag = riga(r); - - const long reg = pag.get_long(PART_NREG); - if (reg == nreg) - { - const int num = pag.get_int(PART_NUMRIG); - if (num == numrig) - { - imp = TImporto(pag.get_char(PART_SEZ), pag.get_real(PART_IMPORTO)); - break; - } - } - } - - return imp; -} - - -void TPartita::update_reg_num(long nreg, const TRectype& mov) -{ - for (int r = _part.last_row(); r > 0; r--) - { - TRectype& pag = _part.row(r, FALSE); - - const long reg = pag.get_long(PART_NREG); - if (reg == nreg) - { - pag.put(PART_NREG, mov.get(MOV_NUMREG)); - pag.put(PART_DATAREG, mov.get(MOV_DATAREG)); - pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC)); - pag.put(PART_DATADOC, mov.get(MOV_DATADOC)); - } - } -} - - -/////////////////////////////////////////////////////////// -// TPartite_array -/////////////////////////////////////////////////////////// - -// Certified 99% -const TString& TPartite_array::key(const TBill& clifo, int anno, const char* num) -{ - if (clifo.tipo() > ' ') - _key.format("%c%3d%3d%6ld%4d%s", clifo.tipo(), 0, 0, clifo.sottoconto(), anno, num); - else - _key.format("%c%3d%3d%6ld%4d%s", - clifo.tipo(), clifo.gruppo(), clifo.conto(), clifo.sottoconto(), anno, num); - return _key; -} - -// Certified 99% -TPartita* TPartite_array::find(const TBill& clifo, int anno, const char* num, bool create) -{ - const TString& k = key(clifo, anno, num); - TPartita* p = (TPartita*)objptr(k); - if (p == NULL && create) - { - p = new TPartita(clifo, anno, num); - if (p->ok()) - add(k, p); - else - { - delete p; - p = NULL; - } - } - return p; -} - -TPartita* TPartite_array::find(const TRectype& r, bool create) -{ - TBill zio; zio.get(r); - const int anno = r.get_int(PART_ANNO); - const char* num = r.get_str(PART_NUMPART); - return find(zio, anno, num, create); -} - -TPartita& TPartite_array::partita(const TBill& clifo, int anno, const char* num) -{ - TPartita* game = find(clifo, anno, num, TRUE); - CHECKS(game, "Partita errata ", num); - return *game; -} - -TPartita& TPartite_array::partita(const TRectype& r) -{ - TPartita* game = find(r, TRUE); - CHECK(game, "Partita errata"); - return *game; -} - -bool TPartite_array::write(bool re) -{ - int err = NOERR; - - TPartita* game; - restart(); - while ((game = (TPartita*)get()) != NULL) - { - err = game->write(re); - if (err != NOERR) // L'errore viene gia' segnalato dalla partita - break; - } - - return err == NOERR; -} - -// Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg -int TPartite_array::add_reg_num(long nreg, int numrig) -{ - TRelation rel(LF_PARTITE); - TRectype& part = rel.lfile().curr(); - - // Costruzione filtro del cursore - part.zero(); - part.put(PART_NREG, nreg); - if (numrig > 0) - part.put(PART_NUMRIG, numrig); - - const TRectype filter(part); - - TCursor cur(&rel, "", 2, &filter, &filter); - - for (cur = 0; cur.ok(); ++cur) - partita(part); // Aggiungi partita se non esiste gia' - - return (int)cur.items(); -} - -TImporto TPartite_array::importo_speso(long nreg, int numrig) -{ - TImporto imp; - add_reg_num(nreg, numrig); - for (TPartita* game = first(); game; game = next()) - imp += game->importo_speso(nreg, numrig); - return imp; -} - -void TPartite_array::update_reg_num(long nreg, const TRectype& mov) -{ - add_reg_num(nreg, 0); - for (TPartita* game = first(); game; game = next()) - game->update_reg_num(nreg, mov); -} - +#include + +#include "pagament.h" + +#include +#include + + +int TPagamento::_rata_ifield(int n, int f) const +{ + TToken_string& t = (TToken_string&)_rate[n]; + return t.get_int(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[6]; + TToken_string& t = (TToken_string&)_rate[n]; + strcpy(kak,t.get(f)); + return kak; +} + + +bool TPagamento::ratapagata(int n) +{ + TToken_string& t = (TToken_string&)_rate[n]; + return t.items() > 6; +} + + + +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" : format("%d",in)) + : format("%d",in), 0); + } +} + +void TPagamento::set_mese_commerciale(bool v, int& sscad) +{ + _dirty = FALSE; + if (_mcomm == v) return; + if (sscad == -1) 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.add(NULL,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) +{ + _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; + + for (int 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.add(NULL,i); + _rate.pack(); + + _dirty = TRUE; +} + + +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 la minchia 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.add(NULL,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(16); + tt->add(day); // scadenza + tt->add(perc.string()); // percentuale + tt->add(type); // tipo + tt->add(""); + tt->add(""); + tt->add(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(16); + + 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 (!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, 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); +} + +TToken_string& TPagamento::set_rata(int index, const real& howmuch, + 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 bool nwr = (tt == NULL); // nuova rata + + if (nwr) tt = new TToken_string(16); + + TDate oldd = index > 0 ? data_rata(index -1) : _inizio; + int day = date - oldd; + real toshare(_tpr < 4 ? _firstr : _secndr); + real perc = (_tpr > 3 && index == 0) ? ZERO : howmuch/toshare; + perc *= real(100.0); + perc.round(2); + + tt->add(day,0); // scadenza + tt->add(perc.string(),1); // percentuale + tt->add(type,2); // tipo + tt->add(date.string(),3); + tt->add(howmuch.string(),4); + tt->add(ulc,5); + if (pagato) tt->add("X",6); + + 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) + { + 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"; +} + +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 interbancari diretti"; break; + case 9: o = "Bonifici"; break; + case 10: 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; + TArray 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 (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) + { + TToken_string& tt = rata(row); + TToken_string& ss = (TToken_string&)srate[row]; + tt.add(typ,2); + ss.add(typ,2); + // 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; + _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.add(NULL,j); + } + else + { + // l'importante e' esagerare + for(int j = row+1; j < srate.items(); j++) + _rate.add(NULL,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; + + int frs = (rdiff == 3 || rdiff == 4) ? row+1 : first; + real mx = (rdiff == 3 || rdiff == 4) ? remainder : rmax; + + // cancelliamo tutto, va' + for (int j = frs; j < srate.items(); j++) + _rate.add(NULL,j); + + if (rdiff != 4) + for (j = frs; sum < mx; j++) + { + // TBI: qui mod se rdiff == 2 + // 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.add(NULL,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); + real zpx = rvl/rmax; // percentuale + dt.add(zpx); + } + for (j = first; j < _rate.items(); j++) + { + TToken_string& tr = rata(j); + real rvl = dt.get(); + tr.add(rvl.string(), is_perc_modified ? 4 : 1); + } + + // 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) + _firstr; + tr.add(tot.string(), 4); + } + + } + + need_recalc = TRUE; + return P_OK; + } // new_value != NULL + } + else // i != row modified + { + 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; + + // 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; + } + TString s(16); + + 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 + + TString s(16); 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", (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 = r.write(); + } + return err; +} + +int TPagamento::rewrite(TTable& r) +{ + TString s(16); 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", (const char*)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(); + ro = toslice/real(rut); ro.trunc(_round); + r1 = ro + (toslice - (ro*real(rut))); + } + + 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) + _firstr); +} + + + +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: + _firstr = _imposta; + _secndr = _imponibile + _spese; + break; + case 2: + _firstr = _spese; + _secndr = _imposta + _imponibile; + break; + case 3: + _firstr = _imposta + _spese; + _secndr = _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) +{ + sf.destroy(-1); + if (_inited && _rate.items() > 0) + { + // si istanzia uno sheet di primanota + for (int i = 0; i < n_rate(); i++) + { + TToken_string& ts = sf.row(-1); + // istanzia, o stronzo + ts.add((const char*)data_rata(i)); + ts.add(perc_rata(i).string()); + ts.add(tpay_rata(i).string()); + ts.add(tipo_rata(i)); + ts.add(desc_tipo(tipo_rata(i))); + if (ratapagata(i)) + { + sf.disable_cell(1,1); // percentuale + sf.disable_cell(1,2); // importo + } + } + } + else if (_rate.items() > 0) // not inited: set edit sheet + { + 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); // percentuale + sf.disable_cell(0,2); // importo + } + 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), _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; +// if (_new && data != NULL) error_box("Modalita' pagamento inesistente"); +} + + +/////////////////////////////////////////////////////////// +// TTree_rectype +/////////////////////////////////////////////////////////// + +TTree_rectype::TTree_rectype(const TRectype& testa, const TRectype& riga, const char* num) + : TRectype(testa), _recarr(riga, num) +{ +} + +TTree_rectype::TTree_rectype(int testa, int riga, const char* num) + : TRectype(testa), _recarr(riga, num) +{ +} + +TTree_rectype::TTree_rectype(const TTree_rectype& t) + : TRectype(t), _recarr(t._recarr) +{ +} + + +TObject* TTree_rectype::dup() const +{ + TTree_rectype* r = new TTree_rectype(*this); + return r; +} + +void TTree_rectype::copy_key_to_row(TRectype& row) const +{ + const int numkey = 0; // Memento! Gli indici delle chiavi partono da zero! + RecDes* recd = rec_des(); // Descrizione del record della testata + + row.zero(); + for (int i = 0; i < recd->Ky[numkey].NkFields; i++) + { + const KeyDes& kd = recd->Ky[numkey]; + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = recd->Fd[nf]; + const char* name = rf.Name; + const TString& val = get(name); + row.put(name, val); + } +} + +int TTree_rectype::fill_array() +{ + TRectype* row = (TRectype*)_recarr.key().dup(); + copy_key_to_row(*row); + const int err = _recarr.read(row); + return err; +} + + +int TTree_rectype::read(TBaseisamfile& f, word op) +{ + int err = TRectype::read(f, op); + if (err == NOERR) + fill_array(); + else + _recarr.destroy_rows(); + return err; +} + +int TTree_rectype::next(TBaseisamfile& f) +{ + int err = TRectype::next(f); + if (err == NOERR) + fill_array(); + else + _recarr.destroy_rows(); + return err; +} + +int TTree_rectype::write(TBaseisamfile& f) const +{ + int err = TRectype::write(f); + if (err == NOERR) + err = _recarr.write(); + return err; +} + +int TTree_rectype::rewrite(TBaseisamfile& f) const +{ + int err = TRectype::rewrite(f); + if (err == NOERR) + err = _recarr.rewrite(); + return err; +} + +int TTree_rectype::remove(TBaseisamfile& f) +{ + int err = TRectype::remove(f); + if (err == NOERR) + err = _recarr.remove(); + return err; +} + +/////////////////////////////////////////////////////////// +// TRiga_scadenze +/////////////////////////////////////////////////////////// + +TRiga_scadenze::TRiga_scadenze() + : TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP") +{ + zero(); +} + +/////////////////////////////////////////////////////////// +// TRiga_partite +/////////////////////////////////////////////////////////// + +TRiga_partite::TRiga_partite() + : TTree_rectype(LF_PARTITE, LF_SCADENZE, "NRATA") +{ + zero(); +} + +TRiga_partite::TRiga_partite(const TRiga_partite& r) + : TTree_rectype(r) +{} + + +int TRiga_partite::read(TBaseisamfile& f, word op) +{ + int err = TRectype::read(f, op); + if (err == NOERR && get_int(PART_TIPOMOV) == 1) + { + TRiga_scadenze* s = new TRiga_scadenze; + copy_key_to_row(*s); + err = _recarr.read(s); // Deve esistere almento una scadenza +#ifdef DBG + if (err != NOERR) + yesnofatal_box("Riga di partite senza nessuna scadenza"); +#endif + } + else + _recarr.destroy_rows(); + return err; +} + +TObject* TRiga_partite::dup() const +{ + return new TRiga_partite(*this); +} + +int TRiga_partite::add_rata(const TRectype& r) +{ + return 1; +} + +int TRiga_partite::ultimo_pagamento(int r) const +{ + const TRiga_scadenze& s = rata(r); + return s.rows_array().last_row(); +} + +// Controlla se la rata r e' stata completamente pagata +bool TRiga_partite::rata_pagata(int r) const +{ + const TRiga_scadenze& scad = rata(r); + real importo(scad.get(SCAD_IMPORTO)); + importo -= scad.get_real(SCAD_IMPORTOPAG); + const bool pagata = importo.is_zero(); + return pagata; +} + + +/////////////////////////////////////////////////////////// +// TPartita +/////////////////////////////////////////////////////////// + +TPartita::TPartita(const TBill& clifo, int anno, const char* num) + : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP") +{ + read(clifo, anno, num); +} + +int TPartita::add_riga(const TRiga_partite& r) +{ + CHECK(r.num() == LF_PARTITE, "Tipo record errato"); + + const char sez = r.get_char(PART_SEZ); + const real val = r.get_real(PART_IMPORTO); + const TImporto imp(sez, val); + + TImporto grow(imp); + const int n = r.get_int(PART_NRIGA); + CHECK(n > 0, "Numero riga nullo"); + if (n <= _part.last_row()) + { + const TRectype& oldrow = riga(n); + const char osez = oldrow.get_char(PART_SEZ); + const real oval = oldrow.get_real(PART_IMPORTO); + const TImporto old(osez, oval); + grow -= old; + } + + return _part.add_row(r); +} + +void TPartita::remove_riga(TRiga_partite& z) +{ + z.zero(PART_IMPORTO); + add_riga(z); + _part.destroy_row(z, TRUE); +} + +// Costruisce le righe della partita +bool TPartita::read(const TBill& clifo, int anno, const char* num) +{ + TRiga_partite* partita = new TRiga_partite; // Record campione della partita + partita->put(PART_TIPOCF, clifo.tipo()); // Tipo clifo + if (clifo.tipo() <= ' ') + { + partita->put(PART_GRUPPO, clifo.gruppo()); // Scrivi gruppo e conto solamente + partita->put(PART_CONTO, clifo.conto()); // nei conti normali (no clifo) + } + partita->put(PART_SOTTOCONTO, clifo.sottoconto()); // Sottoconto o codice clifo + partita->put(PART_ANNO, anno); // Anno partita + partita->put(PART_NUMPART, num); // Numero partita + _part.read(partita); + + TRectype unas(LF_PAGSCA); // Record campione pagamenti non assegnati + unas.zero(); + unas.put(PART_TIPOCF, partita->get(PART_TIPOCF)); // Copia chiave partite + unas.put(PART_GRUPPO, partita->get(PART_GRUPPO)); + unas.put(PART_CONTO, partita->get(PART_CONTO)); + unas.put(PART_SOTTOCONTO, partita->get(PART_SOTTOCONTO)); + unas.put(PART_ANNO, partita->get(PART_ANNO)); + unas.put(PART_NUMPART, partita->get(PART_NUMPART)); + unas.put(PART_NRIGA, 9999); // Numeri magici di non assegamento + unas.put(SCAD_NRATA, 9999); + _unassigned.read(unas); + + return ok(); +} + +bool TPartita::reread() +{ + TBill zio; + conto(zio); + const int year = anno(); + const TString16 num = numero(); + return read(zio, year, num); +} + +bool TPartita::write(bool re) +{ + const bool ok = _part.write(re); + return ok; +} + + +TImporto TPartita::importo_speso(long nreg, int numrig) const +{ + TImporto imp; + + for (int r = _part.last_row(); r > 0; r--) + { + const TRectype& pag = riga(r); + + const long reg = pag.get_long(PART_NREG); + if (reg == nreg) + { + const int num = pag.get_int(PART_NUMRIG); + if (num == numrig) + { + imp = TImporto(pag.get_char(PART_SEZ), pag.get_real(PART_IMPORTO)); + break; + } + } + } + + return imp; +} + + +void TPartita::update_reg_num(long nreg, const TRectype& mov) +{ + for (int r = _part.last_row(); r > 0; r--) + { + TRectype& pag = _part.row(r, FALSE); + + const long reg = pag.get_long(PART_NREG); + if (reg == nreg) + { + pag.put(PART_NREG, mov.get(MOV_NUMREG)); + pag.put(PART_DATAREG, mov.get(MOV_DATAREG)); + pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC)); + pag.put(PART_DATADOC, mov.get(MOV_DATADOC)); + } + } +} + + +/////////////////////////////////////////////////////////// +// TPartite_array +/////////////////////////////////////////////////////////// + +// Certified 99% +const TString& TPartite_array::key(const TBill& clifo, int anno, const char* num) +{ + if (clifo.tipo() > ' ') + _key.format("%c%3d%3d%6ld%4d%s", clifo.tipo(), 0, 0, clifo.sottoconto(), anno, num); + else + _key.format("%c%3d%3d%6ld%4d%s", + clifo.tipo(), clifo.gruppo(), clifo.conto(), clifo.sottoconto(), anno, num); + return _key; +} + +// Certified 99% +TPartita* TPartite_array::find(const TBill& clifo, int anno, const char* num, bool create) +{ + const TString& k = key(clifo, anno, num); + TPartita* p = (TPartita*)objptr(k); + if (p == NULL && create) + { + p = new TPartita(clifo, anno, num); + if (p->ok()) + add(k, p); + else + { + delete p; + p = NULL; + } + } + return p; +} + +TPartita* TPartite_array::find(const TRectype& r, bool create) +{ + TBill zio; zio.get(r); + const int anno = r.get_int(PART_ANNO); + const char* num = r.get_str(PART_NUMPART); + return find(zio, anno, num, create); +} + +TPartita& TPartite_array::partita(const TBill& clifo, int anno, const char* num) +{ + TPartita* game = find(clifo, anno, num, TRUE); + CHECKS(game, "Partita errata ", num); + return *game; +} + +TPartita& TPartite_array::partita(const TRectype& r) +{ + TPartita* game = find(r, TRUE); + CHECK(game, "Partita errata"); + return *game; +} + +bool TPartite_array::write(bool re) +{ + int err = NOERR; + + TPartita* game; + restart(); + while ((game = (TPartita*)get()) != NULL) + { + err = game->write(re); + if (err != NOERR) // L'errore viene gia' segnalato dalla partita + break; + } + + return err == NOERR; +} + +// Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg +int TPartite_array::add_reg_num(long nreg, int numrig) +{ + TRelation rel(LF_PARTITE); + TRectype& part = rel.lfile().curr(); + + // Costruzione filtro del cursore + part.zero(); + part.put(PART_NREG, nreg); + if (numrig > 0) + part.put(PART_NUMRIG, numrig); + + const TRectype filter(part); + + TCursor cur(&rel, "", 2, &filter, &filter); + + for (cur = 0; cur.ok(); ++cur) + partita(part); // Aggiungi partita se non esiste gia' + + return (int)cur.items(); +} + +TImporto TPartite_array::importo_speso(long nreg, int numrig) +{ + TImporto imp; + add_reg_num(nreg, numrig); + for (TPartita* game = first(); game; game = next()) + imp += game->importo_speso(nreg, numrig); + return imp; +} + +void TPartite_array::update_reg_num(long nreg, const TRectype& mov) +{ + add_reg_num(nreg, 0); + for (TPartita* game = first(); game; game = next()) + game->update_reg_num(nreg, mov); +} \ No newline at end of file diff --git a/cg/pagament.h b/cg/pagament.h index 8f116468f..11749c22a 100755 --- a/cg/pagament.h +++ b/cg/pagament.h @@ -49,7 +49,9 @@ class TPagamento : public TObject real _secndr; // importo da distribuire int _fixd[3]; // giorni scadenza fissa, se desiderati - + int _round; // decimali arrotondamento importo + int _int_rate; + int _rata_ifield(int n, int f) const; real _rata_rfield(int n, int f) const; TDate _rata_dfield(int n, int f) const; @@ -79,7 +81,8 @@ public: bool mese_commerciale() const { return _mcomm; } bool rate_differenziate() const { return _rdiff; } int tipo_prima_rata() const { return _tpr; } - + int decs() const { return _round; } + // mi scuso per la mancanza di underscore, ma mi piaceva cosi' bool ratapagata(int n); @@ -101,8 +104,9 @@ public: void set_numero_rate(int n, int sscad = -1); void set_inizio_scadenza(char v) { _inscad = v; } - void set_code(const char* c) { _code = c; } - + void set_code(const char* c) { _code = c; } + void set_round(int n) { _round = n; } + // check consistency: returns word with errors flagged, 0 if ok word validate() const; void strerr(word err, TString& s); @@ -161,6 +165,7 @@ public: virtual ~TPagamento() {} }; + #ifndef __PARTITE_H #include #endif