#include #include #include #include #include #include #include #include "scselect.h" #include "sc2400a.h" #include "sc2400b.h" #include "sc21pec.h" #include #include "../ca/calib01.h" #include "../ca/movana.h" static bool sc_filter_handler(TMask_field& f, KEY k) { if (k == K_SPACE) { TCursor_sheet& cs = (TCursor_sheet&)f.mask(); TCursor& c = *cs.cursor(); TString expr; // Espressione di filtro complessiva if (f.get().full()) // Filtro attivato! { const short id = f.dlg()-500; TString e = f.mask().get(id); // Espressione regolare e.strip("\"'"); // Tolgo caratteri che potrebbero dare problemi if (e.full()) { expr = (c.file().num() == LF_CLIFO) ? CLI_RAGSOC : PCN_DESCR; expr << "?=\"" << e << '"'; expr.upper(); } if (expr.empty()) f.reset(); } c.freeze(false); c.setfilter(expr, true); c.freeze(true); cs.force_update(); cs.post_select(0); } return true; } static bool sc_ragsoc_handler(TMask_field& f, KEY k) { if (k == K_TAB && f.focusdirty()) { TMask_field& chk = f.mask().field(f.dlg()+500); if (f.get().starts_with("*")) chk.set("X"); if (chk.get().full()) sc_filter_handler(chk, K_SPACE); } return true; } /////////////////////////////////////////////////////////// // TESSL_row /////////////////////////////////////////////////////////// TESSL_row::TESSL_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); } TESSL_row::TESSL_row(const char* desc, const TImporto& imp, const TValuta& val) : _riga(9999), _rata(9999), _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, // 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 = _rata - r._rata; } else c = _data < r._data ? -1 : +1; return c; } // Annulla i campi uguali alla riga precedente void TESSL_row::reset_uguali() { _num_doc = ""; _data_doc = botime; _num_prot = 0; _totale = ZERO; } void TESSL_row::set_imp(TForm_item& fi, const real& imp, const char* cod_val) const { fi.set(imp.string()); } TESSL_form& TESSL_row::form() const { TESSL_form* f = TESSL_form::_form; CHECK(f, "NULL form"); return *f; } void TESSL_row::print_on(TPrint_section& body) { TESSL_form& form = (TESSL_form&)body.form(); const bool show_value = form.in_valuta() && in_valuta(); const TString& cod_valuta = show_value ? valuta().codice() : EMPTY_STRING; TForm_item& campo_valuta = body.find_field(PEC_VALUTA); campo_valuta.set(cod_valuta); 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_DESCR); if (num_reg() > 0) // Riga di partita vera e propria (non totale parziale) { TString s(80); s = descr.prompt(); TESSL_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()); 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') { set_imp(dare, imp, cod_valuta); avere.set(""); } else { set_imp(avere, imp, cod_valuta); dare.set(""); } TForm_item& importo_in_euro = body.find_field(PEC_IMPEURO); set_imp(importo_in_euro, _importo_euro, ""); // In generale va espresso nella valuta della ditta TForm_item& scaduto = body.find_field(PEC_SCADUTO); set_imp(scaduto, _scaduto, cod_valuta); TForm_item& esposto = body.find_field(PEC_ESPOSTO); set_imp(esposto, _esposto, cod_valuta); esposto.set_prompt(_salvo_buon_fine ? "*" : " "); TForm_item& totdoc = body.find_field(PEC_TOTDOC); //old_pictures.add(totdoc.picture()); set_imp(totdoc, _totale, cod_valuta); 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()); TForm_item& bloccata = body.find_field(PEC_BLOCCATA); bloccata.set(_bloccata ? "X" : ""); TForm_item& analitica = body.find_field(PEC_ANALITICA); analitica.set(_codici_analitica); TParagraph_string p(_codici_analitica, analitica.width()); const int h = analitica.height(); int i = 0; for (i = 0; p.get() != nullptr && i < h; i++); analitica.section().set_height(p.empty() ? 1 : i); const TString old_prompt(descr.prompt()); descr.set_prompt(""); // Nasconde temporaneamente il prompt per non stampare i body.update(); // crea la vera riga di stampa esposto.set_prompt(" "); descr.set_prompt(old_prompt); // Ripristina il vecchio 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)); } 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 /////////////////////////////////////////////////////////// TPartita* TESSL_array::_sort_game = nullptr; // 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); // 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 in lire const TImporto ritsoc(sum.sezione_ritsoc(), pag.get_real(PAGSCA_RITSOC)); imp += ritsoc; } 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.val2eur(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& 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 == nullptr) { imp = new TImporto; _scaduto.add(imp, n); } return *imp; } // Ordina i pagamenti in ordine di DATAPAG int TESSL_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 TESSL_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(valuta); int riga_corrente_scaduto = 0; const int numpag = rata.rows(); // Numero totale di pagamenti sulla rata TRectype** arrpag = nullptr; // 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 != nullptr) delete arrpag; 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); return *riga; } void TESSL_array::add_row(const TRiga_partite& row) { const bool in_valuta = form().in_valuta() && row.in_valuta(); real importo_in_lire; const char sezione = form().sezione_normale(); const TDate data_op = row.get(PART_DATAREG); if (data_op <= form().data_limite_operazione()) { TString codanal; if (main_app().has_module(CAAUT, CHK_DONGLE)) { const TString& numregcg = row.get(PART_NREG); const long numreg = atol(_anal.decode(numregcg)); if (numreg > 0) { TAnal_mov anal_mov(numreg); TRecord_array & rows = anal_mov.body(); const int nrows = rows.rows(); for (int i = 1; i <= nrows; i++) { const TString80 s = anal_mov.row_code(i); if (s.full() && codanal.find(s) < 0) { if (codanal.full()) codanal << '\n'; if (s.full()) codanal << s; } } } } 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); TESSL_row& rec = new_row(row, data_scad, rata.importo(in_valuta), r); if (in_valuta) { TImporto il(rata.importo(false)); il.normalize(sezione); rec.importo_in_euro(il.valore()); } if (data_scad <= form().data_limite_scaduto()) { const real s = calcola_scaduto(rata, in_valuta); rec.scaduto(s); } rec.rata_bloccata(rata.get_bool(SCAD_BLOCCATA)); rec.codici_analitica(codanal); } } else { const TDate data_pag(row.get(PART_DATAPAG)); const TImporto imp(row.importo(in_valuta, 0x1)); // Importo pulito senza nient'altro TESSL_row& riga = new_row(row, data_pag, imp, RIGA_PAGAMENTO); if (in_valuta) { TImporto i(row.importo(false, 0x1)); i.normalize(sezione); riga.importo_in_euro(i.valore()); } riga.codici_analitica(codanal); 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 (esp) { esposto.normalize(sezione); riga.salvo_buon_fine(sbf); // Esposto salvo buon fine riga.esposto(esposto.valore()); } } TImporto ritenute(row.importo(false, 0x8)); if (!ritenute.is_zero()) { TESSL_row& r = new_row(row, data_pag, TImporto('D', ZERO), RIGA_RITENUTE); r.descrizione(form().describe(PEC_RITENUTE)); if (in_valuta) { ritenute.normalize(sezione); r.importo_in_euro(ritenute.valore()); } else r.importo(ritenute); r.codici_analitica(codanal); } const TImporto abbuoni(row.importo(in_valuta, 0x2)); if (!abbuoni.is_zero()) { TESSL_row& r = new_row(row, data_pag, abbuoni, RIGA_ABBUONI); r.descrizione(form().describe(PEC_ABBUONI)); if (in_valuta) { TImporto il(row.importo(false, 0x2)); il.normalize(sezione == 'D' ? 'A' : 'D'); r.importo_in_euro(il.valore()); } r.codici_analitica(codanal); } TImporto diffcam(row.importo(false, 0x4)); if (!diffcam.is_zero() && !in_valuta) { TESSL_row& r = new_row(row, data_pag, TImporto('D', ZERO), RIGA_DIFFCAMBI); r.descrizione(form().describe(PEC_DIFFCAM)); r.importo(diffcam); r.codici_analitica(codanal); } } } } void TESSL_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' ? 'D' : 'A'; totpag.normalize(sezione); int r; for (r = items() - 1; r >= 0; r--) { TESSL_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++) { TESSL_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); } } } } TESSL_array::TESSL_array(const TPartita& game, const TESSL_form* f) :_form(f), _anal(LF_MOVANA, MOVANA_NUMREG, 3) { int r; for (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() == RIGA_PAGAMENTO) { TImporto* imp = importo_riga_scaduto_ptr(s.riga()); if (imp != nullptr) { imp->normalize(sezione); s.scaduto(imp->valore()); } } } if (items() > 0) { sort(); arrange_scaduto(game); } } /////////////////////////////////////////////////////////// // TESSL_form: form speciale per estratti conto e solleciti /////////////////////////////////////////////////////////// TESSL_form * TESSL_form::_form = nullptr; void TESSL_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; for (word j = 0; j <= r; 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 h1->key().compare(h2->key(), -1, true); // was stricmp } word TESSL_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 != nullptr; obj = arr.get_hashobj()) tot[num_rip++] = obj; qsort(tot, num_rip, sizeof(THash_object*), tot_compare); return num_rip; } void TESSL_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. } TESSL_row rip(desc, t.importo().normalize(), val); rip.scaduto(t.scaduto()); rip.esposto(t.esposto()); rip.importo_in_euro(t.importo_euro()); rip.print_on(body); pr.setfooterline(j + 1, body.row(0)); } } int TESSL_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.smid(p1, 2); while (isalnum(s[p1])) p1++; while (p1 < end && !isalnum(s[p1])) p1++; if (p1 < end) magic2 = s.smid(p1, 2); else magic2.cut(0); } else end = s.len() - 1; const TString right(s.smid(end + 1)); s.cut(pos); s << right; } return pos; } void TESSL_form::change_magic_body(const TESSL_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 TESSL_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 TESSL_form::print_total(int riga, const THash_object& o) { const short MAXID = 5; const short f_id[MAXID] = { PEC_TSALDO, PEC_TSCADUTO, PEC_TESPOSTO, PEC_TIMPEURO, PEC_TUNASSIGNED }; 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); int i; for (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(); const TImporto& imp = t.importo(); 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 rippristinare 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); char sez = imp.sezione(); real num = imp.valore(); if (sez == 'D' && num < 0) { num = abs(num); sez = 'A'; } if (sez == 'A' && num < 0) { num = abs(num); sez = 'D'; } if (sez == 'D') { dare.set(num.string()); avere.set(""); } else { dare.set(""); avere.set(num.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_IMPEURO); if (implire.x() <= 0) { TForm_item& bimplire = body.find_field(PEC_IMPEURO); implire.set_x(bimplire.x()); implire.width() = bimplire.width(); if (bimplire.shown()) implire.show(); else implire.hide(); } //modify_picture(implire,old_pictures,false); implire.set(t.importo_euro().string()); TForm_item& unreferenced = foot.find_field(PEC_UNASSIGNED); if (unreferenced.x() <= 0) { TForm_item& uns = body.find_field(PEC_AVERE); unreferenced.set_x(uns.x()); unreferenced.width() = avere.width(); } //modify_picture(unreferenced,old_pictures,in_valuta); unreferenced.set(t.unassigned().valore().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); } } for (word r = 0; r < _total_rows; r++) printer().setfooterline(riga + r, foot.row(r)); } void TESSL_form::stampa_pedata(TPrinter& pr) { THash_object* tot[MAXTOT]; word num_rip = ordina_totali_per_valuta(tot); // La prima riga del footer deve essere lasciata libera per la fincatura // Ogni sottosezione di totale occupa _total_rows righe: per cui devo calcolare // quanti totali ci stanno nelle righe riservate al footer // const word maxtot = (section('F').height()-1) / _total_rows; if (num_rip > _maxtot) num_rip = _maxtot; for (word j = 0; j < num_rip; j++) print_total(j*_total_rows + 1, *tot[j]); } void TESSL_form::ultima_pagina() { set_last_page(true); } void TESSL_form::header_handler(TPrinter& pr) { pr.resetheader(); _form->stampa_testata(pr); } void TESSL_form::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 TESSL_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 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, impeuro; // Stampa le righe di partita int ultima_riga = 0; int ultima_rata = 0; int r; for (r = 0; r < righe.items(); r++) { TESSL_row& riga = righe.row(r); if (pr.rows_left() <= (body.height() + 1)) { 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; real resp = riga.esposto(); if (resp < ZERO) { resp = -resp; riga.esposto(resp); } riga.print_on(body); pr.print(body.row(0)); totali().add(riga.importo(), riga.scaduto(), riga.esposto(), riga.importo_in_euro(), riga.valuta().codice()); saldo += riga.importo(); scaduto += riga.scaduto(); esposto += riga.esposto(); impeuro += riga.importo_in_euro(); ok = true; } if (ok) { if (_stampa_saldo) { saldo.normalize(); TString desc; desc = describe(PEC_SALDO); const TValuta& val = righe.row(r - 1).valuta(); if (val.in_valuta()) desc << ' ' << val.codice(); TESSL_row sld(desc, saldo, val); sld.scaduto(scaduto); sld.esposto(esposto); sld.importo_in_euro(impeuro); 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, pagetype pt) const { const TForm_item& fi = find_field(sez, pt, id); return fi.prompt(); } void TESSL_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()) { TString key; key.format("%s|%s|H0|%d", (const char *)name(), (const char *)code(), PEC_MEMO); const TRectype & rform = cache().get(LF_RFORM, key); if (!rform.empty()) fi.set(rform.get("TESTO")); } } TESSL_form::TESSL_form(const TSelection_mask & m, bool gesval, short id_datalim, short id_datascad, short id_giorni_rischio) : TForm(BASE_EC_PROFILE, m.get_prof_name()), _in_valuta(false), _num_rip(0), _total_rows(0), _causali(LF_CAUSALI, CAU_DESCR), _movimenti(LF_MOV, MOV_DESCR), _valute("%VAL"), _giorni_rischio(0), _maxtot(1), _stampa_saldo(true) { _form = this; _lingua = m.get_prof_lang(); _who = m.who(); _stampa_esp = stampa_esposto(); TCursor_sheet& cs = m.cur_sheet(); _cursore = cs.cursor(); _dlo = id_datalim > 0 ? m.get_date(id_datalim) : eotime; if (!_dlo.ok()) _dlo = eotime; _dls = id_datascad > 0 ? m.get_date(id_datascad) : eotime; if (!_dls.ok()) _dls = eotime; 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); TPrint_section& head = section('H'); pr.headerlen(head.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); TForm_item& esp = section('B').find_field(PEC_ESPOSTO); if (esp.shown()) esp.show(_stampa_esp); //setta la colonna esposto solo se abilitata genera_intestazioni(odd_page, head.height() - 1); init_header(m); // Set fixed text pr.setfooterhandler(footer_handler); const TPrint_section& foot = section('F'); pr.footerlen(foot.height()); _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); if (_maxtot <= 0 || _maxtot > ((int)foot.height() - 2) / _total_rows) _maxtot = (foot.height() - 2) / _total_rows; int rows[] = { (int)head.height(), (int)(pr.formlen() - foot.height() + 1), 0 }; TPrint_section& fink = section('G'); if (_fincatura) { set_fink_mode(_fincatura == 1 ? false : true); genera_fincatura(odd_page, rows[0] - 2, rows[1] + (_maxtot * _total_rows) + 2, rows); } if (fink.fields() > 0) fink.update(); // Setta il backgroud di stampa } TESSL_form::~TESSL_form() { TPrinter& pr = printer(); pr.setheaderhandler(nullptr); pr.setfooterhandler(nullptr); _form = nullptr; } TSelection_mask::TSelection_mask(const char* name) : TAutomask(name), _who("C"), _key(1), _clifo_rel(nullptr), _pdc_rel(nullptr), _cli_cur_k1(nullptr), _cli_cur_k2(nullptr), _for_cur_k1(nullptr), _for_cur_k2(nullptr), _pdc_cur_k1(nullptr), _pdc_cur_k2(nullptr), _cli_sh_k1(nullptr), _cli_sh_k2(nullptr), _for_sh_k1(nullptr), _for_sh_k2(nullptr), _pdc_sh_k1(nullptr), _pdc_sh_k2(nullptr) { // crea relazioni, cursori e cursor_sheets _clifo_rel = new TRelation(LF_CLIFO); _clifo_rel->add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF"); TString rf = get_user_read_filter(); TRectype filter(LF_CLIFO); filter.put(CLI_TIPOCF, "C"); _cli_cur_k1 = new TCursor(_clifo_rel, rf, 1, &filter, &filter); _cli_cur_k2 = new TCursor(_clifo_rel, rf, 2, &filter, &filter); _cli_sh_k1 = new TCursor_sheet(_cli_cur_k1, " |CODCF|RAGSOC|PAIV", TR("Selezione cliente per codice"), "@1|Codice|Ragione Sociale@50", 0, 1); _cli_sh_k2 = new TCursor_sheet(_cli_cur_k2, " |RAGSOC|CODCF", "Selezione cliente per ragione sociale", "@1|Ragione Sociale@50|Codice", 0, 1); _cli_sh_k2->add_checkbutton(SC_CLIFO + 500, 0, "", 68, 0, 2, 1, "", 10112, 10113).set_handler(sc_filter_handler); if (id2pos(SC_CLIFO) >= 0) { filter.put(CLI_TIPOCF, "F"); _for_cur_k1 = new TCursor(_clifo_rel, rf, 1, &filter, &filter); _for_cur_k2 = new TCursor(_clifo_rel, rf, 2, &filter, &filter); _for_sh_k1 = new TCursor_sheet(_for_cur_k1, " |CODCF|RAGSOC|PAIV", TR("Selezione fornitore per codice"), HR("@1|Codice|Ragione Sociale@50|Partita IVA"),0,1); _for_sh_k2 = new TCursor_sheet(_for_cur_k2, " |RAGSOC|CODCF|PAIV", TR("Selezione fornitore per ragione sociale"), "@1|Ragione Sociale@50|Codice|Partita IVA",0,1); _for_sh_k2->add_string(SC_CLIFO, 0, PR("Ragione sociale "), 1, 0, 50, "").set_handler(sc_ragsoc_handler); _for_sh_k2->add_checkbutton(SC_CLIFO+500, 0, "", 68, 0, 2, 1, "", 10112, 10113).set_handler(sc_filter_handler); } if (id2pos(SC_CLIFO) >= 0 && TToken_string(lfield(SC_CLIFO).get_codes()).items() > 2) { _pdc_rel = new TRelation(LF_PCON); TRectype& filter = _pdc_rel->curr(); _pdc_cur_k1 = new TCursor(_pdc_rel, rf, 1, &filter, &filter); _pdc_cur_k2 = new TCursor(_pdc_rel, rf, 2, &filter, &filter); _pdc_sh_k1 = new TCursor_sheet(_pdc_cur_k1, " |GRUPPO|CONTO|SOTTOCONTO|DESCR", "Selezione conti per codice", "@1|Gruppo|Conto|Sottoconto|Descrizione@50",0,1); _pdc_sh_k2 = new TCursor_sheet(_pdc_cur_k2, " |DESCR|GRUPPO|CONTO|SOTTOCONTO", "Selezione conti per descrizione", "@1|Descrizione@50|Gruppo|Conto|Sottoconto",0,1); _pdc_sh_k2->add_string(SC_CLIFO, 0, PR("Descrizione "), 1, 0, 50, "").set_handler(sc_ragsoc_handler); _pdc_sh_k2->add_checkbutton(SC_CLIFO+500, 0, "", 68, 0, 2, 1, "", 10112, 10113).set_handler(sc_filter_handler); } } TSelection_mask::~TSelection_mask() { safe_delete(_pdc_sh_k2); safe_delete(_pdc_sh_k1); safe_delete(_pdc_cur_k2); safe_delete(_pdc_cur_k1); safe_delete(_pdc_rel); safe_delete(_for_sh_k2); safe_delete(_for_sh_k1); safe_delete(_for_cur_k2); safe_delete(_cli_sh_k2); safe_delete(_cli_sh_k1); safe_delete(_cli_cur_k2); safe_delete(_cli_cur_k1); safe_delete(_clifo_rel); } bool TSelection_mask::stampa_saldo() const { return get_bool(F_STAMPSALDO); } const TString& TSelection_mask::get_prof_lang() const { return get(F_LINPROF); } const TString & TSelection_mask::get_prof_base() const { return get_tmp_string() = BASE_EC_PROFILE; } const TString& TSelection_mask::get_prof_code() const { return get(F_CODPROF); } const TString & TSelection_mask::get_prof_name() const { TString& tmp = get_tmp_string(); tmp = get_prof_code(); tmp << get_prof_lang(); return tmp; } TCursor_sheet& TSelection_mask::cur_sheet() const { TCursor_sheet* cs = nullptr; switch (who()[0]) { case 'C': cs = key() == 1 ? _cli_sh_k1 : _cli_sh_k2; break; case 'F': cs = key() == 1 ? _for_sh_k1 : _for_sh_k2; break; default : cs = key() == 1 ? _pdc_sh_k1 : _pdc_sh_k2; break; } CHECK(cs, "Can't use a NULL TCursor_sheet"); return *cs; } void TSelection_mask::reset_sheets() { _cli_sh_k1->uncheck(-1); _cli_sh_k2->uncheck(-1); if (_for_sh_k1) { _for_sh_k1->uncheck(-1); _for_sh_k2->uncheck(-1); } if (_pdc_sh_k1) { _pdc_sh_k1->uncheck(-1); _pdc_sh_k2->uncheck(-1); } reset(SC_CFCODFR); reset(SC_CFCODTO); reset(SC_CFDESFR); reset(SC_CFDESTO); reset(SC_NSEL); } bool TMail_mask::on_key(KEY k) { if (k == K_SHIFT + K_F12) show(F_TESTEMAIL); return TAutomask::on_key(k); } int sort(TSheet_field & s, int r1, int r2) { int key = s.mask().get_int(F_SORT); int res = 0; if (key == 1) { int cod1 = s.get_long_row_cell(r1, S_CODCF); int cod2 = s.get_long_row_cell(r2, S_CODCF); res = cod1 - cod2; } else { const TString & rag1 = s.get_str_row_cell(r1, S_RAGSOC); const TString & rag2 = s.get_str_row_cell(r2, S_RAGSOC); res = _stricmp(rag1, rag2); } return res; } bool TMail_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_SORT: if (e == fe_modify) { TSheet_field & sh = sfield(F_SHEET); sh.sort(sort); sh.force_update(); } break; case F_SHEET: if (e == se_leave) { TSheet_field & sh = (TSheet_field &) o; const int row = jolly; TString email = sh.get_str_row_cell(row, S_EMAIL); const bool on = email.full(); sh.enable_cell(row, S_SELECTED, on); sh.set_row_cell(S_SELECTED, on, row); sh.force_update(row); } break; default: break; } return true; } // Seleziona tutti i clienti con codice compreso tra due estremi void TSelection_mask::select_clifo_range(long from, long to) { TWait_cursor hourglass; TCursor_sheet& c = cur_sheet(); const long items = c.items(); const int k = key(); TCursor* crs = c.cursor(); if (to == 0 && items) to = c.row(items-1).get_long(k); if (from > to) // Controlla limiti { long tmp = to; to = from; from = tmp; } long last = 0; long firs = 0; TRectype& rec = crs->file().curr(); rec.zero(); rec.put(CLI_TIPOCF,who()); rec.put(CLI_CODCF,from); const TRecnotype start = crs->read(_isgteq); firs = rec.get_long(CLI_CODCF); rec.zero(); rec.put(CLI_TIPOCF,who()); rec.put(CLI_CODCF,to); TRectype recx(rec); TRecnotype end = crs->read(_isgteq); if (rec > recx) { end--; (*crs)-=1; } last = rec.get_long(CLI_CODCF); c.uncheck(-1); for (long i = start; i <= end; i++) c.check(i); if (get(SC_CFCODFR).not_empty()) set(SC_CFCODFR, firs); if (get(SC_CFCODTO).not_empty()) set(SC_CFCODTO, last); set(SC_NSEL, c.checked()); } void TSelection_mask::select_des_clifo_range(const TString& from, const TString & to) { TWait_cursor hourglass; TCursor_sheet& c = cur_sheet(); const long items = c.items(); const int k = key(); CHECK(k == 2, "La chiave deve essere la 2"); TString s_from(from), s_to(to); if (s_to.empty() && items) s_to = c.row(items-1).get(1); s_from.upper(); s_to.upper(); if (s_from > s_to) // Controlla limiti { s_to = from; s_from = to;// ripristina i valori originali (!upper) set(SC_CFDESFR, to); set(SC_CFDESTO, from); } else { if (to.not_empty()) s_to = to; s_from = from; // ripristina i valori originali (!upper) } TString last; TString firs; TCursor* crs = c.cursor(); TRectype& rec = crs->file().curr(); rec.zero(); if (who() >= "C") { rec.put(CLI_TIPOCF, who()); rec.put(CLI_RAGSOC, s_from); } else rec.put(PCN_DESCR, s_from); const TRecnotype start = crs->read(_isgteq); firs = rec.get(who() >= "C" ? CLI_RAGSOC : PCN_DESCR); rec.zero(); rec.put(CLI_TIPOCF, who()); rec.put(CLI_RAGSOC,s_to); if (who() >= "C") { rec.put(CLI_TIPOCF, who()); rec.put(CLI_RAGSOC, s_to); } else rec.put(PCN_DESCR, s_to); TRectype recx(rec); TRecnotype end = crs->read(_isgteq); if (rec > recx) { end--; (*crs)-=1; } last = rec.get(who() >= "C" ? CLI_RAGSOC : PCN_DESCR); c.uncheck(-1); for (long i = start; i <= end; i++) c.check(i); if (get(SC_CFDESFR).not_empty()) set(SC_CFDESFR, firs); if (get(SC_CFDESTO).not_empty()) set(SC_CFDESTO, last); set(SC_NSEL, c.checked()); } // Cerca il primo e l'ultimo cliente selezionati void TSelection_mask::set_clifo_limits() { TWait_cursor hourglass; long from = 0, to = 0; TCursor_sheet& c = cur_sheet(); const long items = c.items(); long first = -1, last = -1; for (long i = 0; i < items; i++) if (c.checked(i)) { if (first == -1) first = i; } if (first != -1) //Optimization... If nothing was found previously skip this test. for (long j = (items-1); j >= 0 ; j--) if (c.checked(j)) if (last == -1) { last = j; break; } if (first!= -1 && last != -1) // Something selected? { TToken_string fitem(c.row(first)); TToken_string litem(c.row(last)); from = fitem.get_long(key()); to = litem.get_long(key()); if (from > to) { long t = to; to=from; from=t; } } set(SC_CFCODFR, from); set(SC_CFCODTO, to); set(SC_NSEL, c.checked()); } void TSelection_mask::set_des_clifo_limits() { TWait_cursor hourglass; long first=-1, last=-1; TString from,to; TCursor_sheet& c = cur_sheet(); const long items = c.items(); CHECK(key() == 2, "La chiave deve essere la 2"); for (long i = 0; i < items; i++) if (c.checked(i)) { if (first == -1) first = i; } if (first != -1) for (long j = (items-1); j >= 0 ; j--) if (c.checked(j)) if (last == -1) { last = j; break; } if (first!= -1 && last != -1) { TToken_string fitem(c.row(first)); TToken_string litem(c.row(last)); from = fitem.get(1); to = litem.get(1); if (from>to) { TString temp(to); to=from; from=temp; } } set(SC_CFDESFR, from); set(SC_CFDESTO, to); set(SC_NSEL, c.checked()); } bool TSelection_mask::get_cc_address(const char * tipo, const long cod, TToken_string& cc) const { TString8 clifo; clifo.format("%s%06ld", (const char *) tipo, cod); TISAM_recordset contacts("USE MULTIREL\nFROM COD=BACON FIRST=#CLIFO\nTO COD=BACON FIRST=#CLIFO"); TToken_string data; contacts.set_var("#CLIFO", clifo); for (bool ok = contacts.move_first(); ok; ok = contacts.move_next()) { data = contacts.get("DATA").as_string(); FOR_EACH_TOKEN(data, tok) { const TFixed_string doc(tok); if (doc.starts_with("sc2400", true) || doc.starts_with("sollec", true)) { const TRectype& rub = cache().get(LF_CONTACT, contacts.get("SECOND").as_int()); TString80 mail = rub.get("MAIL"); if (mail.blank()) mail = rub.get("MAIL2"); if (mail.full() && cc.find(mail) < 0) { cc.add(mail); break; } } } } return cc.full(); } int TSelection_mask::send_doc(long codice, const TString & ragsoc, const TToken_string& email, TToken_string & cc, TToken_string & ccn, bool rcpt, const TString & test_email, const TString & subj, const TString & msg, TLog_report & log) { const bool test = test_email.full(); TFilename pdf; TPrinter & pr = printer(); TToken_string to(email, ';'), attachment("", ';'); TString esito("Invio a "); TString subject(subj); TString message; TString stat("Invio a "); stat << ' ' << ragsoc; xvtil_statbar_set(stat); TDate data; bool sollecito = find_by_id(F_DATALIMSOL) != nullptr; if (sollecito) data = get_date(F_DATALIMSOL); if (!data.ok()) data = get_date(F_DATASEND); if (!data.ok()) data = today; if (subject.blank()) subject << (sollecito ? TR("Sollecito da ") : TR("Estratto conto da ")); subject << ' ' << prefix().firm().ragione_sociale(); TToken_string key; key.add(who()); key.add(codice); const TString & tipo = cache().get(LF_CLIFO, key, CLI_TIPOPERS); if (tipo == "G") message << "Spett. "; else message << "Gent.mo/a "; message << ragsoc << '\n'; if (msg.full()) message << msg << '\n'; else { if (sollecito) message << TR("Si invia in allegato l’estratto conto delle partite aperte al ") << data << TR(" con preghiera di provvedere al saldo quanto prima.") << '\n'; else message << TR("Invio estratto conto al ") << data << TR(" nel file allegato ") << '\n'; } message << TR("Cordiali saluti\nAmministrazione ") << prefix().firm().ragione_sociale(); pdf.temp("cu", "pdf"); attachment.add(pdf); pr.set_export_file(pdf, true); pr.open(); int ret = print_one(who(), codice); if (ret > 0) { pr.close(); esito << email; if (!send_mail(to, cc, ccn, subject, message, attachment, false, rcpt)) { ret = 0; esito << " non "; } esito << " riuscito"; log.log(0, esito); } xvtil_statbar_set(nullptr); return ret; } bool TSelection_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case SC_CLIFO : if (e == fe_modify) { set_who(o.get()); reset_sheets(); } break; case SC_SORTCF : if (e == fe_modify) { set_key(o.get_int()); reset_sheets(); } break; case SC_SELECT : if (e == fe_button) { TCursor_sheet& c = cur_sheet(); c.enable_check(); c.run(); if (key() == 2) set_des_clifo_limits(); else set_clifo_limits(); } break; case SC_RESET : if (e == fe_button) reset_sheets(); break; case SC_CFCODFR : if (e == fe_modify) { const long cod1 = o.get_long(); const long cod2 = get_long(SC_CFCODTO); select_clifo_range(cod1, cod2); } else if (e == fe_button) { TCursor_sheet& c = cur_sheet(); c.cursor()->curr().put(CLI_CODCF, o.get()); c.cursor()->read(); c.disable_check(); c.disable(DLG_USER); if (c.run() == K_ENTER) { TToken_string& t = c.row(c.selected()); const long cod1 = t.get_long(key()); const long cod2 = get_long(SC_CFCODTO); set(SC_CFCODFR, cod1); select_clifo_range(cod1, cod2); } c.enable(DLG_USER); c.enable_check(); } break; case SC_CFCODTO : if (e == fe_modify) { const long cod1 = get_long(SC_CFCODFR); const long cod2 = o.get_long(); select_clifo_range(cod1, cod2); } else if (e == fe_button) { TCursor_sheet& c = cur_sheet(); c.cursor()->curr().put(CLI_CODCF, o.get()); c.cursor()->read(); c.disable_check(); c.disable(DLG_USER); if (c.run() == K_ENTER) { TToken_string& t = c.row(c.selected()); const long cod2 = t.get_long(key()); const long cod1 = get_long(SC_CFCODFR); set(SC_CFCODTO, cod2); select_clifo_range(cod1, cod2); } c.enable(DLG_USER); c.enable_check(); } break; case SC_CFDESFR : if (e == fe_modify) { const TString des1(o.get()); const TString des2(get(SC_CFDESTO)); select_des_clifo_range(des1, des2); } else if (e == fe_button) { TCursor_sheet& c = cur_sheet(); const char* fld = who() >= "C" ? CLI_RAGSOC : PCN_DESCR; const TString& value = o.get(); c.cursor()->curr().put(fld, value); c.cursor()->read(); if (c.find_by_id(SC_CLIFO) != nullptr) c.set(SC_CLIFO, value, 0x3); c.disable_check(); c.disable(DLG_USER); if (c.run() == K_ENTER) { TToken_string& t = c.row(c.selected()); const TString des1(t.get(1)); const TString des2 = get(SC_CFDESTO); set(SC_CFDESFR, des1); select_des_clifo_range(des1, des2); } c.enable(DLG_USER); c.enable_check(); } break; case SC_CFDESTO : if (e == fe_modify) { const TString des2(o.get()); const TString des1(get(SC_CFDESFR)); select_des_clifo_range(des1, des2); } else if (e == fe_button) { TCursor_sheet& c = cur_sheet(); const char* fld = who() >= "C" ? CLI_RAGSOC : PCN_DESCR; const TString& value = o.get(); c.cursor()->curr().put(fld, value); c.cursor()->read(); if (c.find_by_id(SC_CLIFO) != nullptr) c.set(SC_CLIFO, value, 0x3); c.disable_check(); c.disable(DLG_USER); if (c.run() == K_ENTER) { TToken_string& t = c.row(c.selected()); const TString des1(get(SC_CFDESFR)); const TString des2(t.get(1)); set(SC_CFDESTO, des2); select_des_clifo_range(des1, des2); } c.enable(DLG_USER); c.enable_check(); } break; case DLG_EMAIL: if (e == fe_button) { TLog_report log("Invio solleciti"); TMail_mask & mail = mail_mask(); TSheet_field & sh = mail.sfield(F_SHEET); if (who() >= "C") { TCursor & fc = *form().cursor(); TCursor_sheet &s = cur_sheet(); fc.setkey(key()); TRectype filter(LF_CLIFO); filter.put(CLI_TIPOCF, who()); fc.setregion(filter, filter); long failed = 0; // solleciti non stampati mail.load(); sh.reset(); update_checked(); const int last = s.last_one(); { TProgind p(s.items(), "Selezione"); for (long pos = s.first_one(); p.addstatus() && pos <= last; pos++) { fc = pos; const TRectype & cli = fc.curr(); const TString & tipo = cli.get(CLI_TIPOCF); const long codice = cli.get_long(CLI_CODCF); if (s.checked(pos) && some_to_print(tipo, codice)) { TString ragsoc = cli.get(CLI_RAGSOC); TToken_string email; for (int i = 1; email.blank() && i <= 3; i++) { const char order = ini_get_string(CONFIG_USER, "Mail", "Email", "", i)[0]; switch (order) { case 'P': email = cli.get(CLI_PEC); break; case 'N': email = cli.get(CLI_MAIL); break; case 'D': email = cli.get(CLI_DOCMAIL); break; default: break; } } const int nrow = sh.set_row_cell(S_SELECTED, email.full()); sh.enable_cell(nrow, S_SELECTED, email.full()); sh.set_row_cell(S_CODCF, cli.get_long(CLI_CODCF), nrow); sh.set_row_cell(S_EMAIL, email, nrow); ragsoc.strip_double_spaces(); sh.set_row_cell(S_RAGSOC, ragsoc, nrow); } } } sh.sort(sort); if (mail.run() == K_ENTER) { TToken_string cc(mail.get(F_CCEMAIL), ';'); TToken_string ccn(mail.get(F_CCNEMAIL), ';'); const TString test_mail = mail.get(F_TESTEMAIL); const TString from = mail.get(F_FROMEMAIL); const TString pwd = mail.get(F_PASSWORD); const bool rcpt = mail.get_bool(F_RECEIPT); const TString subj = mail.get(F_SUBJ); const TString msg = mail.get(F_MESSAGE); set_test_mail(test_mail); if (from.full()) xvt_set_mail_params(nullptr, nullptr, from, pwd, nullptr); FOR_EACH_SHEET_ITEM(sh, r) { if (sh.get_bool_row_cell(r, S_SELECTED)) { const TToken_string & email = sh.get_str_row_cell(r, S_EMAIL); const long codice = sh.get_long_row_cell(r, S_CODCF); TString ragsoc = sh.get_str_row_cell(r, S_RAGSOC); ragsoc.strip_double_spaces(); get_cc_address(who(), codice, ccn); int ret = send_doc(codice, ragsoc, email, cc, ccn, rcpt, test_mail, subj, msg, log); if (ret < 0) failed++; } } if (failed > 0) warning_box(FR("%ld clienti non sono stati stampati in quanto " "il codice lingua non corrispondeva al profilo di stampa"), failed); } mail.save(EMPTY_STRING, false, false); if (log.rows() > 0) log.preview(); } } break; default: break; } return true; } void TSelection_mask::update_checked() { TCursor_sheet& cs = cur_sheet(); // Sheet di selezione (CLI/FO/PCON) const long checked = cs.checked(); if (checked == 0L) cs.check_all(); } TRecnotype TSelection_mask::get_clifo_range(long& first, long& last) { first = last = 0L; TRecnotype items = 0; if (who() >= "C") { TCursor_sheet & s = cur_sheet(); // Sheet di selezione (CLI/FO/PCON) update_checked(); first = s.last_one(); last = s.last_one(); if (s.checked() == s.items()) items = s.items(); else for (long i = first; i <= last; i++) if (s.checked(i)) items++; } return items; }