#include #include #include #include #include #include #include #include #include #include "..\cg\cgsaldac.h" #include "..\cg\cg2103.h" #include "..\ve\velib.h" #include "panapdc.h" #include "pconana.h" #include "movana.h" #include "rmovana.h" #include "ca3.h" #include "ca3600.h" #include "calib01.h" #include "calib02.h" #include "camask.h" //=============================================================================================== //////////////////////////////////////////////////////// // MASCHERA //////////////////////////////////////////////////////// class TPag_per_cms_mask: public TAnal_report_mask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); const TString& get_report_class() const; bool test_compatible_report(); //pagina di configurazione void config_loader(TSheet_field& sf, const char* paragrafo); void config_setter(TSheet_field& sf, const char* paragrafo); public: TPag_per_cms_mask(); virtual ~TPag_per_cms_mask() {} }; const TString& TPag_per_cms_mask::get_report_class() const { TString& classe = get_tmp_string(); classe = "ca3600a"; return classe; } bool TPag_per_cms_mask::test_compatible_report() { const TString& cls = get_report_class(); const TString& name = get(F_REPORT); bool ok = name.not_empty(); if (ok) { TReport rep; ok = rep.load(name); if (ok) { const TString& classe = rep.get_class(); ok = classe == cls; } } if (!ok) { set(F_REPORT, cls); TFilename path = cls; path.ext("rep"); ok = path.custom_path(); } return ok; } bool TPag_per_cms_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_REPORT: if (e == fe_button) { const TString8 lib = get_report_class(); TFilename path = o.get(); if (select_custom_file(path, "rep", lib)) { path = path.name(); path.ext(""); o.set(path); } } else if (e == fe_close) { if (!test_compatible_report()) return error_box(TR("Impossibile trovare un report compatibile")); } break; case DLG_SAVEREC: if (e == fe_button) { config_setter(sfield(F_PDCC), "Pdcc"); config_setter(sfield(F_PDCA), "Pdca"); } break; default: break; } return TAnal_report_mask::on_field_event(o, e, jolly); } TPag_per_cms_mask::TPag_per_cms_mask() :TAnal_report_mask("ca3600") { //Prima pagina // creazione dei campi della pagina della maschera con lo sheet di cdc/cms/fasi create_sheet(F_RIGHE); //Seconda pagina (sheets dei conti) //Controllo sul tipo di piano dei conti da utilizzare (Analitico/Contabile) TConfig& cfg = ca_config(); const bool use_pdcc = cfg.get_bool("UsePdcc"); set(F_PIANO, use_pdcc ? "Contabile" : "Analitico"); // creazione dei campi della pagina della maschera con lo sheet dei conti if (use_pdcc) //usa conti contabili { hide(-6); //nasconde i campi analitici e mostra quelli contabili show(-5); config_loader(sfield(F_PDCC), "Pdcc"); } else //usa conti analitici { hide(-5); show(-6); short dlg = S_CDC2 + 100; // id del primo campo da generare (maschera di riga dello sheet) int y = 2; const int nfields = create_sheet_fields(F_PDCA, LF_PCONANA, y, dlg); sfield(F_PDCA).sheet_mask().hide(-1); config_loader(sfield(F_PDCA), "Pdca"); } // setta gli handlers a tutti i campi generati della maschera;senza questa chiamata la on_field_event // non puo' funzionare sui campi generati!!! set_handlers(); } void TPag_per_cms_mask::config_loader(TSheet_field& sf, const char* paragrafo) { TFilename configname = "ca3600.ini"; //carica file configurazione conti configname.custom_path(); TConfig configfile(configname, paragrafo); TString_array conti; int n = configfile.list_variables(conti, false, paragrafo, true); FOR_EACH_ARRAY_ROW(conti, i, row) { sf.row(-1) = configfile.get(*row); //carica la riga del .ini senza il contatore sf.check_row(i); } } void TPag_per_cms_mask::config_setter(TSheet_field& sf, const char* paragrafo) { TFilename configname = "ca3600.ini"; //carica file configurazione conti configname.custom_path(); TConfig configfile(configname, paragrafo); configfile.remove_all(); //svuota il paragrafo sul .ini prima di ricompilarlo (se non si facesse //non si riuscirebbero ad ammazzare le righe sul .ini FOR_EACH_SHEET_ROW (sf, i, row) { TToken_string conto(""); conto.add(row->get(0)); conto.add(row->get(1)); conto.add(row->get(2)); conto.add(row->get(3)); //*****nel caso di pdca deve tener conto dei livelli variabili configfile.set("conto", conto, NULL, true, i); } } /////////////////////////////////////////////////////////////// // RECORDSET /////////////////////////////////////////////////////////////// class TPag_per_cms_recordset : public TISAM_recordset { TExternisamfile* _tmp; protected: TDate _dadata, _adata; long _codfor; TString8 _campodata; TString _codcosto, _codcms, _codfas; protected: //da libreria // virtual const TVariant& get(const char* column_name) const; protected: void crea_trr(const TFilename& trr) const; static bool part_callback(const TRelation& rel, void* pJolly); static bool mov_callback(const TRelation& rel, void* pJolly); long find_movimento(const TRectype& riga_pag) const; void find_commesse(const long nreg, const TRectype& riga_pag); public: virtual void set_filter(const TPag_per_cms_mask& msk, const int cms_row, const long codfor); virtual void set_custom_filter(TCursor& cur) const; void scan_pags(const TPag_per_cms_mask& msk); void scan_movs(const TPag_per_cms_mask& msk); TPag_per_cms_recordset(const TString& sql) : TISAM_recordset(sql) { _tmp = NULL;} ~TPag_per_cms_recordset(); }; static TPag_per_cms_recordset* myself = NULL; TPag_per_cms_recordset::~TPag_per_cms_recordset() { } void TPag_per_cms_recordset::set_custom_filter(TCursor& cur) const { relation()->replace(_tmp); //sostituisce il vero file rmovana con quello temporaneo //filtro sul file esterno (_tmp, cioè 1000) sui conti selezionati sulla maschera TRectype darec(cur.curr()), arec(cur.curr()); //curr perchè è il file externisamfile darec.zero(); arec.zero(); //filtro sulla data(non avendo anche codnum non ho la chiave completa per mettere la data nella setregion) TString filtro; if (_dadata.ok()) filtro << "(ANSI(DATA)>=" << _dadata << ")"; if (_adata.ok()) { if (filtro.not_empty()) filtro << "&&"; filtro << "(ANSI(DATA)<=" << _adata << ")"; } cur.setregion(darec, arec); cur.setfilter(filtro); myself = (TPag_per_cms_recordset*)this; } void TPag_per_cms_recordset::crea_trr(const TFilename& trr) const { ofstream of(trr); of << 1000 << endl; of << 14 << endl; of << "CONTO|1|20|0|Conto analitico/contabile" << endl; of << "DESCONTO|1|50|0|Descrizione conto" << endl; of << "NREG|3|7|0|Numero registrazione" << endl; of << "DATAPAG|5|8|0|Data pagamento" << endl; of << "DESCRPAG|1|50|0|Descrizione pagamento" << endl; of << "NDOC|1|6|0|Numero documento" << endl; of << "DATADOC|5|8|0|Data documento" << endl; of << "PROT|2|5|0|Protocollo iva" << endl; of << "TOTDOC|4|18|5|Totale documento" << endl; of << "TOTPAG|4|18|5|Totale pagamento" << endl; of << "TOTRES|4|18|5|Totale residuo" << endl; of << "CODFORN|3|7|0|Codice fornitore" << endl; of << "DESFORN|1|50|0|Descrizione fornitore" << endl; of << "HIDDEN|8|1|0|Record nascosto" << endl; of << 1 << endl; of << "CONTO+NREG+DATAPAG" << endl; } long TPag_per_cms_recordset::find_movimento(const TRectype& riga_pag) const { int n_fatture = 0; //numero di fatture trovate int first_fatt = 0; //numero riga della prima fattura //scan della partita dall'ultima alla prima riga const TPartita partita(riga_pag); for (int p = partita.last(); p > 0; p = partita.pred(p)) { const TRiga_partite& fatt = partita.riga(p); if (fatt.is_fattura()) { n_fatture++; first_fatt = p; } } if (n_fatture > 1) { const int linea_pag = riga_pag.get_int(PART_NRIGA); int linea_fattura = 0; for (int f = first_fatt; (f > 0) && (f <= partita.last()) && (linea_fattura == 0); f = partita.succ(f)) { const TRiga_partite& fatt = partita.riga(f); if (fatt.is_fattura()) { for (int r = 1; r <= fatt.rate(); r++) { const TRiga_scadenze& rata = fatt.rata(r); if (rata.exist(linea_pag)) { linea_fattura = f; break; } } } } if (linea_fattura > 0) // oppure anche (linea_fattura > first_fatt) first_fatt = linea_fattura; } long nreg = 0; if (first_fatt > 0) { const TRiga_partite& fatt = partita.riga(first_fatt); nreg = fatt.get_long(PART_NREG); } return nreg; } bool TPag_per_cms_recordset::mov_callback(const TRelation& rel, void* pJolly) { TPag_per_cms_recordset* recordset = (TPag_per_cms_recordset*)pJolly; const long nreg = rel.curr().get_long(MOV_NUMREG); // recordset->find_commesse_cg(nreg); return true; } void TPag_per_cms_recordset::scan_movs(const TPag_per_cms_mask& msk) { if (_campodata == PART_DATAPAG) // I movimenti non hanno DATAPAG _campodata = PART_DATAREG; TString filtro = "(REG==\"\")&&(TIPOMOV==\"\")"; TRectype darec(LF_MOV), arec(LF_MOV); if (_campodata == MOV_DATAREG) { if (_dadata.ok()) darec.put(MOV_DATAREG, _dadata); if (_adata.ok()) arec.put(MOV_DATAREG, _adata); } else { TString80 f; if (_dadata.ok()) { f.format("&&(ANSI(%s)>=\"%s\")", (const char*)_campodata, _dadata.string(ANSI)); filtro << f; } if (_adata.ok()) { f.format("&&(ANSI(%s)<=\"%s\")", (const char*)_campodata, _adata.string(ANSI)); filtro << f; } } TRelation rel(LF_MOV); TCursor cur(&rel, filtro, 2, &darec, &arec); cur.scan(mov_callback, this, "Movimenti senza saldaconto..."); /* crea_righe_stampa(_righecosti, 1); crea_righe_stampa(_righepagamenti, 2); crea_righe_stampa(_righefiscali, 3); crea_righe_stampa(_righesociali, 4);*/ } //prepara l'assoc con tutte le righe da mandare in stampa per quanto riguarda i movimenti con //saldaconto (siano essi con o senza iva) void TPag_per_cms_recordset::find_commesse(const long nreg, const TRectype& riga_pag) { /* TMovimentoPN pn; pn.curr().put(MOV_NUMREG, nreg); if (pn.read() == NOERR) { const TRectype& movfat = pn.curr(); real totdoc_cms; real totdoc, totdoc_netto; TAssoc_array commesse; //Movimenti CON SALDACONTO //se movimento IVA.. if (pn.iva_items() > 0) { for (int i = 0; i < pn.iva_items(); i++) { const TRectype& rmoviva = pn.iva(i); const TString& codcms = rmoviva.get(RMI_CODCMS); const TString& codfase = rmoviva.get(RMI_FASCMS); const TBill conto(rmoviva); if (cms_in_range(codcms, codfase) && conto.indicatore_bilancio() != 5) { TToken_string cms_fsc = codcms; if (codfase.not_empty()) cms_fsc.add(codfase); const real importo = rmoviva.get_real(RMI_IMPONIBILE); real imposta = rmoviva.get_real(RMI_IMPOSTA); real* imp = (real*)commesse.objptr(cms_fsc); if (imp == NULL) { imp = new real; commesse.add(cms_fsc, imp); } *imp += importo; totdoc_cms += importo; if (imposta != ZERO) { //controllo prorata const TRectype& pla = cache().get("CMS", codcms); const bool prorata = pla.get_bool("B4"); if (prorata) { const TDate datareg = pn.curr().get_date(MOV_DATAREG); const int anno = datareg.year(); TRegistro registro(pn.curr().get(MOV_REG), anno); imposta *= (CENTO - registro.prorata(anno))/CENTO; imposta.round(TCurrency::get_firm_dec()); //ci vanno i decimali della ditta } *imp += imposta; totdoc_cms += imposta; } } } totdoc = totale_documento(pn.curr()); //tot doc con ritenute fiscali + ritenute sociali (da stampare) totdoc_netto = pn.curr().get_real(MOV_TOTDOC); //questo si usa solo per il calcolo del residuo } else //..movimento NON iva (sempre con saldaconto) { for (int i = 0; i < pn.cg_items(); i++) { const TRectype& rmov = pn.cg(i); const TBill conto(rmov); TImporto importo(rmov.get_char(RMV_SEZIONE), rmov.get_real(RMV_IMPORTO)); importo.normalize('D'); if (conto.tipo() > ' ') { totdoc -= importo.valore(); totdoc_netto -= importo.valore(); //valore per il calcolo del residuo continue; } if (cerca_fiscali(conto) || cerca_sociali(conto)) { totdoc -= importo.valore(); //valore da stampare nella colonna Tot.fattura con ritenute continue; } const TString& codcms = rmov.get(RMV_CODCMS); const TString& codfase = rmov.get(RMV_FASCMS); if (cms_in_range(codcms,codfase) && conto.indicatore_bilancio() != 5) { TToken_string cms_fsc = codcms; if (codfase.not_empty()) cms_fsc.add(codfase); real* imp = (real*)commesse.objptr(cms_fsc); if (imp == NULL) { imp = new real; commesse.add(cms_fsc, imp); } *imp += importo.valore(); totdoc_cms += importo.valore(); } } } //parte comune a movimenti IVA e non (vengono anche qui considerate le ritenute fiscali //e sociali perche' possono essere state inserite direttamente nella partita e non nel movimento //(quindi non si puo' in questo caso applicare la totale_documento() //Le ritenute fiscali vanno sempre sommate.. real totpagato = riga_pag.get_real(PART_IMPORTO) + riga_pag.get_real(PART_RITENUTE); //Le ritenute sociali invece vanno testate con la test_swap.. const real ritsoc = riga_pag.get_real(PART_RITSOC); if (!ritsoc.is_zero()) { const TRectype& mov = pn.curr(); TCausale caus(mov.get(MOV_CODCAUS)); const bool swapt = test_swap(caus, false); // Totale invertito ? const bool swaps = test_swap(caus, true); // Ritenute sociali invertite ? if (swapt ^ swaps) // Somma ritenute sociali con segno totpagato -= ritsoc; else totpagato += ritsoc; } const real percentuale = totpagato / totdoc_netto; //calcolo del residuo (solo movimenti saldacontati) //mi servono,dalla riga partita che viene passata,i valori dei campi per la chiave del //file delle scadenze const TPartita match(riga_pag); //ci serve la riga di fattura che origina la nostra riga pagamento const int riga_fatt = cerca_riga_fattura_origine(match, riga_pag); //quanto era stato pagato del documento prima della attuale riga_pag const real totpagato_prec = calcola_pagato_prec(match, riga_fatt, riga_pag); const real perc_prec = totpagato_prec / totdoc_netto; TGeneric_distrib distributore(totdoc_cms * percentuale, TCurrency::get_firm_dec()); TGeneric_distrib distributore_prec(totdoc_cms * perc_prec, TCurrency::get_firm_dec()); { FOR_EACH_ASSOC_OBJECT(commesse, h, k, imp) { const real& impcms = *(real*)imp; distributore.add(impcms); distributore_prec.add(impcms); //distributore di importo pagato sulle commesse } } FOR_EACH_ASSOC_OBJECT(commesse, h, k, imp) { const real& impcms = *(real*)imp; TPag_per_cms_struct* ppcs = new TPag_per_cms_struct; // campi del pagamento ppcs->_tipo = 0; //movimenti da saldaconto ppcs->_codforn = riga_pag.get_long(PART_SOTTOCONTO); ppcs->_datapag = riga_pag.get_date(_campodata); ppcs->_importopagato.set_num(distributore.get()); //pagamento nella partita ppcs->_importopagato_prec.set_num(distributore_prec.get()); //pagamenti precedenti al ppcs->_descrpagamento = riga_pag.get(PART_DESCR); // campi della fattura ppcs->_nreg = nreg; ppcs->_numfat = movfat.get(MOV_NUMDOC); ppcs->_datafat = movfat.get_date(MOV_DATADOC); ppcs->_protiva = movfat.get_long(MOV_PROTIVA); ppcs->_totfat = totdoc; //questo e' quello che viene stampato in Tot.fattura TToken_string cms_fsc = k; ppcs->_commessa = cms_fsc.get(0); ppcs->_fase = cms_fsc.get(1); ppcs->_importocommessa.set_num(impcms); //importo da pagare scritto sulla fattura _righe.add(ppcs); //aggiunge il pagamento all'array dei pagamenti } }*/ } bool TPag_per_cms_recordset::part_callback(const TRelation& rel, void* pJolly) { TPag_per_cms_recordset* recordset = (TPag_per_cms_recordset*)pJolly; const TRectype& riga_part_pag = rel.curr(); const long nreg = recordset->find_movimento(riga_part_pag); //prima cerco un movimento della fattura... /* if (nreg > 0) //..se ne trovo almeno uno cerco la commessa corrispondente recordset->find_commesse(nreg, riga_part_pag);*/ return true; } void TPag_per_cms_recordset::scan_pags(const TPag_per_cms_mask& msk) { //costruzione filtro TRectype filtrec(LF_PARTITE); filtrec.put(PART_TIPOCF, 'F'); filtrec.put(PART_GRUPPO, 0); filtrec.put(PART_CONTO, 0); if (_codfor > 0) filtrec.put(PART_SOTTOCONTO, _codfor); TString filtro = "(TIPOMOV>=\"3\")"; //deve essere un pagamento a fornitore!!! if (_dadata.ok()) { TString80 f; f.format("&&(ANSI(%s)>=\"%s\")", (const char*)_campodata, _dadata.string(ANSI)); filtro << f; } if (_adata.ok()) { TString80 f; f.format("&&(ANSI(%s)<=\"%s\")", (const char*)_campodata, _adata.string(ANSI)); filtro << f; } //applica il filtro alla relazione TRelation rel(LF_PARTITE); TCursor cur(&rel, filtro, 1, &filtrec, &filtrec); cur.scan(part_callback, this, "Movimenti con saldaconto..."); } void TPag_per_cms_recordset::set_filter(const TPag_per_cms_mask& msk, const int cms_row, const long codfor) { //se esiste il file temporano con tracciato persomalizzato lo cancella e lo ricrea vuoto TFilename trr; //file tracciato record trr.tempdir(); trr.add("paid"); TFilename dbf(trr); //file dati trr.ext("trr"); dbf.ext("dbf"); //crea il file .trr in base ai parametri del metodo crea_trr(trr); //svuota la memoria dal vecchio file temporaneo if (_tmp != NULL) delete _tmp; //crea in memoria il nuovo file temporaneo e lo azzera (non si sa mai..) _tmp = new TExternisamfile(dbf, trr); _tmp->zap(); //prende un po' di dati dalla maschera _codcosto = _codcms = _codfas = ""; if (cms_row >= 0) { TSheet_field& sf = msk.sfield(F_RIGHE); TMask& sm = sf.sheet_mask(); //metodo ingannatore per ottenere tutti i campi dallo sheet.. sf.update_mask(cms_row); //..delle cms/fsc/cdc senza rifare il giro della configurazione.. TRelation rel(LF_RMOVANA); //..anale sm.autosave(rel); _codcosto = rel.curr().get(RMOVANA_CODCCOSTO); _codcms = rel.curr().get(RMOVANA_CODCMS); _codfas = rel.curr().get(RMOVANA_CODFASE); } //scelta tipo data di estrazione (registrazione, documento, pagamento) _campodata = PART_DATAREG; switch(msk.get_int(F_TIPODATA)) { case 1:_campodata = PART_DATADOC;break; case 2:_campodata = PART_DATAPAG;break; default:break; } //lettura eventuali date limite (il controllo sul loro valore sara' nei metodi di costruzione //dei filtri _dadata = msk.get_date(F_DATAINI); _adata = msk.get_date(F_DATAFIN); //scansione movimenti con saldaconto scan_pags(msk); //se c'e' un filtro sui fornitori, non si fa lo scan dei movimenti senza saldaconto if (codfor <= 0) scan_movs(msk); } //////////////////////////////////////////////////////// // REPORT //////////////////////////////////////////////////////// class TPag_per_cms_rep : public TAnal_report { protected: virtual bool set_recordset(const TString& sql); virtual bool get_usr_val(const TString& name, TVariant& var) const; public: void set_filter(const TPag_per_cms_mask& msk, const int cms_row, const long codfor); }; bool TPag_per_cms_rep::get_usr_val(const TString& name, TVariant& var) const { return TAnal_report::get_usr_val(name, var); } bool TPag_per_cms_rep::set_recordset(const TString& sql) { TPag_per_cms_recordset* rs = new TPag_per_cms_recordset(sql); return TAnal_report::set_recordset(rs); } void TPag_per_cms_rep::set_filter(const TPag_per_cms_mask& msk, const int cms_row, const long codfor) { TAnal_report::set_recordset(NULL); const char* query ="USE 1000"; //\nJOIN MOVANA INTO NUMREG==NUMRD\nJOIN RMOVANA INTO NUMREG==NUMRD NUMRIG==NRIGA"; TPag_per_cms_recordset* recset = new TPag_per_cms_recordset(query); recset->set_filter(msk, cms_row, codfor); TAnal_report::set_recordset(recset); } //=============================================================================================== //////////////////////////////////////////////////////// // APPLICAZIONE //////////////////////////////////////////////////////// class TPag_per_cms : public TSkeleton_application { public: void stampa_per_commessa(const TPag_per_cms_mask& mask, TReport_book& book, TPag_per_cms_rep& rep, const long codfor); const TMultilevel_code_info& get_level_one() const; virtual void main_loop(); }; //metodo per accattarsi o' primo livello della configurazione CA const TMultilevel_code_info& TPag_per_cms::get_level_one() const { TConfig& cfg = ca_config(); const TString& first_lev = cfg.get("Level(1)"); const int logic = first_lev == "CDC" ? LF_CDC : LF_COMMESSE; return ca_multilevel_code_info(logic); } void TPag_per_cms::stampa_per_commessa(const TPag_per_cms_mask& mask, TReport_book& book, TPag_per_cms_rep& rep, const long codfor) { TSheet_field& sheet = mask.sfield(F_RIGHE); TString video_string; //stringa che compare nella progind if (sheet.empty()) //se non ci sono righe sullo sheet (selezione su tutte le cms/cdc)... { TToken_string& row = sheet.row(-1); //crea la prima riga dello sheet const TMultilevel_code_info& liv1 = get_level_one(); //stabilisce quale è il primo livello (tra CDC e CMS).. TISAM_recordset set(liv1.logic() == LF_CDC ? "USE CDC" : "USE COMMESSE"); //..e di conseguenza scrive la use giusta TProgind pi(set.items(), video_string, true, true); for (int i = 0; set.move_to(i); i++) //fighissimo metodo per scandire un file in 1 riga! { pi.addstatus(1); if (pi.iscancelled()) break; row = set.get((unsigned int)0).as_string(); //prende il valore del primo campo del file (CDC o CMS code) video_string = TR("Scansione"); video_string << " " << row; //completa la stringa da visualizzare sulla progind pi.set_text(video_string); for (int l = liv1.levels()-2; l >= 0; l--) //se la struttura è a più livelli costruisce la tokenstring row.insert("|", liv1.total_len(l)); rep.set_filter(mask, 0, codfor); //fa la set filter sulla prima riga (che è quella usata) book.add(rep); } sheet.destroy(); //cancella le commesse aggiunte in automatico sullo sheet } else //se ha almeno una riga sullo sheet delle cms/cdc... { FOR_EACH_SHEET_ROW(sheet, r, row) //per ogni cdc/cms che appare nello sheet di pag.1 della msk.. { rep.set_filter(mask, r, codfor); //..chiama il metodone globale che crea e compila il file.. //..temporaneo i cui dati riempiranno il report book.add(rep); //aggiunge il report relativo alla cdc/cms corrente al book } } } void TPag_per_cms::main_loop() { TPag_per_cms_mask mask; while (mask.run() == K_ENTER) { //report e book dei report TReport_book book; TString path = mask.get(F_REPORT); if (path.empty()) path = "ca3600a"; TPag_per_cms_rep rep; rep.load(path); const long dacodfor = mask.get_long(F_DACODFOR); const long acodfor = mask.get_long(F_ACODFOR); if (dacodfor > 0 || acodfor > 0) //specifica il range dei clifo.. { TISAM_recordset clifo("USE CLIFO\nFROM TIPOCF='F' CODCF=#DACODFOR\nTO TIPOCF='F' CODCF=#ACODFOR"); clifo.set_var("#DACODFOR", TVariant(dacodfor)); clifo.set_var("#ACODFOR", TVariant(acodfor)); for (bool ok = clifo.move_first(); ok; ok = clifo.move_next()) { const long codforn = clifo.get("CODCF").as_int(); stampa_per_commessa(mask, book, rep, codforn); } } else stampa_per_commessa(mask, book, rep, 0); //se non si specifica alcun clifo... book.print_or_preview(); //stampa il book dei report } } int ca3600(int argc, char* argv[]) { TPag_per_cms a; a.run(argc,argv,TR("Stampa pagato per commessa")); return 0; }