campo-sirio/cg/pagament.cpp
guy aa41da6683 Correzioni minori alle maschere del piano dei conti e dei clienti
Correzioni prima nota e tolto menu principale dalla liquidazione


git-svn-id: svn://10.65.10.50/trunk@1332 c028cbd2-c16b-5b4b-a496-9718f37d4682
1995-05-09 13:31:10 +00:00

1250 lines
32 KiB
C++
Executable File

#include <utility.h>
#include "pagament.h"
#include <mov.h>
#include <scadenze.h>
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 == 0 ? 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 == 0 && _tpr > 0)
{
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 == 0 && v > 0)
{
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;
int p = 100 / n;
int nr = n_rate();
int first = _tpr == 0 ? 0 : 1;
for (int i = first, sum = 0; sum < 100; i++)
{
if ((100 - sum) < p) p = 100 - sum;
sum += p;
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 < n_rate(); 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;
}
}
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)
{
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("");
_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 == 0 ? _firstr : _secndr);
real perc = (_tpr > 0 && 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 == 0 ? 0 : 1;
real toshare(_tpr == 0 ? _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 / 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 = "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 == 0 ? 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 == 0 ? _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 == 0 ? _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");
// 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 > 0 && n_rate() == 1)) return;
if (_tpr > 1) // ripartisci _firstr su tutte le rate
{
first = 1;
toslice = _secndr;
}
_slicer.init(toslice);
if (_tpr > 0)
// 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.reset();
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 > 0)
add_rata(ZERO, sscad == -1 ? 0 : sscad, 1);
add_rata(real(100.0), sscad == -1 ? (_tpr == 0 ? 0 :30) : sscad, 1);
_dirty = TRUE;
for (int i = 0, scr = 0; i < n_rate(); i++)
{
TToken_string& s = sf.row(-1);
scr += scad_rata(i);
s.add(format("%d",scr));
s.add(perc_rata(i).string());
s.add(format("%d",tipo_rata(i)));
s.add(desc_tipo(tipo_rata(i)));
s.add(ulc_rata(i));
}
}
if (_tpr > 0)
{
// 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)
{
if (data != NULL)
_inizio = data;
if (_code.blank() || !read())
_new = TRUE;
// if (_new && data != NULL) error_box("Modalita' pagamento inesistente");
}
///////////////////////////////////////////////////////////
// TPartita
///////////////////////////////////////////////////////////
TPartita::TPartita(int anno, const char* num)
: _scad(LF_SCADENZE, SCAD_NRATA), _part(LF_PARTITE, PART_NRIGA)
{
read(anno, num);
}
int TPartita::add_riga(const TRectype& 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 <= righe())
{
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;
}
_totale += grow;
if (rate() > 0) // Se sono in aggiornamento (non nella read!)
{
const int nr = r.get_int(PART_NRATA);
TRectype scad = rata(nr);
real ip(scad.get(SCAD_IMPORTOPAG));
ip += grow.valore();
scad.put(SCAD_IMPORTOPAG, ip);
add_rata(scad);
}
return _part.add_row(r);
}
void TPartita::remove_riga(TRectype& z)
{
z.zero(PART_IMPORTO);
add_riga(z);
_part.destroy_row(z, TRUE);
}
int TPartita::add_rata(const TRectype& r)
{
return _scad.add_row(r);
}
// Costruisce le righe della partita a partire da 1
bool TPartita::read(int anno, const char* num)
{
TRectype partita(LF_PARTITE); partita.zero();
partita.put(PART_ANNO, anno); partita.put(PART_NUMPART, num);
_part.read(partita);
TRectype scadenza(LF_SCADENZE); scadenza.zero();
scadenza.put(SCAD_ANNO, anno); scadenza.put(SCAD_NUMPART, num);
_scad.read(scadenza);
_totale.set('D', ZERO); // Azzera totale partita
for (int i = 1; i <= righe(); i++)
{
const TRectype& r = riga(i);
const char sez = r.get_char(PART_SEZ);
const real val = r.get_real(PART_IMPORTO);
const TImporto imp(sez, val);
_totale += imp;
}
return ok();
}
bool TPartita::reread()
{
const int year = anno();
const TString16 num = numero();
return read(year, num);
}
bool TPartita::write(bool re)
{
const bool ok = _part.write(re) && _scad.write(re);
return ok;
}
int TPartita::ultimo_pagamento(int rata) const
{
int ultimo = 1;
for (int p = 1; p <= righe(); p++)
{
const TRectype& paga = riga(p);
if (paga.get_int(PART_NRATA) == rata)
{
int u = paga.get_int(PART_NRIGA); // Non pretende che siano in ordine
if (u > ultimo) ultimo = u;
}
}
return ultimo;
}
// Controlla se la rata r e' stata completamente pagata
bool TPartita::rata_pagata(int r) const
{
const TRectype& scad = rata(r);
real importo(scad.get(SCAD_IMPORTO));
importo -= scad.get_real(SCAD_IMPORTOPAG);
const bool pagata = importo.is_zero();
return pagata;
}
TImporto TPartita::importo_speso(long nreg, int numrig) const
{
TImporto imp;
for (int r = righe(); 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));
}
}
return imp;
}
void TPartita::update_reg_num(long nreg, const TRectype& mov)
{
for (int r = righe(); 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(int anno, const char* num)
{
_key.format("%4d%s", anno, num);
return _key;
}
// Certified 99%
TPartita* TPartite_array::find(int anno, const char* num, bool create)
{
const TString& k = key(anno, num);
TPartita* p = (TPartita*)objptr(k);
if (p == NULL && create)
{
p = new TPartita(anno, num);
if (p->ok())
add(k, p);
else
{
delete p;
p = NULL;
}
}
return p;
}
TPartita* TPartite_array::find(const TRectype& r, bool create)
{
const int anno = r.get_int(PART_ANNO);
const char* num = r.get_str(PART_NUMPART);
return find(anno, num, create);
}
TPartita& TPartite_array::partita(int anno, const char* num)
{
TPartita* game = find(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, "", 3, &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);
}