From 5e8580ea894f5cd897de36d7ea5a867e24dfe557 Mon Sep 17 00:00:00 2001 From: guy Date: Fri, 25 Aug 1995 07:39:49 +0000 Subject: [PATCH] Gestione saldaconto: corretto segno acconti e differenza cambio git-svn-id: svn://10.65.10.50/trunk@1737 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- cg/cg2102.cpp | 63 +- cg/cg2102.h | 4 +- cg/cg2105.cpp | 377 +++++++----- cg/saldacon.cpp | 1509 ++++++++++++++++++++++++----------------------- cg/saldacon.h | 403 ++++++------- 5 files changed, 1242 insertions(+), 1114 deletions(-) diff --git a/cg/cg2102.cpp b/cg/cg2102.cpp index 7d04a6e45..7d9206efa 100755 --- a/cg/cg2102.cpp +++ b/cg/cg2102.cpp @@ -96,51 +96,6 @@ real TPrimanota_application::totale_documento() } -bool TPrimanota_application::showpartite_handler(TMask_field& f, KEY k) -{ - bool ok = TRUE; - TMask& m = f.mask(); - - if (m.get(116) == "K") - { - TSheet_field& s = *m.get_sheet(); - const int riga = s.selected(); - if (k == K_SPACE) - { - const bool dirty = app().edit_partite(riga); - if (dirty) - { - if (m.field(103).enabled()) - app().disable_cgs_cells(riga, 'K'); - k = K_ENTER; - } - } - - if (k == K_ENTER) - { - const int currig = riga+1; - const long curreg = app().curr_mask().get_long(F_NUMREG); - TImporto importo; - const TString& imp = m.get(101); - if (imp.not_empty()) - importo.set('D', real(imp)); - else - importo.set('A', real(m.get(102))); - - const TImporto speso(app()._partite.importo_speso(curreg, currig)); - - if (importo != speso) - { - 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); - } - } - } - return ok; -} - - // Determina se un codice sospeso o no // Certified 99% bool TPrimanota_application::suspended_handler(TMask_field& f, KEY k) @@ -309,8 +264,22 @@ void TPrimanota_application::set_cgs_imp(int n, const TImporto& imp) // Certified 100% TImporto TPrimanota_application::get_cgs_imp(int n) { + TSheet_field& s = cgs(); + TImporto importo; - importo = cgs().row(n); + + const TMask& m = s.sheet_mask(); + if (m.is_running() && s.selected() == n) + { + const TString& imp = m.get(101); + if (imp.not_empty()) + importo.set('D', real(imp)); + else + importo.set('A', real(m.get(102))); + } + else + importo = s.row(n); + return importo; } @@ -574,7 +543,7 @@ bool TPrimanota_application::cg_handler(TMask_field& f, KEY k) { const long numreg = f.mask().get_long(F_NUMREG); const int currig = i+1; - const TImporto speso = app().partite().importo_speso(numreg, currig); + const TImporto speso = app().partite().importo_speso(numreg, currig, TRUE); if (importo != speso) { bool ok = yesno_box("L'importo della riga %d dovrebbe essere %c %s\n" diff --git a/cg/cg2102.h b/cg/cg2102.h index 1fe8e0df1..daa6dba1d 100755 --- a/cg/cg2102.h +++ b/cg/cg2102.h @@ -197,7 +197,6 @@ protected: void add_cgs_tot(TMask& m); int set_cgs_row(int n, const TImporto& importo, TBill& conto, const char* desc, char tipo); void set_cgs_imp(int n, const TImporto& importo); - TImporto get_cgs_imp(int n); bool add_cgs_imp(int n, const TImporto& importo); bool sub_cgs_imp(int n, const TImporto& importo); void disable_cgs_cells(int n, char tipo); @@ -221,7 +220,7 @@ protected: bool notify_cgline_deletion(TPartita& partita, long nreg, int numrig); bool notify_cgline_deletion(int numrig); - bool notify_edit_pagamento(TPartita& partita, TRectype& new_pag); + bool notify_edit_pagamento(TPartita& partita, TRectype& new_pag, int deleting = -1); long calcola_m770(int tipo_coll, real& spese, real& compenso, real& iva, real& ritfis); bool link_m770(); @@ -235,6 +234,7 @@ public: TSheet_field& ivas() const; TSheet_field& pags() const; TString_array& pag_rows() { return _pag_rows; } + TImporto get_cgs_imp(int n); TPrimanota_application(); }; diff --git a/cg/cg2105.cpp b/cg/cg2105.cpp index 17576253a..9ada378b1 100755 --- a/cg/cg2105.cpp +++ b/cg/cg2105.cpp @@ -27,6 +27,8 @@ protected: void add_importo(TToken_string& s, const TImporto& i) const; void fill_partite(bool all) const; + real aggiorna_residuo(); + void update_partita(const TPartita& game, int prow, bool all) const; public: TSheet_field& partite() const { return (TSheet_field&)field(P_PARTITE); } @@ -54,11 +56,13 @@ TGame_mask::TGame_mask(const TBill& bill) partite().set_notify(partite_notify); scadenze().sheet_mask().set_handler(100, edit_scadenza_handler); + + aggiorna_residuo(); } bool TGame_mask::annopart_handler(TMask_field& f, KEY k) { - if (k == K_TAB && f.dirty() && f.get().not_empty()) + if (k == K_TAB && f.focusdirty() && f.get().not_empty()) { TMask_field& n = f.mask().field(P_NUMERO); n.set_dirty(); @@ -119,6 +123,20 @@ bool TGame_mask::scambio_handler(TMask_field& f, KEY k) return TRUE; } +real TGame_mask::aggiorna_residuo() +{ + const TMask& cm = app().curr_mask(); + const long cur_reg = cm.get_long(F_NUMREG); + const int rmov = app().cgs().selected(); + + TImporto residuo(app().get_cgs_imp(rmov)); + residuo -= app().partite().importo_speso(cur_reg, rmov+1, TRUE); + + set(P_RESIDUO, residuo.valore().string()); + + return residuo.valore(); +} + bool TGame_mask::partite_notify(TSheet_field& partite, int r, KEY k) { if (k == K_TAB) @@ -161,12 +179,11 @@ bool TGame_mask::partite_notify(TSheet_field& partite, int r, KEY k) row.add(riga.get(PART_NUMDOC)); row.add(riga.get(PART_PROTIVA)); - const TRecord_array& ap = scad.rows_array(); - const int lastp = ap.last_row(); - for (int pa = ap.first_row(); pa <= lastp; pa = ap.succ_row(pa)) + const int lastp = scad.last(); + for (int pa = scad.first(); pa <= lastp; pa = scad.succ(pa)) { const TRiga_partite& rigp = game->riga(pa); - const TRectype& pag = ap.row(pa); + const TRectype& pag = scad.row(pa); TToken_string& row = scadenze.row(-1); row.add(ri); @@ -230,7 +247,11 @@ bool TGame_mask::edit_scadenza_handler(TMask_field& f, KEY k) const bool dirty = app().edit_pagamento(game, nriga, nrata, nrigp); if (dirty) + { + gm.update_partita(game, gm._riga_partite, TRUE); partite_notify(gm.partite(), gm._riga_partite, K_TAB); + gm.aggiorna_residuo(); + } } return TRUE; } @@ -247,6 +268,31 @@ void TGame_mask::add_importo(TToken_string& s, const TImporto& i) const } } +void TGame_mask::update_partita(const TPartita& game, int prow, bool all) const +{ + TImporto saldo, doc, pag, imp; + game.calcola_saldo(saldo, doc, pag, imp); + + if (all || !saldo.is_zero()) + { + int riga_fatt = game.prima_fattura(); + if (riga_fatt < 1) riga_fatt = game.first(); // E' un anticipo + const TRiga_partite& riga = game.riga(riga_fatt); + + TToken_string &r = partite().row(prow); // Stringa di lavoro per lo sheet + r.cut(0); + r.add(riga.get(PART_ANNO)); + r.add(riga.get(PART_NUMPART)); + r.add(riga.get(PART_DATADOC)); + r.add(riga.get(PART_NUMDOC)); + add_importo(r, saldo); + add_importo(r, doc); + add_importo(r, pag); + add_importo(r, imp); + r.add(riga.get(PART_DESCR)); + } +} + void TGame_mask::fill_partite(bool all) const { TString_array& a = partite().rows_array(); @@ -282,30 +328,7 @@ void TGame_mask::fill_partite(bool all) const should_delete_game = TRUE; } - TImporto saldo, doc, pag, imp; - game->calcola_saldo(saldo, doc, pag, imp); - - if (all || !saldo.is_zero()) - { - int riga_fatt = game->prima_fattura(); - if (riga_fatt < 1) riga_fatt = game->first(); // E' un anticipo - - const TRiga_partite& riga = game->riga(riga_fatt); - const TString16 data_doc = riga.get(PART_DATADOC); - const TString16 num_doc = riga.get(PART_NUMDOC); - const char*descr = riga.get(PART_DESCR); - - TToken_string &r = partite().row(-1); // Stringa di lavoro per lo sheet - r.add(anno); - r.add(num); - r.add(data_doc); - r.add(num_doc); - add_importo(r, saldo); - add_importo(r, doc); - add_importo(r, pag); - add_importo(r, imp); - r.add(descr); - } + update_partita(*game, -1, all); if (should_delete_game) delete game; @@ -328,6 +351,44 @@ void TGame_mask::fill_partite(bool all) const // Metodi di prima nota /////////////////////////////////////////////////////////// +bool TPrimanota_application::showpartite_handler(TMask_field& f, KEY k) +{ + bool ok = TRUE; + TMask& m = f.mask(); + + if (m.get(116) == "K") + { + TSheet_field& s = *m.get_sheet(); + const int riga = s.selected(); + if (k == K_SPACE) + { + const bool dirty = app().edit_partite(riga); + if (dirty) + { + if (m.field(103).enabled()) + app().disable_cgs_cells(riga, 'K'); + k = K_ENTER; + } + } + + if (k == K_ENTER) + { + const long curreg = app().curr_mask().get_long(F_NUMREG); + const TImporto importo(app().get_cgs_imp(riga)); + const TImporto speso(app().partite().importo_speso(curreg, riga+1, TRUE)); + + if (importo != speso) + { + ok = yesno_box("L'importo della riga %d dovrebbe essere %c %s\n" + "Si desidera correggerlo?", riga+1, speso.sezione(), speso.valore().string(".")); + if (ok) app().set_cgs_imp(riga, speso); + } + } + } + return ok; +} + + bool TPrimanota_application::edit_partite(int riga) { TToken_string& cgr = cgs().row(riga); @@ -367,8 +428,10 @@ int TPrimanota_application::nuovo_pagamento(TPartita& partita, int nriga, int ra part.put(PART_DATADOC, curr_mask().get(F_DATADOC)); part.put(PART_NUMDOC, curr_mask().get(F_NUMDOC)); part.put(PART_DESCR, curr_mask().get(F_DESCR)); - part.put(PART_CAMBIO, curr_mask().get(S_CAMBIO)); - part.put(PART_DATACAM, curr_mask().get(S_DATACAMBIO)); + + part.put(PART_CODVAL, riga_part.get(PART_CODVAL)); // Meglio prendere il cambio dalle scadenze + part.put(PART_CAMBIO, riga_part.get(PART_CAMBIO)); // piuttosto che dal cangiante mondo delle + part.put(PART_DATACAM, riga_part.get(PART_DATACAM)); // maschere interattive // Copia dati causale corrente const int tipomov = causale().tipomov(); @@ -395,9 +458,11 @@ int TPrimanota_application::nuovo_pagamento(TPartita& partita, int nriga, int ra sezione = (sezione == 'D') ? 'A' : 'D'; // scambia segno } part.put(PART_SEZ, sezione); // Memorizza solo la sezione (importi nulli) + part.put(PART_SEZABB, sezione); + part.put(PART_SEZDIFCAM, sezione); } - TRectype& pagamento = riga_scad.row(nrigp, TRUE); // Crea nuovo pagamento + TRectype& pagamento = riga_scad.new_row(nrigp); // Crea nuovo pagamento int caus = 2; // Calcola riga causale per la contropartita in base al tipo pagamento switch (riga_scad.get_int(SCAD_TIPOPAG)) @@ -425,6 +490,7 @@ int TPrimanota_application::nuovo_pagamento(TPartita& partita, int nriga, int ra causale().bill(caus = 1, contro); // ... prende il primo contro.put(pagamento, TRUE); // Scrive conto contropartita + // Da regalare a Ferdinando if (conto.tipo() > ' ') // Se cliente o fornitore cerca sua banca { TRelation cliforel(LF_CLIFO); @@ -440,6 +506,12 @@ int TPrimanota_application::nuovo_pagamento(TPartita& partita, int nriga, int ra pagamento.put(PAGSCA_CODCAB, clifo.get(CLI_CODCAB)); pagamento.put(PAGSCA_CODAG, cliforel.lfile(LF_CFVEN).get(CLI_CODAG)); } + + /* Prossima implementazione + pagamento.put(PAGSCA_CODABI, riga_scad.get(SCAD_CODABI)); + pagamento.put(PAGSCA_CODCAB, riga_scad.get(SCAD_CODCAB)); + pagamento.put(PAGSCA_CODAG, riga_scad.get(SCAD_CODAG)); + */ pagamento.put(PAGSCA_CODABIPR, riga_scad.get(SCAD_CODABIPR)); pagamento.put(PAGSCA_CODCABPR, riga_scad.get(SCAD_CODCABPR)); @@ -468,123 +540,142 @@ HIDDEN bool importo_handler(TMask_field& f, KEY k) } -bool TPrimanota_application::notify_edit_pagamento(TPartita& p, TRectype& new_pag) -{ - const int nriga = new_pag.get_int(PAGSCA_NRIGA); // Riga fattura - const TRiga_partite& parbas = p.riga(nriga); - - const int nrata = new_pag.get_int(PAGSCA_NRATA); // Numero rata - TRiga_scadenze& scaden = parbas.rata(nrata); - - const int nrigp = new_pag.get_int(PAGSCA_NRIGP); // Riga pagamento - const TRectype& old_pag = scaden.row(nrigp); - const TRiga_partite& somma = p.riga(nrigp); - - const char sez = somma.sezione(); // Sezione importo e ritenute - const char controsez = sez == 'A' ? 'D' : 'A'; // Sezione contropartita - - // Aggiornamento contopartita - const TImporto old_importo(controsez, old_pag.get_real(PAGSCA_IMPORTO)); - TBill old_conto; old_conto.get(old_pag, TRUE); - - const TImporto new_importo(controsez, new_pag.get_real(PAGSCA_IMPORTO)); - TBill new_conto; new_conto.get(new_pag, TRUE); - - if (old_importo != new_importo || old_conto != new_conto) +bool TPrimanota_application::notify_edit_pagamento(TPartita& p, TRectype& new_pag, int deleting) +{ + if (deleting != 0) { - const int old_riga = bill2pos(old_conto, 'I'); - if (old_riga >= 0) - { - const bool empty = sub_cgs_imp(old_riga, old_importo); - if (empty && (new_importo.is_zero() || new_conto != old_conto)) - reset_cgs_row(old_riga); - } + const int nriga = new_pag.get_int(PAGSCA_NRIGA); // Riga fattura + const TRiga_partite& parbas = p.riga(nriga); - // Importo della contropartita - if (!new_importo.is_zero()) + const int nrata = new_pag.get_int(PAGSCA_NRATA); // Numero rata + TRiga_scadenze& scaden = parbas.rata(nrata); + + const int nrigp = new_pag.get_int(PAGSCA_NRIGP); // Riga pagamento + const TRectype& old_pag = scaden.row(nrigp); + const TRiga_partite& somma = p.riga(nrigp); + + const char sez = somma.sezione(); // Sezione importo e ritenute + const char controsez = sez == 'A' ? 'D' : 'A'; // Sezione contropartita + + // Aggiornamento contopartita + const TImporto old_importo(controsez, old_pag.get_real(PAGSCA_IMPORTO)); + TBill old_conto; old_conto.get(old_pag, TRUE); + + const TImporto new_importo(controsez, new_pag.get_real(PAGSCA_IMPORTO)); + TBill new_conto; new_conto.get(new_pag, TRUE); + + if (old_importo != new_importo || old_conto != new_conto) { - const int new_riga = bill2pos(new_conto, 'I'); - if (new_riga < 0) - set_cgs_row(new_riga, new_importo, new_conto, "", 'I'); - else - add_cgs_imp(new_riga, new_importo); - } - } - - // Aggiornamento ritenute - const real old_ritenute(old_pag.get(PAGSCA_RITENUTE)); - const real new_ritenute(new_pag.get(PAGSCA_RITENUTE)); - if (old_ritenute != new_ritenute) - { - const TImporto grow_ritenute(controsez, new_ritenute-old_ritenute); - const riga = type2pos('F'); - if (riga < 0) - { - TBill conto_rit; causale().bill(11, conto_rit); - set_cgs_row(riga, grow_ritenute, conto_rit, "", 'F'); + const int old_riga = bill2pos(old_conto, 'I'); + if (old_riga >= 0) + { + const bool empty = sub_cgs_imp(old_riga, old_importo); + if (empty && (new_importo.is_zero() || new_conto != old_conto)) + reset_cgs_row(old_riga); + } + + // Importo della contropartita + if (!new_importo.is_zero()) + { + const int new_riga = bill2pos(new_conto, 'I'); + if (new_riga < 0) + set_cgs_row(new_riga, new_importo, new_conto, "", 'I'); + else + add_cgs_imp(new_riga, new_importo); + } } - else - { - const bool empty = add_cgs_imp(riga, grow_ritenute); - if (empty) reset_cgs_row(riga); - } - } + + + // Aggiornamento ritenute + const real old_ritenute(old_pag.get(PAGSCA_RITENUTE)); + const real new_ritenute(new_pag.get(PAGSCA_RITENUTE)); + if (old_ritenute != new_ritenute) + { + const TImporto grow_ritenute(controsez, new_ritenute-old_ritenute); + const riga = type2pos('F'); + if (riga < 0) + { + TBill conto_rit; causale().bill(11, conto_rit); + set_cgs_row(riga, grow_ritenute, conto_rit, "", 'F'); + } + else + { + const bool empty = add_cgs_imp(riga, grow_ritenute); + if (empty) reset_cgs_row(riga); + } + } + } // if (deleting != 0) 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, 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) + + if (deleting != 0) { - if (old_ap != ' ') // Se c'era un abbuono ... - { - const int riga_abb = type2pos(old_ap); - CHECK(riga_abb >= 0, "Chiss'e' fregato gli abbuoni?"); - const bool empty = sub_cgs_imp(riga_abb, old_abbuono); - if (empty && new_ap != old_ap) - reset_cgs_row(riga_abb); + const int riga_contabile = app().cgs().selected(); + + // Se c'e' differenza negli abbuoni + if (old_abbuono != new_abbuono || old_ap != new_ap) + { + if (old_ap != ' ') // Se c'era un abbuono ... + { + const int riga_abb = type2pos(old_ap); + CHECK(riga_abb >= 0, "Chiss'e' fregato gli abbuoni?"); + const bool empty = sub_cgs_imp(riga_abb, old_abbuono); + if (empty && new_ap != old_ap) + reset_cgs_row(riga_abb); + + if (deleting != riga_contabile) + { + // Sottrae l'abbuono con la sezione invertita dalla riga contabile + add_cgs_imp(riga_contabile, old_abbuono); + } + } + if (new_ap != ' ') // Se ci sono abbuoni + { + const riga_abb = type2pos(new_ap); + if (riga_abb < 0) + { + TBill conto_abb; causale().bill(new_ap == 'A' ? 9 : 8, conto_abb); + app().set_cgs_row(riga_abb, new_abbuono, conto_abb, "", new_ap); + } + else + add_cgs_imp(riga_abb, new_abbuono); + + if (deleting != riga_contabile) + { + // Aggiunge l'abbuono con la sezione invertita + sub_cgs_imp(riga_contabile, new_abbuono); + } + } + } + + // Se c'e' variazione nella differenza cambi + if (old_diffcam != new_diffcam) + { + const int riga_diffcam = type2pos('C'); + TImporto grow_diffcam(new_diffcam); grow_diffcam -= old_diffcam; - // Sottrae l'abbuono con la sezione invertita dalla riga contabile - add_cgs_imp(riga_contabile, old_abbuono); - } - if (new_ap != ' ') // Se ci sono abbuoni - { - const riga_abb = type2pos(new_ap); - if (riga_abb < 0) + if (riga_diffcam < 0) { - TBill conto_abb; causale().bill(new_ap == 'A' ? 9 : 8, conto_abb); - app().set_cgs_row(riga_abb, new_abbuono, conto_abb, "", new_ap); + TBill conto_diffcam; causale().bill(12, conto_diffcam); + set_cgs_row(riga_diffcam, grow_diffcam, conto_diffcam, "", 'C'); } else - add_cgs_imp(riga_abb, new_abbuono); + { + const bool empty = add_cgs_imp(riga_diffcam, grow_diffcam); + if (empty) reset_cgs_row(riga_diffcam); + } - sub_cgs_imp(riga_contabile, new_abbuono); // Aggiunge l'abbuono con la sezione invertita - } - } - - // Se c'e' variazione nella differenza cambi - if (old_diffcam != new_diffcam) - { - const int riga_diffcam = type2pos('C'); - TImporto grow_diffcam(new_diffcam); grow_diffcam -= old_diffcam; - - if (riga_diffcam < 0) - { - TBill conto_diffcam; causale().bill(12, conto_diffcam); - set_cgs_row(riga_diffcam, grow_diffcam, conto_diffcam, "", 'C'); + if (deleting != riga_contabile) + { + // Aggiunge la differenza con la sezione invertita + sub_cgs_imp(riga_contabile, grow_diffcam); + } } - else - { - 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 - } + } // if (deleting != 0) return empty; } @@ -619,10 +710,10 @@ bool TPrimanota_application::edit_pagamento(TPartita& p, int nriga, int nrata, i // Dati della scadenza che ha generato la partita TReal_field& residuo = (TReal_field&)m.field(S_RESIDUO); residuo.set_decimals(in_valuta ? 2 : 0); - residuo.set(scaden.residuo().string()); // Residuo da pagare - m.set(S_DATASCAD, scaden.get(SCAD_DATASCAD)); // Data della scadenza + residuo.set(scaden.residuo(TRUE).string()); // Residuo da pagare + m.set(S_DATASCAD, scaden.get(SCAD_DATASCAD)); // Data della scadenza m.set(S_SEZIONE_SCAD, parbas.get(PART_SEZ)); // Sezione della rata - m.set(S_RATA, scaden.get(SCAD_NRATA)); + m.set(S_RATA, scaden.get(SCAD_NRATA)); m.set(S_IMPORTO_SCAD, scaden.get(SCAD_IMPORTO)); // Importo della rata m.set(S_IMPORTOVAL_SCAD, scaden.get(SCAD_IMPORTOVAL)); // Importo in valuta @@ -648,13 +739,16 @@ bool TPrimanota_application::edit_pagamento(TPartita& p, int nriga, int nrata, i return key != K_ESC; } + +// Scorre tutte le righe della partita ed azzera i pagamenti relativi a alla riga contabile +// cancellata e decrementa i numeri riga superiori a numrig bool TPrimanota_application::notify_cgline_deletion(TPartita& partita, long nreg, int numrig) { bool found = FALSE; for (int p = partita.last(); p > 0; p = partita.pred(p)) { - const TRiga_partite& part = partita.riga(p); + TRiga_partite& part = partita.riga(p); if (part.get_int(PART_TIPOMOV) == 1) { for (int r = part.rate(); r > 0; r--) @@ -670,12 +764,17 @@ bool TPrimanota_application::notify_cgline_deletion(TPartita& partita, long nreg pag.zero(PAGSCA_IMPORTO); pag.zero(PAGSCA_IMPORTOVAL); pag.zero(PAGSCA_RITENUTE); - notify_edit_pagamento(partita, pag); + notify_edit_pagamento(partita, pag, numrig); found = TRUE; } } } - } + } + else + { + if (numrig > 0 && part.get_long(PART_NREG) == nreg && part.get_int(PART_NUMRIG) > numrig) + part.put(PART_NUMRIG, numrig-1); + } } return found; @@ -685,7 +784,7 @@ bool TPrimanota_application::notify_cgline_deletion(int numrig) { bool found = FALSE; const long nreg = curr_mask().get_long(F_NUMREG); - _partite.add_reg_num(nreg, 0); + _partite.add_reg_num(nreg, 0); // Carica tutte le partite interessate for (TPartita* game = _partite.first(); game; game = _partite.next()) found |= notify_cgline_deletion(*game, nreg, numrig); diff --git a/cg/saldacon.cpp b/cg/saldacon.cpp index fc6afae61..f9cf4db30 100755 --- a/cg/saldacon.cpp +++ b/cg/saldacon.cpp @@ -1,729 +1,782 @@ -#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); -} - +#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 fattura della rata e' in valuta +bool TRiga_scadenze::in_valuta() const +{ + return riga().get(PART_CODVAL).not_empty(); +} + +// Controlla se la rata e' stata completamente pagata +int TRiga_scadenze::pagata() const +{ + for (int p = last(); p > 0; p = pred(p)) + { + const TRectype& pag = row(p); + if (pag.get_char("ACCSAL") == 'S') + break; + } + return p; +} + +// Calcola il totale dei pagamenti (eventualmente in valuta) +TImporto TRiga_scadenze::importo_pagato(bool val) const +{ + const char* imp_field = val && in_valuta() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + const TPartita& game = partita(); + 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 TImporto imp(sum.sezione(), 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 = 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 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() *= riga().get_real(PART_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); + 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 *= riga().get_real(PART_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); + pag.zero(PAGSCA_DIFFCAM); + } + } + } + + return diffcam; +} + +real TRiga_scadenze::residuo(bool val) const +{ + TImporto residuo(importo_da_pagare(val)); + residuo -= importo_pagato(val); + return residuo.valore(); +} + + +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(old_abbuono, TRUE); // Vecchio abbuono in valuta + old_abb = old_abbuono; // Vecchio abbuono in lire + if (in_valuta()) + { + old_abb.valore() *= riga().get_real(PART_CAMBIO); + old_abb.valore().round(); + } + + old_diffcam = calcola_differenza_cambio(FALSE); + + const char* imp_field = in_valuta() ? 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) = new_pag; + + TImporto new_abbuono; + new_ap = calcola_abbuono(new_abbuono, TRUE); // Calcolo abbuono in valuta + + new_abb = new_abbuono; // Calcola nuovo abbuono in lire + if (in_valuta()) + { + new_abb.valore() *= riga().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 != ' ') + { + CHECK(nrigp == pagata(), "Aggiornamento abbuoni inconsistente"); + TRectype& pag = row(nrigp); + pag.put(PAGSCA_ABBUONI, new_abbuono.valore()); + } + sum.update(old_abbuono, new_abbuono, PART_SEZABB, PART_ABBUONI); + + new_diffcam = calcola_differenza_cambio(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 + + 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.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 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); + + 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; +} + +bool TPartita::remove() +{ + _part.destroy_rows(); + return rewrite(); +} + +TImporto TPartita::importo_speso(long nreg, int numrig, bool extra) const +{ + TImporto imp; + + for (int r = last(); 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 valida per forza! + imp += TImporto(sez, part.get_real(PART_IMPORTO)); + + if (extra) + { + TImporto abbuoni(part.get_char(PART_SEZABB), part.get_real(PART_ABBUONI)); + if (part.get(PART_CODVAL).not_empty()) // Se e' 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_num(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_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 = last(); 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 = 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 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; +} + +bool TPartita::chiusa(bool update) +{ + const TRiga_partite& row = riga(first()); + bool chiusa = row.get_bool(PART_CHIUSA); + + if (update) + { + bool forse_chiusa = TRUE; + for (int p = last(); p > 0 && forse_chiusa; p = pred(p)) + { + const TRiga_partite& part = riga(first()); + if (part.get_int(PART_TIPOMOV) == 1) + { + for (int r = part.last(); r > 0; r--) + { + const TRiga_scadenze& scad = part.rata(r); + if (!scad.pagata()) + { + forse_chiusa = FALSE; + break; + } + } + } + } + + if (chiusa != forse_chiusa) + { + chiusa = forse_chiusa; + for (p = last(); p > 0; p = pred(p)) + { + TRiga_partite& part = riga(first()); + part.put(PART_CHIUSA, 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); + 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, bool extra) +{ + TImporto imp; + add_reg_num(nreg, numrig); + for (TPartita* game = first(); game; game = next()) + imp += game->importo_speso(nreg, numrig, extra); + 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 index 835d6c2e7..09dfbdee2 100755 --- a/cg/saldacon.h +++ b/cg/saldacon.h @@ -1,198 +1,205 @@ -#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 +#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); + + const TRecord_array& rows_array() const { return _recarr; } + TRecord_array& rows_array() { return _recarr; } + +public: + const TRectype& row(int r) const { return _recarr.row(r); } + TRectype& row(int r) { return _recarr.row(r, FALSE); } + TRectype& new_row(int r = -1) { return _recarr.row(r > 0 ? r : last()+1, TRUE); } + + int first() const { return _recarr.first_row(); } + int last() const { return _recarr.last_row(); } + int pred(int r) const { return _recarr.pred_row(r); } + int succ(int r) const { return _recarr.succ_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 + + + 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; + real residuo(bool val) const; // Differenza delle due funzioni precedenti + + 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); } + bool remove(); + + 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 + + bool chiusa(bool update = FALSE); + + 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, bool extra) 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, bool extra); + 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