campo-sirio/cg/saldacon.cpp
guy dc6ee6cd72 Gestione saldconto in valuta
git-svn-id: svn://10.65.10.50/trunk@1798 c028cbd2-c16b-5b4b-a496-9718f37d4682
1995-09-08 10:57:44 +00:00

989 lines
25 KiB
C++
Executable File

#include <mask.h>
#include "saldacon.h"
#include <mov.h>
#include <scadenze.h>
#include <pagsca.h>
///////////////////////////////////////////////////////////
// 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();
const KeyDes& kd = recd->Ky[numkey];
for (int i = recd->Ky[numkey].NkFields-1; i >= 0; i--)
{
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;
}
///////////////////////////////////////////////////////////
// Valuta
///////////////////////////////////////////////////////////
TValuta::TValuta(const char* cod, const TDate& dat, const real& cam)
: _cod(cod), _dat(dat), _cam(cam)
{
adjust();
}
TValuta::TValuta() : _cod(""), _dat(TODAY), _cam(1.0)
{}
void TValuta::adjust()
{
_cod.upper();
if (_cod.empty() || _cod == "LIT")
_cam = 1.0;
}
void TValuta::get(const TRectype& rec)
{
_cod = rec.get("CODVAL");
_dat = rec.get("DATACAM");
_cam = rec.get_real("CAMBIO");
adjust();
}
void TValuta::put(TRectype& rec) const
{
rec.put("CODVAL", _cod);
rec.put("DATACAM", _dat);
rec.put("CAMBIO", _cam);
}
void TValuta::set(TMask& m, short v, short d, short c) const
{
m.set(v, _cod);
m.set(d, _dat.string());
m.set(c, _cam.string(2));
}
void TValuta::get(const TMask& m, short v, short d, short c)
{
_cod = m.get(v);
_dat = m.get(d);
_cam = real(m.get(c));
adjust();
}
real TValuta::lit2val(const real& lit) const
{
real val(lit);
val /= _cam;
val.round(2);
return val;
}
real TValuta::val2lit(const real& val) const
{
real lit(val);
lit *= _cam;
lit.round();
return lit;
}
void TValuta::val2lit(real& val) const
{
val *= _cam;
val.round();
}
void TValuta::val2lit(TImporto& imp) const
{
val2lit(imp.valore());
}
///////////////////////////////////////////////////////////
// TRiga_scadenze
///////////////////////////////////////////////////////////
TRiga_scadenze::TRiga_scadenze(TRiga_partite* r)
: TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP"), _riga(r)
{
CHECK(_riga, "Riga nulla");
}
TRiga_scadenze::TRiga_scadenze(const TRiga_scadenze& s)
: TTree_rectype(s), _riga(s._riga)
{
CHECK(_riga, "Riga nulla");
}
TPartita& TRiga_scadenze::partita() const
{
return riga().partita();
}
// Controlla se la fattura della rata e' in valuta
bool TRiga_scadenze::in_valuta() const
{
return riga().in_valuta();
}
// Controlla se la rata e' stata completamente pagata
bool TRiga_scadenze::chiusa() const
{
TImporto imp(importo_da_pagare(TRUE));
imp += importo_pagato(TRUE, 0x3);
return imp.is_zero();
}
// Calcola il totale dei pagamenti (eventualmente in valuta)
TImporto TRiga_scadenze::importo_pagato(bool val, int mode) const
{
CHECKD(mode > 0 && mode < 8, "Bad importo_pagato mode ", mode);
const TPartita& game = partita();
const bool in_val = in_valuta();
const char* imp_field = (val && in_val) ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
TImporto totale;
for (int p = last(); p > 0; p = pred(p))
{
const TRectype& pag = row(p); // Riga pagamento
const TRiga_partite& sum = game.riga(p); // Riga partite
const char sez = sum.sezione();
if (mode & 0x1)
totale += TImporto(sez, pag.get_real(imp_field));
if (mode & 0x2) // Voglio anche gli abbuoni
{
real abb(pag.get_real(PAGSCA_ABBUONI));
if (!val && in_val)
{
abb *= sum.get_real(PART_CAMBIO);
abb.round();
}
totale += TImporto(sez, abb);
}
if (!val && (mode & 0x4)) // Voglio anche le differenze cambi
{
const TImporto diffcam(sez, pag.get_real(PAGSCA_DIFFCAM));
totale += diffcam;
}
}
return totale;
}
// Calcola l'importo da pagare (eventualmente in valuta)
TImporto TRiga_scadenze::importo_da_pagare(bool val) const
{
const char* imp_field = (val && in_valuta()) ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
const TRiga_partite& r = riga(); // Riga fattura
const TImporto totale(r.sezione(), get_real(imp_field));
return totale;
}
// Calcola l'abbuono in valuta della rata e ritorna il suo tipo:
// 'A' abbuono attivo; 'P' abbuono passivo
// La sezione dell'abbuono calcolato e' quella della riga contabile in cui finira'
char TRiga_scadenze::calcola_abbuono(int p, TImporto& abbuono) const
{
bool ap = ' ';
const TRectype& pag = row(p);
if (pag.get_char(PAGSCA_ACCSAL) == 'S')
{
abbuono = importo_da_pagare(TRUE);
abbuono += importo_pagato(TRUE);
for (int r = last(); r > 0; r = pred(r)) if (r != p)
{
const TRiga_partite& sum = partita().riga(r); // Riga partite
const TImporto imp(sum.sezione(), row(r).get_real(PAGSCA_ABBUONI));
abbuono += imp;
}
const int sign = abbuono.valore().sign();
if (sign != 0)
{
if (sign > 0)
ap = abbuono.sezione() == 'D' ? 'P' : 'A';
else
ap = abbuono.sezione() == 'D' ? 'A' : 'P';
}
}
else
abbuono.valore() = ZERO;
return ap;
}
// Calcola la differenza cambi con la sezione da mettere nella riga contabile corrispondente
TImporto TRiga_scadenze::calcola_differenza_cambio(int p, bool update)
{
TImporto diffcam;
if (in_valuta())
{
TRectype& pag = row(p);
const char sez = partita().riga(p).sezione();
if (update)
{
diffcam = importo_da_pagare(FALSE);
diffcam += importo_pagato(FALSE, 0x3); // Conta anche gli abbuoni
diffcam.normalize(sez);
pag.put(PAGSCA_DIFFCAM, diffcam.valore());
}
else
{
diffcam.set(sez, pag.get_real(PAGSCA_DIFFCAM));
}
}
else
{
if (update)
row(p).zero(PAGSCA_DIFFCAM);
}
return diffcam;
}
TImporto TRiga_scadenze::residuo(bool val, int mode) const
{
TImporto residuo(importo_da_pagare(val));
residuo += importo_pagato(val, mode); // Somma con sezione opposta
return residuo;
}
bool TRiga_scadenze::modifica_pagamento(const TRectype& new_pag,
char& old_ap, TImporto& old_abb, TImporto& old_diffcam,
char& new_ap, TImporto& new_abb, TImporto& new_diffcam)
{
const int nrigp = new_pag.get_int(PAGSCA_NRIGP);
const TRectype old_pag(row(nrigp));
TRiga_partite& sum = partita().riga(nrigp);
TImporto old_abbuono;
old_ap = calcola_abbuono(nrigp, old_abbuono); // Vecchio abbuono in valuta
old_abb = old_abbuono; // Vecchio abbuono in lire
if (in_valuta())
{
old_abb.valore() *= sum.get_real(PART_CAMBIO);
old_abb.valore().round();
}
old_diffcam = calcola_differenza_cambio(nrigp, FALSE);
row(nrigp) = new_pag;
row(nrigp).zero(PAGSCA_ABBUONI); // Azzera abbuoni per ricalcolo
row(nrigp).zero(PAGSCA_DIFFCAM); // Azzera differenza cambio per ricalcolo
TImporto new_abbuono;
new_ap = calcola_abbuono(nrigp, new_abbuono); // Calcolo abbuono in valuta
new_abb = new_abbuono; // Calcola nuovo abbuono in lire
if (in_valuta())
{
new_abb.valore() *= sum.get_real(PART_CAMBIO);
new_abb.valore().round();
}
// Scambia sezione per registrazione contabile
old_abbuono.swap_section();
new_abbuono.swap_section();
new_abbuono.normalize(sum.sezione());
if (new_ap != ' ')
row(nrigp).put(PAGSCA_ABBUONI, new_abbuono.valore());
else
row(nrigp).zero(PAGSCA_ABBUONI);
sum.update(old_abbuono, new_abbuono, PART_SEZABB, PART_ABBUONI);
new_diffcam = calcola_differenza_cambio(nrigp, TRUE);
// Memorizza differenza cambi invertita, mettendo new_diffcam prima di old_diffcam!
sum.update(new_diffcam, old_diffcam, PART_SEZDIFCAM, PART_DIFFCAM);
sum.update(old_pag, new_pag, PART_IMPORTO);
sum.update(old_pag, new_pag, PART_IMPORTOVAL);
sum.update(old_pag, new_pag, PART_RITENUTE);
partita().chiusa(TRUE); // Aggiorna flag di chiusura
const bool empty = new_pag.get(PAGSCA_IMPORTO).empty() ||
new_pag.get(PAGSCA_ABBUONI).empty() ||
new_pag.get(PAGSCA_DIFFCAM).empty();
if (empty)
rows_array().destroy_row(nrigp);
return empty;
}
bool TPartita::modifica_pagamento(const TRectype& new_pag)
{
char old_ap, new_ap;
TImporto old_abbuono, new_abbuono, old_diffcam, new_diffcam;
return modifica_pagamento(new_pag,
old_ap, old_abbuono, old_diffcam,
new_ap, new_abbuono, new_diffcam);
}
///////////////////////////////////////////////////////////
// TRiga_partite
///////////////////////////////////////////////////////////
TRiga_partite::TRiga_partite(TPartita* game)
: TTree_rectype(LF_PARTITE, LF_SCADENZE, SCAD_NRATA), _partita(game)
{
CHECK(_partita, "Partita nulla");
}
TRiga_partite::TRiga_partite(const TRiga_partite& r)
: TTree_rectype(r), _partita(r._partita)
{
CHECK(_partita, "Partita nulla");
}
TRiga_scadenze& TRiga_partite::new_row(int r)
{
if (r <= 0) r = last()+1;
if (_recarr.rows() == 0)
{
TRiga_scadenze* scad = new TRiga_scadenze(this);
copy_key_to_row(*scad);
_recarr.set_key(scad); // Altrimenti le righe sarebbero dei TRectype!
}
return (TRiga_scadenze&)_recarr.row(r, TRUE);
}
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(this);
copy_key_to_row(*s);
err = _recarr.read(s); // Deve esistere almento una scadenza
}
else
_recarr.destroy_rows();
return err;
}
int TRiga_partite::ultimo_pagamento(int r) const
{
const TRiga_scadenze& s = rata(r);
return s.last();
}
bool TRiga_partite::update(const TRectype& vec, const TRectype& nuo, const char* field)
{
real totale(get(field));
totale -= vec.get_real(field);
totale += nuo.get_real(field);
put(field, totale);
return totale.is_zero();
}
bool TRiga_partite::update(const TImporto& vec, const TImporto& nuo,
const char* sez, const char* val)
{
bool zero = FALSE;
TImporto growth(nuo); growth -= vec; // Variazione al totale
if (!growth.is_zero())
{
TImporto totale(get_char(sez), get_real(val));
totale += growth; // incrementa il totale
totale.normalize();
put(sez, totale.sezione()); // Aggiorna il totale sul record
put(val, totale.valore());
zero = totale.is_zero();
}
else
zero = get_real(val).is_zero();
return zero;
}
///////////////////////////////////////////////////////////
// TPartita
///////////////////////////////////////////////////////////
TPartita::TPartita(const TBill& clifo, int anno, const char* num)
: _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP")
{
read(clifo, anno, num);
}
TPartita::TPartita()
: _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP")
{}
// Costruisce le righe della partita
bool TPartita::read(const TBill& clifo, int anno, const char* num)
{
TRiga_partite* partita = new TRiga_partite(this); // 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, (int)UNASSIGNED);
unas.put(SCAD_NRATA, (int)UNASSIGNED);
_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
{
int err = _part.write(re);
if (err == NOERR)
err = _unassigned.write(re);
return err == NOERR;
}
bool TPartita::remove()
{
_part.destroy_rows();
_unassigned.destroy_rows();
return rewrite();
}
// Crea un nuova riga partite e gli copia la chiave principale e il conto cliente/fornitore
TRiga_partite& TPartita::nuova_riga()
{
TRiga_partite& nuova = (TRiga_partite&)_part.row(last()+1, TRUE);
const TRiga_partite& prima = riga(first());
nuova.put(PART_GRUPPOCL, prima.get(PART_GRUPPOCL));
nuova.put(PART_CONTOCL, prima.get(PART_CONTOCL));
return nuova;
}
TRiga_scadenze& TPartita::rata(int nriga, int nrata) const
{
if (nriga <= 0) nriga = prima_fattura();
const TRiga_partite& r = riga(nriga);
return r.rata(nrata);
}
bool TPartita::rata_chiusa(int nriga, int nrata) const
{
bool pag = FALSE;
if (nriga != UNASSIGNED)
{
const TRiga_scadenze& r = rata(nriga, nrata);
pag = r.chiusa();
}
return pag;
}
TRectype& TPartita::pagamento(int nriga, int nrata, int nrigp)
{
if (nriga == UNASSIGNED)
return _unassigned.row(nrigp, TRUE);
TRiga_scadenze& r = rata(nriga, nrata);
return r.row(nrigp);
}
bool TPartita::esiste(int nriga, int nrata, int nrigp) const
{
if (nriga == UNASSIGNED)
return _unassigned.exist(nrigp);
if (nrata <= 0)
return _part.exist(nriga);
if (nrigp <= 0)
{
const TRiga_partite& r = riga(nriga);
return r.rows_array().exist(nrata);
}
const TRiga_scadenze& r = rata(nriga, nrata);
return r.rows_array().exist(nrigp);
}
// Ritorna l'importo in lire speso su di una riga contabile
TImporto TPartita::importo_speso(long nreg, int numrig, bool extra) const
{
TImporto imp;
for (int r = last(); r > 0; r = pred(r))
{
const TRiga_partite& part = riga(r);
const long reg = part.get_long(PART_NREG);
if (reg == nreg)
{
const int num = part.get_int(PART_NUMRIG);
if (num == numrig)
{
imp += TImporto(part.sezione(), part.get_real(PART_IMPORTO));
if (extra)
{
TImporto abbuoni(part.get_char(PART_SEZABB), part.get_real(PART_ABBUONI));
if (part.in_valuta())
{
abbuoni.valore() *= part.get_real(PART_CAMBIO);
abbuoni.valore().round();
}
imp += abbuoni;
imp += TImporto(part.get_char(PART_SEZDIFCAM), part.get_real(PART_DIFFCAM));
}
}
}
}
return imp;
}
void TPartita::update_reg(long nreg, const TRectype& mov)
{
for (int r = last(); r > 0; r = pred(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_DATADOC, mov.get(MOV_DATADOC));
pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC));
pag.put(PART_REG, mov.get(MOV_REG));
pag.put(PART_PROTIVA, mov.get(MOV_PROTIVA));
pag.put(PART_CODCAUS, mov.get(MOV_CODCAUS));
}
}
}
// Calcola la riga di movimento relativa a una riga partita
int TPartita::rig2mov(int rp) const
{
const TRiga_partite& r = riga(rp);
return r.get_int(PART_NUMRIG);
}
// Calcola la riga di partita relativa a una riga movimento
int TPartita::mov2rig(long numreg, int rm) const
{
for (int r = last(); r > 0; r = pred(r))
{
const TRiga_partite& row = riga(r);
if (row.get_long(PART_NREG) == numreg)
{
if (rm <= 0 || row.get_int(PART_NUMRIG) == rm)
return r;
}
}
return -1;
}
// Trova la prima riga della partita contenente una fattura
int TPartita::prima_fattura(long nreg) const
{
const int lastrow = last();
for (int r = first(); r <= lastrow; r = succ(r))
{
const TRiga_partite& row = riga(r);
const int tipomov = row.get_int(PART_TIPOMOV);
if (tipomov == 1 || tipomov == 2)
if (nreg == -1 || nreg == row.get_long(PART_NREG))
return r;
}
return -1;
}
// Trova la prima riga della partita contenente una fattura
int TPartita::primo_pagamento(long nreg) const
{
const int lastrow = last();
for (int r = first(); r <= lastrow; r = succ(r))
{
const TRiga_partite& row = riga(r);
const int tipomov = row.get_int(PART_TIPOMOV);
if (tipomov == 3) // TBI controllare per insoluti (tipomov == 6)
if (nreg == -1 || nreg == row.get_long(PART_NREG))
return r;
}
return -1;
}
void TPartita::calcola_saldo(TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp) const
{
doc = pag = imp = TImporto('D', ZERO);
for (int r = last(); r > 0; r = pred(r))
{
const TRiga_partite& row = riga(r);
TImporto i(row.get_char(PART_SEZ), row.get_real(PART_IMPORTO));
switch (row.get_int(PART_TIPOMOV))
{
case 1:
case 2:
doc += i; // documenti
break;
case 3:
pag += i; // pagamenti
break;
default:
imp += i; // altri importi
break;
}
TImporto abbuoni(row.get_char(PART_SEZABB), row.get_real(PART_ABBUONI));
if (row.get(PART_CODVAL).not_empty())
{
abbuoni.valore() *= row.get_real(PART_CAMBIO);
abbuoni.valore().round();
}
imp += abbuoni;
imp += TImporto(row.get_char(PART_SEZDIFCAM), row.get_real(PART_DIFFCAM));
}
saldo = doc;
saldo += pag;
saldo += imp;
}
bool TPartita::utilizzata(int nrigp) const
{
for (int p = last(); p > 0; p = pred(p))
{
const TRiga_partite& fatt = riga(p);
const int tipomov = fatt.get_int(PART_TIPOMOV);
if (tipomov == 1)
{
for (int r = fatt.rate(); r > 0; r--)
{
const TRiga_scadenze& scad = fatt.rata(r);
if (scad.rows_array().exist(nrigp))
return TRUE;
}
}
}
return _unassigned.exist(nrigp);
}
bool TPartita::modifica_pagamento(const TRectype& new_pag,
char& old_ap, TImporto& old_abb, TImporto& old_diffcam,
char& new_ap, TImporto& new_abb, TImporto& new_diffcam)
{
const int nriga = new_pag.get_int(PAGSCA_NRIGA);
const int nrata = new_pag.get_int(PAGSCA_NRATA);
const int nrigp = new_pag.get_int(PAGSCA_NRIGP);
bool empty = FALSE;
if (nriga != UNASSIGNED)
{
TRiga_scadenze& scaden = rata(nriga, nrata);
empty = scaden.modifica_pagamento(new_pag,
old_ap, old_abb, old_diffcam,
new_ap, new_abb, new_diffcam);
}
else
{
const TRectype& old_pag = pagamento(nriga, nrata, nrigp);
TRiga_partite& sum = riga(nrigp);
empty = sum.update(old_pag, new_pag, PART_IMPORTO);
sum.update(old_pag, new_pag, PART_IMPORTOVAL);
sum.update(old_pag, new_pag, PART_RITENUTE);
if (new_pag.get_real(PAGSCA_IMPORTO).is_zero())
_unassigned.destroy_row(nrigp);
else
_unassigned.row(nrigp, FALSE) = new_pag;
old_ap = new_ap = ' '; // Non ci possono essere abbuoni di sorta!
}
if (empty && !utilizzata(nrigp))
_part.destroy_row(nrigp);
return empty;
}
bool TPartita::chiusa(bool update)
{
bool chiusa = FALSE;
if (update)
{
bool forse_chiusa = TRUE;
for (int p = last(); p > 0 && forse_chiusa; p = pred(p))
{
const TRiga_partite& part = riga(p);
if (part.get_int(PART_TIPOMOV) == 1)
{
for (int r = part.last(); r > 0; r--)
{
const TRiga_scadenze& scad = part.rata(r);
if (!scad.chiusa())
{
forse_chiusa = FALSE;
break;
}
}
}
}
if (chiusa != forse_chiusa)
{
chiusa = forse_chiusa;
for (p = last(); p > 0; p = pred(p))
{
TRiga_partite& part = riga(p);
part.put(PART_CHIUSA, chiusa);
}
}
}
else
{
const int ultima = last();
if (ultima > 0)
{
const TRiga_partite& row = riga(ultima);
chiusa = row.get_bool(PART_CHIUSA);
}
}
return chiusa;
}
///////////////////////////////////////////////////////////
// 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);
add(k, p);
}
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);
CHECK(game, "Partita errata");
return *game;
}
TPartita& TPartite_array::partita(const TRectype& r)
{
TPartita* game = find(r, TRUE);
CHECK(game, "Partita errata");
return *game;
}
bool TPartite_array::destroy(const TBill& clifo, int anno, const char* num)
{
const TString& k = key(clifo, anno, num);
return remove(k);
}
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;
}
void TPartite_array::destroy()
{
TAssoc_array::destroy();
_numreg = 0;
}
// Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg
int TPartite_array::add_numreg(long nreg)
{
if (nreg != _numreg)
{
TRelation rel(LF_PARTITE);
TRectype& part = rel.lfile().curr();
// Costruzione filtro del cursore
part.zero();
part.put(PART_NREG, nreg);
const TRectype filter(part);
TCursor cur(&rel, "", 2, &filter, &filter);
for (cur = 0; cur.ok(); ++cur)
partita(part); // Aggiungi partita se non esiste gia'
_numreg = nreg;
}
return items();
}
TImporto TPartite_array::importo_speso(long nreg, int numrig, bool extra)
{
TImporto imp;
add_numreg(nreg);
for (TPartita* game = first(); game; game = next())
imp += game->importo_speso(nreg, numrig, extra);
return imp;
}
void TPartite_array::update_reg(const TRectype& mov, long old_nreg)
{
if (old_nreg <= 0)
old_nreg = mov.get_long(MOV_NUMREG);
add_numreg(old_nreg);
for (TPartita* game = first(); game; game = next())
game->update_reg(old_nreg, mov);
}