diff --git a/sc/sc2100.cpp b/sc/sc2100.cpp index 3cff8363b..8a67e01a9 100755 --- a/sc/sc2100.cpp +++ b/sc/sc2100.cpp @@ -789,7 +789,7 @@ bool TStampaEC_application::print_ec() if (game.chiusa()) { const TDate& dir = form().data_inizio_rischio(); - const TImporto saldo = game.calcola_saldo_al(dir, TRUE); + const TImporto saldo = game.calcola_saldo_al(TRUE, dir); if (saldo.is_zero()) { int r = 0; diff --git a/sc/sc2400.cpp b/sc/sc2400.cpp index 22f9a61a0..2a17dbc7a 100755 --- a/sc/sc2400.cpp +++ b/sc/sc2400.cpp @@ -7,7 +7,6 @@ #include #include "sc2.h" -#include "sc2401.h" #include "sc2402.h" #include "sc2102.h" #include "sc2400a.h" @@ -22,7 +21,7 @@ class TStampaSol_application: public TApplication { TSol_mask *_msk; - TSol_form *_form; + TSol_form *_form; TString _lingua_ditta; bool _gesval; TFile_array _file; @@ -30,15 +29,14 @@ class TStampaSol_application: public TApplication { protected: virtual bool create(); virtual bool destroy(); - virtual bool menu(MENU_TAG m); + virtual bool menu(MENU_TAG mt); virtual void on_firm_change(); public: TSol_mask &mask() { return *_msk; } - TSol_form &form() { return *_form; } + TSol_form &form() { return *_form; } TCursor_sheet &sheet() { return _msk->cur_sheet(); } - bool select_sol(); // metodo per la selezione, punto d'inizio bool print_selected(); // cicla la stampa sugli elementi selezionati bool print_sol(); // stampa l'elemento corrente @@ -46,18 +44,6 @@ public: virtual ~TStampaSol_application() {} }; -bool TStampaSol_application::select_sol() { - TSol_mask &m= mask(); - while (m.run() != K_ESC) { - _form= new TSol_form(m, F_DATALIMSOL); - // !! manca la preparazione della stampa - print_selected(); - delete _form; - _form= NULL; - } - return TRUE; -} - bool TStampaSol_application::print_selected() { TCursor_sheet &s = sheet(); TCursor &c = *s.cursor(); @@ -66,11 +52,11 @@ bool TStampaSol_application::print_selected() { const int key = mask().get_key(); // filtra il cursore del form in mode che diventi uguale al cursor_sheet corrente - TCursor &fc = *form().cursor(); - fc.setkey(key); - TRectype filter(LF_CLIFO); - filter.put(CLI_TIPOCF, who); - fc.setregion(filter, filter); + TCursor &fc = *form().cursor(); + fc.setkey(key); + TRectype filter(LF_CLIFO); + filter.put(CLI_TIPOCF, who); + fc.setregion(filter, filter); const long print_all = !s.one_checked(); // se non ho selezionato nulla allora li stampo tutti long analfabeti = 0; // persone non stampate in quanto aventi lingua errata @@ -79,7 +65,8 @@ bool TStampaSol_application::print_selected() { const long items = c.items(); for (long i=0; i < items; i++) if (print_all || s.checked(i)) { - fc= i; // muove il cursore alla posizione corrente + fc= i; // muove il cursore alla posizione corrente + const bool ok = print_sol(); if (!ok) analfabeti++; } @@ -95,16 +82,16 @@ bool TStampaSol_application::print_selected() { } bool TStampaSol_application::print_sol() { - TSol_form &f= form(); + TSol_form &f= form(); - // preparazione variabili per controllo lingua - const TRectype &clf= f.cursor()->file().curr(); - const TString lincf(clf.get(CLI_CODLIN)); + // preparazione variabili per controllo lingua + const TRectype &clf= f.cursor()->file().curr(); + const TString lincf(clf.get(CLI_CODLIN)); bool ok= TRUE; - // controllo lingua ditta corrente - if ((f.lingua() == _lingua_ditta && !lincf.empty()) || f.lingua() != _lingua_ditta) ok= (lincf == f.lingua()); - if (!ok) return FALSE; // cliente analfabeta + // controllo lingua ditta corrente + if ((f.lingua() == _lingua_ditta && !lincf.empty()) || f.lingua() != _lingua_ditta) ok= (lincf == f.lingua()); + if (!ok) return FALSE; // cliente analfabeta // filtra solo le partite del cliente selezionato TLocalisamfile& partite = _file[LF_PARTITE]; @@ -114,11 +101,49 @@ bool TStampaSol_application::print_sol() { const TRectype filter(partite.curr()); bool one_printed = FALSE; // booleano di controllo di riuscita della stampa - - // !! manca tutta la stampa - - if (one_printed) printer().formfeed(); + const bool sel_tot_saldo = f.get_sel_tot_saldo(); // selezione sul saldo totale cliente + const real sel_importo(f.get_sel_importo()); // importo di selezione + const TDate data_limite_soll(f.data_limite_operazione()); + if (sel_tot_saldo) + { + TImporto saldo; + + for (int err = partite.read(_isgteq); + err == NOERR && partite.curr() == filter; + err = partite.read(_isgreat)) + { + TPartita game(partite.curr()); + saldo += game.calcola_saldo_al(FALSE, data_limite_soll); + } + saldo.normalize(f.sezione_normale()); + + if (saldo.valore() < sel_importo) + return TRUE; + } + for (int err = partite.read(_isgteq); + err == NOERR && partite.curr() == filter; + err = partite.read(_isgreat)) + { + TPartita game(partite.curr()); + TImporto saldo(game.calcola_saldo_al(FALSE, data_limite_soll)); + + saldo.normalize(f.sezione_normale()); + + if (sel_tot_saldo || saldo.valore() >= sel_importo ) + { + const bool printed = form().print_game(game); + if (printed) + one_printed = TRUE; + } + + partite.put(PART_NRIGA, 9999); + } + + if (one_printed) + printer().formfeed(); + + return TRUE; } @@ -148,8 +173,17 @@ void TStampaSol_application::on_firm_change() { _gesval= c.get_bool("GesVal"); } -bool TStampaSol_application::menu(MENU_TAG m) { - select_sol(); +bool TStampaSol_application::menu(MENU_TAG mt) + +{ + TSol_mask &m= mask(); + while (m.run() == K_ENTER) + { + _form= new TSol_form(m, F_DATALIMSOL); + print_selected(); + delete _form; + _form= NULL; + } return FALSE; } diff --git a/sc/sc2400a.h b/sc/sc2400a.h index 058654a3c..436fd6e38 100755 --- a/sc/sc2400a.h +++ b/sc/sc2400a.h @@ -1,19 +1,13 @@ #ifndef __SC2400A_H #define __SC2400A_H -#define F_CODDITTA 101 -#define F_RAGSOC 102 -#define F_CODPROF 103 -#define F_LINPROF 104 -#define F_DESPROF 105 +#ifndef __SC2100A_H +#include "sc2100a.h" +#endif + #define F_DATALIMSOL 106 #define F_STAMPESP 107 #define F_IMPORMIN 108 #define F_RIFIMPMIN 109 -#define F_LUOGOSEND 110 -#define F_DATASEND 111 -// basename of profile -#define BASE_EC_PROFILE "PEC" - #endif diff --git a/sc/sc2401.cpp b/sc/sc2401.cpp index b56e36317..5ece921ed 100755 --- a/sc/sc2401.cpp +++ b/sc/sc2401.cpp @@ -1,19 +1,24 @@ + +#include "../cg/saldacon.h" +#include +#include +#include #include -#include "sc2401.h" -#include "sc2400a.h" +#include "sc21pec.h" +#include "sc2403.h" -#include +#include -TSol_mask::TSol_mask(const char *name) : TSelection_mask(name), _ditta(LF_NDITTE) { +TESSL_mask::TESSL_mask(const char *name) : TSelection_mask(name), _ditta(LF_NDITTE) { _ditta.add(LF_ANAG, "TIPOA==TIPOA|CODANAGR==CODANAGR"); _ditta.add(LF_COMUNI, "COM==COMRF(COMRES)", 1, LF_ANAG, 101); _ditta.add(LF_COMUNI, "COM==COMRES", 1, LF_ANAG, 102); } -TSol_mask::~TSol_mask() {} +TESSL_mask::~TESSL_mask() {} -void TSol_mask::on_firm_change() { +void TESSL_mask::on_firm_change() { TMask::on_firm_change(); _ditta[0].put("CODDITTA", prefix().get_codditta()); @@ -23,18 +28,609 @@ void TSol_mask::on_firm_change() { } } -void TSol_mask::start_run() { +void TESSL_mask::start_run() { on_firm_change(); } -const char *TSol_mask::get_prof_base() const { +const char *TESSL_mask::get_prof_base() const { return BASE_EC_PROFILE; } -const TString &TSol_mask::get_prof_code() const { +const TString &TESSL_mask::get_prof_code() const { return get(F_CODPROF); } -const TString &TSol_mask::get_prof_lang() const { +const TString &TESSL_mask::get_prof_lang() const { return get(F_LINPROF); } + + +/////////////////////////////////////////////////////////// +// TESSL_row +/////////////////////////////////////////////////////////// + +TESSL_row::TESSL_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata): _num_prot(0) { + _riga = row.get_int(PART_NRIGA); + _rata = rata; + + _data = data; + _causale = row.get(PART_CODCAUS); + _data_doc = row.get(PART_DATADOC); + _num_prot = row.get_long(PART_PROTIVA); + _importo = imp; _importo.normalize(); + _totale = row.get_real(PART_IMPTOTPAG); + + _valuta.get(row); +} + +TESSL_row::TESSL_row(const char* desc, const TImporto& imp) + : _riga(9999), _rata(9999), _num_prot(0), _salvo_buon_fine(FALSE) +{ + _descrizione = desc; + _importo = imp; _importo.normalize(); +} + +// le righe dell'estratto conto sono ordinate per data, riga partita, numero rata, +// posizione iniziale nell'array (in caso di uguaglianza di tutto il resto) +int TESSL_row::compare(const TSortable& s) const +{ + const TESSL_row& r = (const TESSL_row&)s; + int c = 0; + if (_data == r._data) + { + c = r._riga - _riga; + if (c == 0) c = r._rata - _rata; + } + else + c = _data < r._data ? +1 : -1; + return c; +} + +void TESSL_row::set_imp(TForm_item& fi, const real& imp, bool valuta) const +{ + TString old_picture; + if (valuta) + { + old_picture = fi.picture(); + + TString new_picture(20); + new_picture = old_picture; + if (old_picture.find(',') > 0) + new_picture << ".###"; + else + new_picture << ",###"; + + fi.set_picture(new_picture); + } + + fi.set(imp.string()); + + if (valuta) + { + fi.set_picture(old_picture); + } +} + +void TESSL_row::print_on(TPrint_section& body) +{ + TESSL_form& form = (TESSL_form&)body.form(); + + TForm_item& causale = body.find_field(PEC_CODCAUS); + causale.set(_causale); + if (_causale.not_empty() && _descrizione.empty()) { + TDecoder& causali = form.causali(); + _descrizione = causali.decode(_causale); + } + + TForm_item& descr = body.find_field(PEC_DESCR1); + descr.set(_descrizione); + + TForm_item& datadoc = body.find_field(PEC_DATADOC); + datadoc.set(_data_doc.string()); + + TForm_item& numdoc = body.find_field(PEC_NUMDOC); + numdoc.set(_num_doc); + + TForm_item& numprot = body.find_field(PEC_PROTIVA); + TString16 protiva; protiva << _num_prot; + numprot.set(protiva); + + TForm_item& datapag = body.find_field(PEC_DATAPAG); + datapag.set(_data.string()); + + const real& imp = _importo.valore(); + TForm_item& dare = body.find_field(PEC_DARE); + TForm_item& avere = body.find_field(PEC_AVERE); + + if (_importo.sezione() == 'D') { + dare.set(imp.string()); + avere.set(""); + } else { + avere.set(imp.string()); + dare.set(""); + } + + TForm_item& importo_in_lire = body.find_field(PEC_IMPLIRE); + importo_in_lire.set(_importo_lire.string()); + + TForm_item& scaduto = body.find_field(PEC_SCADUTO); + scaduto.set(_scaduto.string()); + + TForm_item& esposto = body.find_field(PEC_ESPOSTO); + esposto.set(_esposto.string()); + + TForm_item& sbf = body.find_field(PEC_SBF); + sbf.set(_salvo_buon_fine ? "*" : " "); + + TForm_item& cambio = body.find_field(PEC_CAMBIO); + cambio.set(_valuta.cambio().string()); + + TForm_item& datacambio = body.find_field(PEC_DATACAM); + datacambio.set(_valuta.data().string()); + + body.update(); +} + +static int val_compare(const void* o1, const void* o2) { + const THash_object* h1 = (const THash_object*)o1; + const THash_object* h2 = (const THash_object*)o2; + const TString& s1 = (const TString&)h1->obj(); + const TString& s2 = (const TString&)h2->obj(); + return s2.compare(s1, -1, TRUE); // same as stricmp(s1, s2) in reverse order +} + + +/////////////////////////////////////////////////////////// +// TESSL_array +/////////////////////////////////////////////////////////// + +// Calcola l'importo su di una riga di pagamento +TImporto TESSL_array::importo(const TPartita& game, const TRectype& pag, bool valuta) const +{ + const int nriga = pag.get_int(PAGSCA_NRIGA); + const TRiga_partite& fat = game.riga(nriga); + const bool fat_val = fat.in_valuta(); + + const int nrigp = pag.get_int(PAGSCA_NRIGP); + const TRiga_partite& sum = game.riga(nrigp); + const char sez = sum.sezione(); + + const char* const field = valuta && fat_val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + TImporto imp(sez, pag.get_real(PAGSCA_IMPORTO)); + + if (!fat_val) + imp.valore() += pag.get_real(PAGSCA_RITENUTE); + + if (pag.get_char(PAGSCA_ACCSAL) == 'S') + { + real abb(pag.get(PAGSCA_ABBUONI)); + if (!valuta && fat_val) + { + const TValuta val(sum); + val.val2lit(abb); + abb += pag.get_real(PAGSCA_DIFFCAM); + } + imp.valore() += abb; + } + + return imp; +} + +// Certified 100% +TImporto& TESSL_array::importo_riga_scaduto(int n) +{ + CHECKD(n > 0 && n < 9999, "Riga scaduto errata ", n); + TImporto* imp = importo_riga_scaduto_ptr(n); + if (imp == NULL) + { + imp = new TImporto; + _scaduto.add(imp, n); + } + return *imp; +} + +real TESSL_array::calcola_scaduto(const TRiga_scadenze& rata, bool valuta) +{ + const TPartita& game = rata.partita(); + const char sezione = _form->sezione_normale(); + + TImporto scaduto_rata = rata.importo(TRUE); + + int riga_corrente_scaduto = 0; + + const int lastp = rata.last(); // Ultimo pagamento sulla rata corrente + for (int p = rata.first(); p <= lastp; p = rata.succ(p)) // Qui bisogna andare in avanti! + { + const TRectype& pag = rata.row(p); + const int nrigp = pag.get_int(PAGSCA_NRIGP); + const TRiga_partite& sum = game.riga(nrigp); + TImporto imp = importo(game, pag, valuta); + + tipo_movimento tm = sum.tipo(); // Determina tipo riga + + // Normalmente gli utenti non usano il tipo pagamento insoluto, per cui devo + // riconoscere i pagamenti che in realta' sono a fronte di insoluti: + // 1) hanno tipo movimento = tm_pagamento + // 2) ho gia' incontrato un insoluto + // 3) il saldo della rata e' a zero o sommando l'importo arriva sotto zero + if (tm == tm_pagamento && riga_corrente_scaduto != 0) + { + if (scaduto_rata.is_zero()) + { + tm = tm_pagamento_insoluto; + } + else + { + TImporto p(scaduto_rata); + p += imp; + p.normalize(sezione); + + if (p.valore() < ZERO) + { + scaduto_rata.set('D', ZERO); + imp += p; + tm = tm_pagamento_insoluto; + } + } + } + if (tm == tm_insoluto || tm == tm_pagamento_insoluto) + { + if (tm == tm_insoluto) + riga_corrente_scaduto = nrigp; + else + CHECKD(riga_corrente_scaduto > 0, "Pagamento insoluto senza insoluto ", p); + importo_riga_scaduto(riga_corrente_scaduto) += imp; + } + else + { + scaduto_rata += imp; + } + } + scaduto_rata.normalize(sezione); + return scaduto_rata.valore(); +} + +TESSL_row& TESSL_array::new_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int n) +{ + CHECKD(n > 0, "Numero rata errato: ", n); + TESSL_row* riga = new TESSL_row(row, data, imp, n); + add(riga, n); + return *riga; +} + +void TESSL_array::add_row(const TRiga_partite& row) +{ + const bool in_valuta = form().in_valuta(); + real importo_in_lire(ZERO); + const char sezione = form().sezione_normale(); + + if (row.is_fattura()) + { + for (int r = 1; r <= row.rate(); r++) + { + const TRiga_scadenze& rata = row.rata(r); + const TDate data(rata.get(SCAD_DATASCAD)); + if (data <= form().data_limite_operazione()) + { + TESSL_row& rec = new_row(row, data, rata.importo(in_valuta), r); + if (in_valuta) + { + TImporto i(rata.importo(FALSE)); + i.normalize(sezione); + rec.importo_in_lire(i.valore()); + } + if (data <= form().data_limite_scaduto()) + { + const real s = calcola_scaduto(rata, in_valuta); + rec.scaduto(s); + } + } + } + } + else + { + const TDate data(row.get(PART_DATAPAG)); + if (data <= form().data_limite_operazione()) + { + const TImporto imp(row.importo(in_valuta, 0x1)); + TESSL_row& riga = new_row(row, data, imp, 1); + if (in_valuta) + { + TImporto i(row.importo(FALSE, 0x1)); + i.normalize(sezione); + riga.importo_in_lire(i.valore()); + } + + const int tipo_pag = row.get_int(PART_TIPOPAG); + if (tipo_pag >= 2 && tipo_pag <= 7) // Controlla se e' un pagamento con effetti + { + const TDate data_pag(row.get(PART_DATAPAG)); + const TDate& dls = form().data_limite_scaduto(); + const int gr = form().giorni_rischio(); + + bool sbf = FALSE; + if (gr > 0) + { + const TDate& dir = form().data_inizio_rischio(); + sbf = data_pag > dir && data_pag <= dls; + riga.salvo_buon_fine(sbf); // Esposto salvo buon fine + } + + bool esp = sbf; + if (!esp) + { + esp = gr > 0 ? data_pag >= dls : data_pag > dls; // Esposto normale + } + + if (esp) + { + TImporto esposto(imp); + esposto.normalize(sezione); + riga.esposto(esposto.valore()); + } + } + + const TImporto abbuoni(row.importo(in_valuta, 0x2)); + if (!abbuoni.is_zero()) + { + TESSL_row& r = new_row(row, data, abbuoni, 2); + r.descrizione(form().describe(302)); + if (in_valuta) + { + TImporto i(row.importo(FALSE, 0x2)); + i.normalize(sezione); + r.importo_in_lire(i.valore()); + } + } + + TImporto diffcam(row.importo(FALSE, 0x4)); + if (!diffcam.is_zero()) + { + if (in_valuta) + { + TESSL_row& r = new_row(row, data, TImporto('D', ZERO), 3); + r.descrizione(form().describe(303)); + diffcam.normalize(sezione); + r.importo_in_lire(diffcam.valore()); + } + else + { + TESSL_row& r = new_row(row, data, diffcam, 3); + r.descrizione(form().describe(303)); + } + } + + TImporto ritenute(row.importo(FALSE, 0x8)); + if (!ritenute.is_zero()) + { + if (in_valuta) + { + TESSL_row& r = new_row(row, data, TImporto('D', ZERO), 3); + r.descrizione(form().describe(304)); + ritenute.normalize(sezione); + r.importo_in_lire(ritenute.valore()); + } + else + { + TESSL_row& r = new_row(row, data, ritenute, 3); + r.descrizione(form().describe(304)); + } + } + } + } +} + +TESSL_array::TESSL_array(const TPartita& game, const TESSL_form* f) + :_form(f) +{ + for (int r = game.last(); r > 0; r = game.pred(r)) + add_row(game.riga(r)); + const char sezione = f->sezione_normale(); + for (r = items()-1; r >= 0; r--) + { + TESSL_row& s = row(r); + if (s.rata() == 1) + { + TImporto* imp = importo_riga_scaduto_ptr(s.riga()); + if (imp != NULL) + { + imp->normalize(sezione); + s.scaduto(imp->valore()); + } + } + } + + sort(); +} + + +/////////////////////////////////////////////////////////// +// TESSL_form: form speciale per estratti conto e solleciti +/////////////////////////////////////////////////////////// + +void TESSL_form:: header_handler(TPrinter& pr) +{ + TPrint_section& head = _form->section('H'); + head.reset(); + pr.resetheader(); + + head.update(); + for (word j = 0; j < head.height(); j++) pr.setheaderline(j, head.row(j)); +} + +static int tot_compare(const void* o1, const void* o2) +{ + if (o1 == o2) // Sfrutto una piccola debolezza di qsort: + return 0; // ogni tanto confronta oggetti con se stessi + + const THash_object* h1 = (const THash_object*)o1; + const THash_object* h2 = (const THash_object*)o2; + return stricmp(h1->key(), h2->key()); +} + +void TESSL_form::footer_handler(TPrinter& pr) +{ + TPrint_section& foot = _form->section('F'); + pr.resetfooter(); + + const word MAXTOT = 16; + THash_object* tot[MAXTOT]; + + // I totali sono in un assoc array disordinato per cui li copio in un array e li ordino + // alfabeticamente in base al loro codice valuta + TTotalizer& totali = _form->totali(); + totali.restart(); + + word numtot = 0; + for (THash_object* obj = totali.get_hashobj(); + numtot < MAXTOT && obj != NULL; + obj = totali.get_hashobj()) + tot[numtot++] = obj; + qsort(tot, numtot, sizeof(THash_object*), tot_compare); + + const word maxtot = foot.height() / _form->_footer_used; + if (numtot > maxtot) + numtot = maxtot; + + const TString& riporto = _form->describe(301, 'F'); + + TString desc(80); + TPrint_section& body = _form->section('B'); + for (word j = 0; j < numtot; j++) + { + const word line = j * _form->_footer_used; + const TString& key = tot[j]->key(); + TTotal& t = (TTotal&)(tot[j]->obj()); + + desc = riporto; + if (key.not_empty()) + desc << ' ' << key; + TESSL_row rip(desc, t.importo().normalize()); + rip.scaduto(t.scaduto()); + rip.esposto(t.esposto()); + rip.print_on(body); + + for (int fl = 0; fl < _form->_footer_used; fl++) + pr.setfooterline(line, body.row(fl)); + } +} + + +bool TESSL_form::print_game(const TPartita& game) +{ + bool ok = FALSE; + + TESSL_array righe(game, this); + + TPrinter& pr = printer(); + TPrintrow prow; + + TPrint_section& body = section('B'); + + TImporto saldo; + real scaduto, esposto; + + // Stampa le righe di partita + + int ultima_riga = 0; + int ultima_rata = 0; + + for (int r = 0; r < righe.items(); r++) + { + TESSL_row& riga = righe.row(r); + + if (pr.rows_left() < body.height()) + pr.formfeed(); + + const int ri = riga.riga(); + const int ra = riga.rata(); + if (ri == ultima_riga && ra == ultima_rata+1) + riga.reset_causale(); + ultima_riga = ri; + ultima_rata = ra; + + riga.print_on(body); + pr.print(body.row(0)); + + totali().add(riga.importo(), riga.scaduto(), riga.esposto(), riga.valuta().codice()); + + saldo += riga.importo(); + scaduto += riga.scaduto(); + esposto += riga.esposto(); + ok = TRUE; + } + + if (ok) + { + saldo.normalize(); + + TESSL_row sld(describe(301), saldo); + sld.scaduto(scaduto); + sld.esposto(esposto); + sld.print_on(body); + pr.print(body.row(0)); + + // Salta una riga vuota + TPrintrow vuota; + pr.print(vuota); + } + return ok; +} + +const TString& TESSL_form::describe(short id, char sez) const +{ + const TForm_item& fi = find_field(sez, odd_page, id); + return fi.prompt(); +} + +TESSL_form::TESSL_form(const TESSL_mask& m, short id_datalim, short id_datascad, + short id_giorni_rischio) + :TForm(BASE_EC_PROFILE, m.get_prof_code()), + _causali(LF_CAUSALI, CAU_CODCAUS, CAU_DESCR) + +{ + _form = this; + + TForm_item& imp_lire = find_field('B', odd_page, PEC_IMPLIRE); + _in_valuta = imp_lire.shown(); // Il profilo e' in valuta se c'e' la colonna importo in lire + + _lingua = m.get_prof_lang(); + + TCursor_sheet& cs = m.cur_sheet(); + _cursore = cs.cursor(); + + _dlo = m.get(id_datalim); + if (id_datascad > 0) + _dls = m.get(id_datascad); + else + _dls = _dlo; + if (id_giorni_rischio > 0) + _giorni_rischio = m.get_int(id_giorni_rischio); + + _dir = _dls; _dir -= _giorni_rischio; + + TPrinter& pr = printer(); + + pr.setheaderhandler(header_handler); + pr.headerlen(section('H').height()); + + pr.setfooterhandler(footer_handler); + pr.footerlen(section('F').height()); + const TPrint_section& foot = section('F'); + pr.footerlen(foot.height()); + + for (int i = foot.fields()-1; i >= 0; i--) + { + TForm_item& fi = foot.field(i); + if (fi.y() > _footer_used) + _footer_used = fi.y(); + } +} + +TESSL_form::~TESSL_form() +{ + TPrinter& pr = printer(); + pr.setheaderhandler(NULL); + pr.setfooterhandler(NULL); + _form = NULL; +} diff --git a/sc/sc2401.h b/sc/sc2401.h index 275ccb8ed..2390fa867 100755 --- a/sc/sc2401.h +++ b/sc/sc2401.h @@ -1,11 +1,27 @@ -#ifndef __SC2401_H -#define __SC2401_H + +#ifndef __SC2403_H +#define __SC2403_H + +#include +#include + +#include "../cg/saldacon.h" +#include "sc2102.h" +#include "sc2400a.h" +#include "sc21pec.h" + +#include +#include +#include +#include #ifndef __SCSELECT_H #include "scselect.h" #endif -class TSol_mask: public TSelection_mask { +class TESSL_mask: public TSelection_mask + +{ TRelation _ditta; protected: @@ -15,10 +31,142 @@ protected: public: const char *get_prof_base() const; const TString &get_prof_code() const; - const TString &get_prof_lang() const; + const TString &get_prof_lang() const; - TSol_mask(const char *name); - virtual ~TSol_mask(); + TESSL_mask(const char *name); + virtual ~TESSL_mask(); }; -#endif // __SC2401_H +/////////////////////////////////////////////////////////// +// TESSL_row +/////////////////////////////////////////////////////////// + +class TESSL_row : public TSortable + +{ + TDate _data; // Data scadenza o pagamento + int _riga; // Riga della fattura + int _rata; // Numero rata o progrssivo + + TString _causale; // Codice causale + TString _descrizione; // Sua descrizione + + TDate _data_doc; // Data del documento + TString _num_doc; // Numero documento + long _num_prot; // Protocollo IVA + TImporto _importo; // Importo in valuta + real _importo_lire; // Importo in lire + real _scaduto; // Importo scaduto + real _esposto; // Importo esposto + bool _salvo_buon_fine; // Importo esposto salvo buon fine + real _totale; // Totale documento + TValuta _valuta; // Codice valuta, data cambio e cambio + +protected: // TSortable + virtual int compare(const TSortable& s) const; + void set_imp(TForm_item& fi, const real& imp, bool valuta) const; + +public: + int riga() const { return _riga; } + int rata() const { return _rata; } + + void reset_causale() { _causale.cut(0); _descrizione.cut(0); } + void descrizione(const char* s) { _descrizione = s; } + void importo(const TImporto& i) { _importo = i; } + void scaduto(const real& s) { _scaduto = s; } + void esposto(const real& e) { _esposto = e; } + void importo_in_lire(const real& il) { _importo_lire = il; } + void salvo_buon_fine(bool sbf) { _salvo_buon_fine = sbf; } + + const TValuta& valuta() const { return _valuta; } + const TImporto& importo() const { return _importo; } + real importo_in_lire() const { return _importo_lire; } + real scaduto() const { return _scaduto; } + real esposto() const { return _esposto; } + const TDate& data() const { return _data; } + + void print_on(TPrint_section& body); + + TESSL_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata); + TESSL_row(const char* desc, const TImporto& imp); + virtual ~TESSL_row() {} +}; + +/////////////////////////////////////////////////////////// +// TESSL_form: form speciale per estratti conto +/////////////////////////////////////////////////////////// + +class TESSL_form : public TForm +{ + static TESSL_form* _form; + + TCursor* _cursore; + TTotalizer _totali; + TDecoder _causali; // Decodoficatore dei codici causale + + TString _lingua; + TDate _dlo, _dls, _dir; + int _giorni_rischio; + bool _in_valuta; + int _footer_used; // Numero di righe per ogni valuta del footer + char _who; + +protected: + static void header_handler(TPrinter& p); + static void footer_handler(TPrinter& p); + +public: + TTotalizer& totali() { return _totali; } + TDecoder& causali() { return _causali; } + + const TDate& data_limite_operazione() const { return _dlo; } + const TDate& data_limite_scaduto() const { return _dls; } + int giorni_rischio() const { return _giorni_rischio; } + const TDate& data_inizio_rischio() const { return _dir; } + + const TString& lingua() const { return _lingua; } + bool in_valuta() const { return _in_valuta; } + const TString& describe(short id, char sez = 'B') const; + const char sezione_normale() const { return _who == 'C' ? 'D' : 'A' ; } + + virtual bool print_game(const TPartita& game); + + TESSL_form(const TESSL_mask& m, short id_datalim, short id_datascad = 0, short id_giorni_rischio = 0); + virtual ~TESSL_form(); +}; + +TESSL_form * TESSL_form::_form = NULL; + +/////////////////////////////////////////////////////////// +// TESSL_array +/////////////////////////////////////////////////////////// + +class TESSL_array : public TArray + + +{ + TArray _scaduto; // Array di importi scaduti + + const TESSL_form* _form; + +protected: + TESSL_row& new_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata = 0); + void add_row(const TRiga_partite& row); + + const TESSL_form& form() const { return *_form; } + real calcola_scaduto(const TRiga_scadenze& rata, bool valuta); + + + TImporto* importo_riga_scaduto_ptr(int n) const { return (TImporto*)_scaduto.objptr(n); } + TImporto& importo_riga_scaduto(int n); + + TImporto importo(const TPartita& game, const TRectype& pag, bool valuta) const; + +public: + TESSL_row& row(int r) const { return (TESSL_row&)operator[](r); } + + TESSL_array(const TPartita& game, const TESSL_form* f); + virtual ~TESSL_array() {} +}; + +#endif // __SC2403_H diff --git a/sc/sc2402.cpp b/sc/sc2402.cpp index 6934096ec..88c247bac 100755 --- a/sc/sc2402.cpp +++ b/sc/sc2402.cpp @@ -1,4 +1,3 @@ - #include "../cg/saldacon.h" #include #include @@ -10,287 +9,61 @@ #include +TSol_mask::TSol_mask(const char *name) + :TESSL_mask(name) + +{ +} + +TSol_mask::~TSol_mask() {} + +bool TSol_mask::get_sel_tot_saldo() const + +{ + return get_bool(F_RIFIMPMIN); +} + +real TSol_mask::get_sel_importo() const + +{ + return real(get(F_IMPORMIN)); +} /////////////////////////////////////////////////////////// // TSol_row /////////////////////////////////////////////////////////// -TSol_row::TSol_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata): _num_prot(0) { - _riga = row.get_int(PART_NRIGA); - _rata = rata; +TSol_row::TSol_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata) + :TESSL_row(row, data, imp, rata) - _data = data; - _causale = row.get(PART_CODCAUS); - _data_doc = row.get(PART_DATADOC); - _num_prot = row.get_long(PART_PROTIVA); - _importo = imp; _importo.normalize(); - _totale = row.get_real(PART_IMPTOTPAG); - - _valuta.get(row); +{ } -TSol_row::TSol_row(const char* desc, const TImporto& imp): _num_prot(0) { - _descrizione = desc; - _importo = imp; _importo.normalize(); -} - -// le righe dell'estratto conto sono ordinate per data, riga partita, numero rata, -// posizione iniziale nell'array (in caso di uguaglianza di tutto il resto) -int TSol_row::compare(const TSortable& s) const { - const TSol_row& r = (const TSol_row&)s; - int c = 0; - if (_data == r._data) { - c = r._riga - _riga; - if (c == 0) c = r._rata - _rata; - } else c = _data < r._data ? +1 : -1; - return c; -} - -void TSol_row::print_on(TPrint_section& body) { - TSol_form& form = (TSol_form&)body.form(); - - TForm_item& causale = body.find_field(PEC_CODCAUS); - causale.set(_causale); - if (_causale.not_empty() && _descrizione.empty()) { - TDecoder& causali = form.causali(); - _descrizione = causali.decode(_causale); - } - - TForm_item& descr = body.find_field(PEC_DESCR1); - descr.set(_descrizione); - - TForm_item& datadoc = body.find_field(PEC_DATADOC); - datadoc.set(_data_doc.string()); - - TForm_item& numdoc = body.find_field(PEC_NUMDOC); - numdoc.set(_num_doc); - - TForm_item& numprot = body.find_field(PEC_PROTIVA); - TString16 protiva; protiva << _num_prot; - numprot.set(protiva); - - TForm_item& datapag = body.find_field(PEC_DATAPAG); - datapag.set(_data.string()); - - const real& imp = _importo.valore(); - TForm_item& dare = body.find_field(PEC_DARE); - TForm_item& avere = body.find_field(PEC_AVERE); - - if (_importo.sezione() == 'D') { - dare.set(imp.string()); - avere.set(""); - } else { - avere.set(imp.string()); - dare.set(""); - } - - TForm_item& scaduto = body.find_field(PEC_SCADUTO); - scaduto.set(_scaduto.string()); - - TForm_item& cambio = body.find_field(PEC_CAMBIO); - cambio.set(_valuta.cambio().string()); - - TForm_item& datacambio = body.find_field(PEC_DATACAM); - datacambio.set(_valuta.data().string()); - - body.update(); -} - -static int val_compare(const void* o1, const void* o2) { - const THash_object* h1 = (const THash_object*)o1; - const THash_object* h2 = (const THash_object*)o2; - const TString& s1 = (const TString&)h1->obj(); - const TString& s2 = (const TString&)h2->obj(); - return s2.compare(s1, -1, TRUE); // same as stricmp(s1, s2) in reverse order -} - - -/////////////////////////////////////////////////////////// -// TSol_array -/////////////////////////////////////////////////////////// - -void TSol_array::calcola_scaduto(const TRiga_scadenze& rata, real& scaduto) const { - const TPartita& game = rata.partita(); - TImporto imp_scaduto = rata.importo(TRUE); - - const char* const field = rata.in_valuta() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; - TImporto imp; - - for (int p = rata.last(); p > 0; p = rata.pred(p)) { - const TRectype& pag = rata.row(p); - const TRiga_partite& sum = game.riga(pag.get_int(PAGSCA_NRIGP)); - const tipo_movimento tm = sum.tipo(); - if (tm != tm_insoluto && tm != tm_pagamento_insoluto) { - imp.set(sum.sezione(), pag.get_real(field)); - imp_scaduto += imp; - } - } - const char sezione = game.conto().tipo() == 'C' ? 'D' : 'A'; - imp_scaduto.normalize(sezione); - scaduto = imp_scaduto.valore(); -} - -TSol_row& TSol_array::new_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int n) { - if (n == 0) n = items(); - TSol_row* riga = new TSol_row(row, data, imp, n); - add(riga, n); - return *riga; -} - -void TSol_array::add_row(const TRiga_partite& row) { - if (row.is_fattura()) { - for (int r = 1; r <= row.rate(); r++) { - const TRiga_scadenze& rata = row.rata(r); - const TDate data(rata.get(SCAD_DATASCAD)); - if (data <= form().data_limite_operazione()) { - TSol_row& rec = new_row(row, data, rata.importo(TRUE), r); - if (data <= form().data_limite_scaduto()) { - real s; - calcola_scaduto(rata, s); - rec.scaduto(s); - } - } - } - } else { - const TDate data(row.get(PART_DATAPAG)); - if (data <= form().data_limite_operazione()) { - const TImporto imp(row.importo(FALSE, 0x1)); - new_row(row, data, imp); - - const TImporto abbuoni(row.importo(FALSE, 0x2)); - if (!abbuoni.is_zero()) { - TSol_row& r = new_row(row, data, abbuoni); - const TForm_item& desc_abb = form().find_field('B', odd_page, 302); - r.descrizione(desc_abb.prompt()); - } - - const TImporto diffcam(row.importo(FALSE, 0x4)); - if (!diffcam.is_zero()) { - TSol_row& r = new_row(row, data, diffcam); - const TForm_item& desc_dif = form().find_field('B', odd_page, 303); - r.descrizione(desc_dif.prompt()); - } - } - } -} - -TSol_array::TSol_array(const TPartita& game, const TSol_form* f): _form(f) { - for (int r = game.last(); r > 0; r = game.pred(r)) add_row(game.riga(r)); - sort(); -} +TSol_row::TSol_row(const char* desc, const TImporto& imp) + :TESSL_row(desc, imp) +{} /////////////////////////////////////////////////////////// // TSol_form: form speciale per solleciti /////////////////////////////////////////////////////////// -TSol_form* TSol_form::_form = NULL; +TSol_form::TSol_form(const TSol_mask& m, short id_datalim) + :TESSL_form(m, id_datalim) -void TSol_form::sol_header_handler(TPrinter& pr) { - TPrint_section& head = _form->section('H'); - head.reset(); - pr.resetheader(); - - head.update(); - for (word j = 0; j < head.height(); j++) pr.setheaderline(j, head.row(j)); +{ + _sel_tot_saldo = m.get_sel_tot_saldo(); + _sel_importo = m.get_sel_importo(); } -void TSol_form::sol_footer_handler(TPrinter& pr) { - TPrint_section& foot = _form->section('F'); - pr.resetfooter(); - - const word MAXTOT = 32; - THash_object* tot[MAXTOT]; - - // i totali sono in un assoc array disordinato per cui li copio in un array e li ordino - // alfabeticamente in base al loro codice valuta - TTotalizer& totali = _form->totali(); - totali.restart(); - - word numtot = 0; - for (THash_object* obj = totali.get_hashobj(); numtot < MAXTOT && obj != NULL; obj = totali.get_hashobj()) tot[numtot++] = obj; - qsort(tot, numtot, sizeof(THash_object*), val_compare); - - if (numtot > foot.height()) numtot = foot.height(); - - TPrint_section& body = _form->section('B'); - for (word j = 0; j < numtot; j++) { - const TString& key = tot[j]->key(); - TImporto& imp = (TImporto&)tot[j]->obj(); - TSol_row r(key, imp.normalize()); - r.print_on(body); - const TPrintrow& ri = body.row(0); - pr.setfooterline(j, ri); - } -} +/////////////////////////////////////////////////////////// +// TSol_array +/////////////////////////////////////////////////////////// +TSol_array::TSol_array(const TPartita& game, const TSol_form* f) + :TESSL_array(game, f) -bool TSol_form::print_game(const TPartita& game) -{ - bool ok = FALSE; - - TSol_array righe(game, this); - - TPrinter& pr = printer(); - TPrintrow prow; - - TPrint_section& body = section('B'); - - TImporto saldo; - - // stampa le righe di partita - for (int r = 0; r < righe.items(); r++) - { - TSol_row& riga = righe.row(r); - - if (pr.rows_left() < body.height()) - pr.formfeed(); - - riga.print_on(body); - pr.print(body.row(0)); - - totali().add(riga.importo(), ZERO, ZERO, riga.valuta().codice()); - - saldo += riga.importo(); - ok = TRUE; - } - - if (ok) { - saldo.normalize(); - - const TForm_item& desc_sld = body.find_field(301); - TSol_row sld(desc_sld.prompt(), saldo); - sld.print_on(body); - - // salta una riga vuota - TPrintrow vuota; - pr.print(vuota); - } - return ok; +{ } -TSol_form::TSol_form(const TSol_mask& m, short datafld): TForm(BASE_EC_PROFILE, m.get_prof_code()), _causali(LF_CAUSALI, CAU_CODCAUS, CAU_DESCR) { - _form = this; - _lingua = m.get_prof_lang(); - - TCursor_sheet& cs = m.cur_sheet(); - _cursore = cs.cursor(); - - _dlo = _dls = m.get(datafld); // prende il campo con la data limite sollecito - - TPrinter& pr = printer(); - - pr.setheaderhandler(sol_header_handler); - pr.headerlen(section('H').height()); - - pr.setfooterhandler(sol_footer_handler); - pr.footerlen(section('F').height()); -} - -TSol_form::~TSol_form() { - TPrinter& pr = printer(); - pr.setheaderhandler(NULL); - pr.setfooterhandler(NULL); - _form = NULL; -} diff --git a/sc/sc2402.h b/sc/sc2402.h index 566687231..757356fbc 100755 --- a/sc/sc2402.h +++ b/sc/sc2402.h @@ -17,41 +17,31 @@ #include #include +class TSol_mask: public TESSL_mask + +{ + +protected: + +public: + bool get_sel_tot_saldo() const ; + real get_sel_importo() const ; + + TSol_mask(const char *name); + virtual ~TSol_mask(); +}; /////////////////////////////////////////////////////////// // TSol_row /////////////////////////////////////////////////////////// -class TSol_row : public TSortable { - TDate _data; - int _riga; - int _rata; +class TSol_row : public TESSL_row + +{ - TString _causale; - TString _descrizione; - - TDate _data_doc; - TString _num_doc; - long _num_prot; - TImporto _importo; - TImporto _importo_lire; - real _scaduto; - real _totale; - TValuta _valuta; - protected: // TSortable - virtual int compare(const TSortable& s) const; public: - void descrizione(const char* s) { _descrizione = s; } - void scaduto(const real& s) { _scaduto = s; } - - const TValuta& valuta() const { return _valuta; } - const TImporto& importo() const { return _importo; } - const TDate& data() const { return _data; } - - void print_on(TPrint_section& body); - TSol_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata); TSol_row(const char* desc, const TImporto& imp); virtual ~TSol_row() {} @@ -62,52 +52,30 @@ public: // TSol_form: form speciale per estratti conto /////////////////////////////////////////////////////////// -class TSol_form : public TForm { - static TSol_form* _form; - - TCursor* _cursore; - TTotalizer _totali; - TDecoder _causali; - - TString _lingua; - TDate _dlo, _dls; +class TSol_form : public TESSL_form { + bool _sel_tot_saldo; + real _sel_importo; protected: - static void sol_header_handler(TPrinter& p); - static void sol_footer_handler(TPrinter& p); public: - TTotalizer& totali() { return _totali; } - TDecoder& causali() { return _causali; } - - const TDate& data_limite_operazione() const { return _dlo; } - const TDate& data_limite_scaduto() const { return _dls; } - const TString& lingua() const { return _lingua; } - - bool print_game(const TPartita& game); - - TSol_form(const TSol_mask& m, short datafld); - virtual ~TSol_form(); + bool get_sel_tot_saldo() const { return _sel_tot_saldo;} + const real & get_sel_importo() const { return _sel_importo; } + TSol_form(const TSol_mask& m, short id_datalim); + virtual ~TSol_form() {} }; - /////////////////////////////////////////////////////////// // TSol_array /////////////////////////////////////////////////////////// -class TSol_array : public TArray { - const TSol_form* _form; +class TSol_array : public TESSL_array + +{ protected: - TSol_row& new_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata = 0); - void add_row(const TRiga_partite& row); - - const TSol_form& form() const { return *_form; } - void calcola_scaduto(const TRiga_scadenze& rata, real& scaduto) const; public: - TSol_row& row(int r) const { return (TSol_row&)operator[](r); } - TSol_array(const TPartita& game, const TSol_form* f); virtual ~TSol_array() {} };