From f4b8fb1e127aa91314369baae32b315ed815b625 Mon Sep 17 00:00:00 2001 From: guy Date: Thu, 24 Aug 1995 07:39:29 +0000 Subject: [PATCH] Separato saldacon da pagament git-svn-id: svn://10.65.10.50/trunk@1733 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- cg/cg2102.cpp | 22 +- cg/cg2102.h | 4 + cg/cg2105.cpp | 9 +- cg/saldacon.cpp | 729 ++++++++++++++++++++++++++++++++++++++++++++++++ cg/saldacon.h | 198 +++++++++++++ 5 files changed, 949 insertions(+), 13 deletions(-) create mode 100755 cg/saldacon.cpp create mode 100755 cg/saldacon.h diff --git a/cg/cg2102.cpp b/cg/cg2102.cpp index 142bee6c1..7d04a6e45 100755 --- a/cg/cg2102.cpp +++ b/cg/cg2102.cpp @@ -131,14 +131,9 @@ bool TPrimanota_application::showpartite_handler(TMask_field& f, KEY k) if (importo != speso) { - ok = yesno_box("L'importo dei pagamenti %c %s\ne' diverso dall'importo sulla riga %d.\n" - "Si desidera correggerlo?", speso.sezione(), speso.valore().string("."), currig); - if (ok) - { - const bool dare = speso.sezione() == 'D'; - m.set(101, dare ? speso.valore().string() : ""); - m.set(102, dare ? "" : speso.valore().string()); - } + ok = yesno_box("L'importo della riga %d dovrebbe essere %c %s\n" + "Si desidera correggerlo?", currig, speso.sezione(), speso.valore().string(".")); + if (ok) app().set_cgs_imp(riga, speso); } } } @@ -301,6 +296,13 @@ void TPrimanota_application::set_cgs_imp(int n, const TImporto& imp) TSheet_field& s = cgs(); imp.add_to(s.row(n), 0); s.force_update(n); + + TMask& m = s.sheet_mask(); + if (m.is_running() && s.selected() == n) + { + m.set(101, imp.sezione() == 'D' ? imp.valore().string() : ""); + m.set(102, imp.sezione() == 'A' ? imp.valore().string() : ""); + } } // Legge l'importo della riga n e lo ritorna col segno dovuto @@ -575,8 +577,8 @@ bool TPrimanota_application::cg_handler(TMask_field& f, KEY k) const TImporto speso = app().partite().importo_speso(numreg, currig); if (importo != speso) { - bool ok = yesno_box("L'importo dei pagamenti %c %s\ne' diverso dall'importo sulla riga %d.\n" - "Si desidera correggerlo?", speso.sezione(), speso.valore().string("."), currig); + bool ok = yesno_box("L'importo della riga %d dovrebbe essere %c %s\n" + "Si desidera correggerlo?", currig, speso.sezione(), speso.valore().string(".")); if (ok) app().set_cgs_imp(i, speso); else return FALSE; } diff --git a/cg/cg2102.h b/cg/cg2102.h index 10534d9bc..1fe8e0df1 100755 --- a/cg/cg2102.h +++ b/cg/cg2102.h @@ -9,6 +9,10 @@ #include "pagament.h" #endif +#ifndef __SALDACON_H +#include "saldacon.h" +#endif + #ifndef __CGLIB_H #include "cglib.h" #endif diff --git a/cg/cg2105.cpp b/cg/cg2105.cpp index f2bf00e5b..17576253a 100755 --- a/cg/cg2105.cpp +++ b/cg/cg2105.cpp @@ -533,13 +533,14 @@ bool TPrimanota_application::notify_edit_pagamento(TPartita& p, TRectype& new_pa char old_ap, new_ap; TImporto old_abbuono, new_abbuono, old_diffcam, new_diffcam; const bool empty = p.modifica_pagamento(new_pag, - old_ap, old_abbuono, new_abbuono, + old_ap, old_abbuono, old_diffcam, new_ap, new_abbuono, new_diffcam); + const int riga_contabile = app().cgs().selected(); + // Se c'e' differenza negli abbuoni if (old_abbuono != new_abbuono || old_ap != new_ap) { - const int riga_contabile = app().cgs().selected(); if (old_ap != ' ') // Se c'era un abbuono ... { const int riga_abb = type2pos(old_ap); @@ -561,7 +562,8 @@ bool TPrimanota_application::notify_edit_pagamento(TPartita& p, TRectype& new_pa } else add_cgs_imp(riga_abb, new_abbuono); - sub_cgs_imp(riga_contabile, new_abbuono); // Aggiunge l'abbuono con la sezione invertita + + sub_cgs_imp(riga_contabile, new_abbuono); // Aggiunge l'abbuono con la sezione invertita } } @@ -581,6 +583,7 @@ bool TPrimanota_application::notify_edit_pagamento(TPartita& p, TRectype& new_pa const bool empty = add_cgs_imp(riga_diffcam, grow_diffcam); if (empty) reset_cgs_row(riga_diffcam); } + sub_cgs_imp(riga_contabile, grow_diffcam); // Aggiunge la differenza con la sezione invertita } return empty; diff --git a/cg/saldacon.cpp b/cg/saldacon.cpp new file mode 100755 index 000000000..fc6afae61 --- /dev/null +++ b/cg/saldacon.cpp @@ -0,0 +1,729 @@ +#include "saldacon.h" + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////// +// 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(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 rata e' in valuta +bool TRiga_scadenze::in_valuta() const +{ + return get(SCAD_CODVAL).not_empty(); +} + +// Controlla se la rata e' stata completamente pagata +int TRiga_scadenze::pagata() const +{ + const TRecord_array& a = rows_array(); + for (int p = a.last_row(); p > 0; p = a.pred_row(p)) + { + const TRectype& pag = a.row(p); + if (pag.get_char("ACCSAL") == 'S') + return p; + } + return 0; +} + +// Calcola il totale dei pagamenti (eventualmente in valuta) +TImporto TRiga_scadenze::importo_pagato(bool val) const +{ + const TPartita& game = partita(); + const char* imp_field = in_valuta() && val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + TImporto totale; + const TRecord_array& a = rows_array(); + for (int p = a.last_row(); p > 0; p = a.pred_row(p)) + { + const TRectype& pag = a.row(p); // Riga pagamento + const TRiga_partite& sum = game.riga(p); // Riga partite + const TImporto imp(sum.get_char(PART_SEZ), pag.get_real(imp_field)); + totale += imp; + } + + return totale; +} + +// Calcola l'importo da pagare (eventualmente in valuta) +TImporto TRiga_scadenze::importo_da_pagare(bool val) const +{ + const char* imp_field = in_valuta() && val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + const TRiga_partite& r = riga(); // Riga fattura + const TImporto totale(r.get_char(PART_SEZ), get_real(imp_field)); + return totale; +} + +// Calcola l'abbuono 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(TImporto& abbuono, bool val) const +{ + bool ap = ' '; + if (pagata()) + { + abbuono = importo_da_pagare(TRUE); + abbuono += importo_pagato(TRUE); + + 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'; + } + + if (val && in_valuta()) + { + abbuono.valore() *= get_real(SCAD_CAMBIO); + abbuono.valore().round(); + } + } + 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(bool update) +{ + TImporto diffcam; + + if (in_valuta()) + { + const int riga_saldo = pagata(); + if (riga_saldo > 0) + { + TRectype& pag = row(riga_saldo, FALSE); + const TRiga_partite& sum = partita().riga(riga_saldo); + const char sez = sum.sezione(); + + if (update) + { + diffcam = importo_da_pagare(FALSE); + diffcam += importo_pagato(FALSE); + + real a = pag.get_real(PAGSCA_ABBUONI); + if (in_valuta()) + { + a *= get_real(SCAD_CAMBIO); + a.round(); + } + + const TImporto abb_lit(sez, a); + diffcam += abb_lit; + diffcam.normalize(sez); + pag.put(PAGSCA_DIFFCAM, diffcam.valore()); + } + else + { + diffcam.set(sez, pag.get_real(PAGSCA_DIFFCAM)); + } + } + else + if (update) + { + for (int p = last(); p > 0; p = pred(p)) + { + TRectype& pag = row(p, FALSE); + pag.zero(PAGSCA_DIFFCAM); + } + } + } + + return diffcam; +} + +real TRiga_scadenze::residuo() const +{ + const char* imp_field = get(SCAD_CODVAL).not_empty() ? SCAD_IMPORTOVAL : SCAD_IMPORTO; + const real da_pagare(get(imp_field)); + const real pagato(get(SCAD_IMPORTOPAG)); + const real residuo = da_pagare - pagato; + 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); + + old_ap = calcola_abbuono(old_abb, FALSE); + old_diffcam = calcola_differenza_cambio(FALSE); + + const char* imp_field = get(SCAD_CODVAL).not_empty() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + const real importo(new_pag.get(imp_field)); + const bool empty = importo.is_zero(); + if (empty) + rows_array().destroy_row(nrigp); + else + row(nrigp, FALSE) = new_pag; + + TImporto abbuono; + new_ap = calcola_abbuono(abbuono, TRUE); // Calcolo abbuono in valuta + + TImporto imp(abbuono); imp.swap_section(); + imp.normalize(sum.sezione()); + if (new_ap != ' ') + { + CHECK(nrigp == pagata(), "Aggiornamento abbuoni inconsistente"); + TRectype& pag = row(nrigp, FALSE); + pag.put(PAGSCA_ABBUONI, imp.valore()); + + new_abb = abbuono; + if (in_valuta()) + { + new_abb.valore() *= get_real(SCAD_CAMBIO); + new_abb.valore().round(); + } + } + else + new_abb.valore() = ZERO; + + sum.update(old_abb, new_abb, PART_SEZABB, PART_ABBUONI); + + new_diffcam = calcola_differenza_cambio(TRUE); + sum.update(old_diffcam, new_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); + + return empty; +} + +/////////////////////////////////////////////////////////// +// TRiga_partite +/////////////////////////////////////////////////////////// + +TRiga_partite::TRiga_partite(TPartita* game) + : TTree_rectype(LF_PARTITE, LF_SCADENZE, "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"); +} + + +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 +#ifdef DBG + if (_recarr.rows() == 0) + yesnofatal_box("Riga di fattura senza nessuna scadenza"); +#endif + } + else + _recarr.destroy_rows(); + return err; +} + +int TRiga_partite::ultimo_pagamento(int r) const +{ + const TRiga_scadenze& s = rata(r); + return s.rows_array().last_row(); +} + +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 grow(nuo); grow -= vec; // Variazione al totale + + if (!grow.is_zero()) + { + const char sezione = get_char(sez); // Sezione del totale + TImporto totale; + if (sezione > ' ') // Se c'era una sezione (e quindi un importo) ... + totale.set(sezione, get_real(val)); // ... inizializza il totale + else + CHECKS(vec.is_zero(), "Sezione errata per l'importo ", val); + totale += grow; // 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); + +#ifdef DBG + for (int p = last(); p > 0; p = pred(p)) + CHECKD(riga(p)._partita == this, "Riga partite inconsistente", p); +#endif + + 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, 0); // Numeri magici di non assegamento + unas.put(SCAD_NRATA, 0); + _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 = pred(r)) + { + const TRectype& 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) + { + const char sez = part.get_char(PART_SEZ); // Deve essere valido per forza! + imp.set(sez, part.get_real(PART_IMPORTO)); + + const char sezabb = part.get_char(PART_SEZABB); // Puo' essere nullo + if (sezabb > ' ') + imp += TImporto(sezabb, part.get_real(PART_ABBUONI)); + + const char sezdifcam = part.get_char(PART_SEZDIFCAM); // Puo' essere nullo + if (sezdifcam > ' ') + imp += TImporto(sezdifcam, part.get_real(PART_DIFFCAM)); + break; + } + } + } + + return imp; +} + + +void TPartita::update_reg_num(long nreg, const TRectype& mov) +{ + for (int r = _part.last_row(); 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_NUMDOC, mov.get(MOV_NUMDOC)); + pag.put(PART_DATADOC, mov.get(MOV_DATADOC)); + } + } +} + +// 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 = _part.last_row(); r > 0; r = pred(r)) + { + const TRiga_partite& row = riga(r); + if (row.get_long(PART_NREG) == numreg && row.get_int(PART_NUMRIG) == rm) + return r; + } + return -1; +} + +// Trova la prima riga della partita contenente una fattura +int TPartita::prima_fattura() 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) + 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 = _part.last_row(); 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; + } + + i.set(row.get_char(PART_SEZ), row.get_real(PART_ABBUONI)); + imp += i; + + i.set(row.get_char(PART_SEZ), row.get_real(PART_DIFFCAM)); + imp += i; + } + + saldo = doc; + saldo += pag; + saldo += imp; +} + + +bool TPartita::utilizzata(int nrigp) const +{ + for (int p = _part.last_row(); 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 FALSE; +} + +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 TRiga_partite& fattura = riga(nriga); + + const int nrata = new_pag.get_int(PAGSCA_NRATA); + TRiga_scadenze& scaden = fattura.rata(nrata); + + const int nrigp = new_pag.get_int(PAGSCA_NRIGP); + const TRectype& old_pag = scaden.row(nrigp); + + const bool empty = scaden.modifica_pagamento(new_pag, + old_ap, old_abb, old_diffcam, + new_ap, new_abb, new_diffcam); + + if (empty && !utilizzata(nrigp)) + _part.destroy_row(nrigp); + + return empty; +} + +/////////////////////////////////////////////////////////// +// 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/saldacon.h b/cg/saldacon.h new file mode 100755 index 000000000..835d6c2e7 --- /dev/null +++ b/cg/saldacon.h @@ -0,0 +1,198 @@ +#ifndef __SALDACON_H +#define __SALDACON_H + +#ifndef __ASSOC_H +#include +#endif + +#ifndef __RELATION_H +#include +#endif + +#ifndef __CONTO_H +#include "conto.h" +#endif + +#ifndef __PARTITE_H +#include +#endif + +class TTree_rectype : public TRectype +{ +protected: + TRecord_array _recarr; + + void copy_key_to_row(TRectype& row) const; + int fill_array(); + +protected: // TRectype + virtual TObject* dup() const; + + virtual int read(TBaseisamfile& f, word op = _isequal); + virtual int next(TBaseisamfile& f); + virtual int write(TBaseisamfile& f) const; + virtual int rewrite(TBaseisamfile& f) const; + virtual int remove(TBaseisamfile& f); + +public: + const TRecord_array& rows_array() const { return _recarr; } + TRecord_array& rows_array() { return _recarr; } + const TRectype& row(int r) const { return ((TRecord_array&)_recarr).row(r, FALSE); } + TRectype& row(int r, bool create) { return _recarr.row(r, create); } + + int last() const { return _recarr.last_row(); } + int pred(int r) const { return _recarr.pred_row(r); } + + TTree_rectype(const TRectype& testata, const TRectype& riga, const char* num); + TTree_rectype(int testata, int riga, const char* num); + TTree_rectype(const TTree_rectype& t); + virtual ~TTree_rectype() {} +}; + + +class TRiga_scadenze : public TTree_rectype +{ + friend class TPartita; + friend class TRiga_partite; + + TRiga_partite* _riga; + +protected: + char calcola_abbuono(TImporto& abbuono, bool val) const; + TImporto calcola_differenza_cambio(bool update); + + bool modifica_pagamento(const TRectype& new_pag, + char& old_ap, TImporto& old_abb, TImporto& old_diffcam, + char& new_ap, TImporto& new_abb, TImporto& new_diffcam); + +protected: // TRecord_tree + virtual TObject* dup() const { return new TRiga_scadenze(*this); } + +public: + int pagata() const; // Riga che chiude la rata o 0 se non pagata completamente + + real residuo() const; + + bool in_valuta() const; + + TPartita& partita() const; + TRiga_partite& riga() const { CHECK(_riga, "Riga nulla"); return *_riga; } // Riga partite + + TImporto importo_pagato(bool val) const; + TImporto importo_da_pagare(bool val) const; + + TRiga_scadenze(TRiga_partite* riga); + TRiga_scadenze(const TRiga_scadenze& s); + virtual ~TRiga_scadenze() {} +}; + +class TRiga_partite : public TTree_rectype +{ + friend class TPartita; + friend class TRiga_scadenze; + TPartita* _partita; + +protected: + bool update(const TRectype& vec, const TRectype& nuo, const char* field); + bool update(const TImporto& vec, const TImporto& nuo, const char* sez, const char* val); + +public: // TTree_rectype + virtual TObject* dup() const { return new TRiga_partite(*this); } + virtual int read(TBaseisamfile& f, word op); + +public: + int rate() const { return _recarr.rows(); } + TRiga_scadenze& rata(int r) const { return (TRiga_scadenze&)_recarr.row(r); } + + int ultimo_pagamento(int rata) const; + char sezione() const { return get_char("SEZ"); } + + TPartita& partita() const { CHECK(_partita, "Partita nulla"); return *_partita; } + + TRiga_partite(TPartita* game); + TRiga_partite(const TRiga_partite& r); + virtual ~TRiga_partite() {} +}; + +class TPartita : public TObject +{ + TRecord_array _part; + TRecord_array _unassigned; + +public: // TObject + virtual bool ok() const { return _part.rows() > 0; } + +public: + TRiga_partite& riga(int r) const { return (TRiga_partite&)_part.row(r); } + TRiga_partite& nuova_riga() { return (TRiga_partite&)_part.row(last()+1, TRUE); } + + int succ(int r) const { return _part.succ_row(r); } + int pred(int r) const { return _part.pred_row(r); } + int first() const { return _part.first_row(); } + int last() const { return _part.last_row(); } + + bool reread(); + bool read(const TBill& clifo, int anno, const char* num); + bool write(bool re = FALSE); + bool rewrite() { return write(TRUE); } + + int mov2rig(long nreg, int rmov) const; + int rig2mov(int rmov) const; + int prima_fattura() const; + bool utilizzata(int r) const; // Controlla se esistono pagamenti sommati alla riga r + + void conto(TBill& c) const { c.get(_part.key()); } + int anno() const { return _part.key().get_int(PART_ANNO); } + const TString& numero() const { return _part.key().get(PART_NUMPART); } + const TString& descrizione() const { return _part.key().get(PART_DESCR); } + + TImporto importo_speso(long numreg, int numrig) const; + void update_reg_num(long nreg, const TRectype& mov); + void calcola_saldo(TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp) const; + + bool modifica_pagamento(const TRectype& new_pag, + char& old_ap, TImporto& old_abb, TImporto& old_diffcam, + char& new_ap, TImporto& new_abb, TImporto& new_diffcam); + + TPartita(const TBill& clifo, int anno, const char* num); + TPartita(); +}; + + +class TPartite_array : private TAssoc_array +{ + TString80 _key; // Work string + +protected: + const TString& key(const TBill& clifo, int anno, const char* num); // Build key for TAssoc_array + TPartita* find(const TBill& clifo, int anno, const char* numero, bool create); + TPartita* find(const TRectype& part, bool create); + +public: // TAssoc_array + virtual void destroy() { TAssoc_array::destroy(); } + +public: + TPartita& partita(const TBill& clifo, int anno, const char* numero); + TPartita& partita(const TRectype& r); + + TPartita* exist(const TBill& clifo, int anno, const char* numero) const + { return ((TPartite_array*)this)->find(clifo, anno, numero, FALSE); } + + TPartita* exist(const TRectype& part) const + { return ((TPartite_array*)this)->find(part, FALSE); } + + bool write(bool re = FALSE); + bool rewrite() { return write(TRUE); } + + int add_reg_num(long numreg, int numrig); + TImporto importo_speso(long numreg, int numrig); + void update_reg_num(long nreg, const TRectype& mov); + + TPartita* first() { restart(); return next(); } + TPartita* next() { return (TPartita*)get(); } + + TPartite_array() {} + virtual ~TPartite_array() {} +}; + +#endif