From 0516fcfdde9411c42f89e5a97e536b8b53bbb73d Mon Sep 17 00:00:00 2001 From: guy Date: Wed, 9 Aug 1995 09:52:08 +0000 Subject: [PATCH] Gestione del saldaconto in prima nota git-svn-id: svn://10.65.10.50/trunk@1696 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- cg/cg0200.cpp | 7 +- cg/cg0500.cpp | 6 +- cg/cg2100.cpp | 29 +- cg/cg2100c.uml | 17 +- cg/cg2101.cpp | 3 - cg/cg2102.cpp | 18 +- cg/cg2102.h | 9 +- cg/cg2104.cpp | 381 ++++--- cg/cg5300.cpp | 4 +- cg/cg5500.cpp | 4 +- cg/cg5500.h | 4 +- cg/deliva.frm | 8 +- cg/pagament.cpp | 2782 +++++++++++++++++++++++++---------------------- cg/pagament.h | 95 +- 14 files changed, 1824 insertions(+), 1543 deletions(-) diff --git a/cg/cg0200.cpp b/cg/cg0200.cpp index ac0ad9af1..428708620 100755 --- a/cg/cg0200.cpp +++ b/cg/cg0200.cpp @@ -47,7 +47,7 @@ protected: virtual void on_config_change(); //////////// - static bool indsp_notify(int r, KEY key); + static bool indsp_notify(TSheet_field& s, int r, KEY key); static bool indsp_handler(TMask_field& f, KEY key) ; virtual int write(const TMask& m); virtual int rewrite(const TMask& m); @@ -553,10 +553,8 @@ bool TClifo_application::indsp_handler(TMask_field& f, KEY key) return TRUE; } -bool TClifo_application::indsp_notify(int r, KEY key) +bool TClifo_application::indsp_notify(TSheet_field& indsp, int r, KEY key) { - TSheet_field& indsp=app().indsp_sheet(); - switch (key) { case K_SPACE: @@ -564,7 +562,6 @@ bool TClifo_application::indsp_notify(int r, KEY key) // Request to modify row #r // Disable field CODIND update # of row TMask& m = indsp.sheet_mask(); - if (m.get_int(F_CODINDI)==0) // Is it a new row ? m.set(F_CODINDI,(long)(r+1)); m.disable(F_CODINDI); diff --git a/cg/cg0500.cpp b/cg/cg0500.cpp index ec3d8c36e..92216add4 100755 --- a/cg/cg0500.cpp +++ b/cg/cg0500.cpp @@ -57,7 +57,7 @@ protected: static bool sottoconto_hndl (TMask_field& f, KEY k); static bool codcausim_hndl (TMask_field& f, KEY k); static bool m770_hndl (TMask_field& f, KEY k); - static bool ss_notify (int r, KEY k); + static bool ss_notify (TSheet_field& s, int r, KEY k); bool fill_sheet(TMask&); @@ -498,11 +498,11 @@ bool TCaus_app::cod_reg_hndl (TMask_field& f, KEY k) // Handler della maschera dello spreadsheet //////////////////////////////////////////////////////////////////////////// -bool TCaus_app::ss_notify(int r, KEY k) +bool TCaus_app::ss_notify(TSheet_field& s, int r, KEY k) { if (k == K_ENTER) { - TToken_string &riga = app().ss().row(r); + TToken_string &riga = s.row(r); const int g = riga.get_int(3); if (g == 0) // riga azzerata app().clear(r); // pulisco la riga anche nell'array diff --git a/cg/cg2100.cpp b/cg/cg2100.cpp index e861e521e..e2c900fe2 100755 --- a/cg/cg2100.cpp +++ b/cg/cg2100.cpp @@ -143,21 +143,22 @@ TMask* TPrimanota_application::load_mask(int n) bool TPrimanota_application::user_create() { - _tabcom = new TLocalisamfile(LF_TABCOM); - _tab = new TLocalisamfile(LF_TAB); - _caus = new TLocalisamfile(LF_CAUSALI); - _rcaus = new TLocalisamfile(LF_RCAUSALI); - _clifo = new TLocalisamfile(LF_CLIFO); - _pcon = new TLocalisamfile(LF_PCON); - _attiv = new TLocalisamfile(LF_ATTIV); - _saldo = new TLocalisamfile(LF_SALDI); - _comuni = new TLocalisamfile(LF_COMUNI); - _occas = new TLocalisamfile(LF_OCCAS); - _nditte = new TLocalisamfile(LF_NDITTE); - _scadenze = new TLocalisamfile(LF_SCADENZE); - + _tabcom = new TLocalisamfile(LF_TABCOM); + _tab = new TLocalisamfile(LF_TAB); + _caus = new TLocalisamfile(LF_CAUSALI); + _rcaus = new TLocalisamfile(LF_RCAUSALI); + _clifo = new TLocalisamfile(LF_CLIFO); + _pcon = new TLocalisamfile(LF_PCON); + _attiv = new TLocalisamfile(LF_ATTIV); + _saldo = new TLocalisamfile(LF_SALDI); + _comuni = new TLocalisamfile(LF_COMUNI); + _occas = new TLocalisamfile(LF_OCCAS); + _nditte = new TLocalisamfile(LF_NDITTE); + _scadenze = new TLocalisamfile(LF_SCADENZE); + _pagamenti = new TLocalisamfile(LF_PAGSCA); + _rel = new TMovimentoPN; - _rel->add(LF_PARTITE, "NREG=NUMREG", 2); + _rel->add(LF_PARTITE, "NREG=NUMREG", 2); // Collega la partita aperta dalla fattura _causale = new TCausale(); _giornale = new TLibro_giornale(); diff --git a/cg/cg2100c.uml b/cg/cg2100c.uml index 967acc575..c6797588e 100755 --- a/cg/cg2100c.uml +++ b/cg/cg2100c.uml @@ -413,7 +413,7 @@ BEGIN FLAGS "H" END -STRING F_VALUTA 3 +STRING S_VALUTA 3 BEGIN PROMPT 1 12 "Valuta " HELP "Codice della valuta per operazione con l'estero" @@ -421,18 +421,18 @@ BEGIN FLAGS "UZ" GROUP 3 USE %VAL - INPUT CODTAB F_VALUTA + INPUT CODTAB S_VALUTA DISPLAY "Codice" CODTAB DISPLAY "Nome@50" S0 DISPLAY "Cambio@15" R10 DISPLAY "Ultimo aggiornamento" D0 - OUTPUT F_VALUTA CODTAB - OUTPUT F_CAMBIO R10 + OUTPUT S_VALUTA CODTAB + OUTPUT S_CAMBIO R10 CHECKTYPE NORMAL WARNING "Codice valuta assente" END -NUMBER F_CAMBIO 12 5 +NUMBER S_CAMBIO 12 5 BEGIN PROMPT 20 12 "Cambio " HELP "Cambio della valuta per operazione con l'estero" @@ -442,13 +442,6 @@ BEGIN PICTURE ".5" END -BOOLEAN F_VISVAL -BEGIN - PROMPT 47 12 "Visualizza importi in valuta" - HELP "Indicare se visualizzare gli importi in valuta (non in Lit.)" - GROUP 3 -END - NUMBER F_TOTALE 15 BEGIN PROMPT 1 13 "Totale documento " diff --git a/cg/cg2101.cpp b/cg/cg2101.cpp index 091047621..b32f092a9 100755 --- a/cg/cg2101.cpp +++ b/cg/cg2101.cpp @@ -166,10 +166,7 @@ int TMovimentoPN::registra(bool re, bool force) int err = re ? TRelation::rewrite(force) : TRelation::write(force); if (err != NOERR) - { - CHECKD(!m.empty(), "Record empty after error ", err); return err; - } if (!re) _cg.renum_key("NUMREG", numreg); diff --git a/cg/cg2102.cpp b/cg/cg2102.cpp index 4c41a5da7..2ef8294c7 100755 --- a/cg/cg2102.cpp +++ b/cg/cg2102.cpp @@ -465,7 +465,7 @@ void TPrimanota_application::cgs_pack() if (can_remove(r)) { if (salda && row_type(r) == ' ') - cg_notify(i, K_DEL); + cg_notify(cgs(), i, K_DEL); rows.destroy(i, salda); } } @@ -688,13 +688,12 @@ void TPrimanota_application::generazione_righe_cg(int r) } -bool TPrimanota_application::cg_notify(int r, KEY k) +bool TPrimanota_application::cg_notify(TSheet_field& cg, int r, KEY k) { switch(k) { case K_SPACE: { - TSheet_field& cg = app().cgs(); const char tipo = row_type(cg.row(r)); cg.sheet_mask().enable(DLG_DELREC, tipo <= ' '); } @@ -930,12 +929,11 @@ void TPrimanota_application::ivas_pack() } // Certified 50% -bool TPrimanota_application::iva_notify(int r, KEY k) +bool TPrimanota_application::iva_notify(TSheet_field& iva, int r, KEY k) { static int oldpos,oldposiva; static real oldimp, oldiva; - TSheet_field& iva = app().ivas(); TToken_string& row = iva.row(r); const TCausale& cau = app().causale(); @@ -1247,7 +1245,7 @@ bool TPrimanota_application::num_handler(TMask_field& f, KEY key) "si desidera continuare ugualmente"); } - if (ok) + if (ok) // Riempie a mano i campi necessari nel caso non sia stato usata la ricerca F9 { m.set(F_DATAREG, mov.get("DATAREG"), TRUE); m.set(F_DATACOMP, mov.get("DATACOMP"), TRUE); @@ -1687,7 +1685,7 @@ bool TPrimanota_application::main_codiva_handler(TMask_field& f, KEY key) TToken_string& row = app().ivas().row(0); TMask& m = f.mask(); - iva_notify(0, K_SPACE); + iva_notify(app().ivas(), 0, K_SPACE); const TCodiceIVA iva(f.get()); const bool corr = app().causale().corrispettivi(); @@ -1710,7 +1708,7 @@ bool TPrimanota_application::main_codiva_handler(TMask_field& f, KEY key) } app().ivas().force_update(0); - iva_notify(0, K_ENTER); + iva_notify(app().ivas(), 0, K_ENTER); } } return TRUE; @@ -1915,9 +1913,9 @@ bool TPrimanota_application::solaiva_handler(TMask_field& f, KEY key) { oldrow = r; r = ""; - iva_notify(i, K_SPACE); + iva_notify(iva, i, K_SPACE); r = oldrow; - iva_notify(i, K_ENTER); + iva_notify(iva, i, K_ENTER); } pi.setstatus(i+1); } diff --git a/cg/cg2102.h b/cg/cg2102.h index 2e4566b4f..6e5e1e96d 100755 --- a/cg/cg2102.h +++ b/cg/cg2102.h @@ -36,6 +36,7 @@ class TPrimanota_application : public TRelation_application TLocalisamfile* _occas; TLocalisamfile* _nditte; TLocalisamfile* _scadenze; + TLocalisamfile* _pagamenti; TPagamento* _pag; @@ -104,11 +105,11 @@ class TPrimanota_application : public TRelation_application static bool cg_conto_handler(TMask_field& f, KEY key); static bool codpag_handler(TMask_field& f, KEY key); - static bool iva_notify(int r, KEY key); + static bool iva_notify(TSheet_field& s, int r, KEY key); static bool iva_handler(TMask_field& f, KEY key); - static bool cg_notify(int r, KEY key); + static bool cg_notify(TSheet_field& s, int r, KEY key); static bool cg_handler(TMask_field& f, KEY key); - static bool pag_notify(int r, KEY key); + static bool pag_notify(TSheet_field& s, int r, KEY key); void reset_sheet_row(TSheet_field& s, int n); @@ -209,7 +210,7 @@ protected: void write_scadenze(const TMask& m); bool edit_partite(int riga); - bool edit_scadenze(int anno, const char* num); + bool edit_scadenze(const TBill& clifo, int anno, const char* num); int nuovo_pagamento(TPartita& partita, int rata, int rmov, TRectype& part); bool edit_pagamento(TPartita& partita, TRectype& part); diff --git a/cg/cg2104.cpp b/cg/cg2104.cpp index 2ca36562b..90f1f6dce 100755 --- a/cg/cg2104.cpp +++ b/cg/cg2104.cpp @@ -4,17 +4,18 @@ // -------------------------------------------------------------------------- #include +#include "pagament.h" #include "cg2102.h" #include "cg2100.h" #include "cg21sld.h" -#include "pagament.h" +#include "cg2100p.h" #include #include #include -bool TPrimanota_application::pag_notify(int r, KEY k) +bool TPrimanota_application::pag_notify(TSheet_field&, int r, KEY k) { TPagamento& pag = app().pagamento(); TSheet_field& ps = app().pags(); @@ -340,7 +341,7 @@ void TPrimanota_application::write_scadenze(const TMask& m) int gruppo = (tipocf == 'C' || tipocf == 'F') ? 0 : _rel->cg(0).get_char("GRUPPO"); int conto = (tipocf == 'C' || tipocf == 'F') ? 0 : _rel->cg(0).get_char("CONTO"); long sottoconto = _rel->cg(0).get_long("SOTTOCONTO"); - int nriga = 1; + const int nriga = 1; int numrig = 1; partita.put(PART_ANNO, anno); @@ -400,9 +401,14 @@ void TPrimanota_application::write_scadenze(const TMask& m) { new_scad = FALSE; scadenza.zero(); - scadenza.put("ANNO", anno); - scadenza.put("NUMPART", numpart); - scadenza.put("NRATA", i+1); + scadenza.put(SCAD_TIPOCF, tipocf); + scadenza.put(SCAD_GRUPPO, gruppo); + scadenza.put(SCAD_CONTO, conto); + scadenza.put(SCAD_SOTTOCONTO, sottoconto); + scadenza.put(SCAD_ANNO, anno); + scadenza.put(SCAD_NUMPART, numpart); + scadenza.put(SCAD_NRIGA, nriga); + scadenza.put(SCAD_NRATA, i+1); if (scadenza.read() != NOERR) { @@ -414,6 +420,7 @@ void TPrimanota_application::write_scadenze(const TMask& m) scadenza.put(SCAD_SOTTOCONTO, sottoconto); scadenza.put(SCAD_ANNO, anno); scadenza.put(SCAD_NUMPART, numpart); + scadenza.put(SCAD_NRIGA, nriga); scadenza.put(SCAD_NRATA, i+1); } // set everything @@ -447,24 +454,159 @@ void TPrimanota_application::write_scadenze(const TMask& m) // Sheet partite /////////////////////////////////////////////////////////// +HIDDEN void add_importo(TToken_string& s, const TImporto& i) +{ + if (i.is_zero()) + s.add(""); + else + { + s.add(i.valore().string()); + s << ' ' << i.sezione(); + } +} + +HIDDEN bool partite_notify(TSheet_field& partite, int r, KEY k) +{ + if (k == K_TAB) + { + TMask& m = partite.mask(); + TSheet_field& scadenze = (TSheet_field&)m.field(P_SCADENZE); + scadenze.destroy(); + + const TBill zio(m.get_int(P_GRUPPO), m.get_int(P_CONTO), + m.get_long(P_SOTTOCONTO), m.get(P_TIPOC)[0]); + TToken_string& row = partite.row(r); + const int anno = row.get_int(0); + const TString16 num = row.get(); + m.set(P_ANNO, anno); // Aggiorna campi di ricerca + m.set(P_NUMERO, num); + + TPartita game(zio, anno, num); + TRecord_array& p = game.rows_array(); + const int lastr = p.last_row(); + for (int r = p.first_row(); r <= lastr; r++) if (p.exist(r)) + { + const TRiga_partite& riga = game.riga(r); + for (int ra = 1; ra <= riga.rate(); ra++) + { + const TRiga_scadenze& scad = riga.rata(ra); + TToken_string& row = scadenze.row(-1); + row.add(ra); + row.add(riga.get(PART_DATADOC)); + row.add(riga.get(PART_NREG)); + row.add(riga.get(PART_DATAREG)); + row.add(scad.get(SCAD_DATASCAD)); + row.add(scad.get(SCAD_IMPORTO)); + row.add(scad.get(SCAD_IMPORTOVAL)); + row.add(riga.get(PART_DESCR)); + 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++) if (ap.exist(pa)) + { + const TRectype& pag = ap.row(pa); + + TToken_string& row = scadenze.row(-1); + row.add(""); + row.add(riga.get(PART_DATADOC)); + row.add(riga.get(PART_DATAREG)); + row.add(scad.get(SCAD_DATASCAD)); + row.add(pag.get_real(SCAD_IMPORTO).string(0, 0)); + row.add(pag.get_real(SCAD_IMPORTOVAL).string(0, 2)); + row.add(riga.get(PART_DESCR)); + row.add(riga.get(PART_NUMDOC)); + row.add(riga.get(PART_PROTIVA)); + } + } + } + scadenze.force_update(); + } + + return TRUE; +} + +HIDDEN bool numpart_handler(TMask_field& f, KEY k) +{ + if (k == K_TAB && f.dirty()) + { + const TMask& m = f.mask(); + const int anno = m.get_int(P_ANNO); + const TString16 num = f.get(); + if (anno > 0 && num.not_empty()) + { + TSheet_field& sheet = (TSheet_field&)m.field(P_PARTITE); + for (int i = 0; i < sheet.items(); i++) + { + TToken_string& row = sheet.row(i); + if (anno == row.get_int(0)) // Se corrisponde l'anno e ... + if (num == row.get()) // corrisponde il numero partita ... + { + sheet.select(i); // Seleziona la partita + partite_notify(sheet, i, K_TAB); // ed esplodi le sue righe + break; + } + } + if (i >= sheet.items()) + f.warning_box("Partita inesistente"); + } + } + return TRUE; +} + +HIDDEN bool annopart_handler(TMask_field& f, KEY k) +{ + if (k == K_TAB && f.dirty() && f.get().not_empty()) + { + TMask_field& n = f.mask().field(P_NUMERO); + n.set_dirty(); + numpart_handler(f, k); + } + return TRUE; +} + + +HIDDEN bool scambio_handler(TMask_field& f, KEY k) +{ + const TMask& m = f.mask(); + if (k == K_SPACE && m.is_running()) + { + const TSheet_field& sheet = (TSheet_field&)m.field(P_SCADENZE); + sheet.swap_columns(103, 109); + sheet.swap_columns(104, 110); + } + return TRUE; +} + bool TPrimanota_application::edit_partite(int riga) { TToken_string& cgr = cgs().row(riga); const TBill b(cgr, 2, 0x3); // Legge il conto della riga selezionata if (!b.ok()) return FALSE; - + begin_wait(); - TString caption("Partite aperte del conto "); - caption << b.gruppo() << ' ' << b.conto() << ' ' << b.sottoconto(); + TMask mask("cg2100p"); // Inizializzazione maschera di selezione partite - TArray_sheet a(-1, -1, 0, 0, caption, "Anno|Numero@7|Dare@15R|Avere@15R|Descrizione@50", 0x8); + const char tipocf[2] = { b.tipo(), '\0' }; + mask.set(P_TIPOC, tipocf); + mask.set(P_GRUPPO, b.gruppo()); + mask.set(P_CONTO, b.conto()); + mask.set(P_SOTTOCONTO, b.sottoconto()); + mask.set(P_DESCR, ((TBill&)b).descrizione()); + + mask.set_handler(P_ANNO, annopart_handler); + mask.set_handler(P_NUMERO, numpart_handler); + mask.set_handler(P_SCAMBIO, scambio_handler); + + TSheet_field& sheet = (TSheet_field&)mask.field(P_PARTITE); + sheet.set_notify(partite_notify); + TString_array& a = sheet.rows_array(); TLocalisamfile partita(LF_PARTITE); - partita.setkey(2); // Chiave per conto - - partita.zero(); + partita.zero(); if (b.tipo() > ' ') // Ignora gruppo e conto dei clifo { partita.put(PART_TIPOCF, b.tipo()); @@ -472,76 +614,121 @@ bool TPrimanota_application::edit_partite(int riga) } else b.put(partita.curr()); // Scrive completamente i conti normali - const TRectype recpar(partita.curr());// Record campione + const TRectype filter(partita.curr());// Record campione int ult, anno; // Anno ultima partita TString16 last, num; // Ultimo numero partita e numero corrente - long nreg; TString desc; // Descrizione prima partita del gruppo + TString16 numdoc; + TString16 datadoc; + TImporto saldo; // Saldo ultima parita + TImporto documenti; // Documenti ultima parita + TImporto pagamenti; // Pagamenti ultima parita + TImporto importi; // Altri importi ultima parita TToken_string r(80); const long curreg = curr_mask().get_long(F_NUMREG); // Numero registrazione - for (int err = partita.read(_isgteq); err == NOERR && partita.curr() == recpar; err = partita.next()) + for (int err = partita.read(_isgteq); err == NOERR && partita.curr() == filter; err = partita.next()) { - num = partita.get(PART_NUMPART); anno = partita.get_int(PART_ANNO); - nreg = partita.get_long(PART_NREG); - + num = partita.get(PART_NUMPART); + + const int tipomov = partita.get_int(PART_TIPOMOV); if (num == last && anno == ult) // Se la partita e' la stessa ... { const TImporto i(partita.get_char(PART_SEZ), partita.get_real(PART_IMPORTO)); + switch (tipomov) + { + case 1: + case 2: + documenti += i; + break; + case 3: + pagamenti += i; + break; + default: + importi += i; + break; + } saldo += i; // ... incrementa totale } else { - if (!saldo.is_zero() || nreg == curreg) // Se il saldo non e' nullo allora e' aperta + if (!saldo.is_zero()) // Se il saldo non e' nullo allora e' aperta { r.cut(0); - r.add(ult); r.add(last); - saldo.add_to(r, 2); + r.add(ult); + r.add(last); + r.add(datadoc); + r.add(numdoc); + add_importo(r, saldo); + add_importo(r, documenti); + add_importo(r, pagamenti); + add_importo(r, importi); r.add(desc); a.add(r); // Aggiunge partita alla lista } - ult = anno; - last = num; - desc = partita.get(PART_DESCR); + ult = anno; + last = num; + numdoc = partita.get(PART_NUMDOC); + datadoc = partita.get(PART_DATADOC); + desc = partita.get(PART_DESCR); + saldo.set(partita.get_char(PART_SEZ), partita.get_real(PART_IMPORTO)); + switch (tipomov) + { + case 1: + case 2: + documenti = saldo; + pagamenti.set('D', ZERO); + importi.set('D', ZERO); + break; + case 3: + pagamenti = saldo; + documenti.set('D', ZERO); + importi.set('D', ZERO); + break; + default: + importi = saldo; + documenti.set('D', ZERO); + pagamenti.set('D', ZERO); + break; + } } } - if (!saldo.is_zero() || nreg == curreg) // Aggiunge ultima partita se aperta + if (!saldo.is_zero()) // Aggiunge ultima partita se aperta { r.cut(0); - r.add(ult); r.add(last); - saldo.add_to(r, 2); + r.add(ult); + r.add(last); + r.add(datadoc); + r.add(numdoc); + add_importo(r, saldo); + add_importo(r, documenti); + add_importo(r, pagamenti); + add_importo(r, importi); r.add(desc); a.add(r); } end_wait(); - bool dirty = FALSE; - - KEY k = a.items() > 0 ? K_ENTER : K_ESC; // Esce se non ci sono righe - while (k == K_ENTER) + if (a.items() > 0) { - k = a.run(); - if (k == K_ENTER) - { - const int anno = a.row().get_int(0); - const TString16 num = a.row().get(1); - dirty |= edit_scadenze(anno, num); // Edita pagamenti - } - } + sheet.force_update(); + mask.run(); + } - return dirty; + return TRUE; } int TPrimanota_application::nuovo_pagamento(TPartita& partita, int rata, int rmov, TRectype& part) -{ +{ +/* CHECKD(rata >= 1 && rata <= partita.rate(), "Rata errata ", rata); CHECKD(!partita.rata_pagata(rata), "Rata pagata ", rata); @@ -569,7 +756,7 @@ int TPrimanota_application::nuovo_pagamento(TPartita& partita, int rata, int rmo part.zero(PART_REG); part.zero(PART_PROTIVA); - part.put(PART_SEZ, (partita.totale().sezione() == 'D') ? 'A' : 'D'); +// part.put(PART_SEZ, (partita.totale().sezione() == 'D') ? 'A' : 'D'); part.zero(PART_IMPORTO); // Azzera importi vari part.zero(PART_IMPOSTA); part.zero(PART_SPESE); @@ -662,105 +849,22 @@ int TPrimanota_application::nuovo_pagamento(TPartita& partita, int rata, int rmo part.put(PART_CODCABPR, tmp); return nriga+1; +*/ + return 1; } // Edit scadenze relative all'anno/numero partita specificati -bool TPrimanota_application::edit_scadenze(int anno, const char* num) +bool TPrimanota_application::edit_scadenze(const TBill& clifo, int anno, const char* num) { TString caption; caption.format("Pagamenti della partita %s dell'anno %d", num, anno); TArray_sheet a(-1, -1, 0, 0, caption, "Rata|Data@10|Dare@15R|Avere@15R|Descrizione@50|Riga", 0x8); - TPartita& partita = _partite.partita(anno, num); - + TPartita& partita = _partite.partita(clifo, anno, num); + const long curreg = curr_mask().get_long(F_NUMREG); // Numero registrazione corrente const int currig = cgs().selected()+1; // Numero riga corrente - TToken_string r(80); // Work string - - KEY k = K_ENTER; - bool dirty = TRUE, one_dirty = FALSE; - - while (k == K_ENTER) - { - if (dirty) - { - const TString desc(partita.descrizione()); - - a.destroy(); - long nr; - - const char sez_par = partita.riga(1).get_char(PART_SEZ); - - for (int s = 1; s <= partita.rate(); s++) - { - const TRectype& rata = partita.rata(s); - r.cut(0); - r.add(rata.get(SCAD_NRATA)); - r.add(rata.get(SCAD_DATASCAD)); - if (sez_par == 'A') - { - r.add(rata.get(SCAD_IMPORTO)); - r.add(""); - } - else - { - r.add(""); - r.add(rata.get(SCAD_IMPORTO)); - } - r.add(desc); - r.add("S"); - nr = a.add(r); - if (partita.rata_pagata(s)) - a.disable(nr); - - for (int p = 1; p <= partita.righe(); p++) - { - const TRectype& paga = partita.riga(p); - if (paga.get_int(PART_NRATA) == s) - { - r.cut(0); - r.add(s); - r.add(paga.get(PART_DATAREG)); - const char sez = paga.get_char(PART_SEZ); - if (sez == 'D') - { - r.add(paga.get(PART_IMPORTO)); - r.add(""); - } - else - { - r.add(paga.get(PART_IMPORTO)); - r.add(""); - } - r.add(paga.get(PART_DESCR)); - r.add(paga.get(PART_NRIGA)); - nr = a.add(r); - if (paga.get_long(PART_NREG) != curreg || paga.get_int(PART_NUMRIG) != currig) - a.disable(nr); - } - } - } - } - - k = a.run(); - if (k == K_ENTER) - { - const int rata = a.row().get_int(0); - int nrig = a.row().get_int(5); // Numero riga pagamento corrente - - TRectype part(LF_PARTITE); - - if (nrig == 0) // Se ho cliccato su una scadenza ... - nrig = nuovo_pagamento(partita, rata, currig, part); - else - part = partita.riga(nrig); - - dirty = edit_pagamento(partita, part); - one_dirty |= dirty; - } // if k == K_ENTER - } // while k == K_ENTER - - return one_dirty; + return FALSE; } @@ -792,7 +896,8 @@ static bool importopag_handler(TMask_field& f, KEY k) bool TPrimanota_application::edit_pagamento(TPartita& p, TRectype& part) -{ +{ +/* TMask m("cg2100s"); m.set_handler(S_IMPORTOPAG, importopag_handler); @@ -880,6 +985,8 @@ bool TPrimanota_application::edit_pagamento(TPartita& p, TRectype& part) } return key != K_ESC; +*/ + return FALSE; } bool TPrimanota_application::notify_cgline_deletion(TPartita& partita, long nreg, int numrig) @@ -887,7 +994,7 @@ bool TPrimanota_application::notify_cgline_deletion(TPartita& partita, long nreg bool found = FALSE; const int riga_ritenute = type2pos('F'); - for (int r = partita.righe(); r > 0; r--) + for (int r = 1; r > 0; r--) { TRectype pag(partita.riga(r)); @@ -917,19 +1024,19 @@ bool TPrimanota_application::notify_cgline_deletion(TPartita& partita, long nreg else error_box("Non esiste la riga dell'importo di un pagamento della riga %d", numrig); } - partita.remove_riga(pag); +// partita.remove_riga(pag); found = TRUE; } else { const int n = pag.get_int(PART_NUMRIG); pag.put(PART_NUMRIG, n-1); - partita.add_riga(pag); +// partita.add_riga(pag); } } else // numrig == 0 { - partita.remove_riga(pag); // Cancellazione pura e semplice +// partita.remove_riga(pag); // Cancellazione pura e semplice found = TRUE; // usata solo da ::remove } } // if reg == numreg diff --git a/cg/cg5300.cpp b/cg/cg5300.cpp index ff2b0971d..140a34e5f 100755 --- a/cg/cg5300.cpp +++ b/cg/cg5300.cpp @@ -51,7 +51,7 @@ protected: // Relapp protected: void check_registers(int year); void init_array(TMask& m, bool update); - static bool sheet_action(int r, KEY k); + static bool sheet_action(TSheet_field& s, int r, KEY k); public: @@ -175,7 +175,7 @@ bool TParaliq_app::user_destroy() return TRUE; } -bool TParaliq_app::sheet_action(int r, KEY k) +bool TParaliq_app::sheet_action(TSheet_field& s, int r, KEY k) { // non si possono cancellare o aggiungere righe in PLA return (k != K_DEL && k != K_INS); diff --git a/cg/cg5500.cpp b/cg/cg5500.cpp index 3e107fff4..8e0a97e5c 100755 --- a/cg/cg5500.cpp +++ b/cg/cg5500.cpp @@ -214,13 +214,13 @@ void Visliq_app::set_mask_freq(TMask& m) } -bool Visliq_app::sheet_action(int r, KEY k) +bool Visliq_app::sheet_action(TSheet_field& s, int r, KEY k) { // non si possono cancellare o aggiungere righe return (k != K_DEL && k != K_INS); } -bool Visliq_app::vers_action(int r, KEY k) +bool Visliq_app::vers_action(TSheet_field& s, int r, KEY k) { // non si possono cancellare o aggiungere righe return (k != K_DEL && k != K_INS); diff --git a/cg/cg5500.h b/cg/cg5500.h index 2f8538873..71e40a782 100755 --- a/cg/cg5500.h +++ b/cg/cg5500.h @@ -60,8 +60,8 @@ protected: static const char* link_handler(TMask&, int, const char*, bool doubleclick); - static bool sheet_action(int r, KEY k); - static bool vers_action(int r, KEY k); + static bool sheet_action(TSheet_field& s, int r, KEY k); + static bool vers_action(TSheet_field& s, int r, KEY k); public: diff --git a/cg/deliva.frm b/cg/deliva.frm index b6f11f97d..c1fa9a85d 100755 --- a/cg/deliva.frm +++ b/cg/deliva.frm @@ -213,7 +213,7 @@ STRINGA BEGIN KEY "Partita IVA" PROMPT 12 30 "" - PICTURE "# # # # # # # ~ ~ ~ #" + PICTURE "# # # # # # # ^ ^ ^ #" FIELD 6->PAIV END @@ -229,7 +229,7 @@ NUMERO BEGIN KEY "Anno di versamento" PROMPT 40 35 "" - PICTURE "~ ~ @ @" + PICTURE "^ ^ @ @" FIELD CODTAB[6,9] END @@ -299,7 +299,7 @@ NUMERO BEGIN KEY "Importo in cifre" PROMPT 20 52 "" - PICTURE "###.###.###~~~" + PICTURE "###.###.###^^^" FIELD R0 END @@ -347,7 +347,7 @@ STRINGA BEGIN KEY "Codice Filiale" PROMPT 70 62 "" - PICTURE "~ ~ @ @" + PICTURE "^ ^ @ @" FIELD S8 END diff --git a/cg/pagament.cpp b/cg/pagament.cpp index c26822114..ef90de5d9 100755 --- a/cg/pagament.cpp +++ b/cg/pagament.cpp @@ -1,1322 +1,1462 @@ -#include - -#include "pagament.h" - -#include -#include - -int TPagamento::_rata_ifield(int n, int f) const -{ - TToken_string& t = (TToken_string&)_rate[n]; - return t.get_int(f); -} - -real TPagamento::_rata_rfield(int n, int f) const -{ - TToken_string& t = (TToken_string&)_rate[n]; - return real(t.get(f)); -} - -TDate TPagamento::_rata_dfield(int n, int f) const -{ - TToken_string& t = (TToken_string&)_rate[n]; - return TDate(t.get(f)); -} - -const char* TPagamento::_rata_sfield(int n, int f) const -{ - static char kak[6]; - TToken_string& t = (TToken_string&)_rate[n]; - strcpy(kak,t.get(f)); - return kak; -} - - -bool TPagamento::ratapagata(int n) -{ - TToken_string& t = (TToken_string&)_rate[n]; - return t.items() > 6; -} - - - -void TPagamento::set_intervallo_rate(int in) -{ - _dirty = TRUE; - if (_mcomm && (in % 30) != 0) - _mcomm = FALSE; - for (int i = 0; i < n_rate(); i++) - { - TToken_string& ts = rata(i); - ts.add(i == 0 ? (scad_rata(0) == 0 ? "0" : format("%d",in)) - : format("%d",in), 0); - } -} - -void TPagamento::set_mese_commerciale(bool v, int& sscad) -{ - _dirty = FALSE; - if (_mcomm == v) return; - if (sscad == -1) sscad = 30; - - if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1); - set_intervallo_rate(sscad); - - _mcomm = v; -} - -void TPagamento::set_rate_differenziate(int v) -{ - _dirty = FALSE; - if (!_rdiff && v == 2) return; - - if (v == 2 && (100 % n_rate()) == 0) - { - int p = 100 / n_rate(); - for (int i = _tpr < 4 ? 0 : 1; i < n_rate(); i++) - { - TToken_string& tt = rata(i); - tt.add(p,1); - } - _rdiff = !(v == 2); - _dirty = TRUE; - } -} - -void TPagamento::set_tipo_prima_rata(int v, int sscad) -{ - _dirty = FALSE; - if (_tpr == v) return; - - if (v < 4 && _tpr > 3) - { - for (int i = n_rate() - 1; i > 0; i--) - { - TToken_string& tt = rata(i); - tt.add(scad_rata(i-1),0); - tt.add(tipo_rata(i-1),2); - tt.add(ulc_rata(i-1),5); - } - _rate.add(NULL,0); - _rate.pack(); - } - else if ( _tpr < 4 && v > 3) - { - TToken_string* ttn = new TToken_string(32); - ttn->add(0,0); - ttn->add(0,1); - ttn->add(1,2); - ttn->add("",3); - ttn->add("",4); - ttn->add("",5); - _rate.insert(ttn,0); - for (int i = 0; i < (n_rate()-1); i++) - { - TToken_string& tt = rata(i); - tt.add(scad_rata(i+1),0); - tt.add(tipo_rata(i+1),2); - tt.add(ulc_rata(i+1),5); - } - } - _tpr = v; - _dirty = TRUE; -} - -void TPagamento::set_numero_rate(int n, int sscad) -{ - _dirty = FALSE; - if (n == 0 || n == n_rate()) return; - - real p = real(100) / real(n); - p.round(2); - int nr = n_rate(); - int first = _tpr < 4 ? 0 : 1; - real sum = 0.0; - - for (int i = first; sum < real(100.0); i++) - { - if ((real(100.0) - sum) < p) - p = real(100.0) - sum; - - sum += p; - - // if necessary add remainder on first one - if ((real(100.0) - sum) /* still */ < p) - { - real prc = perc_rata(first); - prc += real(100.0) - sum; - TToken_string& rt = rata(first); - rt.add(prc.string(),1), - sum = 100; - } - - set_rata(i, real(p), - i == 0 ? (i < nr ? scad_rata(0) : 0): - (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad), - (i < nr ? tipo_rata(i) : tipo_rata(nr-1))); - } - // erase remaining - for (; i < nr; i++) - _rate.add(NULL,i); - _rate.pack(); - - _dirty = TRUE; -} - - -void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata) -{ - if (mcomm) - { - int nm = scad / 30; - int ny = nm / 12; - nm %= 12; - - int newm = d.month() + nm; - if (newm > 12) { newm -= 12; ny++; } - - bool last = d.is_end_month() && inizio_scadenza() == 'M'; - - int dy = d.day(); - - // la palla del febbraio & c. - if (rata > 1) - { - TDate oldd(data_rata(rata-2)); - if (oldd.day() > dy) dy = oldd.day(); - } - - d.set_day(1); // il giorno 1 ce l'hanno tutti - d.set_month(newm); - d.set_year(d.year()+ny); - - d.set_end_month(); - if (!last && dy < d.day()) - d.set_day(dy); - } - else - { - d += scad; - } - - // riaggiusta la minchia se ci sono scadenze fissate - if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0) - { - for (int i = 0; i < 3; i++) - { - if (_fixd[i] > d.day()) - { - if (d.last_day(d.month(), d.year()) <= _fixd[i]) - d.set_day(_fixd[i]); - else d.set_end_month(); - break; - } - } - - if (i == 3) - { - if (_fixd[0] > 0 && _fixd[0] < d.day()) - { - d.set_day(_fixd[0]); - d.set_month(d.month() == 12 ? 1 : d.month() + 1); - } - } - - } -} - - -void TPagamento::set_default_type(int type, bool change_existing) -{ - _def_tpr = type; - if (change_existing) - { - for (int i = 0; i < n_rate(); i++) - { - TToken_string& tt = rata(i); - tt.add(type, 2); - } - _dirty = TRUE; - } -} - -void TPagamento::set_default_ulc(const char* ulc, bool change_existing) -{ - _def_ulc = ulc; - if (change_existing) - { - for (int i = 0; i < n_rate(); i++) - { - TToken_string& tt = rata(i); - tt.add(ulc, 5); - } - _dirty = TRUE; - } -} - -void TPagamento::remove_rata(int i) -{ - // non fa nessun ricalcolo, si limita ad impacchettare se - // necessario - _rate.add(NULL,i); - _rate.pack(); - _dirty = TRUE; -} - -TToken_string& TPagamento::add_rata(real perc, int day, int type, const char* ulc) -{ - TToken_string* tt = new TToken_string(16); - tt->add(day); // scadenza - tt->add(perc.string()); // percentuale - tt->add(type); // tipo - tt->add(""); - tt->add(""); - tt->add(ulc); - _rate.add(tt); - _dirty = TRUE; - return *tt; -} - -TToken_string& TPagamento::set_rata (int index, real perc, int day, int type, - const char* ulc, const char* imp, - const char* data) -{ - TToken_string* tt = (TToken_string*)_rate.objptr(index); - const bool nwr = (tt == NULL); - if (nwr) tt = new TToken_string(16); - - tt->add(day,0); // scadenza - tt->add(perc.string(),1); // percentuale - tt->add(type,2); // tipo - tt->add(data == NULL ? "" : data,3); - tt->add(imp == NULL ? "" : imp,4); - tt->add(ulc == NULL ? "" : ulc,5); - - if (!nwr) - { - if (index > _rate.items()) - { - error_box("Rate non contigue"); - delete tt; - } - } - else - { - _rate.add(tt,index); - _dirty = TRUE; - } - return *tt; -} - -void TPagamento::set_imprata(int i, real r) -{ - TToken_string& tt = (TToken_string&)_rate[i]; - TDate d = _inizio; - - for (int n = 0; n <= i; n++) - next_scad(d, scad_rata(n), _mcomm, n); - - tt.add((const char*)d, 3); - tt.add(r.string(), 4); -} - -TToken_string& TPagamento::set_rata(int index, const real& howmuch, - const TDate& date, int type,const char* ulc, bool pagato) -{ - // calcola percentuali e scadenze a partire dagli importi - TToken_string* tt = (TToken_string*)_rate.objptr(index); - - const bool nwr = (tt == NULL); // nuova rata - - if (nwr) tt = new TToken_string(16); - - TDate oldd = index > 0 ? data_rata(index -1) : _inizio; - int day = date - oldd; - real toshare(_tpr < 4 ? _firstr : _secndr); - real perc = (_tpr > 3 && index == 0) ? ZERO : howmuch/toshare; - perc *= real(100.0); - perc.round(2); - - tt->add(day,0); // scadenza - tt->add(perc.string(),1); // percentuale - tt->add(type,2); // tipo - tt->add(date.string(),3); - tt->add(howmuch.string(),4); - tt->add(ulc,5); - if (pagato) tt->add("X",6); - - if (!nwr) - { - if (index > _rate.items()) - { - error_box("Rate non contigue"); - delete tt; - } - } - else - { - _rate.add(tt, index); - _dirty = TRUE; - } - return *tt; -} - - - -word TPagamento::validate() const -{ - word res = 0x0000; - real r(0.0); - - int first = _tpr < 4 ? 0 : 1; - real toshare(_tpr < 4 ? _firstr : _secndr); - TDistrib ds(toshare,0); - - // check percentages & prepare slicer - for (int i = first; i < n_rate(); i++) - { - real p(perc_rata(i)); - ds.add(p); - r += p; - } - - if (r != real(100.0)) - res |= P_RSUM; - - - if (_inited) - { - ds.init(toshare); - // check importi rate consistenti con la percentuale - for (int i = first; i < n_rate(); i++) - { - real r1(tpay_rata(i)); - real r2(ds.get()); - if (r1 != r2) - { res |= P_IMPNC; break; } - } - - // check errori date scadenze (se istanziate) - TDate d(data_rata(0)); - if (d < _inizio) - res |= P_INIZIO; - for (i = 1; i < n_rate(); i++) - { - if (data_rata(i) <= d) - { res |= P_SCAD; break; } - d = data_rata(i); - } - } - return res; -} - - -void TPagamento::strerr(word err, TString& s) -{ - s = "Errore:"; - if (err & P_RSUM) - s << "\n Le percentuali non sommano a 100"; - if (err & P_IMPNC) - s << "\n Le percentuali sono inconsistenti con gli importi"; - if (err & P_SCAD) - s << "\n Le scadenze non sono consecutive"; - if (err & P_INIZIO) - s << "\n La prima rata e' antecedente alla data movimento"; -} - -const char* TPagamento::desc_tpr() const -{ - const char* o; - switch (_tpr) - { - case 0: o = "Totale su tutte le rate"; break; - case 1: o = "Tutte le imposte su 1a"; break; - case 2: o = "Tutte le spese su 1a"; break; - case 3: o = "Imposte + spese su 1a"; break; - case 4: o = "Spese + merce su 1a"; break; - case 5: o = "Merce + imposte su 1a"; break; - case 6: o = "Tutta la merce su 1a"; break; - } - return o; -} - -const char* TPagamento::desc_tipo(int i) const -{ - const char* o; - switch (i) - { - case 1: o = "Rimessa diretta o contanti"; break; - case 2: o = "Tratta"; break; - case 3: o = "Ricevuta bancaria"; break; - case 4: o = "Cessione"; break; - case 5: o = "Paghero'"; break; - case 6: o = "Lettera di credito"; break; - case 7: o = "Tratta accettata"; break; - case 8: o = "Rapporti interbancari diretti"; break; - case 9: o = "Bonifici"; break; - case 10: o = "Altro pagamento"; break; - } - return o; -} - -word TPagamento::recalc_rate(int row, bool is_perc_modified, - const char* new_value, const char* scad, - const char* typ, int rdiff, bool mcomm, - bool& need_recalc) - // ricalcola le rate sulla base di parametri modificati sulla riga row - // parametri: tutti i const char* possono essere NULL, il che vuol dire - // che i dati corrispondenti non sono stati modificati; - // se new_value non e' NULL puo' essere la percentuale (e - // allora is_perc_modified e' TRUE) o l'importo. Non e' - // possibile modificare entrambi; se succede viene data - // priorita' alla percentuale. -{ - CHECK(!(!is_perc_modified && new_value != NULL && !_inited), - "A'stronzo! E famme 'na pippa! Me dai n'importo che nun ce sta? Ma Vaffanculo!"); - - if (_rate.items() == 0) return P_OK; - - real rsum(0.0), newv(0.0), rmax(0.0); - int oldtype = tipo_rata(0); - int oldscad = scad_rata(0); - TDate lastdate = data_rata(0); - int first = _tpr < 4 ? 0 : 1; - TArray srate(_rate); // rate come erano - - - if (srate.items() > 1) - { - // calcola defaults per tipo pagamento e scadenza - // nel caso di rate nuove - oldscad = scad_rata(1); - } - - if (oldscad == 0) oldscad = 30; - if (oldtype == 0) oldtype = 1; - - if (new_value != NULL) - { - newv = new_value; - rmax = is_perc_modified? (real) 100.0 : (_tpr < 4 ? _firstr : _secndr); - if (newv > rmax) return P_RSUM; - } - - bool exhausted = FALSE; - - for (int i = first; i < srate.items(); i++) - { - if (i == row) - { - if (typ != NULL) - { - TToken_string& tt = rata(row); - TToken_string& ss = (TToken_string&)srate[row]; - tt.add(typ,2); - ss.add(typ,2); - // no error is possible - } - - if (scad != NULL) - { - // if !_inited scad e' il n. giorni, se no e' la rata - if (_inited) - { - TToken_string& tt = rata(row); - TToken_string& ss = (TToken_string&)srate[row]; - lastdate = scad; - // controlla errore sulla data scadenza - if (i > 0) - { - oldscad = (int)(lastdate - data_rata(i-1)); - if (oldscad <= 0l) return P_SCAD; - } - else if (lastdate < _inizio) return P_INIZIO; - tt.add(scad,3); - ss.add(scad,3); - // ricalcola rate successive: se si vuole modificarne solo una - // ci si fotte e si disabilita il ricalcolo - TDate ddd (lastdate); - for (int j = row+1; j < srate.items(); j++) - { - TToken_string& tt = rata(j); - TToken_string& ss = (TToken_string&)srate[j]; - next_scad(ddd,scad_rata(j),mcomm,j); - tt.add(ddd.string(),3); - ss.add(ddd.string(),3); - need_recalc = TRUE; - } - } - else - { - // nulla di speciale visto che si memorizza la derivata - int sc = atoi(scad); - for (int i = 0; i < row; i ++) - sc -= scad_rata(i); - if (sc < 0 || (row > 0 && sc == 0)) return P_SCAD; - if (_mcomm && (sc % 30) != 0) _mcomm = FALSE; - TToken_string& tt = rata(row); - TToken_string& ss = (TToken_string&)srate[row]; - tt.add(sc,0); - ss.add(sc,0); - need_recalc = TRUE; - } - } - - // here's the bell - if (new_value != NULL) - { - if (newv == ZERO || (rsum+newv) > rmax) - return P_RSUM; - // did not sforate - rsum += newv; - TToken_string& rt = rata(row); - // setta nuovo valore e ricalcola cio' che ne consegue - if (is_perc_modified) rt.add(new_value,1); - else rt.add(new_value,4); - // riaggiusta le rate rimanenti - real remainder(0.0); remainder = rmax - rsum; - if (!(exhausted = (remainder == real(0.0)))) - { - // controlla se rdiff e' compatibile con - // i dati e se e' il caso riaggiusta - if (rdiff == 3 && !((remainder % newv.integer()) == ZERO)) - rdiff = 2; - if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) - rdiff = 1; - _rdiff = (rdiff == 1 || rdiff == 3 || rdiff == 4); - - // procedi - if (rdiff == 1) - { - // cancella tutte le rate successive, aggiungi un'unica rata - // con il resto dell'importo - if (row < (srate.items()-1)) - { - TToken_string& trt = rata(row+1); - trt.add(remainder.string(), is_perc_modified ? 1 : 4); - for(int j = row+2; j < srate.items(); j++) - _rate.add(NULL,j); - } - else - { - // l'importante e' esagerare - for(int j = row+1; j < srate.items(); j++) - _rate.add(NULL,j); - - TToken_string& trt = add_rata(is_perc_modified ? remainder : (real) 0.0, - oldscad, oldtype); - if (!is_perc_modified) trt.add(remainder.string(),4); - if (_inited) - { - TDate dd = data_rata(row); - next_scad(dd,oldscad,mcomm,row); - trt.add(dd.string(),3); - } - } - } - else // rate non differenziate (dall'inizio o da row) - { - // ripartisci l'importo nel numero necessario di rate per - // mantenere costante il valore - real sum(0.0); - if (_inited) lastdate = data_rata(rdiff == 2 ? first : row); - - TDate dd(lastdate); - int type = oldtype; - int nscd = oldscad; - - int frs = (rdiff == 3 || rdiff == 4) ? row+1 : first; - real mx = (rdiff == 3 || rdiff == 4) ? remainder : rmax; - - // cancelliamo tutto, va' - for (int j = frs; j < srate.items(); j++) - _rate.add(NULL,j); - - if (rdiff != 4) - for (j = frs; sum < mx; j++) - { - // se c'e' la vecchia rata si tengono i parametri - // altrimenti si calcolano - if (j < srate.items()) - { - TToken_string& trt = (TToken_string&)srate[j]; - if (_inited) dd = trt.get(3); - type = atoi(trt.get(2)); - nscd = j == 0 ? 0 : atoi(trt.get(0)); - if (type == 0) type = 1; - if (j > 0 && nscd == 0) nscd = oldscad; - if (_inited && dd == lastdate && j > 0) - next_scad(dd,nscd,mcomm,j); - } - else if (_inited) - { - if (dd <= botime) dd = lastdate; - next_scad(dd,nscd,mcomm,j); - } - - TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, - nscd, type); - if (_inited) - ttr.add(dd.string(), 3); - if (!is_perc_modified) - ttr.add(newv.string(),4); - sum += newv; - } - else // rdiff == 4; uguali finche' possibile - { - bool basta = FALSE; - for (j = frs; ; j++) - { - // ultima rata puo' differire dalle precedenti - if (mx - sum <= newv) - { - newv = mx - sum; - basta = TRUE; - } - // se c'e' la vecchia rata si tengono i parametri - // altrimenti si calcolano - if (j < srate.items()) - { - TToken_string& trt = (TToken_string&)srate[j]; - if (_inited) dd = trt.get(3); - type = atoi(trt.get(2)); - nscd = j == 0 ? 0 : atoi(trt.get(0)); - if (type == 0) type = 1; - if (j > 0 && nscd == 0) nscd = oldscad; - if (_inited && dd == lastdate && j > 0) - next_scad(dd,nscd,mcomm,j); - } - else if (_inited) next_scad(dd,nscd,mcomm,j); - - TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, - nscd, type); - if (_inited) - ttr.add(dd.string(), 3); - if (!is_perc_modified) - ttr.add(newv.string(),4); - if (basta) break; - sum += newv; - } - } - } - - } - else // exhausted - { - for(int j = row+1; j < srate.items(); j++) - _rate.add(NULL,j); - } - - - if (_inited) - { - // ricalcola il valore secondario (non modificato) - real toshare(100.0); - if (is_perc_modified) - toshare = (_tpr < 4 ? _firstr : _secndr); - TDistrib dt(toshare,0); - - for (int j = first; j < _rate.items(); j++) - { - real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); - real zpx = rvl/rmax; // percentuale - dt.add(zpx); - } - for (j = first; j < _rate.items(); j++) - { - TToken_string& tr = rata(j); - real rvl = dt.get(); - tr.add(rvl.string(), is_perc_modified ? 4 : 1); - } - } - - need_recalc = TRUE; - return P_OK; - } // new_value != NULL - } - else // i != row modified - { - if (i > 0 && !((perc_rata(i-1) == perc_rata(i)))) - { - if (rdiff == 2) rdiff = 1; - _rdiff = FALSE; - } - if (is_perc_modified) - rsum += perc_rata(i); - else - rsum += tpay_rata(i); - - lastdate = data_rata(i); - oldtype = tipo_rata(i); - oldscad = scad_rata(i); - if (_inited && i > 0) - { - if (data_rata(i) <= data_rata(i-1)) - return P_SCAD; - } - else if (lastdate < _inizio) - return P_INIZIO; - } - } - - return P_OK; -} - - -bool TPagamento::read(TTable* t, TTable* r) -{ - // puo' chiamarla chiunque - bool istnew = FALSE; - if (t == NULL) - { - t = new TTable("%CPG"); - istnew = TRUE; - } - t->zero(); t->put("CODTAB",_code); - if (t->read() != NOERR) return FALSE; - - // set everything - _rdiff = t->get_bool("B1"); - _mcomm = t->get_bool("B0"); - _tpr = *((const char*)(t->get("S3"))); - _inscad = *((const char*)(t->get("S1"))); - _code = t->get("CODTAB"); - _name = t->get("S0"); - _fixd[0] = t->get_int("I0"); - _fixd[1] = t->get_int("I1"); - _fixd[2] = t->get_int("I2"); - - // TBI aggiusta _inizio secondo INSCAD; vedi mese commerciale etc. - if (_inscad == 'M') - { - if (_mcomm) _inizio.set_month(_inizio.month() == 2 ? 28 : 30); - else _inizio.set_end_month(); - } - else if (_inscad == 'F' && _mcomm && _inizio.month() == 31) - _inizio.set_month(30); - - // leggi rate e scadenze - bool isrnew = FALSE; - if (r == NULL) - { - r = new TTable("%RPG"); - isrnew = TRUE; - } - TString s(16); - - for (int i = 0; ;i++) - { - r->zero(); s.format("%s%3d",(const char*)_code, i); - r->put("CODTAB", (const char*)s); - if (r->read() != NOERR) break; - TToken_string* tt = new TToken_string(16); - tt->add((const char*)(r->get("I0"))); // scadenza - tt->add((const char*)(r->get("R0"))); // percentuale - tt->add((const char*)(r->get("I1"))); // tipo - // data e importo - TDate d = _inizio; - next_scad(d,(int)(r->get_long("I0")),_mcomm,i); - tt->add((const char*)d); - tt->add(""); - tt->add(r->get("S1")); - _slicer.add((real)r->get("R0")); - _rate.add(tt); - } - - if (istnew) delete t; - if (isrnew) delete r; - - return TRUE; -} - - -int TPagamento::write(TTable& r) -{ - // Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una - // relapp, che ha scritto il file principale - - TString s(16); int err = NOERR; - for (int i = 0; err == NOERR && i < n_rate(); i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - r.put("I0", (long)scad_rata(i)); - r.put("R0", perc_rata(i).string()); - r.put("I1", (long)tipo_rata(i)); - r.put("S1", ulc_rata(i)); - err = r.write(); - } - return err; -} - -int TPagamento::rewrite(TTable& r) -{ - TString s(16); int err = NOERR; - for (int i = 0; err == NOERR && i < n_rate(); i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - bool was = (r.read() == NOERR); - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - r.put("I0", (long)scad_rata(i)); - r.put("R0", perc_rata(i).string()); - r.put("I1", (long)tipo_rata(i)); - r.put("S1", ulc_rata(i)); - err = (was ? r.rewrite() : r.write()); - } - // erase possible rates > current n. rates - for (;err == NOERR;i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - if (r.read() == NOERR) err = r.remove(); - else break; - } - return err; -} - -int TPagamento::remove(TTable& r) -{ - TString s(16); int err = NOERR; - for (int i = 0 ; err == NOERR; i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - if (r.read() == NOERR) err = r.remove(); - else break; - } - return err; -} - -void TPagamento::set_rate_auto() -{ - // vedi rate esistenti e tipo prima rata - // deve fare riferimento ad un tipo pagamento esistente - // e sensato - int first = 0; - - real toslice = _firstr; - - if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1)) return; - if (_tpr > 1) // ripartisci _firstr su tutte le rate - { - first = 1; - toslice = _secndr; - } - - _slicer.init(toslice); - - if (_tpr > 3) - // prima rata obbligatoria - set_imprata(0, _firstr); - - for (int i = first; i < n_rate(); i++) - // setta le fette e le date di scadenza - set_imprata(i, _slicer.get()); -} - - - -void TPagamento::set_total(const real& imponibile, const real& imposta, const real& spese) -{ - _imponibile = imponibile; - _imposta = imposta; - _spese = spese; - _inited = TRUE; - - // istanzia _firstr e _secndr a seconda di _tpr - switch(_tpr) - { - case 0: - _firstr = _imponibile + _imposta + _spese; - _secndr = 0.0; - break; - case 1: - _firstr = _imposta; - _secndr = _imponibile + _spese; - break; - case 2: - _firstr = _spese; - _secndr = _imposta + _imponibile; - break; - case 3: - _firstr = _imposta + _spese; - _secndr = _imponibile; - break; - case 4: - _firstr = _spese + _imponibile; - _secndr = _imposta; - break; - case 5: - _firstr = _imponibile + _imposta; - _secndr = _spese; - break; - case 6: - _firstr = _imponibile; - _secndr = _imposta + _spese; - break; - } - - real toslice = _tpr > 1 ? _secndr : _firstr; - - _slicer.init(toslice, TRUE); - - for (int i = 0; i < _rate.items(); i++) - { - TToken_string& t = (TToken_string&)_rate[i]; - real rr(t.get(1)); - _slicer.add(rr); - } -} - - -void TPagamento::set_sheet(TSheet_field& sf, int sscad) -{ - sf.destroy(-1); - if (_inited && _rate.items() > 0) - { - // si istanzia uno sheet di primanota - for (int i = 0; i < n_rate(); i++) - { - TToken_string& ts = sf.row(-1); - // istanzia, o stronzo - ts.add((const char*)data_rata(i)); - ts.add(perc_rata(i).string()); - ts.add(tpay_rata(i).string()); - ts.add(tipo_rata(i)); - ts.add(desc_tipo(tipo_rata(i))); - if (ratapagata(i)) - { - sf.disable_cell(1,1); // percentuale - sf.disable_cell(1,2); // importo - } - } - } - else if (_rate.items() > 0) // not inited: set edit sheet - { - for (int i = 0, scr = 0; i < n_rate(); i++) - { - TToken_string& s = sf.row(-1); - scr += scad_rata(i); - s.add(scr); - s.add(perc_rata(i).string()); - s.add(tipo_rata(i)); - s.add(desc_tipo(tipo_rata(i))); - s.add(ulc_rata(i)); - } - } - else // new: set with 1 or 2 rates according to tpr - { - if (_tpr > 3) - add_rata(ZERO, sscad == -1 ? 0 : sscad, _def_tpr, _def_ulc); - add_rata(real(100.0), sscad == -1 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc); - - _dirty = TRUE; - - for (int i = 0, scr = 0; i < n_rate(); i++) - { - TToken_string& s = sf.row(-1); - scr += scad_rata(i); - s.add(scr); - s.add(perc_rata(i).string()); - s.add(tipo_rata(i)); - s.add(desc_tipo(tipo_rata(i))); - s.add(ulc_rata(i)); - } - } - if (_tpr > 3) - { - // disabilita campi da non toccare sulla prima rata - if (_inited) - { - sf.disable_cell(0,1); // percentuale - sf.disable_cell(0,2); // importo - } - else - { - sf.disable_cell(0,1); // percentuale - } - } - sf.force_update(); -} - -TPagamento::TPagamento(const char* codtab, const char* data) : -_slicer(0.0,0), _new(FALSE), _imponibile(0.0), _imposta(0.0), -_spese(0.0), _code(codtab), _dirty(FALSE), _inited(FALSE), -_def_tpr(1), _def_ulc("") -{ - _fixd[0] = _fixd[1] = _fixd[2] = 0; - if (data != NULL) - _inizio = data; - if (_code.blank() || !read()) - _new = TRUE; -// if (_new && data != NULL) error_box("Modalita' pagamento inesistente"); -} - - -/////////////////////////////////////////////////////////// -// TPartita -/////////////////////////////////////////////////////////// - -TPartita::TPartita(int anno, const char* num) - : _scad(LF_SCADENZE, SCAD_NRATA), _part(LF_PARTITE, PART_NRIGA) -{ - read(anno, num); -} - -int TPartita::add_riga(const TRectype& r) -{ - CHECK(r.num() == LF_PARTITE, "Tipo record errato"); - - const char sez = r.get_char(PART_SEZ); - const real val = r.get_real(PART_IMPORTO); - const TImporto imp(sez, val); - - TImporto grow(imp); - const int n = r.get_int(PART_NRIGA); - CHECK(n > 0, "Numero riga nullo"); - if (n <= righe()) - { - const TRectype& oldrow = riga(n); - const char osez = oldrow.get_char(PART_SEZ); - const real oval = oldrow.get_real(PART_IMPORTO); - const TImporto old(osez, oval); - grow -= old; - } - _totale += grow; - - if (rate() > 0) // Se sono in aggiornamento (non nella read!) - { - const int nr = r.get_int(PART_NRATA); - TRectype scad = rata(nr); - real ip(scad.get(SCAD_IMPORTOPAG)); - ip += grow.valore(); - scad.put(SCAD_IMPORTOPAG, ip); - add_rata(scad); - } - - return _part.add_row(r); -} - -void TPartita::remove_riga(TRectype& z) -{ - z.zero(PART_IMPORTO); - add_riga(z); - _part.destroy_row(z, TRUE); -} - -int TPartita::add_rata(const TRectype& r) -{ - return _scad.add_row(r); -} - -// Costruisce le righe della partita a partire da 1 -bool TPartita::read(int anno, const char* num) -{ - TRectype partita(LF_PARTITE); partita.zero(); - partita.put(PART_ANNO, anno); partita.put(PART_NUMPART, num); - _part.read(partita); - - TRectype scadenza(LF_SCADENZE); scadenza.zero(); - scadenza.put(SCAD_ANNO, anno); scadenza.put(SCAD_NUMPART, num); - _scad.read(scadenza); - - _totale.set('D', ZERO); // Azzera totale partita - - for (int i = 1; i <= righe(); i++) - { - const TRectype& r = riga(i); - const char sez = r.get_char(PART_SEZ); - const real val = r.get_real(PART_IMPORTO); - const TImporto imp(sez, val); - _totale += imp; - } - - return ok(); -} - -bool TPartita::reread() -{ - const int year = anno(); - const TString16 num = numero(); - return read(year, num); -} - -bool TPartita::write(bool re) -{ - const bool ok = _part.write(re) && _scad.write(re); - return ok; -} - -int TPartita::ultimo_pagamento(int rata) const -{ - int ultimo = 1; - - for (int p = 1; p <= righe(); p++) - { - const TRectype& paga = riga(p); - if (paga.get_int(PART_NRATA) == rata) - { - const int u = paga.get_int(PART_NRIGA); // Non pretende che siano in ordine - if (u > ultimo) ultimo = u; - } - } - return ultimo; -} - -// Controlla se la rata r e' stata completamente pagata -bool TPartita::rata_pagata(int r) const -{ - const TRectype& scad = rata(r); - real importo(scad.get(SCAD_IMPORTO)); - importo -= scad.get_real(SCAD_IMPORTOPAG); - const bool pagata = importo.is_zero(); - return pagata; -} - -TImporto TPartita::importo_speso(long nreg, int numrig) const -{ - TImporto imp; - - for (int r = righe(); r > 0; r--) - { - const TRectype& pag = riga(r); - - const long reg = pag.get_long(PART_NREG); - if (reg == nreg) - { - const int num = pag.get_int(PART_NUMRIG); - if (num == numrig) - imp += TImporto(pag.get_char(PART_SEZ), pag.get_real(PART_IMPORTO)); - } - } - - return imp; -} - - -void TPartita::update_reg_num(long nreg, const TRectype& mov) -{ - for (int r = righe(); r > 0; r--) - { - TRectype& pag = _part.row(r, FALSE); - - const long reg = pag.get_long(PART_NREG); - if (reg == nreg) - { - pag.put(PART_NREG, mov.get(MOV_NUMREG)); - pag.put(PART_DATAREG, mov.get(MOV_DATAREG)); - pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC)); - pag.put(PART_DATADOC, mov.get(MOV_DATADOC)); - } - } -} - - -/////////////////////////////////////////////////////////// -// TPartite_array -/////////////////////////////////////////////////////////// - -// Certified 99% -const TString& TPartite_array::key(int anno, const char* num) -{ - _key.format("%4d%s", anno, num); - return _key; -} - -// Certified 99% -TPartita* TPartite_array::find(int anno, const char* num, bool create) -{ - const TString& k = key(anno, num); - TPartita* p = (TPartita*)objptr(k); - if (p == NULL && create) - { - p = new TPartita(anno, num); - if (p->ok()) - add(k, p); - else - { - delete p; - p = NULL; - } - } - return p; -} - -TPartita* TPartite_array::find(const TRectype& r, bool create) -{ - const int anno = r.get_int(PART_ANNO); - const char* num = r.get_str(PART_NUMPART); - return find(anno, num, create); -} - -TPartita& TPartite_array::partita(int anno, const char* num) -{ - TPartita* game = find(anno, num, TRUE); - CHECKS(game, "Partita errata ", num); - return *game; -} - -TPartita& TPartite_array::partita(const TRectype& r) -{ - TPartita* game = find(r, TRUE); - CHECK(game, "Partita errata"); - return *game; -} - -bool TPartite_array::write(bool re) -{ - int err = NOERR; - - TPartita* game; - restart(); - while ((game = (TPartita*)get()) != NULL) - { - err = game->write(re); - if (err != NOERR) // L'errore viene gia' segnalato dalla partita - break; - } - - return err == NOERR; -} - -// Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg -int TPartite_array::add_reg_num(long nreg, int numrig) -{ - TRelation rel(LF_PARTITE); - TRectype& part = rel.lfile().curr(); - - // Costruzione filtro del cursore - part.zero(); - part.put(PART_NREG, nreg); - if (numrig > 0) - part.put(PART_NUMRIG, numrig); - - const TRectype filter(part); - - TCursor cur(&rel, "", 3, &filter, &filter); - - for (cur = 0; cur.ok(); ++cur) - partita(part); // Aggiungi partita se non esiste gia' - - return (int)cur.items(); -} - -TImporto TPartite_array::importo_speso(long nreg, int numrig) -{ - TImporto imp; - add_reg_num(nreg, numrig); - for (TPartita* game = first(); game; game = next()) - imp += game->importo_speso(nreg, numrig); - return imp; -} - -void TPartite_array::update_reg_num(long nreg, const TRectype& mov) -{ - add_reg_num(nreg, 0); - for (TPartita* game = first(); game; game = next()) - game->update_reg_num(nreg, mov); -} - +#include + +#include "pagament.h" + +#include +#include + +int TPagamento::_rata_ifield(int n, int f) const +{ + TToken_string& t = (TToken_string&)_rate[n]; + return t.get_int(f); +} + +real TPagamento::_rata_rfield(int n, int f) const +{ + TToken_string& t = (TToken_string&)_rate[n]; + return real(t.get(f)); +} + +TDate TPagamento::_rata_dfield(int n, int f) const +{ + TToken_string& t = (TToken_string&)_rate[n]; + return TDate(t.get(f)); +} + +const char* TPagamento::_rata_sfield(int n, int f) const +{ + static char kak[6]; + TToken_string& t = (TToken_string&)_rate[n]; + strcpy(kak,t.get(f)); + return kak; +} + + +bool TPagamento::ratapagata(int n) +{ + TToken_string& t = (TToken_string&)_rate[n]; + return t.items() > 6; +} + + + +void TPagamento::set_intervallo_rate(int in) +{ + _dirty = TRUE; + if (_mcomm && (in % 30) != 0) + _mcomm = FALSE; + for (int i = 0; i < n_rate(); i++) + { + TToken_string& ts = rata(i); + ts.add(i == 0 ? (scad_rata(0) == 0 ? "0" : format("%d",in)) + : format("%d",in), 0); + } +} + +void TPagamento::set_mese_commerciale(bool v, int& sscad) +{ + _dirty = FALSE; + if (_mcomm == v) return; + if (sscad == -1) sscad = 30; + + if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1); + set_intervallo_rate(sscad); + + _mcomm = v; +} + +void TPagamento::set_rate_differenziate(int v) +{ + _dirty = FALSE; + if (!_rdiff && v == 2) return; + + if (v == 2 && (100 % n_rate()) == 0) + { + int p = 100 / n_rate(); + for (int i = _tpr < 4 ? 0 : 1; i < n_rate(); i++) + { + TToken_string& tt = rata(i); + tt.add(p,1); + } + _rdiff = !(v == 2); + _dirty = TRUE; + } +} + +void TPagamento::set_tipo_prima_rata(int v, int sscad) +{ + _dirty = FALSE; + if (_tpr == v) return; + + if (v < 4 && _tpr > 3) + { + for (int i = n_rate() - 1; i > 0; i--) + { + TToken_string& tt = rata(i); + tt.add(scad_rata(i-1),0); + tt.add(tipo_rata(i-1),2); + tt.add(ulc_rata(i-1),5); + } + _rate.add(NULL,0); + _rate.pack(); + } + else if ( _tpr < 4 && v > 3) + { + TToken_string* ttn = new TToken_string(32); + ttn->add(0,0); + ttn->add(0,1); + ttn->add(1,2); + ttn->add("",3); + ttn->add("",4); + ttn->add("",5); + _rate.insert(ttn,0); + for (int i = 0; i < (n_rate()-1); i++) + { + TToken_string& tt = rata(i); + tt.add(scad_rata(i+1),0); + tt.add(tipo_rata(i+1),2); + tt.add(ulc_rata(i+1),5); + } + } + _tpr = v; + _dirty = TRUE; +} + +void TPagamento::set_numero_rate(int n, int sscad) +{ + _dirty = FALSE; + if (n == 0 || n == n_rate()) return; + + real p = real(100) / real(n); + p.round(2); + int nr = n_rate(); + int first = _tpr < 4 ? 0 : 1; + real sum = 0.0; + + for (int i = first; sum < real(100.0); i++) + { + if ((real(100.0) - sum) < p) + p = real(100.0) - sum; + + sum += p; + + // if necessary add remainder on first one + if ((real(100.0) - sum) /* still */ < p) + { + real prc = perc_rata(first); + prc += real(100.0) - sum; + TToken_string& rt = rata(first); + rt.add(prc.string(),1), + sum = 100; + } + + set_rata(i, real(p), + i == 0 ? (i < nr ? scad_rata(0) : 0): + (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad), + (i < nr ? tipo_rata(i) : tipo_rata(nr-1))); + } + // erase remaining + for (; i < nr; i++) + _rate.add(NULL,i); + _rate.pack(); + + _dirty = TRUE; +} + + +void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata) +{ + if (mcomm) + { + int nm = scad / 30; + int ny = nm / 12; + nm %= 12; + + int newm = d.month() + nm; + if (newm > 12) { newm -= 12; ny++; } + + bool last = d.is_end_month() && inizio_scadenza() == 'M'; + + int dy = d.day(); + + // la palla del febbraio & c. + if (rata > 1) + { + TDate oldd(data_rata(rata-2)); + if (oldd.day() > dy) dy = oldd.day(); + } + + d.set_day(1); // il giorno 1 ce l'hanno tutti + d.set_month(newm); + d.set_year(d.year()+ny); + + d.set_end_month(); + if (!last && dy < d.day()) + d.set_day(dy); + } + else + { + d += scad; + } + + // riaggiusta la minchia se ci sono scadenze fissate + if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0) + { + for (int i = 0; i < 3; i++) + { + if (_fixd[i] > d.day()) + { + if (d.last_day(d.month(), d.year()) <= _fixd[i]) + d.set_day(_fixd[i]); + else d.set_end_month(); + break; + } + } + + if (i == 3) + { + if (_fixd[0] > 0 && _fixd[0] < d.day()) + { + d.set_day(_fixd[0]); + d.set_month(d.month() == 12 ? 1 : d.month() + 1); + } + } + + } +} + + +void TPagamento::set_default_type(int type, bool change_existing) +{ + _def_tpr = type; + if (change_existing) + { + for (int i = 0; i < n_rate(); i++) + { + TToken_string& tt = rata(i); + tt.add(type, 2); + } + _dirty = TRUE; + } +} + +void TPagamento::set_default_ulc(const char* ulc, bool change_existing) +{ + _def_ulc = ulc; + if (change_existing) + { + for (int i = 0; i < n_rate(); i++) + { + TToken_string& tt = rata(i); + tt.add(ulc, 5); + } + _dirty = TRUE; + } +} + +void TPagamento::remove_rata(int i) +{ + // non fa nessun ricalcolo, si limita ad impacchettare se + // necessario + _rate.add(NULL,i); + _rate.pack(); + _dirty = TRUE; +} + +TToken_string& TPagamento::add_rata(real perc, int day, int type, const char* ulc) +{ + TToken_string* tt = new TToken_string(16); + tt->add(day); // scadenza + tt->add(perc.string()); // percentuale + tt->add(type); // tipo + tt->add(""); + tt->add(""); + tt->add(ulc); + _rate.add(tt); + _dirty = TRUE; + return *tt; +} + +TToken_string& TPagamento::set_rata (int index, real perc, int day, int type, + const char* ulc, const char* imp, + const char* data) +{ + TToken_string* tt = (TToken_string*)_rate.objptr(index); + const bool nwr = (tt == NULL); + if (nwr) tt = new TToken_string(16); + + tt->add(day,0); // scadenza + tt->add(perc.string(),1); // percentuale + tt->add(type,2); // tipo + tt->add(data == NULL ? "" : data,3); + tt->add(imp == NULL ? "" : imp,4); + tt->add(ulc == NULL ? "" : ulc,5); + + if (!nwr) + { + if (index > _rate.items()) + { + error_box("Rate non contigue"); + delete tt; + } + } + else + { + _rate.add(tt,index); + _dirty = TRUE; + } + return *tt; +} + +void TPagamento::set_imprata(int i, real r) +{ + TToken_string& tt = (TToken_string&)_rate[i]; + TDate d = _inizio; + + for (int n = 0; n <= i; n++) + next_scad(d, scad_rata(n), _mcomm, n); + + tt.add((const char*)d, 3); + tt.add(r.string(), 4); +} + +TToken_string& TPagamento::set_rata(int index, const real& howmuch, + const TDate& date, int type,const char* ulc, bool pagato) +{ + // calcola percentuali e scadenze a partire dagli importi + TToken_string* tt = (TToken_string*)_rate.objptr(index); + + const bool nwr = (tt == NULL); // nuova rata + + if (nwr) tt = new TToken_string(16); + + TDate oldd = index > 0 ? data_rata(index -1) : _inizio; + int day = date - oldd; + real toshare(_tpr < 4 ? _firstr : _secndr); + real perc = (_tpr > 3 && index == 0) ? ZERO : howmuch/toshare; + perc *= real(100.0); + perc.round(2); + + tt->add(day,0); // scadenza + tt->add(perc.string(),1); // percentuale + tt->add(type,2); // tipo + tt->add(date.string(),3); + tt->add(howmuch.string(),4); + tt->add(ulc,5); + if (pagato) tt->add("X",6); + + if (!nwr) + { + if (index > _rate.items()) + { + error_box("Rate non contigue"); + delete tt; + } + } + else + { + _rate.add(tt, index); + _dirty = TRUE; + } + return *tt; +} + + + +word TPagamento::validate() const +{ + word res = 0x0000; + real r(0.0); + + int first = _tpr < 4 ? 0 : 1; + real toshare(_tpr < 4 ? _firstr : _secndr); + TDistrib ds(toshare,0); + + // check percentages & prepare slicer + for (int i = first; i < n_rate(); i++) + { + real p(perc_rata(i)); + ds.add(p); + r += p; + } + + if (r != real(100.0)) + res |= P_RSUM; + + + if (_inited) + { + ds.init(toshare); + // check importi rate consistenti con la percentuale + for (int i = first; i < n_rate(); i++) + { + real r1(tpay_rata(i)); + real r2(ds.get()); + if (r1 != r2) + { res |= P_IMPNC; break; } + } + + // check errori date scadenze (se istanziate) + TDate d(data_rata(0)); + if (d < _inizio) + res |= P_INIZIO; + for (i = 1; i < n_rate(); i++) + { + if (data_rata(i) <= d) + { res |= P_SCAD; break; } + d = data_rata(i); + } + } + return res; +} + + +void TPagamento::strerr(word err, TString& s) +{ + s = "Errore:"; + if (err & P_RSUM) + s << "\n Le percentuali non sommano a 100"; + if (err & P_IMPNC) + s << "\n Le percentuali sono inconsistenti con gli importi"; + if (err & P_SCAD) + s << "\n Le scadenze non sono consecutive"; + if (err & P_INIZIO) + s << "\n La prima rata e' antecedente alla data movimento"; +} + +const char* TPagamento::desc_tpr() const +{ + const char* o; + switch (_tpr) + { + case 0: o = "Totale su tutte le rate"; break; + case 1: o = "Tutte le imposte su 1a"; break; + case 2: o = "Tutte le spese su 1a"; break; + case 3: o = "Imposte + spese su 1a"; break; + case 4: o = "Spese + merce su 1a"; break; + case 5: o = "Merce + imposte su 1a"; break; + case 6: o = "Tutta la merce su 1a"; break; + } + return o; +} + +const char* TPagamento::desc_tipo(int i) const +{ + const char* o; + switch (i) + { + case 1: o = "Rimessa diretta o contanti"; break; + case 2: o = "Tratta"; break; + case 3: o = "Ricevuta bancaria"; break; + case 4: o = "Cessione"; break; + case 5: o = "Paghero'"; break; + case 6: o = "Lettera di credito"; break; + case 7: o = "Tratta accettata"; break; + case 8: o = "Rapporti interbancari diretti"; break; + case 9: o = "Bonifici"; break; + case 10: o = "Altro pagamento"; break; + } + return o; +} + +word TPagamento::recalc_rate(int row, bool is_perc_modified, + const char* new_value, const char* scad, + const char* typ, int rdiff, bool mcomm, + bool& need_recalc) + // ricalcola le rate sulla base di parametri modificati sulla riga row + // parametri: tutti i const char* possono essere NULL, il che vuol dire + // che i dati corrispondenti non sono stati modificati; + // se new_value non e' NULL puo' essere la percentuale (e + // allora is_perc_modified e' TRUE) o l'importo. Non e' + // possibile modificare entrambi; se succede viene data + // priorita' alla percentuale. +{ + CHECK(!(!is_perc_modified && new_value != NULL && !_inited), + "A'stronzo! E famme 'na pippa! Me dai n'importo che nun ce sta? Ma Vaffanculo!"); + + if (_rate.items() == 0) return P_OK; + + real rsum(0.0), newv(0.0), rmax(0.0); + int oldtype = tipo_rata(0); + int oldscad = scad_rata(0); + TDate lastdate = data_rata(0); + int first = _tpr < 4 ? 0 : 1; + TArray srate(_rate); // rate come erano + + + if (srate.items() > 1) + { + // calcola defaults per tipo pagamento e scadenza + // nel caso di rate nuove + oldscad = scad_rata(1); + } + + if (oldscad == 0) oldscad = 30; + if (oldtype == 0) oldtype = 1; + + if (new_value != NULL) + { + newv = new_value; + rmax = is_perc_modified? (real) 100.0 : (_tpr < 4 ? _firstr : _secndr); + if (newv > rmax) return P_RSUM; + } + + bool exhausted = FALSE; + + for (int i = first; i < srate.items(); i++) + { + if (i == row) + { + if (typ != NULL) + { + TToken_string& tt = rata(row); + TToken_string& ss = (TToken_string&)srate[row]; + tt.add(typ,2); + ss.add(typ,2); + // no error is possible + } + + if (scad != NULL) + { + // if !_inited scad e' il n. giorni, se no e' la rata + if (_inited) + { + TToken_string& tt = rata(row); + TToken_string& ss = (TToken_string&)srate[row]; + lastdate = scad; + // controlla errore sulla data scadenza + if (i > 0) + { + oldscad = (int)(lastdate - data_rata(i-1)); + if (oldscad <= 0l) return P_SCAD; + } + else if (lastdate < _inizio) return P_INIZIO; + tt.add(scad,3); + ss.add(scad,3); + // ricalcola rate successive: se si vuole modificarne solo una + // ci si fotte e si disabilita il ricalcolo + TDate ddd (lastdate); + for (int j = row+1; j < srate.items(); j++) + { + TToken_string& tt = rata(j); + TToken_string& ss = (TToken_string&)srate[j]; + next_scad(ddd,scad_rata(j),mcomm,j); + tt.add(ddd.string(),3); + ss.add(ddd.string(),3); + need_recalc = TRUE; + } + } + else + { + // nulla di speciale visto che si memorizza la derivata + int sc = atoi(scad); + for (int i = 0; i < row; i ++) + sc -= scad_rata(i); + if (sc < 0 || (row > 0 && sc == 0)) return P_SCAD; + if (_mcomm && (sc % 30) != 0) _mcomm = FALSE; + TToken_string& tt = rata(row); + TToken_string& ss = (TToken_string&)srate[row]; + tt.add(sc,0); + ss.add(sc,0); + need_recalc = TRUE; + } + } + + // here's the bell + if (new_value != NULL) + { + if (newv == ZERO || (rsum+newv) > rmax) + return P_RSUM; + // did not sforate + rsum += newv; + TToken_string& rt = rata(row); + // setta nuovo valore e ricalcola cio' che ne consegue + if (is_perc_modified) rt.add(new_value,1); + else rt.add(new_value,4); + // riaggiusta le rate rimanenti + real remainder(0.0); remainder = rmax - rsum; + if (!(exhausted = (remainder == real(0.0)))) + { + // controlla se rdiff e' compatibile con + // i dati e se e' il caso riaggiusta + if (rdiff == 3 && !((remainder % newv.integer()) == ZERO)) + rdiff = 2; + if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) + rdiff = 1; + _rdiff = (rdiff == 1 || rdiff == 3 || rdiff == 4); + + // procedi + if (rdiff == 1) + { + // cancella tutte le rate successive, aggiungi un'unica rata + // con il resto dell'importo + if (row < (srate.items()-1)) + { + TToken_string& trt = rata(row+1); + trt.add(remainder.string(), is_perc_modified ? 1 : 4); + for(int j = row+2; j < srate.items(); j++) + _rate.add(NULL,j); + } + else + { + // l'importante e' esagerare + for(int j = row+1; j < srate.items(); j++) + _rate.add(NULL,j); + + TToken_string& trt = add_rata(is_perc_modified ? remainder : (real) 0.0, + oldscad, oldtype); + if (!is_perc_modified) trt.add(remainder.string(),4); + if (_inited) + { + TDate dd = data_rata(row); + next_scad(dd,oldscad,mcomm,row); + trt.add(dd.string(),3); + } + } + } + else // rate non differenziate (dall'inizio o da row) + { + // ripartisci l'importo nel numero necessario di rate per + // mantenere costante il valore + real sum(0.0); + if (_inited) lastdate = data_rata(rdiff == 2 ? first : row); + + TDate dd(lastdate); + int type = oldtype; + int nscd = oldscad; + + int frs = (rdiff == 3 || rdiff == 4) ? row+1 : first; + real mx = (rdiff == 3 || rdiff == 4) ? remainder : rmax; + + // cancelliamo tutto, va' + for (int j = frs; j < srate.items(); j++) + _rate.add(NULL,j); + + if (rdiff != 4) + for (j = frs; sum < mx; j++) + { + // se c'e' la vecchia rata si tengono i parametri + // altrimenti si calcolano + if (j < srate.items()) + { + TToken_string& trt = (TToken_string&)srate[j]; + if (_inited) dd = trt.get(3); + type = atoi(trt.get(2)); + nscd = j == 0 ? 0 : atoi(trt.get(0)); + if (type == 0) type = 1; + if (j > 0 && nscd == 0) nscd = oldscad; + if (_inited && dd == lastdate && j > 0) + next_scad(dd,nscd,mcomm,j); + } + else if (_inited) + { + if (dd <= botime) dd = lastdate; + next_scad(dd,nscd,mcomm,j); + } + + TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, + nscd, type); + if (_inited) + ttr.add(dd.string(), 3); + if (!is_perc_modified) + ttr.add(newv.string(),4); + sum += newv; + } + else // rdiff == 4; uguali finche' possibile + { + bool basta = FALSE; + for (j = frs; ; j++) + { + // ultima rata puo' differire dalle precedenti + if (mx - sum <= newv) + { + newv = mx - sum; + basta = TRUE; + } + // se c'e' la vecchia rata si tengono i parametri + // altrimenti si calcolano + if (j < srate.items()) + { + TToken_string& trt = (TToken_string&)srate[j]; + if (_inited) dd = trt.get(3); + type = atoi(trt.get(2)); + nscd = j == 0 ? 0 : atoi(trt.get(0)); + if (type == 0) type = 1; + if (j > 0 && nscd == 0) nscd = oldscad; + if (_inited && dd == lastdate && j > 0) + next_scad(dd,nscd,mcomm,j); + } + else if (_inited) next_scad(dd,nscd,mcomm,j); + + TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, + nscd, type); + if (_inited) + ttr.add(dd.string(), 3); + if (!is_perc_modified) + ttr.add(newv.string(),4); + if (basta) break; + sum += newv; + } + } + } + + } + else // exhausted + { + for(int j = row+1; j < srate.items(); j++) + _rate.add(NULL,j); + } + + + if (_inited) + { + // ricalcola il valore secondario (non modificato) + real toshare(100.0); + if (is_perc_modified) + toshare = (_tpr < 4 ? _firstr : _secndr); + TDistrib dt(toshare,0); + + for (int j = first; j < _rate.items(); j++) + { + real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); + real zpx = rvl/rmax; // percentuale + dt.add(zpx); + } + for (j = first; j < _rate.items(); j++) + { + TToken_string& tr = rata(j); + real rvl = dt.get(); + tr.add(rvl.string(), is_perc_modified ? 4 : 1); + } + } + + need_recalc = TRUE; + return P_OK; + } // new_value != NULL + } + else // i != row modified + { + if (i > 0 && !((perc_rata(i-1) == perc_rata(i)))) + { + if (rdiff == 2) rdiff = 1; + _rdiff = FALSE; + } + if (is_perc_modified) + rsum += perc_rata(i); + else + rsum += tpay_rata(i); + + lastdate = data_rata(i); + oldtype = tipo_rata(i); + oldscad = scad_rata(i); + if (_inited && i > 0) + { + if (data_rata(i) <= data_rata(i-1)) + return P_SCAD; + } + else if (lastdate < _inizio) + return P_INIZIO; + } + } + + return P_OK; +} + + +bool TPagamento::read(TTable* t, TTable* r) +{ + // puo' chiamarla chiunque + bool istnew = FALSE; + if (t == NULL) + { + t = new TTable("%CPG"); + istnew = TRUE; + } + t->zero(); t->put("CODTAB",_code); + if (t->read() != NOERR) return FALSE; + + // set everything + _rdiff = t->get_bool("B1"); + _mcomm = t->get_bool("B0"); + _tpr = *((const char*)(t->get("S3"))); + _inscad = *((const char*)(t->get("S1"))); + _code = t->get("CODTAB"); + _name = t->get("S0"); + _fixd[0] = t->get_int("I0"); + _fixd[1] = t->get_int("I1"); + _fixd[2] = t->get_int("I2"); + + // TBI aggiusta _inizio secondo INSCAD; vedi mese commerciale etc. + if (_inscad == 'M') + { + if (_mcomm) _inizio.set_month(_inizio.month() == 2 ? 28 : 30); + else _inizio.set_end_month(); + } + else if (_inscad == 'F' && _mcomm && _inizio.month() == 31) + _inizio.set_month(30); + + // leggi rate e scadenze + bool isrnew = FALSE; + if (r == NULL) + { + r = new TTable("%RPG"); + isrnew = TRUE; + } + TString s(16); + + for (int i = 0; ;i++) + { + r->zero(); s.format("%s%3d",(const char*)_code, i); + r->put("CODTAB", (const char*)s); + if (r->read() != NOERR) break; + TToken_string* tt = new TToken_string(16); + tt->add((const char*)(r->get("I0"))); // scadenza + tt->add((const char*)(r->get("R0"))); // percentuale + tt->add((const char*)(r->get("I1"))); // tipo + // data e importo + TDate d = _inizio; + next_scad(d,(int)(r->get_long("I0")),_mcomm,i); + tt->add((const char*)d); + tt->add(""); + tt->add(r->get("S1")); + _slicer.add((real)r->get("R0")); + _rate.add(tt); + } + + if (istnew) delete t; + if (isrnew) delete r; + + return TRUE; +} + + +int TPagamento::write(TTable& r) +{ + // Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una + // relapp, che ha scritto il file principale + + TString s(16); int err = NOERR; + for (int i = 0; err == NOERR && i < n_rate(); i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + r.put("I0", (long)scad_rata(i)); + r.put("R0", perc_rata(i).string()); + r.put("I1", (long)tipo_rata(i)); + r.put("S1", ulc_rata(i)); + err = r.write(); + } + return err; +} + +int TPagamento::rewrite(TTable& r) +{ + TString s(16); int err = NOERR; + for (int i = 0; err == NOERR && i < n_rate(); i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + bool was = (r.read() == NOERR); + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + r.put("I0", (long)scad_rata(i)); + r.put("R0", perc_rata(i).string()); + r.put("I1", (long)tipo_rata(i)); + r.put("S1", ulc_rata(i)); + err = (was ? r.rewrite() : r.write()); + } + // erase possible rates > current n. rates + for (;err == NOERR;i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + if (r.read() == NOERR) err = r.remove(); + else break; + } + return err; +} + +int TPagamento::remove(TTable& r) +{ + TString s(16); int err = NOERR; + for (int i = 0 ; err == NOERR; i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + if (r.read() == NOERR) err = r.remove(); + else break; + } + return err; +} + +void TPagamento::set_rate_auto() +{ + // vedi rate esistenti e tipo prima rata + // deve fare riferimento ad un tipo pagamento esistente + // e sensato + int first = 0; + + real toslice = _firstr; + + if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1)) return; + if (_tpr > 1) // ripartisci _firstr su tutte le rate + { + first = 1; + toslice = _secndr; + } + + _slicer.init(toslice); + + if (_tpr > 3) + // prima rata obbligatoria + set_imprata(0, _firstr); + + for (int i = first; i < n_rate(); i++) + // setta le fette e le date di scadenza + set_imprata(i, _slicer.get()); +} + + + +void TPagamento::set_total(const real& imponibile, const real& imposta, const real& spese) +{ + _imponibile = imponibile; + _imposta = imposta; + _spese = spese; + _inited = TRUE; + + // istanzia _firstr e _secndr a seconda di _tpr + switch(_tpr) + { + case 0: + _firstr = _imponibile + _imposta + _spese; + _secndr = 0.0; + break; + case 1: + _firstr = _imposta; + _secndr = _imponibile + _spese; + break; + case 2: + _firstr = _spese; + _secndr = _imposta + _imponibile; + break; + case 3: + _firstr = _imposta + _spese; + _secndr = _imponibile; + break; + case 4: + _firstr = _spese + _imponibile; + _secndr = _imposta; + break; + case 5: + _firstr = _imponibile + _imposta; + _secndr = _spese; + break; + case 6: + _firstr = _imponibile; + _secndr = _imposta + _spese; + break; + } + + real toslice = _tpr > 1 ? _secndr : _firstr; + + _slicer.init(toslice, TRUE); + + for (int i = 0; i < _rate.items(); i++) + { + TToken_string& t = (TToken_string&)_rate[i]; + real rr(t.get(1)); + _slicer.add(rr); + } +} + + +void TPagamento::set_sheet(TSheet_field& sf, int sscad) +{ + sf.destroy(-1); + if (_inited && _rate.items() > 0) + { + // si istanzia uno sheet di primanota + for (int i = 0; i < n_rate(); i++) + { + TToken_string& ts = sf.row(-1); + // istanzia, o stronzo + ts.add((const char*)data_rata(i)); + ts.add(perc_rata(i).string()); + ts.add(tpay_rata(i).string()); + ts.add(tipo_rata(i)); + ts.add(desc_tipo(tipo_rata(i))); + if (ratapagata(i)) + { + sf.disable_cell(1,1); // percentuale + sf.disable_cell(1,2); // importo + } + } + } + else if (_rate.items() > 0) // not inited: set edit sheet + { + for (int i = 0, scr = 0; i < n_rate(); i++) + { + TToken_string& s = sf.row(-1); + scr += scad_rata(i); + s.add(scr); + s.add(perc_rata(i).string()); + s.add(tipo_rata(i)); + s.add(desc_tipo(tipo_rata(i))); + s.add(ulc_rata(i)); + } + } + else // new: set with 1 or 2 rates according to tpr + { + if (_tpr > 3) + add_rata(ZERO, sscad == -1 ? 0 : sscad, _def_tpr, _def_ulc); + add_rata(real(100.0), sscad == -1 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc); + + _dirty = TRUE; + + for (int i = 0, scr = 0; i < n_rate(); i++) + { + TToken_string& s = sf.row(-1); + scr += scad_rata(i); + s.add(scr); + s.add(perc_rata(i).string()); + s.add(tipo_rata(i)); + s.add(desc_tipo(tipo_rata(i))); + s.add(ulc_rata(i)); + } + } + if (_tpr > 3) + { + // disabilita campi da non toccare sulla prima rata + if (_inited) + { + sf.disable_cell(0,1); // percentuale + sf.disable_cell(0,2); // importo + } + else + { + sf.disable_cell(0,1); // percentuale + } + } + sf.force_update(); +} + +TPagamento::TPagamento(const char* codtab, const char* data) : +_slicer(0.0,0), _new(FALSE), _imponibile(0.0), _imposta(0.0), +_spese(0.0), _code(codtab), _dirty(FALSE), _inited(FALSE), +_def_tpr(1), _def_ulc("") +{ + _fixd[0] = _fixd[1] = _fixd[2] = 0; + if (data != NULL) + _inizio = data; + if (_code.blank() || !read()) + _new = TRUE; +// if (_new && data != NULL) error_box("Modalita' pagamento inesistente"); +} + + +/////////////////////////////////////////////////////////// +// 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() + : TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP") +{ + zero(); +} + +/////////////////////////////////////////////////////////// +// TRiga_partite +/////////////////////////////////////////////////////////// + +TRiga_partite::TRiga_partite() + : TTree_rectype(LF_PARTITE, LF_SCADENZE, "NRATA") +{ + zero(); +} + +TRiga_partite::TRiga_partite(const TRiga_partite& r) + : TTree_rectype(r) +{} + + +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; + copy_key_to_row(*s); + err = _recarr.read(s); // Deve esistere almento una scadenza +#ifdef DBG + if (err != NOERR) + yesnofatal_box("Riga di partite senza nessuna scadenza"); +#endif + } + else + _recarr.destroy_rows(); + return err; +} + +TObject* TRiga_partite::dup() const +{ + return new TRiga_partite(*this); +} + +int TRiga_partite::add_rata(const TRectype& r) +{ + return 1; +} + +int TRiga_partite::ultimo_pagamento(int r) const +{ + const TRiga_scadenze& s = rata(r); + return s.rows_array().last_row(); +} + +// Controlla se la rata r e' stata completamente pagata +bool TRiga_partite::rata_pagata(int r) const +{ + const TRiga_scadenze& scad = rata(r); + real importo(scad.get(SCAD_IMPORTO)); + importo -= scad.get_real(SCAD_IMPORTOPAG); + const bool pagata = importo.is_zero(); + return pagata; +} + + +/////////////////////////////////////////////////////////// +// TPartita +/////////////////////////////////////////////////////////// + +TPartita::TPartita(const TBill& clifo, int anno, const char* num) + : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP") +{ + read(clifo, anno, num); +} + +int TPartita::add_riga(const TRiga_partite& r) +{ + CHECK(r.num() == LF_PARTITE, "Tipo record errato"); + + const char sez = r.get_char(PART_SEZ); + const real val = r.get_real(PART_IMPORTO); + const TImporto imp(sez, val); + + TImporto grow(imp); + const int n = r.get_int(PART_NRIGA); + CHECK(n > 0, "Numero riga nullo"); + if (n <= _part.last_row()) + { + const TRectype& oldrow = riga(n); + const char osez = oldrow.get_char(PART_SEZ); + const real oval = oldrow.get_real(PART_IMPORTO); + const TImporto old(osez, oval); + grow -= old; + } + + return _part.add_row(r); +} + +void TPartita::remove_riga(TRiga_partite& z) +{ + z.zero(PART_IMPORTO); + add_riga(z); + _part.destroy_row(z, TRUE); +} + +// Costruisce le righe della partita +bool TPartita::read(const TBill& clifo, int anno, const char* num) +{ + TRiga_partite* partita = new TRiga_partite; // 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, 9999); // Numeri magici di non assegamento + unas.put(SCAD_NRATA, 9999); + _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--) + { + const TRectype& pag = riga(r); + + const long reg = pag.get_long(PART_NREG); + if (reg == nreg) + { + const int num = pag.get_int(PART_NUMRIG); + if (num == numrig) + { + imp = TImporto(pag.get_char(PART_SEZ), pag.get_real(PART_IMPORTO)); + break; + } + } + } + + return imp; +} + + +void TPartita::update_reg_num(long nreg, const TRectype& mov) +{ + for (int r = _part.last_row(); r > 0; r--) + { + TRectype& pag = _part.row(r, FALSE); + + const long reg = pag.get_long(PART_NREG); + if (reg == nreg) + { + pag.put(PART_NREG, mov.get(MOV_NUMREG)); + pag.put(PART_DATAREG, mov.get(MOV_DATAREG)); + pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC)); + pag.put(PART_DATADOC, mov.get(MOV_DATADOC)); + } + } +} + + +/////////////////////////////////////////////////////////// +// TPartite_array +/////////////////////////////////////////////////////////// + +// Certified 99% +const TString& TPartite_array::key(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/pagament.h b/cg/pagament.h index 2fe26f57f..8f116468f 100755 --- a/cg/pagament.h +++ b/cg/pagament.h @@ -165,57 +165,103 @@ public: #include #endif -class TPartita : public TObject -{ - TRecord_array _scad, _part; - TImporto _totale; +class TTree_rectype : public TRectype +{ +protected: + TRecord_array _recarr; -public: // TObject - virtual bool ok() const { return rate() > 0; } + 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; } + + 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 +{ +public: + TRiga_scadenze(); + virtual ~TRiga_scadenze() {} +}; + +class TRiga_partite : public TTree_rectype +{ +public: // TTree_rectype + virtual TObject* dup() const; + virtual int read(TBaseisamfile& f, word op); public: - int add_riga(const TRectype& r); - const TRectype& riga(int r) const { return _part.row(r); } - void remove_riga(TRectype& z); - int righe() const { return _part.rows(); } - + int rate() const { return _recarr.rows(); } + TRiga_scadenze& rata(int r) const { return (TRiga_scadenze&)_recarr.row(r); } bool rata_pagata(int r) const; int add_rata(const TRectype& r); - const TRectype& rata(int r) const { return _scad.row(r); } - int rate() const { return _scad.rows(); } int ultimo_pagamento(int rata) const; + + TRiga_partite(); + 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: + int add_riga(const TRiga_partite& r); + const TRiga_partite& riga(int r) const { return (const TRiga_partite&)_part.row(r); } + TRecord_array& rows_array() { return _part; } + + void remove_riga(TRiga_partite& z); bool reread(); - bool read(int anno, const char* num); + bool read(const TBill& clifo, int anno, const char* num); bool write(bool re = FALSE); bool rewrite() { return write(TRUE); } - int anno() const { return riga(1).get_int(PART_ANNO); } - const TString& numero() const { return riga(1).get(PART_NUMPART); } - const TString& descrizione() const { return riga(1).get(PART_DESCR); } - const TImporto& totale() const { return _totale; } + 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); - TPartita(int anno, const char* num); + TPartita(const TBill& clifo, int anno, const char* num); }; class TPartite_array : private TAssoc_array { - TString16 _key; // Work string + TString80 _key; // Work string protected: - const TString& key(int anno, const char* num); // Build key for TAssoc_array - TPartita* find(int anno, const char* numero, bool create); + 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(int anno, const char* numero); + TPartita& partita(const TBill& clifo, int anno, const char* numero); TPartita& partita(const TRectype& r); bool write(bool re = FALSE); @@ -228,7 +274,8 @@ public: TPartita* first() { restart(); return next(); } TPartita* next() { return (TPartita*)get(); } - TPartite_array() {} + TPartite_array() {} + virtual ~TPartite_array() {} }; #endif