#include #include #include #include #include #include #include #include #include #include #include "..\cg\cgsaldac.h" #include "..\cg\cg2101.h" #include "..\cg\cg2103.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 DLG_PRINT: if (e == fe_button) { main_app().print(); return false; } break; case DLG_PREVIEW: if (e == fe_button) { main_app().preview(); return false; } break; 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"); ***per ora solo Pdcc*** } 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); //carica i parametri dei conti per lo sheet dei conti contabili config_loader(sfield(F_PDCC), "Pdcc"); // 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 = "ca3600a.ini"; //carica file configurazione conti configname.custom_path(); TConfig configfile(configname, paragrafo); TString_array conti; 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 = "ca3600a.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 _dacodfor, _acodfor; TString16 _campodata; TString _codcosto, _codcms, _codfas; TAssoc_array _costi,_pagamenti,_fiscali,_sociali; //array che contengono i conti letti dal .ini 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); void find_commesse_cg(const TRectype& mov); bool check_cms_cdc_fsc(const TRectype& rec_analriga); const TString& query_movama_by_numregcg(const long nreg); void lettura_conti(TAssoc_array& assoc, const char tipoconto); int cerca_riga_fattura_origine(const TPartita& match, const TRectype& riga_pag); real totale_documento(const TRectype& mov) const; real calcola_pagato_prec(const TPartita& match, const int riga_fatt, const TRectype& riga_pag); bool test_swap(TCausale& caus, bool ritsoc) const; bool cerca_conto(const char tipo, const TBill& bill, const TAssoc_array& assoc) const; int cerca_costo(const TBill& bill) const; int cerca_pagamento(const TBill& bill) const; bool cerca_fiscali(const TBill& bill) const; bool cerca_sociali(const TBill& bill) const; public: virtual void set_filter(const TPag_per_cms_mask& msk, const int cms_row, const long dacodfor, const long acodfor, const TString& campodata); virtual void set_custom_filter(TCursor& cur) const; void scan_pags(); void scan_movs(); TPag_per_cms_recordset(const TString& sql) : TISAM_recordset(sql) { _tmp = NULL;} ~TPag_per_cms_recordset(); }; ////////////////////////////////// // generica ////////////////////////////////// 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; TString80 f; if (_dadata.ok()) { f.format("(ANSI(%s)>=\"%s\")", (const char*)_campodata, _dadata.string(ANSI)); filtro << f; } if (_adata.ok()) { if (filtro.not_empty()) filtro << "&&"; f.format("(ANSI(%s)<=\"%s\")", (const char*)_campodata, _adata.string(ANSI)); filtro << f; } cur.setregion(darec, arec); cur.setfilter(filtro); myself = (TPag_per_cms_recordset*)this; } //simpatico metodo per riempire in automatico i campi di intestazione speciali const TVariant& TPag_per_cms_recordset::get(const char* column_name) const { if (*column_name == '#') { if (strcmp(column_name, "#COSTO") == 0) { TVariant& var = get_tmp_var(); var = _codcosto; return var; } if (strcmp(column_name, "#COMMESSA") == 0) { TVariant& var = get_tmp_var(); var = _codcms; return var; } if (strcmp(column_name, "#FASE") == 0) { TVariant& var = get_tmp_var(); var = _codfas; return var; } } return TISAM_recordset::get(column_name); } void TPag_per_cms_recordset::crea_trr(const TFilename& trr) const { TString chiave; ofstream of(trr); of << 1000 << endl; of << 16 << endl; of << "CODFORN|3|6|0|Codice fornitore" << endl; of << "DESFORN|1|50|0|Descrizione fornitore" << endl; of << "NREG|3|7|0|Numero registrazione" << endl; of << "DATAREG|5|8|0|Data 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 << "CDC|1|20|0|Centro di costo" << endl; of << "CMS|1|20|0|Commessa" << endl; of << "FSC|1|10|0|Fase" << endl; of << "HIDDEN|8|1|0|Record nascosto" << endl; of << 1 << endl; //l'ordinamento dipende dal tipo di data selezionato sulla maschera chiave << "CODFORN+FSC+NREG+"; chiave << _campodata; of << chiave << endl; } void TPag_per_cms_recordset::lettura_conti(TAssoc_array& assoc, const char tipoconto) { TConfig conti("ca3600a.ini","Pdcc"); //paragrafo da scandire nell'ini (solo conti contabili!!) TAssoc_array& vars = conti.list_variables(); FOR_EACH_ASSOC_STRING(vars, h, k, val) //riempie l'assoc con i soli valori del paragrafo dell'ini { if (*val == tipoconto) //mette nell'assocarray solo i conti corrispondenti al tipoconto passato assoc.add(val); } } bool TPag_per_cms_recordset::cerca_conto(const char tipo, const TBill& bill, const TAssoc_array& assoc) const { TToken_string key(15); key.add(tipo); key.add(bill.gruppo()); if (assoc.is_key(key)) return true; key.add(bill.conto()); if (assoc.is_key(key)) return true; key.add(bill.sottoconto()); if (assoc.is_key(key)) return true; return false; } int TPag_per_cms_recordset::cerca_costo(const TBill& bill) const { if (cerca_conto('C', bill, _costi)) return 1; else return 0; } int TPag_per_cms_recordset::cerca_pagamento(const TBill& bill) const { if (cerca_conto('P', bill, _pagamenti)) return 2; else return 0; } bool TPag_per_cms_recordset::cerca_fiscali(const TBill& bill) const { return cerca_conto('F', bill, _fiscali); } bool TPag_per_cms_recordset::cerca_sociali(const TBill& bill) const { return cerca_conto('S', bill, _sociali); } // Controlla sulla causale se il segno del totale documento (ritsoc=FALSE) // o quello delle ritenute sociali (ritsoc=TRUE) e' invertito rispetto al normale bool TPag_per_cms_recordset::test_swap(TCausale& caus, bool ritsoc) const { const char sez = ritsoc ? caus.sezione_ritsoc() : caus.sezione_clifo(); const bool s = (caus.iva() == iva_vendite) ^ (sez == 'D'); return s; } // Calcola il totale del documento tenendo conto del segno della prima riga e di quella delle // ritenute sociali sulla causale real TPag_per_cms_recordset::totale_documento(const TRectype& mov) const { real tot = mov.get_real(MOV_TOTDOC); // Legge totale const real ritfis = mov.get_real(MOV_RITFIS); tot += ritfis; // Somma ritenute fiscali const real ritsoc = mov.get_real(MOV_RITSOC); if (!ritsoc.is_zero()) { 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 tot -= ritsoc; else tot += ritsoc; } return tot; } int TPag_per_cms_recordset::cerca_riga_fattura_origine(const TPartita& match, const TRectype& riga_pag) { //scansione delle righe partita passata, precedenti alla riga_pag const int k = riga_pag.get_int(PART_NRIGA); for (int i = match.pred(k); i > 0; i = match.pred(i)) { const TRiga_partite& riga_part = match.riga(i); if (riga_part.is_fattura()) { for (int j = riga_part.rate(); j > 0; j--) { if (match.esiste(i, j, k)) //se esiste il pagamento k della rata j della riga partita i contenente la fattura return i; } } } return 0; } real TPag_per_cms_recordset::calcola_pagato_prec(const TPartita& match, const int riga_fatt, const TRectype& riga_pag) { real pagato = ZERO; if (riga_fatt > 0) { const int k = riga_pag.get_int(PART_NRIGA); const TDate data_rif = riga_pag.get(_campodata); //data di riferimento selezionata sulla maschera const TRiga_partite& riga_part = match.riga(riga_fatt); for (int i = riga_part.rate(); i > 0; i--) { TRiga_scadenze& sc = riga_part.rata(i); for (int j = sc.last(); j > 0; j = sc.pred(j)) { const TRiga_partite& pag = match.riga(j); const TDate datapag = pag.get_date(_campodata); const long cmp = datapag - data_rif; //la riga pagamento e' da considerare quando ha data anteriore a quella di riferimento oppur //ha data uguale ma numero di registrazione inferiore (insomma, il pagamento e' precedente //a quello di riga_pag) if (cmp < 0 || (cmp == 0 && j <= k)) { pagato += pag.get_real(PAGSCA_IMPORTO); } } } } return pagato; } ///////////////////////////////////// // movimenti senza saldaconto ///////////////////////////////////// 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; } //prepara gli oggetti (_righecosti,_righepagamenti) contenenti le righe dei pagamenti.. //..senza saldaconto void TPag_per_cms_recordset::find_commesse_cg(const TRectype& mov) { const long numregcg = mov.get_long(MOV_NUMREG); //cerca un record di MOVANA che abbia numregcg = nreg;usa il nuovo metodo fighissimo.. //..con la isam query implementato nella query_movama_by_numregcg() TISAM_recordset movana(query_movama_by_numregcg(numregcg)); const TRecnotype items = movana.items(); if (items > 0) { if (items > 1) error_box(TR("Esiste piu' di un movimento analitico collegato al movimento contabile %ld"),numregcg); movana.move_last(); //si posiziona sul record corretto //prepara il record tmpcurr sul file temporaneo _tmp su cui registrare i dati da stampare TRectype& tmpcurr = _tmp->curr(); tmpcurr.zero(); //crea il movana legato al mov const TAnal_mov anal_mov(mov); const TRecord_array& anal_rows = anal_mov.body(); for (int j = 1; j <= anal_rows.rows(); j++) //scansiona righe analitiche.. { const TRectype& anal_row = anal_rows[j]; if (check_cms_cdc_fsc(anal_row)) { //prende il conto sulla riga analitica e lo confronta con quelli della configurazione const TString& conto_riga_analitica = anal_row.get(RMOVANA_CODCONTO); const int gruppo_anal = atoi(conto_riga_analitica.left(3)); const int conto_anal = atoi(conto_riga_analitica.mid(3,3)); const long sottoconto_anal = atol(conto_riga_analitica.mid(6,6)); const TBill conto(gruppo_anal, conto_anal, sottoconto_anal); int tipo = cerca_costo(conto) || cerca_pagamento(conto); if (tipo > 0) { const char sezione = anal_row.get_char(RMOVANA_SEZIONE); const real valore = anal_row.get_real(RMOVANA_IMPORTO); TImporto imp(sezione, valore); switch (tipo) { case 1:imp.normalize('D');break; case 2:imp.normalize('A');break; //case 3:imp.normalize('D');break; //case 4:imp.normalize('A');break; default:break; } //deve aggiungere ora al file temporaneo il record //codice fornitore e descrizione const long codforn = mov.get_long(MOV_CODCF); if (codforn > 0) { tmpcurr.put("CODFORN", codforn); TString16 keyclifo; keyclifo.format("F|%ld", codforn); const TRectype& rec_clifo = cache().get(LF_CLIFO, keyclifo); tmpcurr.put("DESFORN", rec_clifo.get(CLI_RAGSOC)); } //nreg,data pagamento,descrizione pagamento tmpcurr.put("NREG", numregcg); tmpcurr.put("DATAREG", mov.get_date(MOV_DATAREG)); tmpcurr.put("DATAPAG", mov.get_date(MOV_DATACOMP)); //documento origine tmpcurr.put("NDOC", mov.get_long(MOV_NUMDOC)); tmpcurr.put("DATADOC", movana.get(MOV_DATADOC).as_date()); tmpcurr.put("TOTDOC", movana.get(MOV_TOTDOC).as_real()); //importi tmpcurr.put("TOTPAG", imp.valore()); //tmpcurr.put("TOTRES", ); //pagamenti precedenti al //campi relativi a cdc,commessa,fase tmpcurr.put("CMS",anal_row.get(RMOVANA_CODCMS)); tmpcurr.put("CDC",anal_row.get(RMOVANA_CODCCOSTO)); tmpcurr.put("FSC",anal_row.get(RMOVANA_CODFASE)); //e finalmente aggiunge il record al file temporaneo _tmp->write(); } } } //for(j0... } bool TPag_per_cms_recordset::mov_callback(const TRelation& rel, void* pJolly) { TPag_per_cms_recordset* recordset = (TPag_per_cms_recordset*)pJolly; recordset->find_commesse_cg(rel.curr()); return true; } void TPag_per_cms_recordset::scan_movs() { if (_campodata == PART_DATAPAG) // I movimenti non hanno DATAPAG _campodata = MOV_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..."); } bool TPag_per_cms_recordset::check_cms_cdc_fsc(const TRectype& rec_analriga) { if (_codcosto.not_empty() && _codcosto != rec_analriga.get(RMOVANA_CODCCOSTO)) return false; if (_codcms.not_empty() && _codcms != rec_analriga.get(RMOVANA_CODCMS)) return false; if (_codfas.not_empty() && _codfas != rec_analriga.get(RMOVANA_CODFASE)) return false; return true; } ////////////////////////////////////// // movimenti con saldaconto ////////////////////////////////////// const TString& TPag_per_cms_recordset::query_movama_by_numregcg(const long nreg) { TString& query = get_tmp_string(); query << "USE MOVANA KEY 3\n"; query << "FROM NUMREGCG=" << nreg << "\n"; query << "TO NUMREGCG=" << nreg; return query; } //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) { //cerca un record di MOVANA che abbia numregcg = nreg;usa il nuovo metodo fighissimo.. //..con la isam query implementato nella query_movama_by_numregcg() TISAM_recordset movana(query_movama_by_numregcg(nreg)); const TRecnotype items = movana.items(); if (items <= 0) return; if (items > 1) warning_box(TR("Esiste piu' di un movimento analitico collegato al movimento contabile %ld"),nreg); movana.move_last(); //si posiziona sul record corretto //crea il movana e le sue righe const TAnal_mov anal_mov(movana.get(MOVANA_NUMREG).as_int()); TRecord_array& anal_rows = anal_mov.body(); //scandisce le righe del movana alla ricerca di righe compatibili con le commesse sullo sheet int m; for (m = anal_rows.last_row(); m > 0; m--) { if (check_cms_cdc_fsc(anal_rows[m])) break; } //se non ne ha trovata manco una di righe buone esce! if (m <= 0) return; //prepara il record tmpcurr sul file temporaneo _tmp su cui registrare i dati da stampare TRectype& tmpcurr = _tmp->curr(); tmpcurr.zero(); //crea un movimento p.n. con il numero reg che viene passato al metodo (nreg relativo.. //..ad un movimento della fattura originaria) 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) { //trova le RMOVANA del MOVANA corrente che hanno il conto = a quello della i-esima rigaiva for (int j = 0; j < pn.iva_items(); j++) { const TRectype& rmoviva = pn.iva(j); const TBill zio(rmoviva); //il tutto si fa solo se l'indicatore di bilancio del conto nella riga iva e' != 5 if (zio.indicatore_bilancio() != 5) { //e vediamo 'sto conto della riga iva.. const int gruppo_iva = zio.gruppo(); const int conto_iva = zio.conto(); const long sottoconto_iva = zio.sottoconto(); real imponibile_iva = rmoviva.get_real(RMI_IMPONIBILE); real imposta_iva = rmoviva.get_real(RMI_IMPOSTA); const TString& tipodet = rmoviva.get(RMI_TIPODET); //controlla se l'imposta va sommata (tipo detrazione iva non nulla) if (tipodet.full()) imponibile_iva += imposta_iva; //distributore per il lordo iva (che sara' distribuito successivamente in base.. //..agli importi delle righe analitiche corretti per le % iva TGeneric_distrib agip (imponibile_iva, TCurrency::get_firm_dec()); for (int k = 1; k <= anal_rows.rows(); k++) //scansiona righe analitiche.. { real perc_ded_iva = UNO; //%iva deducibile (di default 100, a meno del prorata) if (imposta_iva != ZERO) { //controllo prorata const TString80 commessa_riga_anal = anal_rows[k].get(RMOVANA_CODCMS); const TRectype& pla = cache().get(LF_COMMESSE, commessa_riga_anal); const bool prorata = pla.get_bool("PRORATA"); if (prorata) { const TDate datareg = pn.curr().get_date(MOV_DATAREG); const int anno = datareg.year(); TRegistro registro(pn.curr().get(MOV_REG), anno); //%deducibilità iva rivista con il prorata perc_ded_iva = (CENTO - registro.prorata(anno))/CENTO; imposta_iva.round(TCurrency::get_firm_dec()); //ci vanno i decimali della ditta } } //if imposta_iva... //prende il conto sulla riga analitica e lo confronta con quello della riga iva const int gruppo_anal = atoi(anal_rows[k].get(RMOVANA_CODCONTO).left(3)); const int conto_anal = atoi(anal_rows[k].get(RMOVANA_CODCONTO).mid(3,3)); const long sottoconto_anal = atol(anal_rows[k].get(RMOVANA_CODCONTO).mid(6,6)); //il codconto anale e iva coincidono?.. if (gruppo_iva == gruppo_anal && conto_iva == conto_anal && sottoconto_iva == sottoconto_anal) { //..in tal caso aggiunge l'importo della riga analitica al distributore, dopo.. //..averlo corretto in base alle % precedentemente calcolate real importo_anal = anal_rows[k].get_real(RMOVANA_IMPORTO); const real perc_iva = imposta_iva / imponibile_iva; const real perc_corretta_iva = perc_iva * (UNO - perc_ded_iva); importo_anal = importo_anal * (UNO - perc_corretta_iva); agip.add(importo_anal); } //if(gruppo_iva==... } //for (anal_rows... for (int l = 1; l <= anal_rows.rows(); l++) //..allora le scansiona.. { //prende il conto sulla riga analitica e lo confronta con quello della riga iva const int gruppo_anal = atoi(anal_rows[l].get(RMOVANA_CODCONTO).left(3)); const int conto_anal = atoi(anal_rows[l].get(RMOVANA_CODCONTO).mid(3,3)); const long sottoconto_anal = atol(anal_rows[l].get(RMOVANA_CODCONTO).mid(6,6)); //il codconto anale e iva coincidono? if (gruppo_iva == gruppo_anal && conto_iva == conto_anal && sottoconto_iva == sottoconto_anal) { //impoerto real importo = agip.get(); //commessa,cdc,fase della riga analitica devono essere coincidenti con quelle dello sheet if (check_cms_cdc_fsc(anal_rows[l])) { //costruzione dell'assoc_array 'commesse' con cms/cdc/fsc ed importi TToken_string cms_cdc_fsc; cms_cdc_fsc.add(anal_rows[l].get(RMOVANA_CODCMS)); cms_cdc_fsc.add(anal_rows[l].get(RMOVANA_CODCCOSTO)); cms_cdc_fsc.add(anal_rows[l].get(RMOVANA_CODFASE)); real* imp = (real*)commesse.objptr(cms_cdc_fsc); //aggiunge un elemento all'assoc_array... if (imp == NULL) { imp = new real; commesse.add(cms_cdc_fsc, imp); } *imp += importo; totdoc_cms += importo; } //if check_cms_cdc_fsc... } //if(gruppo_iva==... } //for (anal_rows... } //if indicatore_bilancio!=5... } //for (pn.iva_items(... 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 } //if(pn.iva_items(... else //..movimento NON iva (sempre con saldaconto) { for (int j = 0; j < pn.cg_items(); j++) { const TRectype& rmov = pn.cg(j); const TBill zio_cg(rmov); TImporto importo(rmov.get_char(RMV_SEZIONE), rmov.get_real(RMV_IMPORTO)); importo.normalize('D'); if (zio_cg.tipo() > ' ') { totdoc -= importo.valore(); totdoc_netto -= importo.valore(); //valore per il calcolo del residuo } else if (cerca_fiscali(zio_cg) || cerca_sociali(zio_cg)) totdoc -= importo.valore(); //valore da stampare nella colonna Tot.fattura con ritenute } //for j < pn.cg_items... for (int k = 1; k <= anal_rows.rows(); k++) //..allora le scansiona.. { //prende gr/co/sott sulla riga analitica... const int gruppo_anal = atoi(anal_rows[k].get(RMOVANA_CODCONTO).left(3)); const int conto_anal = atoi(anal_rows[k].get(RMOVANA_CODCONTO).mid(3,3)); const long sottoconto_anal = atol(anal_rows[k].get(RMOVANA_CODCONTO).mid(6,6)); //..e crea il conto contabile corrispondente TBill conto_cg(gruppo_anal, conto_anal, sottoconto_anal); //l'indicatore di bilancio del conto contabile appena creato e' valido? if (conto_cg.indicatore_bilancio() != 5) { const real importo_anal = anal_rows[k].get_real(RMOVANA_IMPORTO); //costruzione dell'assoc_array 'commesse' con cms/cdc/fsc ed importi TToken_string cms_cdc_fsc; cms_cdc_fsc.add(anal_rows[k].get(RMOVANA_CODCMS)); cms_cdc_fsc.add(anal_rows[k].get(RMOVANA_CODCCOSTO)); cms_cdc_fsc.add(anal_rows[k].get(RMOVANA_CODFASE)); real* imp = (real*)commesse.objptr(cms_cdc_fsc); if (imp == NULL) { imp = new real; commesse.add(cms_cdc_fsc, imp); } TImporto importo(anal_rows[k].get_char(RMOVANA_SEZIONE), anal_rows[k].get_real(RMOVANA_IMPORTO)); importo.normalize('D'); *imp += importo.valore(); totdoc_cms += importo.valore(); } //if(conto_cg.indicatore... } //for(kwrite(); } //FOR_EACH_... } //pn.read()... } 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() { //costruzione filtro TRectype dafiltrec(LF_PARTITE); dafiltrec.put(PART_TIPOCF, 'F'); dafiltrec.put(PART_GRUPPO, 0); dafiltrec.put(PART_CONTO, 0); dafiltrec.put(PART_SOTTOCONTO, _dacodfor); TRectype afiltrec(dafiltrec); afiltrec.put(PART_SOTTOCONTO, _acodfor); 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, &dafiltrec, &afiltrec); 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 dacodfor, const long acodfor, const TString& campodata) { //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"); //scelta tipo data di estrazione (registrazione, documento, pagamento) //deve stare qui per poter generare la chiave del file temporaneo in base al tipo di data di estrazione _campodata = campodata; //stessa cosa per il simpatico codice fornitore _dacodfor = dacodfor; _acodfor = acodfor; //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); } //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); //carica i conti memorizzati nel ca3600.ini,registrandoli negli assoc_array _costi ecc... lettura_conti(_costi, 'C'); lettura_conti(_pagamenti, 'P'); lettura_conti(_fiscali, 'F'); lettura_conti(_sociali, 'S'); //scansione movimenti con saldaconto scan_pags(); //se c'e' un filtro sui fornitori, non si fa lo scan dei movimenti senza saldaconto if (dacodfor <= 0 && acodfor <= 0) scan_movs(); } //////////////////////////////////////////////////////// // 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 dacodfor, const long acodfor, const TString& campodata); }; 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 dacodfor, const long acodfor, const TString& campodata) { 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, dacodfor, acodfor, campodata); TAnal_report::set_recordset(recset); } //=============================================================================================== //////////////////////////////////////////////////////// // APPLICAZIONE //////////////////////////////////////////////////////// class TPag_per_cms : public TSkeleton_application { TPag_per_cms_mask* _mask; protected: virtual void print(); virtual void preview(); void print_or_preview(const bool stampa); virtual void main_loop(); public: void stampa_per_commessa(const TPag_per_cms_mask& mask, TReport_book& book, TPag_per_cms_rep& rep, const long dacodfor, const long acodfor, const TString& campodata); const TMultilevel_code_info& get_level_one() const; }; //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 dacodfor, const long acodfor, const TString& campodata) { 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, dacodfor, acodfor, campodata); //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, dacodfor, acodfor, campodata); //..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::print() { print_or_preview(true); } void TPag_per_cms::preview() { print_or_preview(false); } void TPag_per_cms::print_or_preview(const bool stampa) { //il programma si puo' usare SOLO se in contabilita' analitica si usa il piano dei conti contabile TConfig& cfg = ca_config(); const bool use_pdcc = cfg.get_bool("UsePdcc"); if (!use_pdcc) { error_box(TR("Programma funzionante SOLO se in contabilita' analitica si usa il piano dei conti contabile")); return; } //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); //scelta tipo data di estrazione (registrazione, documento, pagamento) //viene presa qui perche' serve subito alla set_filter del report prima che venga.. //..utilizzata nel recordset TString16 campodata = PART_DATAREG; switch(_mask->get_int(F_TIPODATA)) { case 1: campodata = PART_DATADOC; break; case 2: campodata = PART_DATAPAG; break; default: break; } //scansione su tutti i fornitori selezionati; questa opzione e' praticamente utile solo.. //..quando il numero di fornitori selezionati non e' elevato;infatti,per ogni fornitore.. //..selezionato, viene eseguito tutto il giro del programma const long dacodfor = _mask->get_long(F_DACODFOR); const long acodfor = _mask->get_long(F_ACODFOR); stampa_per_commessa(*_mask, book, rep, dacodfor, acodfor, campodata); //se non si specifica alcun clifo... if (stampa) book.print(); //stampa il book dei report else book.preview(); //anteprima } void TPag_per_cms::main_loop() { _mask = new TPag_per_cms_mask; _mask->run(); delete _mask; _mask = NULL; } int ca3600(int argc, char* argv[]) { TPag_per_cms a; a.run(argc,argv,TR("Stampa pagato per commessa")); return 0; }