campo-sirio/cg/pagament.cpp
guy ceb86a9c6b cg0500.cpp Corretta lettura anno iva da config
cg2100.cpp     Rifatta gestione pagamento immediato
cg2102.cpp     COrretto handler della data di registrazione
cg2104.cpp     Corretta gestione numero di riferimento partita
cg2105.cpp     Proposto in automatico l'importo dei pagamenti
cg2200.cpp     Azzerata ad ogni ciclo la maschera dei provisori
cg3100.cpp     Eliminati tutti gli accessi diretti alla tabella esercizi
cg3600.cpp     Aggiunta gestione e salvataggio colonne
cglib04.cpp    Tolti accessi diretti alla tabella degli esercizi
pagament.cpp   Corretta creazione nuove rate rispettando le classificazioni


git-svn-id: svn://10.65.10.50/trunk@3985 c028cbd2-c16b-5b4b-a496-9718f37d4682
1996-12-10 08:23:20 +00:00

1890 lines
53 KiB
C++
Executable File

#include <applicat.h>
#include <utility.h>
#include "pagament.h"
#include "cg2100.h"
#include <mov.h>
#include <partite.h>
#include <scadenze.h>
#include <pagsca.h>
// se settato, si usa per rate nuove l'intervallo rate default (letto da tab. pagamenti)
#define USE_DEFAULT_INT_RATE 1
inline void swap(int& x, int& y) {int tmp = x; x = y; y = tmp; }
int TPagamento::_rata_ifield(int n, int f) const
{
TToken_string& t = (TToken_string&)_rate[n];
return t.get_int(f);
}
long TPagamento::_rata_lfield(int n, int f) const
{
TToken_string& t = (TToken_string&)_rate[n];
return t.get_long(f);
}
real TPagamento::_rata_rfield(int n, int f) const
{
TToken_string& t = (TToken_string&)_rate[n];
return real(t.get(f));
}
TDate TPagamento::_rata_dfield(int n, int f) const
{
TToken_string& t = (TToken_string&)_rate[n];
return TDate(t.get(f));
}
const char* TPagamento::_rata_sfield(int n, int f) const
{
static char kak[16];
TToken_string& t = (TToken_string&)_rate[n];
const char* k = t.get(f);
if (k != NULL)
strncpy(kak, k, 16);
else
kak[0] = '\0';
return kak;
}
void TPagamento::set_inizio(const TDate& d, bool rispetta_date)
{
_datadoc = d;
_inizio = d;
_inited = TRUE;
// aggiusta _inizio secondo INSCAD; vedi mese commerciale etc.
if (_inscad == 'M')
_inizio.set_end_month();
else
{
if (_inscad == 'F' && _mcomm && _inizio.day() == 31)
_inizio.set_day(30);
}
TDate data(rispetta_date ? data_rata(0) : _inizio); // Aggiusta data iniziale con i gironi prima rata
if (!rispetta_date)
next_scad(data, scad_rata(0), _mcomm, 0);
bool dummy;
recalc_rate(0, FALSE, NULL, NULL, data.string(), NULL, NULL, _rdiff, _mcomm, dummy);
}
void TPagamento::set_intervallo_rate(int in)
{
if (_mcomm && (in % 30) != 0)
{
if (yesno_box("E' specificato \"mese commerciale\". Si desidera annullarlo?"))
_mcomm = FALSE;
else
return;
}
for (int i = 1; i < n_rate(); i++)
{
TToken_string& ts = rata(i);
ts.add(in, 0);
}
_int_rate = in;
_dirty = TRUE;
}
void TPagamento::set_mese_commerciale(bool v, int& sscad)
{
_dirty = FALSE;
if (_mcomm == v) return;
if (sscad < 0) sscad = 30;
if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1);
set_intervallo_rate(sscad);
_mcomm = v;
}
void TPagamento::set_rate_differenziate(int v)
{
_dirty = FALSE;
if (_rdiff ^ v == 2) return;
if (v == 2 && (100 % n_rate()) == 0)
{
int p = 100 / n_rate();
for (int i = _tpr < 4 ? 0 : 1; i < n_rate(); i++)
{
TToken_string& tt = rata(i);
tt.add(p,1);
}
}
_rdiff = (v != 2);
_dirty = TRUE;
}
void TPagamento::set_tipo_prima_rata(int v, int sscad)
{
_dirty = FALSE;
if (_tpr == v) return;
if (!_inited)
{
if (v < 4 && _tpr > 3)
{
for (int i = n_rate() - 1; i > 0; i--)
{
TToken_string& tt = rata(i);
tt.add(scad_rata(i-1),0);
tt.add(tipo_rata(i-1),2);
tt.add(ulc_rata(i-1),5);
}
_rate.destroy(0, TRUE);
}
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);
}
if (n_rate() == 2 && scad_rata(1) == 0)
{
// l'unica rata aveva scadenza 0; ci mettiamo n.giorni default
TToken_string& tt = rata(1);
tt.add(_int_rate, 0);
}
}
}
else
{
if ((_tpr > 3 && (v > 0 && v < 3)) || (v > 3 && (_tpr > 0 && _tpr < 3)))
{
// swap _firstr and _secndr
real tmp(_firstr);
_firstr = _secndr;
_secndr = tmp;
tmp = _firstl;
_firstl = _secndl;
_secndl = tmp;
}
}
_tpr = v;
_dirty = TRUE;
}
void TPagamento::set_numero_rate(int n, int sscad, int rdiff)
{
if (n <= 0) return;
_dirty = FALSE;
const int nr = n_rate();
const int first = _tpr < 4 ? 0 : 1;
real sum = 0.0;
int i = 0;
bool inv = in_valuta();
// diciamo che gli diciamo il numero giusto
if (first == 1 && n < 2) return;
int nact = first == 1 ? n - 1 : n;
real p = real(100) / real(nact);
p.round(2);
if (_inited || (!_inited && rdiff == 1)) // se e' inited rdiff e' 2 per forza
{
real tot = _inited ? importo_da_dividere(FALSE) : real(100.0);
real oot;
if (inv)
oot = importo_da_dividere(TRUE);
if (nact == 1)
{
if (_inited)
{
set_imprata(first, tot, FALSE);
if (inv) set_imprata(first, oot, TRUE);
}
set_percrata(first, real(100.0));
if (_inited && _tpr > 0 && _tpr < 4)
{
set_imprata(first, importo_rata(first,FALSE) + importo_da_non_dividere(FALSE), FALSE);
if (inv)
set_imprata(first, importo_rata(first,TRUE) + importo_da_non_dividere(TRUE), TRUE);
}
i = first + 1; // per rimozione successiva
}
else
{
if (nr == first + 1)
{
// suddividi equamente e riaggiusta la percentuale di conseguenza
real div = tot / real(nact);
real oiv;
if (inv)
oiv = oot/real(nact);
if (_inited)
{
div.round(_roundlit);
if (inv) oiv.round(_roundval);
}
real perc = (100.0 * div) / tot;
real rem(tot);
real oem(oot);
real p(perc);
p.round(2);
for (i = first; i < n; i++)
{
if (i > first)
{
int scd = sscad == -1 ? scad_rata(first) : sscad;
#ifdef USE_DEFAULT_INT_RATE
if (scd == 0)
scd = _int_rate;
#endif
add_rata(perc, scd, tipo_rata(0), ulc_rata(0));
}
if (_inited)
{
set_imprata (i, div, FALSE);
rem -= importo_rata(i,FALSE);
if (inv)
{
set_imprata (i, oiv, TRUE);
oem -= importo_rata(i,TRUE);
}
}
else
rem -= p;
set_percrata(i, perc);
}
if (_inited && _tpr > 0 && _tpr < 4)
{
set_imprata(0, importo_rata(0,FALSE) + importo_da_non_dividere(FALSE), FALSE);
if (inv)
set_imprata(0, importo_rata(0,TRUE) + importo_da_non_dividere(TRUE), TRUE);
}
if (rem != ZERO || oem != ZERO)
{
if (_inited)
{
real r(importo_rata(first,FALSE) + rem);
real or;
if (inv) or = importo_rata(first,TRUE) + oem;
set_imprata(first, r, FALSE);
if (inv) set_imprata(first, or, TRUE);
if (_inited && _tpr > 0 && _tpr < 4)
{
r -= importo_da_non_dividere(FALSE);
if (inv) or -= importo_da_non_dividere(TRUE);
}
set_percrata(first, 100 * r / tot);
}
else
{
const real r(perc_rata(first) + rem);
set_percrata(first, r);
}
}
}
else if (nr > first + 1)
{
// dalla prima nota e' abilitato solo se rdiff == 2
// e' selezionato UGUALI: devo: lasciare la prima
// rata com'e' (a meno che non ce ne sia una sola) e
// suddividere il resto dell'importo tra le altre
real rfirst = _inited ? importo_rata(0,FALSE) : perc_rata(0);
real ofirst;
if (inv)
ofirst = importo_rata(0,TRUE);
if (_inited && _tpr > 0 && _tpr < 4)
{
rfirst -= importo_da_non_dividere(FALSE);
if (inv)
ofirst -= importo_da_non_dividere(TRUE);
}
real rest = tot - (_tpr >= 4 ? ZERO : rfirst);
real oest;
if (inv)
oest = oot - (_tpr >= 4 ? ZERO : ofirst);
real div = rest / real(nact - (first > 0 ? 0 : 1));
real oiv;
if (inv)
oiv = oest / real(nact - (first > 0 ? 0 : 1));
if (_inited)
{
div.round(_roundlit);
if (inv)
oiv.round(_roundval);
}
real perc = (100.0 * div)/tot;
real rem(rest);
real oem(oest);
real p(perc);
p.round(2);
for (i = 1; i < n; i++)
{
if (i >= nr)
{
int scd = sscad == -1 ? scad_rata(first) : sscad;
#ifdef USE_DEFAULT_INT_RATE
if (scd == 0)
scd = _int_rate;
#endif
add_rata(perc, (sscad == -1 ? scad_rata(nr-1) : sscad),
tipo_rata(nr-1), ulc_rata(nr-1));
}
if (_inited)
{
set_imprata (i, div, FALSE);
rem -= div;
if (inv)
{
set_imprata (i, oiv, TRUE);
oem -= oiv;
}
}
else
rem -= p;
set_percrata(i, perc);
}
if (rem != ZERO)
{
if (_inited)
{
real r(importo_rata(first,FALSE) + rem);
real or;
if (inv) or = importo_rata(first,TRUE) + oem;
set_imprata(first, r, FALSE);
if (inv) set_imprata(first, or, TRUE);
if (_inited && _tpr > 0 && _tpr < 4)
r -= importo_da_non_dividere(FALSE);
set_percrata(first, 100 * r / tot);
}
else
{
const real r(perc_rata(first) + rem);
set_percrata(first, r);
}
}
}
}
}
else
{
for (i = first; sum < real(100.0); i++)
{
if ((real(100.0) - sum) < p)
p = real(100.0) - sum;
sum += p;
// if necessary add remainder on first one
if ((real(100.0) - sum) /* still */ < p)
{
real prc = perc_rata(first);
prc += real(100.0) - sum;
TToken_string& rt = rata(first);
rt.add(prc.string(),1),
sum = 100;
}
int scd = i == 0 ? (i < nr ? scad_rata(0) : 0) :
(sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad);
#ifdef USE_DEFAULT_INT_RATE
if (i != 0 && scd == 0)
scd = _int_rate;
#endif
set_rata(i, real(p), scd, (i < nr ? tipo_rata(i) : tipo_rata(nr-1)), FALSE);
}
}
// erase remaining
remove_rate_from(i);
if (_inited)
{
set_inizio(_datadoc, TRUE);
adjust_perc(rdiff, inv);
}
adjust_fixed_scad();
_dirty = TRUE;
}
void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata)
{
if (mcomm && (rata > 0 || (scad % 30) == 0))
{
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';
const bool last = inizio_scadenza() == 'M' || _datadoc.is_end_month();
int dy = d.day();
// la palla del febbraio & c. ???
if (rata > 1)
{
const 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);
*/
if (last)
d.set_end_month();
else
d.set_day(dy);
}
else
{
d += scad;
}
}
void TPagamento::set_default_type(int type, bool change_existing)
{
_def_tpr = type;
if (change_existing)
{
for (int i = 0; i < n_rate(); i++)
{
TToken_string& tt = rata(i);
tt.add(type, 2);
}
_dirty = TRUE;
}
}
void TPagamento::set_default_ulc(const char* ulc, bool change_existing)
{
_def_ulc = ulc;
if (change_existing)
{
for (int i = 0; i < n_rate(); i++)
{
TToken_string& tt = rata(i);
tt.add(ulc, 5);
}
_dirty = TRUE;
}
}
void TPagamento::remove_rata(int i)
{
// non fa nessun ricalcolo, si limita ad impacchettare se necessario
_rate.destroy(i, TRUE);
_dirty = TRUE;
}
void TPagamento::remove_rate_from(int i)
{
// elimina dall'ultima a quella indicata (compresa)
for (int j = n_rate() - 1; j >= i; j--)
_rate.destroy(j);
_dirty = TRUE;
}
TToken_string& TPagamento::add_rata()
{
// rata vuota, con -1 sulla scadenza per segnalare
TToken_string* tt = new TToken_string("-1| | | | | | | ");
_rate.add(tt);
_dirty = TRUE;
return *tt;
}
TToken_string& TPagamento::add_rata(real perc, int day, int type, const char* ulc)
{
TToken_string* tt = new TToken_string(64);
tt->add(day); // scadenza
tt->add(perc.string()); // percentuale
tt->add(type); // tipo
tt->add(""); // data
tt->add(""); // importo valuta
tt->add(ulc); // ulc
tt->add(""); // ratapagata
tt->add(""); // importo lire
_rate.add(tt);
_dirty = TRUE;
return *tt;
}
TToken_string& TPagamento::set_rata (int index, real perc, int day, int type,
bool val, const char* ulc, const char* imp, const char* data)
{
TToken_string* tt = (TToken_string*)_rate.objptr(index);
const bool nwr = (tt == NULL);
if (nwr) tt = new TToken_string(64);
tt->add(day,0); // scadenza
tt->add(perc.string(),1); // percentuale
tt->add(type,2); // tipo
tt->add(data == NULL ? "" : data, 3);
tt->add(imp == NULL ? "" : imp, val ? 4 : 7);
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, const real& r, bool v)
{
TToken_string& tt = (TToken_string&)_rate[i];
tt.add(r.string(), v ? 4 : 7);
}
void TPagamento::set_percrata(int i, real r)
{
TToken_string& tt = (TToken_string&)_rate[i];
tt.add(r.string(), 1);
}
void TPagamento::set_datarata(int i, const TDate & d)
{
TToken_string& tt = (TToken_string&)_rate[i];
tt.add((const char *) d, 3);
}
real TPagamento::recalc_percrata(int i, bool v)
{
real hm(importo_da_dividere(v));
if (i == 0 && _tpr > 3) return ZERO;
real tpay(importo_rata(i,v));
if (i == 0 && _tpr > 0 && _tpr < 4)
tpay -= importo_da_non_dividere(v);
real perc = tpay * 100.0 / hm;
perc.round(2);
set_percrata(i, perc);
return perc;
}
TToken_string& TPagamento::set_rata(int index, const real& impval, const real& implit,
const TDate& date, int type,const char* ulc, bool pagato)
{
// calcola percentuali e scadenze a partire dagli importi
TToken_string* tt = _rate.rowptr(index);
const int first = _tpr < 4 ? 0 : 1;
const bool nwr = (tt == NULL); // nuova rata
if (nwr) tt = new TToken_string(64);
const TDate oldd = index > 0 ? data_rata(index -1) : _inizio;
const long day = date - oldd;
const real toshare = importo_da_dividere(in_valuta());
real hm = in_valuta() ? impval : implit;
if (index == first && _tpr > 0 && _tpr < 4)
hm -= importo_da_non_dividere(in_valuta());
real perc = (_tpr > 3 && index == 0) ? ZERO : hm/toshare;
perc *= real(100.0);
perc.round(2);
tt->cut(0);
tt->add(day); // 0 - scadenza
tt->add(perc.string()); // 1 - percentuale
tt->add(type); // 2 - tipo
tt->add(date.string()); // 3 - data
tt->add(impval.string()); // 4 - importo
tt->add(ulc); // 5 - ulc(era?)
tt->add(pagato ? "X" : " "); // 6 - pagata
tt->add(implit.string()); // 7 - Importo in lire
if (!nwr)
{
if (index > _rate.items())
{
error_box("Rate non contigue");
delete tt;
}
}
else
{
_rate.add(tt, index);
_dirty = TRUE;
}
return *tt;
}
word TPagamento::validate() const
{
word res = 0x0000;
int warnscad = 0;
real r(0.0);
int first = _tpr < 4 ? 0 : 1;
// check percentages & prepare slicer
for (int i = first; i < n_rate(); i++)
r += perc_rata(i);
r -= real(100.0);
real delta(0.005);
delta = delta * real(n_rate());
r = abs(r);
if (r > delta)
res |= P_RSUM;
if (_inited)
{
real tot;
for (int i = 0; i < n_rate(); i++)
{
const real tpay(tlit_rata(i));
if (tpay.is_zero())
res |= P_ZEROLIT;
tot += tpay;
}
tot.round(_roundlit);
// serve per fatture in valuta, onde evitare cazzi e canguri
real tmax = importo_da_dividere(FALSE) + importo_da_non_dividere(FALSE);
tmax.round(_roundlit);
if (tot != tmax) res |= P_TOTNCLIT;
if (in_valuta())
{
tot = 0.0;
for (int i = 0; i < n_rate(); i++)
{
const real tpay(tval_rata(i));
if (tpay.is_zero())
res |= P_ZEROVAL;
tot += tpay;
}
tot.round(_roundval);
// serve per fatture in valuta, onde evitare cazzi e canguri
real tmax = importo_da_dividere(TRUE) + importo_da_non_dividere(TRUE);
tmax.round(_roundval);
if (tot != tmax) res |= P_TOTNCVAL;
}
// check errori date scadenze (se istanziate)
TDate d(data_rata(0));
if (d < _datadoc) // _inizio
res |= P_INIZIO;
for (i = 1; i < n_rate(); i++)
{
if (data_rata(i) < d)
{ res |= P_SCAD; break; }
if (data_rata(i) == d)
warnscad++;
d = data_rata(i);
}
}
if (warnscad && !yesno_box("N. %d rate cadono nello stesso giorno. Si desidera proseguire?", warnscad+1))
res |= P_SCAD;
return res;
}
void TPagamento::strerr(word err, TString& s)
{
s = "Errore:\n";
if (err & P_RSUM)
s << "- le percentuali non sommano a 100\n";
if (err & P_IMPNC)
s << "- le percentuali sono inconsistenti con gli importi\n";
if (err & P_SCAD)
s << "- le scadenze non sono consecutive\n";
if (err & P_INIZIO)
s << "- la prima rata e' antecedente alla data del documento (" << _datadoc << ")\n"; // _inizio
if (err & P_NEG)
s << "- l'importo dato e' inferiore al minimo possibile\n";
if (err & P_TROP)
s << "- l'importo dato e' superiore al massimo possibile\n";
if (err & P_TOTNCLIT)
{
const real tot = importo_da_dividere(FALSE) + importo_da_non_dividere(FALSE);
real imp;
for (int i = 0; i < n_rate(); i++)
imp += tlit_rata(i);
char pic[3] = ".0";
pic[1] += _roundlit;
s << "- la somma degli importi in lire (" << imp.string(pic);
s << ") e' diversa dal\ntotale del documento in lire(" << tot.string(pic) << ")\n";
}
if (err & P_TOTNCVAL)
{
const real tot = importo_da_dividere(TRUE) + importo_da_non_dividere(TRUE);
real imp;
for (int i = 0; i < n_rate(); i++)
imp += tval_rata(i);
char pic[3] = ".0";
pic[1] += _roundval;
s << "- la somma degli importi in valuta (" << imp.string(pic);
s << ") e' diversa dal\ntotale del documento in valuta(" << tot.string(pic) << ")\n";
}
if (err & P_MCOMM)
s << "- scadenze incompatibili con il mese commerciale\n";
if (err & P_ZEROLIT)
s << "- almeno una rata ha importo in lire uguale a zero\n";
if (err & P_ZEROVAL)
s << "- almeno una rata ha importo in valuta uguale a zero\n";
if (err & P_SCWIDE)
s << "- le scadenze sono troppo distanti\n";
if (err & P_TOOMANY)
s << "- il calcolo genera piu' di 999 rate!\n";
}
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 = "Solo imposte"; break;
case 5: o = "Solo spese"; break;
case 6: o = "Imposte + spese"; break;
default: o = ""; break;
}
return o;
}
const char* TPagamento::desc_tipo(int tipo, char ulc, bool* ok) const
{
const char* o = "";
if (ok != NULL) *ok = TRUE;
if (ulc > ' ')
{
const char key[] = { tipo+'0', toupper(ulc), '\0' };
TTable clr("%CLR");
clr.put("CODTAB", key);
const int err = clr.read();
if (err == NOERR)
o = clr.get("S0");
else if (ok != NULL)
*ok = FALSE;
}
if (*o == '\0')
{
switch (tipo)
{
case 0: o = "Altro pagamento"; break;
case 1: o = "Rimessa diretta o contanti"; break;
case 2: o = "Tratta"; break;
case 3: o = "Ricevuta Bancaria"; break;
case 4: o = "Cessione"; break;
case 5: o = "Paghero'"; break;
case 6: o = "Lettera di credito"; break;
case 7: o = "Tratta accettata"; break;
case 8: o = "Rapporti interban. diretti"; break;
case 9: o = "Bonifici"; break;
default: o = ""; if (ok != NULL) *ok = FALSE; break;
}
}
return o;
}
word TPagamento::recalc_rate(int row, bool is_perc_modified,
const char* new_value, const char* new_lire,
const char* scad, const char* typ, const char* ulc,
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 || new_lire != 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);
const int last_rata = _rate.items() - 1;
int oldtype = tipo_rata(last_rata);
TString oldulc = ulc_rata(last_rata);
int oldscad = scad_rata(last_rata);
TDate lastdate = data_rata(0);
int first = _tpr < 4 ? 0 : 1;
TString_array srate(_rate); // rate come erano
int warnscad = 0;
if (oldscad <= 0) oldscad = _int_rate;
if (oldtype <= 0) oldtype = _def_tpr;
bool exhausted = FALSE;
for (int i = 0; i < srate.items(); i++)
{
if (i == row)
{
if (typ != NULL)
{
for (int k = 0; k < srate.items(); k++)
{
// deve farlo per tutte dalla 1 in poi se rdiff == 2,
// soltanto per row diversamente
if ((rdiff == 2 && row > 0 && k > 0) || k == row)
{
TToken_string& tt = rata(k);
TToken_string& ss = (TToken_string&)srate[k];
tt.add(typ,2);
ss.add(typ,2);
tt.add(ulc,5);
ss.add(ulc,5);
need_recalc = TRUE;
// no error is possible
}
}
}
if (ulc != NULL)
{
for (int k = 0; k < srate.items(); k++)
{
// deve farlo per tutte dalla 1 in poi se rdiff == 2,
// soltanto per row diversamente
if ((rdiff == 2 && row > 0 && k > 0) || k == row)
{
TToken_string& tt = rata(k);
TToken_string& ss = (TToken_string&)srate[k];
tt.add(ulc,5);
ss.add(ulc,5);
need_recalc = TRUE;
// no error is possible
}
}
}
if (scad != NULL)
{
// if !_inited scad e' il n. giorni, se no e' la rata
if (_inited)
{
TToken_string& tt = rata(row);
TToken_string& ss = (TToken_string&)srate[row];
lastdate = scad;
int lastscad = oldscad;
// controlla errore sulla data scadenza
if (i > 0)
{
oldscad = lastscad = (int)(lastdate - data_rata(i-1));
if (oldscad < 0l) return P_SCAD;
}
else
{
if (lastdate < _datadoc)
return P_INIZIO; // _inizio
lastscad = scad_rata(0);
}
tt.add(scad,3); tt.add(lastscad, 0);
ss.add(scad,3); ss.add(lastscad, 0);
// 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& ttt = rata(j);
TToken_string& sss = (TToken_string&)srate[j];
next_scad(ddd,scad_rata(j), mcomm,j);
ttt.add(ddd.string(),3);
sss.add(ddd.string(),3);
need_recalc = TRUE;
}
}
else
{
// nulla di speciale visto che si memorizza la derivata
long sc = atol(scad);
for (int i = 0; i < row; i ++)
sc -= scad_rata(i);
if (sc < 0) return P_SCAD;
if (row > 0 && sc == 0 &&
!yesno_box("Due o piu' rate cadranno nello stesso giorno. Si conferma l'immissione?"))
return P_SCAD;
if (sc > 10000L) return P_SCWIDE;
if (_mcomm && row > 0 && (sc % 30) != 0)
return P_MCOMM;
TToken_string& tt = rata(row);
TToken_string& ss = (TToken_string&)srate[row];
tt.add(sc,0);
ss.add(sc,0);
need_recalc = TRUE;
}
}
if (new_value != NULL)
{
need_recalc = TRUE;
// questa la subappaltiamo, per evitare l'inferno
return change_value(row, real(new_value), rdiff, is_perc_modified, mcomm, TRUE);
}
if (new_lire != NULL)
{
need_recalc = TRUE;
// questa pure la subappaltiamo, sempre per evitare l'inferno
return change_value(row, real(new_lire), rdiff, is_perc_modified, mcomm, FALSE);
}
}
else // i != row modified
{
if (rdiff == 2)
continue;
if (scad != NULL)
{
// check sulle scadenze solo se si sono modificate
lastdate = data_rata(i);
if (_inited && i > 0)
{
if (data_rata(i) < data_rata(i-1))
return P_SCAD;
}
else if (_inited && lastdate < _inizio)
return P_INIZIO;
}
}
}
adjust_fixed_scad();
return P_OK;
}
word TPagamento::change_value(int rata, real user_val, int rdiff, bool is_perc,
bool mcomm, bool valuta)
{
word err = 0;
switch (rdiff)
{
case 1:
err = change_value_differenziate(rata, user_val, is_perc, valuta);
break;
case 2:
err = change_value_uguali(rata, user_val, is_perc, valuta);
break;
case 3:
err = change_value_uguali_prossima(rata, user_val, is_perc, valuta);
break;
case 4:
err = change_value_uguali_possible(rata, user_val, is_perc, valuta);
break;
}
if (!err)
{
// riaggiusta gli altri parametri se si sono create rate nuove
adjust_parameters(mcomm);
// risistema scadenze fisse se necessario
adjust_fixed_scad();
// riaggiusta le percentuali o gli importi rispetto al dato modificato
if (_inited)
{
// questa aggiusta anche l'eventuale importo in lire se si e' in valuta
// e si e' modificato l'importo in valuta
adjust_perc_imp(is_perc, rdiff, valuta);
// se era in valuta e ho modificato le percentuali aggiustalo anche in lire
if (valuta && is_perc) adjust_perc_imp(is_perc, rdiff, FALSE);
}
_dirty = TRUE;
}
return err;
}
// Sulla prima riga, se il tipo rata e > 0 il valore (importo o percentuale)
// puo' anche essere nullo, altrimenti deve essere positivo
bool TPagamento::sign_ok(const real& val, int row) const
{
const bool ok = val.sign() > (row == 0 && _tpr > 0 ? -1 : 0);
return ok;
}
// le quattro che seguono modificano le rate (solo importi o percentuali), e
// lasciano in last_old l'indice dell'ultima rata rimasta dalle vecchie che
// hanno adoperato
word TPagamento::change_value_differenziate(int row, real user_val, bool is_perc, bool v)
{
// importi totali, da non suddividere, da suddividere
real to_share = is_perc ? real(100.0) : importo_da_dividere(v);
real to_subtract = ZERO;
if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc)
to_subtract = importo_da_non_dividere(v);
real user_div = user_val - to_subtract;
const int first = _tpr > 3 ? 1 : 0;
_rdiff = TRUE;
if (!sign_ok(user_div, row))
return P_NEG;
// togli rate gia' presenti
for (int i = first; i < row; i++)
{
to_share -= (is_perc ? perc_rata(i): importo_rata(i,v));
if (i == 0 && !is_perc && _tpr > 0 && _tpr < 4)
to_share += importo_da_non_dividere(v);
}
real remainder = to_share - user_div;
if (remainder.sign() < 0) return P_TROP;
const int tok_ind = is_perc ? 1 : (v ? 4 : 7);
rata(row).add(user_val.string(), tok_ind);
if (!remainder.is_zero())
{
if (n_rate() <= row + 1) add_rata();
rata(row+1).add(remainder.string(), tok_ind);
}
// elimina rate successive
remove_rate_from(remainder.is_zero() ? row +1 : row+2);
return 0;
}
word TPagamento::change_value_uguali(int row, real user_val, bool is_perc, bool v)
{
// importi totali, da non suddividere, da suddividere
real to_share = is_perc ? real(100.0) : importo_da_dividere(v);
real to_subtract = ZERO;
if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc)
to_subtract = importo_da_non_dividere(v);
real user_div = user_val - to_subtract;
real remainder = to_share - user_div;
const int tok_ind = is_perc ? 1 : (v ? 4 : 7);
const int first = _tpr > 3 ? 1 : 0;
_rdiff = FALSE;
if (!sign_ok(user_div, row))
return P_NEG;
// la prima viene mantenuta uguale (vale solo per la 0 anche se _tpr > 4)
// se si modifica la prima, si suddivide l'importo rimanente tra tutte le
// altre e si aggiunge il residuo alla prima; il n. rate viene mantenuto
if (row == 0)
{
if (n_rate() == 1)
{
// se il numero rate e' 1 si aggiungono rate uguali a coprire l'importo
if ((to_share - user_div) < user_div) return 0;
real div = to_share / user_div;
real delta = to_share - (user_div * div.integer());
if (div > real(999.0)) return P_TOOMANY;
for (int i = 0; i < div.integer(); i++)
{
if (n_rate() <= i) add_rata();
rata(i).add(i == 0 ? user_val.string() : user_div.string(), tok_ind);
}
// add residuo
if (!delta.is_zero())
{
real tp = is_perc ? perc_rata(first) : importo_rata(first,v);
tp += delta;
rata(first).add(tp.string(), tok_ind);
}
}
else // n. rate > 1, modificata la rata 0: _tpr e' per forza < 4
{
real div = remainder / real(n_rate() - 1);
div.round(is_perc ? 2 : round(v));
real delta = remainder - (div * real(n_rate() - 1));
rata(0).add(user_val.string(), tok_ind);
if (remainder.is_zero())
{
remove_rate_from(1);
return 0;
}
// ripartisci il resto
for (int i = 1; i < n_rate(); i++)
rata(i).add(div.string(), tok_ind);
if (!delta.is_zero())
{
user_val += delta;
rata(0).add(user_val.string(), tok_ind);
}
}
}
// dalla seconda in poi, tutte le rate devono essere uguali a quella indicata
// (a meno dell'importo non suddivisibile se c'e' (to_subtract); il numero rate
// puo' cambiare. Si rispetta il valore della rata 0
// se c'e' un residuo lo metto sulla prima calcolabile (dipende da _tpr)
else
{
real first_imp;
if (_tpr < 4)
{
first_imp = is_perc ? perc_rata(0) : importo_rata(0,v);
if (_tpr > 0 && !is_perc) first_imp -= importo_da_non_dividere(v);
}
real div = (to_share - first_imp)/user_val;
if (div < real(1.0)) return P_TROP;
if (div > real(999.0)) return P_TOOMANY;
real delta = (to_share - first_imp) - user_val * real(div.integer());
for (int i = 1; i < div.integer()+1l; i++)
{
if (n_rate() <= i) add_rata();
rata(i).add(user_val.string(), tok_ind);
}
remove_rate_from(i);
if (!delta.is_zero())
{
real tp = is_perc ? perc_rata(first) : importo_rata(first,v);
tp += delta;
rata(first).add(tp.string(), tok_ind);
}
}
return 0;
}
word TPagamento::change_value_uguali_prossima(int row, real user_val, bool is_perc, bool v)
{
_rdiff = TRUE;
// uguali finche' possibile da row in poi; residuo su first
// importi totali, da non suddividere, da suddividere
real to_share = is_perc ? real(100.0) : importo_da_dividere(v);
real to_subtract = ZERO;
if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc)
to_subtract = importo_da_non_dividere(v);
real user_div = user_val - to_subtract;
const int tok_ind = is_perc ? 1 : (v ? 4 : 7);
const int first = _tpr > 3 ? 1 : 0;
if (!sign_ok(user_div, row))
return P_NEG;
// togli rate gia' presenti
for (int i = first; i < row; i++)
{
to_share -= (is_perc ? perc_rata(i): importo_rata(i,v));
if (i == 0 && !is_perc && _tpr > 0 && _tpr < 4)
to_share += importo_da_non_dividere(v);
}
real div = to_share/user_div;
if (div < real(1.0)) return P_TROP;
if (div > real(999.0)) return P_TOOMANY;
real delta = to_share - (user_div * div.integer());
for (i = row; i < (row + div.integer()); i++)
{
if (n_rate() <= i) add_rata();
rata(i).add(user_div.string(), tok_ind);
}
remove_rate_from(i);
if (!delta.is_zero())
{
real r = is_perc ? perc_rata(first) : importo_rata(first,v);
r += delta;
rata(first).add(r.string(), tok_ind);
}
return 0;
}
word TPagamento::change_value_uguali_possible(int row, real user_val, bool is_perc, bool v)
{
_rdiff = TRUE;
// uguali finche' possibile da row in poi; residuo come rata a parte
real to_share = is_perc ? real(100.0) : importo_da_dividere(v);
real to_subtract = ZERO;
if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc)
to_subtract = importo_da_non_dividere(v);
real user_div = user_val - to_subtract;
const int tok_ind = is_perc ? 1 : (v ? 4 : 7);
const int first = _tpr > 3 ? 1 : 0;
if (!sign_ok(user_div, row))
return P_NEG;
// togli rate gia' presenti
for (int i = first; i < row; i++)
{
to_share -= (is_perc ? perc_rata(i): importo_rata(i,v));
if (i == 0 && !is_perc && _tpr > 0 && _tpr < 4)
to_share += importo_da_non_dividere(v);
}
real div = to_share/user_div;
if (div < real(1.0)) return P_TROP;
if (div > real(999.0)) return P_TOOMANY;
real delta = to_share - (user_div * div.integer());
for (i = row; i < (row + div.integer()); i++)
{
if (n_rate() <= i) add_rata();
rata(i).add(user_div.string(), tok_ind);
}
if (!delta.is_zero())
{
if (n_rate() <= i) add_rata();
rata(i++).add(delta.string(), tok_ind);
}
remove_rate_from(i);
return 0;
}
void TPagamento::adjust_parameters(bool mcomm)
{
TDate last_date;
int last_type;
TString16 last_ulc;
int last_scad;
for (int i = 0; i < n_rate(); i++)
{
if (scad_rata(i) != -1)
{
last_date = data_rata(i);
last_type = tipo_rata(i);
last_ulc = ulc_rata(i);
last_scad = scad_rata(i);
}
else
{
TToken_string& r = rata(i);
#ifdef USE_DEFAULT_INT_RATE
r.add(last_scad == 0 ? _int_rate : last_scad, 0);
#else
r.add(last_scad, 0);
#endif
r.add(last_type, 2);
r.add(last_ulc, 5);
if (_inited)
{
#ifdef USE_DEFAULT_INT_RATE
next_scad(last_date, last_scad == 0 ? _int_rate : last_scad, mcomm, i);
#else
next_scad(last_date, last_scad, mcomm, i);
#endif
r.add(last_date, 3);
}
}
}
}
void TPagamento::adjust_perc(int rdiff, bool v)
{
real other = importo_da_dividere(v);
const int first = _tpr > 3 ? 1 : 0;
for (int j = first; j < _rate.items(); j++)
{
real rvl = importo_rata(j,v);
// togli pezzo di troppo
if (j == first && _tpr > 0 && _tpr < 4)
rvl -= importo_da_non_dividere(v);
real zpx = (rvl * 100.0)/other; // percentuale
zpx.round(2);
set_percrata(j, zpx);
}
if (in_valuta())
{
// riaggiusta l'importo rimanente
real tot = importo_da_dividere(!v);
TDistrib dt(tot); dt.set_dec(round(!v));
for (j = first; j < _rate.items(); j++)
{
real rvl = importo_rata(j,v);
// togli pezzo di troppo
if (j == first && _tpr > 0 && _tpr < 4)
rvl -= importo_da_non_dividere(v);
dt.add(rvl/other);
}
for (j = first; j < _rate.items(); j++)
{
real rvl = dt.get();
// aggiungi pezzo mancante
if (j == first && _tpr > 0 && _tpr < 4)
rvl += importo_da_non_dividere(!v);
set_imprata(j, rvl, !v);
}
}
}
void TPagamento::adjust_perc_imp(bool is_perc, int rdiff, bool v)
{
if (!is_perc)
{
adjust_perc(rdiff, v);
return;
}
real toshare(importo_da_dividere(v));
const real other(100.0);
bool inv = in_valuta();
TDistrib dt(toshare, round(v));
const int first = _tpr > 3 ? 1 : 0;
TDistrib ot(0.0, 0); // slicer per l'importo non modificato
if (inv)
{
ot.init(importo_da_dividere(!v));
ot.set_dec(round(v));
}
for (int j = _rate.items() - 1; j >= first ; j--)
{
real rvl = perc_rata(j);
// togli pezxo di troppo
real zpx = rvl/other; // percentuale
dt.add(zpx);
if (inv) ot.add(zpx);
}
real rem(toshare);
real oem(0.0);
if (inv) oem = importo_da_dividere(!v);
for (j = n_rate() - 1; j >= first ; j--)
{
real rfirst(0.0);
real ofirst(0.0);
TToken_string& tr = rata(j);
real rvl = dt.get();
rem -= rvl;
real ovl;
if (inv)
{
ovl = ot.get();
oem -= ovl;
}
if (j == first)
{
rfirst = rvl;
if (!rem.is_zero()) rfirst += rem;
if (inv)
{
ofirst = ovl;
if (!oem.is_zero()) ofirst += oem;
}
}
if (j == first && _tpr > 0 && _tpr < 4)
{
rfirst += importo_da_non_dividere(v);
if (inv)
ofirst += importo_da_non_dividere(!v);
}
tr.add((j == first ? rfirst.string() : rvl.string()), v ? 4 : 7);
if (inv)
tr.add((j == first ? ofirst.string() : ovl.string()), v ? 7 : 4);
}
}
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;
_rate.destroy();
// set everything
_rdiff = t->get_bool("B1");
_mcomm = t->get_bool("B0");
_tpr = t->get_int("S3");
_inscad = t->get_char("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");
_int_rate = t->get_int("I3");
#ifdef USE_DEFAULT_INT_RATE
// if (_int_rate == 0) _int_rate = 30;
#endif
// aggiusta _inizio secondo INSCAD; vedi mese commerciale etc.
if (_inscad == 'M')
_inizio.set_end_month();
else if (_inscad == 'F' && _mcomm && _inizio.day() == 31)
_inizio.set_day(30);
// leggi rate e scadenze
bool isrnew = FALSE;
if (r == NULL)
{
r = new TTable("%RPG");
isrnew = TRUE;
}
TString16 s;
for (int i = 0; ;i++)
{
r->zero(); s.format("%s%3d",(const char*)_code, i);
r->put("CODTAB", (const char*)s);
if (r->read() != NOERR)
break;
TToken_string* tt = new TToken_string(48);
tt->add((const char*)(r->get("I0"))); // scadenza
tt->add((const char*)(r->get("R0"))); // percentuale
tt->add((const char*)(r->get("I1"))); // tipo
// data e importo
TDate d = _inizio;
next_scad(d,(int)(r->get_long("I0")),_mcomm,i);
tt->add((const char*)d);
tt->add("");
tt->add(r->get("S1")); // ulteriore classificazione
_rate.add(tt);
}
if (istnew) delete t;
if (isrnew) delete r;
return TRUE;
}
int TPagamento::write(TTable& r)
{
// Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una
// relapp, che ha scritto il file principale
TString16 s;
int err = NOERR;
for (int i = 0; err == NOERR && i < n_rate(); i++)
{
r.zero(); s.format("%s%3d",(const char*)_code, i);
r.put("CODTAB", s);
r.put("I0", (long)scad_rata(i));
r.put("R0", perc_rata(i).string());
r.put("I1", (long)tipo_rata(i));
r.put("S1", ulc_rata(i));
err = r.write();
}
return err;
}
int TPagamento::rewrite(TTable& r)
{
TString16 s; int err = NOERR;
for (int i = 0; err == NOERR && i < n_rate(); i++)
{
r.zero(); s.format("%s%3d",(const char*)_code, i);
r.put("CODTAB", s);
bool was = (r.read() == NOERR);
r.zero(); s.format("%s%3d",(const char*)_code, i);
r.put("CODTAB", (const char*)s);
r.put("I0", (long)scad_rata(i));
r.put("R0", perc_rata(i).string());
r.put("I1", (long)tipo_rata(i));
r.put("S1", ulc_rata(i));
err = (was ? r.rewrite() : r.write());
}
// erase possible rate > current n. rate
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)
{
TString16 s; int err = NOERR;
for (int i = 0 ; err == NOERR; i++)
{
r.zero(); s.format("%s%3d", (const char*)_code, i);
r.put("CODTAB", 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
if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1))
return;
int first = _tpr > 3 ? 1 : 0;
main_app().begin_wait();
set_inizio(_datadoc);
for (int v = 0; v < (in_valuta() ? 2 : 1); v++)
{
real toslice = importo_da_dividere(v);
if (_tpr > 3) set_imprata(0, importo_da_non_dividere(v), v);
real r1(0.0), ro(0.0);
if (!_rdiff)
{
const int rut = _tpr > 3 ? n_rate() - 1 : n_rate();
if (rut > 1) // Guy was here! Don't kill me for this
{
real refrata = real(100.0)/real(rut); refrata.round(2);
if (perc_rata(first+1) == refrata) // tutte uguali nonostante perc arrotondate
{
ro = toslice / real(rut);
ro.round(round(v));
r1 = toslice - (ro * real(rut-1));
}
else // la prima e' diversa
{
// usa la percentuale per la prima rata
r1 = (toslice * perc_rata(first))/real(100.0);
const real reminder = toslice - r1;
if (!reminder.is_zero())
{
ro = reminder/real(rut-1); ro.round(round(v));
r1 = (toslice - (ro*real(rut-1)));
}
}
}
else
r1 = toslice;
r1.round(round(v));
}
real rdi, rdsum;
for (int i = first; i < n_rate(); i++)
// setta le fette e le date di scadenza
{
if (_rdiff)
{
rdi = toslice*(perc_rata(i)/real(100.0));
rdi.round(round(v));
if (i > first) rdsum += rdi;
}
set_imprata(i, _rdiff ? rdi : (i == first ? r1 : ro), v);
}
if (_rdiff)
set_imprata(first, toslice - rdsum, v);
// se e' nei primi tre casi, si somma l'importo da non dividere alla
// prima rata
if (_tpr > 0 && _tpr < 4)
set_imprata(0, importo_rata(0,v) + importo_da_non_dividere(v), v);
}
// risistema rate per scadenze fisse
adjust_fixed_scad();
main_app().end_wait();
}
const real& TPagamento::importo_da_dividere(bool v) const
{
if (_tpr < 4) return v ? _firstr : _firstl;
else return v ? _secndr : _secndl;
}
const real& TPagamento::importo_da_non_dividere(bool v) const
{
if (_tpr < 4) return v ? _secndr : _secndl;
else return v ? _firstr : _firstl;
}
void TPagamento::set_total(const real& ib, const real& im, const real& sp)
{
_in_valuta = FALSE;
_cambio = 1.0;
_firstr = _secndr = ZERO; // Azzera importi in valuta
init_total(ib, im, sp, FALSE); // setta regolarmente totali in lire
}
void TPagamento::set_total_valuta(const real& ib, const real& im, const real& sp, const real& c,
const real& ibl, const real& iml, const real& spl)
{
const bool era_valuta = _in_valuta;
_in_valuta = TRUE;
_cambio = c;
if (_cambio.sign() <= 0)
_cambio = real(1.0);
// setta regolarmente totali in lire
init_total(ibl, iml, spl, FALSE);
// ripeti tutto con la valuta
init_total(ib, im, sp, TRUE);
if (!era_valuta && _in_valuta)
adjust_perc_imp(TRUE, _rdiff, TRUE);
}
void TPagamento::init_total(const real& ib, const real& im, const real& sp, bool valuta)
{
const int round = valuta ? _roundval : _roundlit;
real& ibp = valuta ? _imponval : _imponlit;
real& imp = valuta ? _imposval : _imposlit;
real& spp = valuta ? _speseval : _speselit;
real& frs = valuta ? _firstr : _firstl;
real& scn = valuta ? _secndr : _secndl;
ibp = ib; ibp.round(round);
imp = im; imp.round(round);
spp = sp; spp.round(round);
_inited = TRUE;
// istanzia _firstr e _secndr a seconda di _tpr
switch(_tpr)
{
case 0:
frs = ibp + imp + spp;
scn = 0.0;
break;
case 1:
scn = imp;
frs = ibp + spp;
break;
case 2:
scn = spp;
frs = ibp + imp;
break;
case 3:
scn = imp + spp;
frs = ibp;
break;
case 4:
scn = spp + ibp;
frs = imp;
break;
case 5:
scn = ibp + imp;
frs = spp;
break;
case 6:
scn = ibp;
frs = imp + spp;
break;
}
}
void TPagamento::set_sheet(TSheet_field& sf, int sscad)
{
main_app().begin_wait();
if (_rate.items() == 0)
{
if (_tpr > 3)
add_rata(ZERO, sscad <= 0 ? 0 : sscad, _def_tpr, _def_ulc);
add_rata(real(100.0), sscad <= 0 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc);
_dirty = TRUE;
}
if (_inited)
{
// si istanzia uno sheet di primanota
for (int i = 0; i < n_rate(); i++)
{
TToken_string& ts = sf.row(i);
ts.add(data_rata(i), 0); // 0 - Data scadenza
if (in_valuta())
{
ts.add(tlit_rata(i).string(), 1); // 1 - Importo in lire
ts.add(tval_rata(i).string(), 2); // 2 - Importo in valuta
}
else
{
ts.add(tlit_rata(i).string(), 1); // 1 - Importo
ts.add("", 2);
}
ts.add(perc_rata(i).string(), 3); // 3 - Percentuale
const int tr = tipo_rata(i);
const char uc = ulc_rata(i)[0];
ts.add(tr, 4); // 4 - Tipo rata
ts.add(uc, 5); // 5 - Ulteriore classificazione
ts.add(desc_tipo(tr, uc), 6); // 6 - Descrizione tipo rata
}
for (int d = sf.items()-1; d >= i; d--)
sf.destroy(d, FALSE);
sf.enable_column(2, in_valuta());
}
else
{
long scr = 0L;
for (int i = 0; i < n_rate(); i++)
{
TToken_string& s = sf.row(i);
scr += scad_rata(i);
s = "";
s.add(scr);
s.add(perc_rata(i).string());
const int tr = tipo_rata(i);
const char uc = ulc_rata(i)[0];
s.add(tr);
s.add(uc);
s.add(desc_tipo(tr, uc));
}
for (int d = sf.items()-1; d >= i; d--)
sf.destroy(d, FALSE);
}
const bool abilita = _tpr <= 3;
// disabilita campi da non toccare sulla prima rata
if (_inited)
{
// sf.enable_cell(0, 1, abilita); // importo
// sf.enable_cell(0, 2, abilita); // in valuta
// sf.enable_cell(0, 3, abilita); // percentuale
sf.force_update();
}
else
{
sf.enable_cell(0, 1, abilita); // percentuale
}
main_app().end_wait();
}
void TPagamento::adjust_fixed_scad()
{
if (!_inited) return;
for (int i = 0; i < n_rate(); i++)
{
TDate d = data_rata(i);
// riaggiusta se ci sono scadenze fissate
if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0)
{
for (int i = 0; i < 3; i++)
{
if (_fixd[i] >= d.day())
{
if (d.last_day(d.month(), d.year()) >= _fixd[i])
d.set_day(_fixd[i]);
else
d.set_end_month();
break;
}
}
if (i == 3)
{
if (_fixd[0] > 0 && _fixd[0] < d.day())
{
d.set_day(_fixd[0]);
const bool chyear = d.month() == 12;
d.set_month(chyear ? 1 : d.month() + 1);
if (chyear) d.set_year(d.year() + 1);
}
}
}
TToken_string& tt = rata(i);
tt.add(d.string(), 3);
}
}
TPagamento::TPagamento(const char* codtab, const char* data) :
_new(FALSE), _mcomm(FALSE), _imponlit(0.0), _imposlit(0.0),
_speselit(0.0), _cambio(1.0), _in_valuta(FALSE),
_code(codtab), _dirty(FALSE), _inited(FALSE),
_def_tpr(1), _def_ulc(""), _roundval(3), _int_rate(30), _tpr(0), _rdiff(FALSE),
_was_tpr4(FALSE), _roundlit(0), _imponval(0.0), _imposval(0.0), _speseval(0.0)
{
_fixd[0] = _fixd[1] = _fixd[2] = 0;
if (data != NULL && *data)
_inizio = data;
else
_inizio = TDate(TODAY);
_datadoc = _inizio;
if (_code.blank() || !read())
_new = TRUE;
}