#include #include #include #include #include #include #include "../cg/saldacon.h" #include "sc2.h" #include "sc2101.h" #include "sc2102.h" #include "sc2100a.h" #include "sc21pec.h" #include #include #include #include #include /////////////////////////////////////////////////////////// // TEC_form /////////////////////////////////////////////////////////// class TEC_form : public TForm { friend class TEC_row; static TEC_form* _form; enum { MAXTOT = 16 }; TCursor* _cursore; TTotalizer _totali; TDecoder _causali; // Decodificatore dei codici causale TDecoder _valute; // Decodificatore dei codici valuta TDecoder _movimenti; // Decodificatore delle descrizioni dei movimenti TString _lingua; // Codice lingua del form TDate _dlo, _dls, _dir; // Data limite operazione, scaduto e inizio rischio int _giorni_rischio; // Numero giorni rischio nella maschera di selezione bool _in_valuta; // Il form e' in valuta int _fincatura; // 0 = nessuna, 1 = testo, 2 = grafica word _num_rip; // Numero di righe usate per i riporti word _total_rows; // Numero di righe usate per i totali word _maxtot; // Numero massimo di totali da stampare protected: void init_header(const TMask& m); word ordina_totali_per_valuta(THash_object* tot[MAXTOT]); int find_magic(TString& s, TString& magic1, TString& magic2) const; void change_magic_body(const TEC_row& o, TString& s); void change_magic_footer(const THash_object& o, TString& s); void modify_picture(TForm_item& fi, TString_array& op, const bool in_valuta); void print_total(int riga, const THash_object& o); void stampa_testata(TPrinter& p); void stampa_pedata(TPrinter& p); void stampa_riporti(TPrinter& p); static void ec_header_handler(TPrinter& p); static void ec_footer_handler(TPrinter& p); public: TTotalizer& totali() { return _totali; } TDecoder& causali() { return _causali; } TDecoder& valute() { return _valute; } TDecoder& movimenti() { return _movimenti; } 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 = 'H', pagetype pt = last_page) const; void azzera_totali(); void ultima_pagina(); bool print_game(const TPartita& game); TEC_form(const TEC_mask& m, bool gesval); virtual ~TEC_form(); }; TEC_form* TEC_form::_form = NULL; /////////////////////////////////////////////////////////// // TEC_row // Rappresenta una singola riga di stampa /////////////////////////////////////////////////////////// class TEC_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 long _num_reg; // Numero registrazione 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; TEC_form& form() const; public: int riga() const { return _riga; } int rata() const { return _rata; } void reset_uguali(); void descrizione(const char* s) { _descrizione = s; } void importo(const TImporto& i) { _importo = i; } void importo_lire(const real& i) { _importo_lire = i; } void scaduto(const real& s) { _scaduto = s; } void esposto(const real& e) { _esposto = e; } void salvo_buon_fine(bool sbf) { _salvo_buon_fine = sbf; } const TString& causale() const { return _causale; } const TString& descrizione() const { return _descrizione; } long num_reg() const { return _num_reg; } const TDate& data() const { return _data; } const TImporto& importo() const { return _importo; } const real& importo_lire() const { return _importo_lire; } real scaduto() const { return _scaduto; } real esposto() const { return _esposto; } const TValuta& valuta() const { return _valuta; } bool in_valuta() const { return _valuta.in_valuta(); } void print_on(TPrint_section& body); TEC_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata); TEC_row(const char* desc, const TImporto& imp, const TValuta& val); virtual ~TEC_row() {} }; TEC_row::TEC_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata) : _num_prot(0), _num_reg(0), _salvo_buon_fine(FALSE) { _riga = row.get_int(PART_NRIGA); _rata = rata; _data = data; _causale = row.get(PART_CODCAUS); _data_doc = row.get(PART_DATADOC); _num_doc = row.get(PART_NUMDOC); _num_prot = row.get_long(PART_PROTIVA); _num_reg = row.get_long(PART_NREG); _importo = imp; _importo.normalize(); _descrizione = row.get(PART_DESCR); _valuta.get(row); const bool valuta = form().in_valuta() && _valuta.in_valuta(); const char* const field = valuta ? PART_IMPTOTVAL : PART_IMPTOTDOC; _totale = row.get_real(field); } TEC_row::TEC_row(const char* desc, const TImporto& imp, const TValuta& val) : _riga(9999), _rata(9999), _num_doc(0), _num_prot(0), _num_reg(0), _salvo_buon_fine(FALSE) { _descrizione = desc; _importo = imp; _importo.normalize(); _valuta = val; } // Le righe dell'estratto conto sono ordinate per data, riga partita, numero rata o // posizione iniziale nell'array (in caso di uguaglianza di tutto il resto) int TEC_row::compare(const TSortable& s) const { const TEC_row& r = (const TEC_row&)s; int c = 0; if (_data == r._data) { c = _riga - r._riga; if (c == 0) c = _rata - r._rata; } else c = _data > r._data ? +1 : -1; return c; } // Annulla i campi uguali alla riga precedente void TEC_row::reset_uguali() { _num_doc = ""; _data_doc = botime; _num_prot = 0; _totale = ZERO; } void TEC_row::set_imp(TForm_item& fi, const real& imp, bool valuta) const { TString old_picture(20); if (valuta) { old_picture = fi.picture(); TString new_picture(20); if (old_picture.empty()) { new_picture = valuta ? ".3" : "."; } else { new_picture = old_picture; if (old_picture.find(',') > 0) new_picture << ".@@@"; else new_picture << ",@@@"; } const int w = fi.width(); int exceed = w - new_picture.len(); if (exceed<0 && w>0) { exceed=::abs(exceed); new_picture = new_picture.mid(exceed,new_picture.len()-exceed); } fi.set_picture(new_picture); } fi.set(imp.string()); } TEC_form& TEC_row::form() const { TEC_form* f = TEC_form::_form; CHECK(f, "NULL form"); return *f; } void TEC_row::print_on(TPrint_section& body) { TEC_form& form = (TEC_form&)body.form(); const bool valuta = form.in_valuta() && in_valuta(); TForm_item& causale = body.find_field(PEC_CODCAUS); causale.set(_causale); TForm_item& descr = body.find_field(PEC_DESCR); if (num_reg() > 0) // Riga di partita vera e propria (non totale parziale) { TString s(80); s = descr.prompt(); TEC_form::_form->change_magic_body(*this, s); descr.set(s); } else 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()); TString_array old_pictures; const real& imp = _importo.valore(); TForm_item& dare = body.find_field(PEC_DARE); TForm_item& avere = body.find_field(PEC_AVERE); old_pictures.add(dare.picture()); old_pictures.add(avere.picture()); if (_importo.sezione() == 'D') { set_imp(dare, imp, valuta); avere.set(""); } else { set_imp(avere, imp, valuta); dare.set(""); } TForm_item& scaduto = body.find_field(PEC_SCADUTO); old_pictures.add(scaduto.picture()); set_imp(scaduto, _scaduto, valuta); TForm_item& esposto = body.find_field(PEC_ESPOSTO); old_pictures.add(esposto.picture()); set_imp(esposto, _esposto, valuta); esposto.set_prompt(_salvo_buon_fine ? "*" : " "); TForm_item& totdoc = body.find_field(PEC_TOTDOC); old_pictures.add(totdoc.picture()); set_imp(totdoc, _totale, valuta); TForm_item& lire = body.find_field(PEC_IMPLIRE); lire.set(_importo_lire.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()); const TString old_prompt(descr.prompt()); descr.set_prompt(""); // Nasconde temporaneamente il prompt per non stampare i body.update(); // Crea vera riga di stampa esposto.set_prompt(" "); // Ripristina il vecchi prompt descr.set_prompt(old_prompt); dare.set_picture(old_pictures.row(0)); avere.set_picture(old_pictures.row(1)); scaduto.set_picture(old_pictures.row(2)); esposto.set_picture(old_pictures.row(3)); totdoc.set_picture(old_pictures.row(4)); } /////////////////////////////////////////////////////////// // TEC_array /////////////////////////////////////////////////////////// class TEC_array : public TArray { TArray _scaduto; // Array di importi scaduti const TEC_form* _form; // Form che contiene l'array di righe protected: TEC_row& new_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int rata = 0); void add_row(const TRiga_partite& row); const TEC_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; static TPartita* _sort_game; static int ordina_pag(const void* pag1, const void* pag2); void arrange_scaduto(const TPartita& game); public: TEC_row& row(int r) const { return (TEC_row&)operator[](r); } TEC_array(const TPartita& game, const TEC_form* f); virtual ~TEC_array() {} }; TPartita* TEC_array::_sort_game = NULL; // Calcola l'importo su di una riga di pagamento TImporto TEC_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); // Riga di fattura const bool fat_val = fat.in_valuta(); const int nrigp = pag.get_int(PAGSCA_NRIGP); const TRiga_partite& sum = game.riga(nrigp); // Riga di pagamento const char sez = sum.sezione(); const char* const field = valuta && fat_val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; TImporto imp(sez, pag.get_real(field)); // Importo base if (!fat_val) imp.valore() += pag.get_real(PAGSCA_RITENUTE); // Sommo le ritenute se sono il lire if (pag.get_char(PAGSCA_ACCSAL) == 'S') // Se il pagamento ha abbuoni o differenze cambio { real abb(pag.get(PAGSCA_ABBUONI)); if (!valuta && fat_val) // Se voglio gli abbuoni in lire ma la fattura non lo e' { const TValuta val(sum); // Leggo il cambio dalla riga di partita val.val2lit(abb); // Converto in lire gli abbuoni abb += pag.get_real(PAGSCA_DIFFCAM); // Sommo l'eventuale differenza cambio (gia' in lire) } imp.valore() += abb; // Sommo il tutto all'importo base (sez e' uguale per tutti i valori) } return imp; } // Certified 100% TImporto& TEC_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; } // Ordina i pagamenti in ordine di DATAPAG int TEC_array::ordina_pag(const void* pag1, const void* pag2) { const int r1 = (*(TRectype**)pag1)->get_int(PAGSCA_NRIGP); const TDate d1 = _sort_game->riga(r1).get(PART_DATAPAG); const int r2 = (*(TRectype**)pag2)->get_int(PAGSCA_NRIGP); const TDate d2 = _sort_game->riga(r2).get(PART_DATAPAG); const int diff = d1 == d2 ? 0 : (d1 > d2 ? +1 : -1); return diff; } real TEC_array::calcola_scaduto(const TRiga_scadenze& rata, bool valuta) { const TPartita& game = rata.partita(); const char sezione = game.conto().tipo() == 'C' ? 'D' : 'A'; TImporto scaduto_rata = rata.importo(TRUE); int riga_corrente_scaduto = 0; const int numpag = rata.rows(); // Numero totale di pagamenti sulla rata TRectype** arrpag = NULL; // Array di puntatori ai pagamenti if (numpag > 0) { arrpag = new TRectype*[numpag]; int i = 0; for (int p = rata.last(); p > 0; p = rata.pred(p)) arrpag[i++] = (TRectype*)&rata.row(p); // Copia puntatori ai pagamenti nell'array _sort_game = (TPartita*)&game; // Inizializza partita di appoggio al sort qsort(arrpag, numpag, sizeof(TRectype*), ordina_pag); } for (int i = 0; i < numpag; i++) { const TRectype& pag = *arrpag[i]; 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 ", nrigp); importo_riga_scaduto(riga_corrente_scaduto) += imp; } else { scaduto_rata += imp; } } if (arrpag != NULL) delete arrpag; scaduto_rata.normalize(sezione); return scaduto_rata.valore(); } TEC_row& TEC_array::new_row(const TRiga_partite& row, const TDate& data, const TImporto& imp, int n) { CHECKD(n > 0, "Numero rata errato: ", n); TEC_row* riga = new TEC_row(row, data, imp, n); add(riga); return *riga; } void TEC_array::add_row(const TRiga_partite& row) { const bool in_valuta = form().in_valuta() && row.in_valuta(); const char sezione = row.get_char(PART_TIPOCF) == 'C' ? 'D' : 'A'; const TDate data_op(row.get(PART_DATAREG)); if (data_op <= form().data_limite_operazione()) { if (row.is_fattura()) { for (int r = 1; r <= row.rate(); r++) { const TRiga_scadenze& rata = row.rata(r); const TDate data_scad(rata.get(SCAD_DATASCAD)); TEC_row& rec = new_row(row, data_scad, rata.importo(in_valuta), r); if (data_scad <= form().data_limite_scaduto()) { const real s = calcola_scaduto(rata, in_valuta); rec.scaduto(s); } if (in_valuta) { TImporto il = rata.importo(FALSE); il.normalize(sezione); rec.importo_lire(il.valore()); } } } else { const TDate data_pag(row.get(PART_DATAPAG)); const TImporto imp(row.importo(in_valuta, 0x1)); // Importo pulito senza nient'altro TEC_row& riga = new_row(row, data_pag, imp, 10); const int tipo_pag = row.get_int(PART_TIPOPAG); const tipo_movimento tipo_mov = row.tipo(); // Controlla se e' un pagamento con effetti if ((tipo_mov == tm_pagamento || tipo_mov == tm_pagamento_insoluto) && (tipo_pag >= 2 && tipo_pag <= 7)) { const TDate& dls = form().data_limite_scaduto(); const int gr = form().giorni_rischio(); const TDate& dir = form().data_inizio_rischio(); bool sbf = FALSE; TImporto esposto(row.esposto(in_valuta, dls, dir, sbf)); bool esp = !esposto.is_zero(); /* 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); const char sezione = row.get_char(PART_TIPOCF) == 'C' ? 'A' : 'D'; esposto.normalize(sezione); riga.salvo_buon_fine(sbf); // Esposto salvo buon fine riga.esposto(esposto.valore()); } } const TImporto abbuoni(row.importo(in_valuta, 0x2)); if (!abbuoni.is_zero()) { TEC_row& rec = new_row(row, data_pag, abbuoni, 20); rec.descrizione(form().describe(PEC_ABBUONI)); if (in_valuta) { TImporto il(row.importo(FALSE, 0x2)); il.normalize(sezione); rec.importo_lire(il.valore()); } } TImporto diffcam(row.importo(FALSE, 0x4)); if (!diffcam.is_zero() && !in_valuta) { TEC_row& rec = new_row(row, data_pag, TImporto('D', ZERO), 30); rec.descrizione(form().describe(PEC_DIFFCAM)); rec.importo(diffcam); } TImporto ritenute(row.importo(FALSE, 0x8)); if (!ritenute.is_zero()) { TEC_row& rec = new_row(row, data_pag, TImporto('D', ZERO), 40); rec.descrizione(form().describe(PEC_RITENUTE)); if (in_valuta) { ritenute.normalize(sezione); rec.importo_lire(ritenute.valore()); } else rec.importo(ritenute); } } } } void TEC_array::arrange_scaduto(const TPartita& game) { const bool in_valuta = form().in_valuta() && row(0).in_valuta(); TImporto totpag(game.importo_pagato_unassigned(in_valuta)); const char sezione = game.conto().tipo() == 'C' ? 'A' : 'D'; totpag.normalize(sezione); for (int r = items()-1; r >= 0; r--) { TEC_row& s = row(r); real imp(s.scaduto()); if (imp.sign() < 0) { totpag += TImporto(sezione, -imp); s.scaduto(ZERO); } } for (r = 0; r < items() && totpag.valore() > ZERO; r++) { TEC_row& s = row(r); real imp = s.scaduto(); if (imp.sign() > 0) { if (imp >= totpag.valore()) { imp -= totpag.valore(); s.scaduto(imp); totpag = TImporto(sezione, ZERO); } else { s.scaduto(ZERO); totpag -= TImporto(sezione, imp); } } } } TEC_array::TEC_array(const TPartita& game, const TEC_form* f) : _form(f) { for (int r = game.last(); r > 0; r = game.pred(r)) add_row(game.riga(r)); const char sezione = game.conto().tipo() == 'C' ? 'D' : 'A'; for (r = items()-1; r >= 0; r--) { TEC_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()); } } } if (items() > 0) { sort(); arrange_scaduto(game); } } /////////////////////////////////////////////////////////// // Form speciale per estratti conto /////////////////////////////////////////////////////////// void TEC_form::stampa_testata(TPrinter& pr) { TPrint_section& head = section('H'); TForm_item& pagina = head.find_field(PEC_PAGINA); TString16 pg; pg << int(pr.getcurrentpage()); pagina.set(pg); head.update(); const word r = head.height()-1; TPrintrow& head_row = head.row(r-1); for (word j = 0; j <= r; j++) pr.setheaderline(j, head.row(j)); } // Confronta due totali in valuta alfabeticamente 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()); } word TEC_form::ordina_totali_per_valuta(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& arr = totali(); arr.restart(); word num_rip = 0; for (THash_object* obj = arr.get_hashobj(); num_rip < MAXTOT && obj != NULL; obj = arr.get_hashobj()) tot[num_rip++] = obj; qsort(tot, num_rip, sizeof(THash_object*), tot_compare); return num_rip; } void TEC_form::stampa_riporti(TPrinter& pr) { THash_object* tot[MAXTOT]; _num_rip = ordina_totali_per_valuta(tot); if (_num_rip > _maxtot) _num_rip = _maxtot; const TString& riporto = describe(PEC_RIPORTO); TString desc(80); TPrint_section& body = section('B'); for (word j = 0; j < _num_rip; j++) { const TString& key = tot[j]->key(); TTotal& t = (TTotal&)(tot[j]->obj()); desc = riporto; TValuta val; if (key.not_empty()) { desc << ' ' << key; TValuta val1(key,botime,ZERO); // E' una valuta fittizia, giusto per far val = val1; // eseguire in set_imp() i calcoli per i decimali. } TEC_row rip(desc, t.importo().normalize(),val); rip.scaduto(t.scaduto()); rip.esposto(t.esposto()); rip.importo_lire(t.importo_lire()); rip.print_on(body); pr.setfooterline(j+1, body.row(0)); } } int TEC_form::find_magic(TString& s, TString& magic1, TString& magic2) const { const int pos = s.find('<', 0); int end; if (pos >= 0) { end = s.find('>', pos); if (end > pos) { int p1 = pos+1; magic1 = s.mid(p1, 2); while (isalnum(s[p1])) p1++; while (p1 < end && !isalnum(s[p1])) p1++; if (p1 < end) magic2 = s.mid(p1, 2); else magic2.cut(0); } else end = s.len()-1; const TString right(s.mid(end+1)); s.cut(pos); s << right; } return pos; } void TEC_form::change_magic_body(const TEC_row& row, TString& s) { TString magic1(4), magic2(4), val(50); int pos; while ((pos = find_magic(s, magic1, magic2)) >= 0) { val.cut(0); if (magic1 == "PA" || magic2 == "PA") { val = row.descrizione(); if (val.empty()) val = causali().decode(row.causale()); } if (magic1 == "MO" || magic2 == "MO") { val = movimenti().decode(row.num_reg()); } s.insert(val, pos); } } void TEC_form::change_magic_footer(const THash_object& o, TString& s) { TString magic1(4), magic2(4), val(50); int pos; while ((pos = find_magic(s, magic1, magic2)) >= 0) { val.cut(0); if (magic1 == "DA") { const TDate& d = magic2 == "SC" ? _dls : _dlo; if (d != eotime) val = d.string(); } if (magic1 == "VA") val = o.key(); if (magic1 == "DE") val = valute().decode(o.key()); s.insert(val, pos); } } void TEC_form::modify_picture(TForm_item& fi, TString_array& op, const bool in_valuta) { TString pic(20); pic = fi.picture(); op.add(pic); const int w = fi.width(); if (in_valuta && _in_valuta) { if (pic.find(',') > 0) pic << ".###"; else pic << ",@@@"; int exceed = w - pic.len(); if (exceed<0 && w>0) { exceed=::abs(exceed); pic = pic.mid(exceed,pic.len()-exceed); } } // oltre a cio' deve correggere la picture, in modo che tutti gli importi del // footer risultino incolonnati correttamente. // (nel body cio' e' fatto in TForm_number::put_paragraph()) const int l = pic.len(); if (w>l) { int gap = w-l; TString stmp(gap); // cosi' mette gli spazi necessari davanti alla picture stmp.fill(' '); // in modo da colmare il vuoto pic.insert(stmp); } fi.set_picture(pic); } void TEC_form::print_total(int riga, const THash_object& o) { const short MAXID = 4; const short f_id[MAXID] = { PEC_TSALDO, PEC_TSCADUTO, PEC_TESPOSTO, PEC_TIMPLIRE }; TString_array prompt(MAXID); TPrint_section& foot = section('F'); TPrint_section& body = section('B'); TForm_item& bdesc = body.find_field(PEC_DESCR); // Sostituisce magic-names nei prompt TString s(80); for (int i = 0; i < MAXID; i++) { TForm_item& desc_field = foot.find_field(f_id[i]); if (desc_field.shown()) { s = desc_field.prompt(); prompt.add(s, i); change_magic_footer(o, s); desc_field.set_prompt(s); if (desc_field.x() <= 0) desc_field.set_x(bdesc.x()); } } const TTotal& t = (const TTotal&)o.obj(); TImporto imp = t.importo(); imp.normalize(); const bool in_valuta = o.key().not_empty(); TForm_item& dare = foot.find_field(PEC_DARE); TForm_item& avere = foot.find_field(PEC_AVERE); TString_array old_pictures;//pictures da ripristinare dopo aver stampato if (dare.x() <= 0 || avere.x() <= 0) { TForm_item& bdare = body.find_field(PEC_DARE); dare.set_x(bdare.x()); dare.width() = bdare.width(); TForm_item& bavere = body.find_field(PEC_AVERE); avere.set_x(bavere.x()); avere.width() = bavere.width(); } modify_picture(dare,old_pictures,in_valuta); modify_picture(avere,old_pictures,in_valuta); if (imp.sezione() == 'D') { dare.set(imp.valore().string()); avere.set(""); } else { dare.set(""); avere.set(imp.valore().string()); } TForm_item& scaduto = foot.find_field(PEC_SCADUTO); if (scaduto.x() <= 0) { TForm_item& bscaduto = body.find_field(PEC_SCADUTO); scaduto.set_x(bscaduto.x()); scaduto.width() = bscaduto.width(); } modify_picture(scaduto,old_pictures,in_valuta); scaduto.set(t.scaduto().string()); TForm_item& esposto = foot.find_field(PEC_ESPOSTO); if (esposto.x() <= 0) { TForm_item& besposto = body.find_field(PEC_ESPOSTO); esposto.set_x(besposto.x()); esposto.width() = besposto.width(); } modify_picture(esposto,old_pictures,in_valuta); esposto.set(t.esposto().string()); TForm_item& implire = foot.find_field(PEC_IMPLIRE); if (implire.x() <= 0) { TForm_item& bimplire = body.find_field(PEC_IMPLIRE); implire.set_x(bimplire.x()); esposto.width() = bimplire.width(); if (bimplire.shown()) implire.show(); else implire.hide(); } modify_picture(implire,old_pictures,FALSE); implire.set(t.importo_lire().string()); foot.update(); // Ripristina prompt originari for (i = 0; i < MAXID; i++) { const TString* p = (const TString*)prompt.objptr(i); if (p) { TForm_item& desc_field = foot.find_field(f_id[i]); desc_field.set_prompt(*p); } } if (old_pictures.items() > 0)//restore old pictures { dare.set_picture(old_pictures.row(0)); avere.set_picture(old_pictures.row(1)); scaduto.set_picture(old_pictures.row(2)); esposto.set_picture(old_pictures.row(3)); implire.set_picture(old_pictures.row(4)); } for (word r = 0; r < _total_rows; r++) printer().setfooterline(riga + r, foot.row(r)); } void TEC_form::stampa_pedata(TPrinter& pr) { THash_object* tot[MAXTOT]; word num_rip = ordina_totali_per_valuta(tot); if (num_rip > _maxtot) num_rip = _maxtot; for (word j = 0; j < num_rip; j++) print_total(j*_total_rows+1, *tot[j]); } void TEC_form::ultima_pagina() { set_last_page(TRUE); } void TEC_form::ec_header_handler(TPrinter& pr) { pr.resetheader(); _form->stampa_testata(pr); } void TEC_form::ec_footer_handler(TPrinter& pr) { pr.resetfooter(); if (_form->page(pr) > 0) // Normal page _form->stampa_riporti(pr); else // Last page _form->stampa_pedata(pr); } void TEC_form::azzera_totali() { totali().destroy(); // Azzera tutti i riporti _num_rip = 0; // Azzera il numero di righe di riporto set_last_page(FALSE); // Azzera il flag di ultima pagina di stampa TPrint_section& foot = section('F'); printer().footerlen(foot.height()); printer().setcurrentpage(1); } bool TEC_form::print_game(const TPartita& game) { bool ok = FALSE; TEC_array righe(game, this); TPrinter& pr = printer(); TPrintrow prow; TPrint_section& body = section('B'); TImporto saldo; real scaduto, esposto, implire; // Stampa le righe di partita int ultima_riga = 0; int ultima_rata = 0; for (int r = 0; r < righe.items(); r++) { TEC_row& riga = righe.row(r); if (pr.rows_left() <= (body.height()+1)) // salto pagina { pr.formfeed(); for (word nr = 0; nr < _num_rip; nr++) { TPrintrow* fl = pr.getfooterline(nr + 1); CHECKD(fl, "Manca la riga di riporto ", nr + 1); pr.print(*fl); } } const int ri = riga.riga(); const int ra = riga.rata(); if (ri == ultima_riga && ra == ultima_rata+1) riga.reset_uguali(); ultima_riga = ri; ultima_rata = ra; riga.print_on(body); pr.print(body.row(0)); totali().add(riga.importo(), riga.scaduto(), riga.esposto(), riga.importo_lire(), riga.valuta().codice()); saldo += riga.importo(); scaduto += riga.scaduto(); esposto += riga.esposto(); implire += riga.importo_lire(); ok = TRUE; } if (ok) { saldo.normalize(); const TString & dessaldo = describe(PEC_SALDO); TString desc(80); const TValuta & val = righe.row(r-1).valuta(); desc = dessaldo; desc << ' ' << val.codice(); TEC_row sld(desc, saldo, val); sld.scaduto(scaduto); sld.esposto(esposto); sld.importo_lire(implire); sld.print_on(body); pr.print(body.row(0)); } return ok; } const TString& TEC_form::describe(short id, char sez, pagetype pt) const { const TForm_item& fi = find_field(sez, pt, id); return fi.prompt(); } void TEC_form::init_header(const TMask& m) { TPrint_section& head = section('H'); TForm_item& luogo_invio = head.find_field(PEC_LUOGOIN); luogo_invio.set(m.get(F_LUOGOSEND)); TForm_item& data_invio = head.find_field(PEC_DATAIN); data_invio.set(m.get(F_DATASEND)); TForm_item& fi = head.find_field(PEC_MEMO); if (fi.shown()) { TLocalisamfile f(LF_RFORM); f.put("TIPOPROF", name()); f.put("CODPROF", code()); f.put("SEZ", "H0"); f.put("ID", PEC_MEMO); const int err = f.read(); if (err == NOERR) fi.set(f.get("TESTO")); } if (_fincatura) { TPrint_section& fink = section('G'); if (fink.fields() > 0) fink.update(); // Setta il backgroud di stampa } } TEC_form::TEC_form(const TEC_mask& m, bool gesval) : TForm(BASE_EC_PROFILE, m.get_prof_name()), _in_valuta(FALSE), _num_rip(0), _total_rows(0), _causali(LF_CAUSALI, CAU_CODCAUS, CAU_DESCR), _movimenti(LF_MOV, MOV_NUMREG, MOV_DESCR), _valute("%VAL") { _form = this; TCursor_sheet& cs = m.cur_sheet(); _cursore = cs.cursor(); _lingua = m.get_prof_lang(); // Lingua profilo _dlo = m.get(F_DATALIMOP); if (!_dlo.ok()) _dlo = eotime; _dls = m.get(F_DATALIMSC); _giorni_rischio = m.get_int(F_GIORISCH); _dir = _dls; _dir -= _giorni_rischio; TPrinter& pr = printer(); pr.setheaderhandler(ec_header_handler); TPrint_section& head = section('H'); pr.headerlen(head.height()); pr.setfooterhandler(ec_footer_handler); const TPrint_section& foot = section('F'); pr.footerlen(foot.height()); TForm_item& flags = find_field('H', last_page, PEC_FLAGS); TToken_string f(flags.prompt()); _in_valuta = gesval && f.get_char(0) == 'X'; // Il profilo e' in valuta se c'e' il flag di valuta _fincatura = f.get_int(1); if (_fincatura > 0) { const int first = head.height()-2; const int last = pr.formlen(); const int horiz[] = { first+2, last-foot.height()+1, 0 }; set_mode((bkg_mode)_fincatura); genera_fincatura(odd_page, first, last, horiz); } TForm_item& uns = section('F').find_field(PEC_UNASSIGNED); TForm_item& tuns = section('F').find_field(PEC_TUNASSIGNED); if (uns.shown()) uns.hide(); if (tuns.shown()) tuns.hide(); genera_intestazioni(odd_page, head.height() - 1); init_header(m); // Set fixed text _total_rows = 1; for (word fi = 0; fi < foot.fields(); fi++) { const TForm_item& item = foot.field(fi); if (item.shown()) { const word y = (word)item.y(); if (y > _total_rows) _total_rows = y; } } _maxtot = f.get_int(3); // La prima e l'ultima riga del footer devono essere lasciate libere per la fincatura // Ogni totale occupa _total_rows righe: per cui posso calcolare il massimo di totali // che posso stampare nel footer. const word max = (foot.height() - 2) / _total_rows; if (_maxtot <= 0 || _maxtot > max) _maxtot = max; } TEC_form::~TEC_form() { TPrinter& pr = printer(); pr.setheaderhandler(NULL); pr.setfooterhandler(NULL); _form = NULL; } /////////////////////////////////////////////////////////// // Stampa estratti conto /////////////////////////////////////////////////////////// class TStampaEC_application : public TApplication { TEC_mask* _msk; TEC_form* _form; TFile_array _file; TString _lingua_ditta; bool _gesval; protected: // TApplication virtual bool create(); virtual bool destroy(); virtual bool menu(MENU_TAG m); virtual void on_firm_change(); public: static TStampaEC_application& app() { return (TStampaEC_application&)main_app(); } public: TEC_mask& mask() { return *_msk; } TCursor_sheet& sheet() { return _msk->cur_sheet(); } TEC_form& form() { return *_form; } bool print_selected(); // print selected items int print_ec(); // print one item TStampaEC_application(); virtual ~TStampaEC_application() {} }; bool TStampaEC_application::print_selected() { TCursor_sheet& s = sheet(); TCursor& c = *s.cursor(); const char who = mask().get_who(); const int key = mask().get_key(); // Filtra il cursore del form in mode che diventi uguale al cursor_sheet corrente // Qui sarebbe bello copiarsi l'indice dell'altro cursore 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 printer().open(); 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 const int ret = print_ec(); if (ret < 0) analfabeti++; } printer().close(); if (analfabeti > 0) warning_box("%ld clienti/fornitori non sono stati stampati in quanto " "il codice lingua non corrispondeva al profilo di stampa", analfabeti); return TRUE; } int TStampaEC_application::print_ec() { begin_wait(); TEC_form& f = form(); const TRectype& clf = f.cursor()->file().curr(); const TString lincf(clf.get(CLI_CODLIN)); bool ok = TRUE; // make controllations per lingua profilo/CF if ((f.lingua() == _lingua_ditta && !lincf.empty()) || f.lingua() != _lingua_ditta) ok = lincf == f.lingua(); if (!ok) // Cliente analfabeta return -1; f.azzera_totali(); // Azzera totali di fine pagina // Filtra solo le partite del cliente selezionato TLocalisamfile& partite = _file[LF_PARTITE]; partite.zero(); partite.put(PART_TIPOCF, clf.get(CLI_TIPOCF)); partite.put(PART_SOTTOCONTO, clf.get(CLI_CODCF)); const TRectype filter(partite.curr()); const bool stampa_chiuse = mask().get_bool(F_STAMPCHIU); const TDate data_chiuse = mask().get(F_DATACHIU); TString status; bool one_printed = FALSE; // Non ho stampato ancora nulla for (int err = partite.read(_isgteq); err == NOERR && partite.curr() == filter; err = partite.read(_isgreat)) { TPartita game(partite.curr()); status.cut(0); status << game.anno() << ' ' << game.numero(); xvt_statbar_set(status); do_events(); // if (game.chiusa()) // { const TDate& dir = f.data_inizio_rischio(); const TDate& dlo = f.data_limite_operazione(); const TDate& dls = f.data_limite_scaduto(); const TImporto saldo = game.calcola_saldo_al(f.in_valuta(), dlo, dls, dir); if (saldo.is_zero()) { int r = 0; if (stampa_chiuse) { for (r = game.last(); r > 0 ; r = game.pred(r)) { const TRiga_partite& riga = game.riga(r); if (riga.is_fattura()) { const TDate dd(riga.get(PART_DATADOC)); if (dd >= data_chiuse) break; } } } if (r == 0) continue; } // } if (one_printed) { TPrintrow empty; // Salta una riga vuota printer().print(empty); // (Non farlo alla fine di ogni partita!) } const bool printed = form().print_game(game); if (printed) one_printed = TRUE; partite.put(PART_NRIGA, 9999); } if (one_printed) { f.ultima_pagina(); printer().formfeed(); if (printer().isfax()) { const char* tipo = clf.get_char(CLI_TIPOCF) == 'C' ? "Clienti" : "Fornitori"; const char* codice = clf.get(CLI_CODCF); printer().send_fax(tipo, codice); } } xvt_statbar_set(NULL); end_wait(); return one_printed ? 1 : 0; } /////////////////////////////////////////////////////////// // Generic TApplication methods /////////////////////////////////////////////////////////// bool TStampaEC_application::create() { TApplication::create(); _file.open(LF_TABCOM, LF_TAB, LF_CAUSALI, LF_MOV, LF_RMOV, 0); _file.open(LF_NDITTE, LF_ANAG, LF_COMUNI, LF_RFORM, 0); _file.open(LF_CLIFO, LF_PARTITE, LF_SCADENZE, LF_PAGSCA ,0); _msk = new TEC_mask("sc2100a"); dispatch_e_menu(MENU_ITEM(1)); return TRUE; } bool TStampaEC_application::destroy() { delete _msk; _file.close(); return TApplication::destroy(); } void TStampaEC_application::on_firm_change() { mask().reset(); TApplication::on_firm_change(); TConfig c(CONFIG_DITTA, "cg"); _lingua_ditta = c.get("CodLin"); _gesval = c.get_bool("GesVal"); } bool TStampaEC_application::menu(MENU_TAG) { TEC_mask& m = mask(); while (m.run() != K_QUIT) { _form = new TEC_form(m, _gesval); print_selected(); delete _form; _form = NULL; } return FALSE; } TStampaEC_application::TStampaEC_application() : _lingua_ditta(1), _msk(NULL), _form(NULL) {} int sc2100(int argc, char** argv) { TStampaEC_application app; app.run(argc, argv, "Stampa Estratti Conto"); return 0; }