#include #include #include #include #include "tc9.h" #include "tc9100a.h" #include "../cg/cg2101.h" #include "../cg/cg2103.h" #include "../cg/cgsaldac.h" #include #include "../ca/calib01.h" #include "../ca/rmovana.h" #include "../ve/velib.h" class TInvioP_file: public TFile_text { protected: virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str); public: TInvioP_file(const TString& file_name); }; TInvioP_file::TInvioP_file(const TString& file_name) : TFile_text(file_name, "tc9100a.ini") {} ////////////////////////////////////////////////////// // MASCHERA ////////////////////////////////////////////////////// class TInvioP_mask : public TAutomask { protected: bool on_field_event(TOperable_field& o, TField_event e, long jolly); void config_loader(TSheet_field& sf, const char* paragrafo); void config_setter(TSheet_field& sf, const char* paragrafo); public: TInvioP_mask(); virtual ~TInvioP_mask(){}; }; TInvioP_mask::TInvioP_mask() :TAutomask ("tc9100a") { config_loader(sfield(F_PDCC), "Pdcc"); } bool TInvioP_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_CODDITTA: if (e==fe_init && o.empty()) { set(F_CODDITTA, main_app().get_firm()); ((TEdit_field&) o).check(); disable(F_CODDITTA); } break; case DLG_SAVEREC: if (e == fe_button) { config_setter(sfield(F_PDCC), "Pdcc"); } break; default: break; } return true; } void TInvioP_mask::config_loader(TSheet_field& sf, const char* paragrafo) { //carica file configurazione conti; attenzione!!!il file di configurazione in questione e' il //medesimo del programma per la stampa del pagato in contabilita' analitica, visto che i due //programmi necessitano degli stessi conti TFilename configname = "ca3600a.ini"; configname.custom_path(); TConfig configfile(configname, paragrafo); TString_array conti; int first_enabled_row = -1; 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); TString pippo = sf.row(i); pippo = pippo.left(1); //disabilita le righe di tipo C e P che riguardano la sola stampa.. /* if (pippo == "C" || pippo == "P") //..del pagato sf.disable_row(i); else { if (first_enabled_row < 0) //se la riga non e' C o P deve incrementare il contatore della.. first_enabled_row = i; //..prima riga disabilitata }*/ } if (first_enabled_row >= 0) //se il contatore della prima riga disabilitata e' stato.. sf.select(first_enabled_row); //..incrementato, sposta il focus alla prima riga abile } void TInvioP_mask::config_setter(TSheet_field& sf, const char* paragrafo) { TFilename configname = "ca3600a.ini"; 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)); configfile.set("conto", conto, NULL, true, i); } } ////////////////////////////////////////////// // STRUCT (saldo di 1 conto) ////////////////////////////////////////////// struct TInvioP_saldo : public TObject { TString16 _zio; TImporto _importo; TInvioP_saldo(const TRectype& r); TInvioP_saldo(const TString& zio, const TImporto& importo); }; TInvioP_saldo::TInvioP_saldo(const TRectype& r) { const TBill zio(r); _zio = zio.string(0x8); const char sezione = r.get_char(RMV_SEZIONE); const real imp = r.get_real(RMV_IMPORTO); _importo.set(sezione, imp); _importo.normalize(); } TInvioP_saldo::TInvioP_saldo(const TString& zio, const TImporto& importo) : _zio(zio), _importo(importo) {} ////////////////////////////////////////////// // SALDI MOVIMENTO CONTABILE ////////////////////////////////////////////// class TInvioP_saldi_cg : public TArray { public: //prende l'oggetto i-esimo (in questo caso un TInvioP_saldo) e ritorna il conto di tale oggetto const TString& conto(int i) { return ((TInvioP_saldo*)objptr(i))->_zio; } //stessa roba ma per l'importo TImporto& importo(int i) { return ((TInvioP_saldo*)objptr(i))->_importo; } bool sottrai_importo(const TString& conto, const TImporto& importo); void somma(const TRectype& rmov); void sottrai(const TRectype& rmovana); }; void TInvioP_saldi_cg::somma(const TRectype& rmov) { TInvioP_saldo* s = new TInvioP_saldo(rmov); add(s); } bool TInvioP_saldi_cg::sottrai_importo(const TString& zio, const TImporto& imp) { int k; //caso fortunato //scandisce gli elementi dell'array;se ne trova uno (k-esimo) con conto ed importo coincidenti.. //..con quelli passati al metodo, azzera l'importo di tale elemento dell'array for (k = 0; k < items(); k++) { if (conto(k) == zio && importo(k) == imp) { importo(k).set('D', ZERO); return true; } } //caso sfortunato //in questo caso gli importi dell'elemento k-esimo dell'array e passato al metodo NON coincidono TImporto residuo = imp; int ultima_riga_buona = -1; for (k = 0; k < items() && !residuo.is_zero(); k++) { if (conto(k) == zio) { TImporto& val = importo(k); residuo.normalize(val.sezione()); if (residuo >= val) { residuo -= val; val.set('D', ZERO); } else { val -= residuo; residuo.set('D', ZERO); } ultima_riga_buona = k; } } //alla fine del ciclo sull'array resta un residuo non nullo.. if (!residuo.is_zero()) { residuo.normalize(); residuo.swap_section(); if (ultima_riga_buona >= 0) importo(ultima_riga_buona) += residuo; } return true; } void TInvioP_saldi_cg::sottrai(const TRectype& rmovana) { //adesso tocca alle righe contabili senza commessa const int gruppo = atoi(rmovana.get(RMOVANA_CODCONTO).left(3)); const int conto = atoi(rmovana.get(RMOVANA_CODCONTO).mid(3,3)); const long sottoconto = atol(rmovana.get(RMOVANA_CODCONTO).mid(6,6)); const TBill zio(gruppo, conto, sottoconto); const TImporto importo(rmovana.get_char(RMOVANA_SEZIONE), rmovana.get_real(RMOVANA_IMPORTO)); sottrai_importo(zio.string(0x8), importo); } ////////////////////////////////////////////// // APPLICAZIONE ////////////////////////////////////////////// class TInvioP : public TSkeleton_application { TCursor* _cur; TInvioP_mask* _msk; TDate _dataini, _datafin; long _nregcosto, _nregpag; real _importo; char _accsal; TConfig* _configfile; TAssoc_array _fiscali,_sociali, _costi, _pagamenti; //array che contengono i conti protected: virtual bool create(void); virtual bool destroy(void); virtual void main_loop() ; void invio_proforma(); bool i_proforma_movimenti(); bool i_proforma_righe(TCursor& cur, TInvioP_file* trasfile); bool i_proforma_pagamenti(); bool i_proforma_clifor(char tipocf = 'C'); bool i_proforma_conti(); real totale_documento(TMovimentoPN& pn, const bool includi_ritenute = true) const; void lettura_conti(TAssoc_array& assoc, const char tipoconto); bool cerca_conto(const TBill& bill, const TAssoc_array& assoc, const char tipoconto) const; bool cerca_fiscali(const TBill& bill) const; bool cerca_sociali(const TBill& bill) const; int cerca_pagamento(const TBill& bill) const; int cerca_costo(const TBill& bill) const; bool test_swap(TCausale& caus, bool ritsoc) const; real calcola_pagamento(TRectype& curpag_rec, real& iva_indetraibile); bool sottrai_iva(TMovimentoPN& pn, const TRectype& rigaiva); void stringa_grcosot(TRecord_text& recrighe, const TString& zio); long calcola_fattura_originale(long nreg) const; bool calcola_imponibile_totdoc(const long nreg, const TRectype& pag_rec, real& imponibile, real& totdoc, real& totpagato, real& iva_indetraibile) const; void calcola_imposte(const real& importo, const real& imposta, const TString& codind, real& iva_det, real& iva_ind) const; public: const real get_importo() {return _importo;} const long get_nregcosto() const {return _nregcosto;} const long get_nregpag() const {return _nregpag;} const char get_accsal() const {return _accsal;} const TString& get_vocespesa(const TString& zio) const; TInvioP_file* apri_file(const char* nome); void chiudi_file(TInvioP_file* trasfile); TInvioP() {}; virtual ~TInvioP() {}; }; // restituisce un riferimento all' applicazione inline TInvioP& app() { return (TInvioP&) main_app();} // gestione dei messaggi estesi nei campi void TInvioP_file::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str) { const TString code(s.get(0)); TString valore; if (code == "_FISSO") { // gestione dei campi fissi per i record delle riba // sintassi: _FISSO,! // dove: è la stringa fissa da emettere TString in(s.get()); CHECK(in[0]=='!',"Macro _FISSO senza carattere '!'"); in.ltrim(1); in.trim(); valore = in; } else if (code == "_TELEFONO") { valore = str; valore.trim(); str = cur.curr().get("PTEL"); valore << str; valore.trim(); } else if (code == "_RAGSOC") { valore = str; valore = valore.strip_double_spaces(); } else if (code == "_FLAG") { if (app().get_accsal() == 'S') valore = "S"; else valore = "A"; } else if (code == "_NREGCOSTO") { valore.format("%ld", app().get_nregcosto()); } else if (code == "_NREGPAG") { valore.format("%ld", app().get_nregpag()); } else if (code == "_IMPORTO") { valore = app().get_importo().string(); } else NFCHECK("Macro non definita: %s", (const char *)code); str = valore; } TInvioP_file* TInvioP::apri_file(const char* nome) { TFilename filename = _msk->get(F_DESTINAZIONE); filename.add(nome); filename.ext("txt"); if (filename.exist()) remove(filename); TInvioP_file* trasfile = new TInvioP_file(filename); trasfile->open(filename,'w'); trasfile->force_record_separator(); return trasfile; } void TInvioP::chiudi_file(TInvioP_file* trasfile) { trasfile->close(); delete trasfile; } const TString& TInvioP::get_vocespesa(const TString& zio) const { TConfig configfile("tc9100conf.ini", "OPZIONI"); const TString16 confstringa = configfile.get("CONFSTRINGA"); const int len = confstringa.len(); TLocalisamfile panapdc(LF_PANAPDC); panapdc.zero(); panapdc.setkey(2); panapdc.put("GRUPPO", atoi(zio.mid(0,3))); panapdc.put("CONTO", atoi(zio.mid(3,3))); panapdc.put("SOTTOCONTO", atol(zio.mid(6,6))); const TRectype r(panapdc.curr()); for (panapdc.read(); !panapdc.eof(); panapdc.next()) { if (panapdc.curr() != r) break; const TString& codconto = panapdc.get("CODCONTO"); if (codconto.starts_with(confstringa)) return codconto.mid(len); } return EMPTY_STRING; } bool TInvioP::i_proforma_conti() { TInvioP_file* trasfile = apri_file("pianocon"); TRelation rel(LF_PCON); TCursor cur(&rel); const long cur_items = cur.items(); if (cur_items != 0) { TProgind pi(cur_items, "Trasferimento conti...", true, true); cur.freeze(); TRectype& cur_rec = cur.curr(); for (cur = 0; cur.pos() < cur_items; ++(cur)) { pi.addstatus(1); if (pi.iscancelled()) break; TRecord_text rec; rec.set_type("P"); trasfile->autoload(rec, cur); trasfile->write(rec); } } chiudi_file(trasfile); return true; } bool TInvioP::i_proforma_movimenti() { TInvioP_file* trasfile = apri_file("registra"); //file testate TInvioP_file* trasfilerighe = apri_file("righe"); //file righe movimenti //trasferimento testate movimenti (cerca direttamente sui movimenti analitici in chiave 2.. //..,cioè per DATACOMP e con NUMREGCG!=0 TRectype da(LF_MOV); TRectype a(LF_MOV); da.put(MOV_DATAREG, _dataini); a.put(MOV_DATAREG, _datafin); TRelation rel(LF_MOV); rel.add(LF_CAUSALI, "CODCAUS==CODCAUS"); TCursor cur(&rel, "", 2, &da, &a); //chiave per data const long cur_items = cur.items(); if (cur_items != 0) { //prepara i record di tipo testata da scrivere TRecord_text rec; rec.set_type("T"); TProgind pi(cur_items, "Trasferimento movimenti...", true, true); cur.freeze(); const TRectype& cur_rec = cur.curr(); for (cur = 0; cur.pos() < cur_items; ++(cur)) { pi.addstatus(1); if (pi.iscancelled()) break; //carica e scrive il record di testata in base alle informazioni contenute nel tc9100a.ini trasfile->autoload(rec, cur); trasfile->write(rec); //trasferisce le righe del movimento analitico corrente solo i_proforma_righe(cur, trasfilerighe); } } chiudi_file(trasfilerighe); chiudi_file(trasfile); return true; } bool TInvioP::i_proforma_righe(TCursor& cur, TInvioP_file* trasfilerighe) { //---- righe movimenti ---- TInvioP_saldi_cg conti_importi; //Creo un movimento PN (con numreg = a quello del mov)che servira' un po' dovunque TMovimentoPN pn; pn.curr() = cur.curr(); if (pn.read() == NOERR) { for (int j = 0; j < pn.cg_items(); j++) conti_importi.somma(pn.cg(j)); } TRecord_text recrighe; //istanzia il tipo record corretto da scrivere sul trasfilerighe recrighe.set_type("R"); TAnal_mov analmov(cur.curr()); //..istanzia il movimento analitico con numregcg=numreg del mov const long analrighe_items = analmov.body().rows(); if (analrighe_items > 0) //se il movana ha righe.. { TRelation rel_rmovana(LF_RMOVANA); //crea una relazione sulle righe anali cui aggiunge mov e movana rel_rmovana.add(LF_MOVANA, "NUMREG==NUMREG"); rel_rmovana.add(LF_MOV, "NUMREG==NUMREGCG", 1, LF_MOVANA); TCursor cur_rmovana(&rel_rmovana); //crea il cursore sulle righe analitiche che serve per poter usare la autoload cur_rmovana.curr(LF_MOVANA) = analmov; cur_rmovana.curr(LF_MOV) = cur.curr(); for (int i = 1; i <= analrighe_items; i++) { //..e scandisce le righe const TRectype& riga = analmov.body().row(i); //inganna il cursore passandogli la riga analitica in esame (bastardo!) cur_rmovana.curr() = riga; //carica le righe analitiche trasfilerighe->autoload(recrighe, cur_rmovana); //toglie le righe contabili corrispondenti che sono appena state aggiunte con la autoload (sarebbero.. //..duplicate se non lo facesse!!!) conti_importi.sottrai(riga); //procedura orrenda per eliminare gli zeri dai gr/co/sot e passarli come stringhe! const TString16 zio = cur_rmovana.curr().get(RMOVANA_CODCONTO); stringa_grcosot(recrighe, zio); //procedura per scrivere la fase che deve essere spezzata in due per sottoprogetto ed edizione const TString& codfase = riga.get(RMOVANA_CODFASE); if (codfase.full()) { recrighe.add(codfase.left(4), 14); recrighe.add(codfase.mid(4,4), 15); } //procedura per ricavare la voce di spesa const TString& vocespesa = get_vocespesa(zio); recrighe.add(vocespesa, 16); //scrive sul file di trasferimento (alla faccia della semplicita'!) trasfilerighe->write(recrighe); } } //prende le righe contabili che non sono state eliminate dalle analitiche nelle sottrai(riga).. //..in modo da passare anche quelle (in caso contrario sarebbero andati perduti gli importi di.. //..tali righe che non avevano commessa!) const long conti_importi_items = conti_importi.items(); TString workstring; //stringa di lavoro che serve nel ciclo sotto for (int k = 0; k < conti_importi_items; k++) { if (!conti_importi.importo(k).is_zero()) { //aggiunge i valori ai campi uno ad uno perchè non ha un cursore per fare l'autoload recrighe.destroy(); recrighe.add(pn.curr().get(MOV_NUMREG), 0); //numreg workstring = "N"; recrighe.add(workstring, 1); //rigaiva TImporto& imp = conti_importi.importo(k); workstring.cut(0) << imp.sezione(); recrighe.add(workstring, 2); //sezione //procedura orrenda per eliminare gli zeri dai gr/co/sot e passarli come stringhe! const TString& zio = conti_importi.conto(k); stringa_grcosot(recrighe, zio); char tipocf = pn.curr().get_char(MOV_TIPO); long codcf = pn.curr().get_long(MOV_CODCF); if (tipocf < 'C') // Nei pagamenti la prima nota non scrive TIPO e CODCF in testata, per cui... { workstring = recrighe.get(3); workstring << '|' << recrighe.get(4); tipocf = cache().get(LF_PCON, workstring, PCN_TMCF)[0]; if (tipocf >= 'C') codcf = atol(recrighe.get(5)); } //procedura per stringare il codice clifo if (tipocf >= 'C' && codcf > 0L) { workstring.cut(0) << tipocf; recrighe.add(workstring, 6); // tipocf workstring.format("%ld", codcf); recrighe.add(workstring, 7); // codcf } else { recrighe.add(EMPTY_STRING, 6); // tipocf recrighe.add(EMPTY_STRING, 7); // codcf } recrighe.add(pn.curr().get(RMV_DESCR), 8); //descrizione recrighe.add(imp.valore().string(), 9); //importo //procedura per ricavare la voce di spesa const TString& vocespesa = get_vocespesa(zio); recrighe.add(vocespesa, 16); //e finalmente scrive le righe avanzate... trasfilerighe->write(recrighe); } } //---- righe iva ---- //adesso tocca alle righe iva...e sara' un casino indicibile! //assoc array contenente tutti i diversi conti che incontrera' nello scanning delle righe iva TAssoc_array conti; //causale del movimento: serve per conoscere il tipo di detraibilita' dell'iva (piu' sotto) const TCausale caus(pn.curr().get(MOV_CODCAUS)); const int anno = pn.curr().get_date(MOV_DATAREG).year(); real imp_detr, iva_detr, imp_indetr, iva_indetr; //scanning delle righe iva alla ricerca dei conti che compaiono for (int l = 0; l < pn.iva_items(); l++) { //prende il conto e lo mette nell'assoc_array dei conti (notare che, essendo un assoc_array,.. //..non vengono inseriti doppioni! mitico!!) TBill conto; conto.get(pn.iva(l)); const char* codconto = conto.string(0x8); //ad ogni conto lega un assoc_array (codivae) che conterra' tutti i codici iva legati a quel.. //..conto nelle righe iva con i relativi importi TAssoc_array* codivae = (TAssoc_array*) conti.objptr(codconto); if (codivae == NULL) //se non esiste l'assoc_array legato al conto lo crea { codivae = new TAssoc_array; //aggiunge all'assoc_array conti il suo elemento assoc_array codivae..ha un assoc_array.. //..di assoc_array! conti.add(codconto, codivae); } const TString4 codiva = pn.iva(l).get(RMI_CODIVA); //prende il codice iva dalla riga iva //aggiungere qui eventuale codice intero di indetraibilita' //ad ogni codiva presente in codivae lega un importo che risultera' la somma di tutti gli.. //..importi con lo stesso conto e codice iva real* tot_imp = (real*) codivae->objptr(codiva); if (tot_imp == NULL) //se non esiste l'importo legato al codice iva lo crea { tot_imp = new real; //aggiunge all'assoc_array codivae il suo elemento real tot_imp codivae->add(codiva, tot_imp); } //accresce l'importo tot_imp relativo alla coppia codiva+codconto corrente const real imponibile = pn.iva(l).get_real(RMI_IMPONIBILE); const real imposta = pn.iva(l).get_real(RMI_IMPOSTA); const TString4 codind = pn.iva(l).get(RMI_TIPODET); pn.analizza_riga_IVA(imponibile, imposta, caus, anno, codiva, codind, imp_detr, iva_detr, imp_indetr, iva_indetr); *tot_imp += imp_detr + imp_indetr + iva_indetr; //aggiungere qui eventuale imposta } TRecord_text recrigheiva; //istanzia il tipo record corretto da scrivere sul trasfilerighe recrigheiva.set_type("I"); int nrighe = 0; TRelation rel_rmoviva(LF_RMOVIVA); rel_rmoviva.add(LF_MOV, "NUMREG==NUMREG"); TCursor cur_rmoviva(&rel_rmoviva); cur_rmoviva.curr(LF_MOV) = cur.curr(); const long analrigheiva_items = analmov.body().rows(); for (int n = 1; n <= analrigheiva_items; n++) { //scanning delle righe analitiche per estrarne i conti e controllare se compaiono nell'assoc_array.. //..dei conti riempito con i conti trovati nelle righe iva const TRectype& riga = analmov.body().row(n); const TString& codconto = riga.get(RMOVANA_CODCONTO); TAssoc_array* codivae = (TAssoc_array*) conti.objptr(codconto); //assoc_array codivae del codconto //se ha almeno un codice iva associato a questo conto nell'assoc_array dei conti.. if (codivae != NULL) { //..prende l'importo della riga analitica.. real importo_riga = riga.get_real(RMOVANA_IMPORTO); //..lo ridistribuisce secondo le percentuali iva TGeneric_distrib distributore(importo_riga, TCurrency::get_firm_dec()); FOR_EACH_ASSOC_OBJECT((*codivae), h, k, imp) { const real& imp_iva = *(real*)imp; distributore.add(imp_iva); } //crea una riga iva dal cursore, con numreg = numreg della testata del mov originale TRectype& rigaiva = cur_rmoviva.curr(LF_RMOVIVA); rigaiva.put(RMI_NUMREG, pn.curr().get(MOV_NUMREG)); //scan dell'assoc_array ridistribuito e inserimento dei valori nella riga iva appena creata FOR_EACH_ASSOC_OBJECT((*codivae), hi, ki, impi) { rigaiva.put(RMI_NUMRIG, ++nrighe); rigaiva.put(RMI_GRUPPO, codconto.mid(0,3)); rigaiva.put(RMI_CONTO, codconto.mid(3,3)); rigaiva.put(RMI_SOTTOCONTO, codconto.mid(6,6)); const TBill zio(rigaiva); rigaiva.put(RMI_TIPOC, zio.tipo()); rigaiva.put(RMI_IMPONIBILE, distributore.get()); rigaiva.put(RMI_CODIVA, ki); //deve sottrarre gli importi trovati dalle righe iva originali sottrai_iva(pn, rigaiva); //scrittura delle righe di tipo I; notare che il cur passato alla autoload altri non e'.. //..che la rigaiva appena completata trasfilerighe->autoload(recrigheiva, cur_rmoviva); //procedura ignorante per stringare il codice clifo if (zio.tipo() > ' ') { const long sottoconto = zio.sottoconto(); TString cf; cf.format("%ld", sottoconto); recrigheiva.add(cf, 7); } recrigheiva.add(riga.get(RMOVANA_DESCR).left(40), 8); //descrizione riga iva = riga anale corrente recrigheiva.add(riga.get(RMOVANA_CODCMS), 13); //commessa presa dalla riga analitica corrente //procedura per scrivere la fase che deve essere spezzata in due per sottoprogetto ed edizione const TString& codfase = riga.get(RMOVANA_CODFASE); if (codfase.full()) { recrighe.add(codfase.left(4), 14); recrighe.add(codfase.mid(4,4), 15); } //procedura per ricavare la voce di spesa TString uncle = zio.string(0x8); const TString& vocespesa = get_vocespesa(uncle); recrighe.add(vocespesa, 16); trasfilerighe->write(recrigheiva); } } //if(codivae!=.. } //for(analmov.rows.. const long righeiva_items = pn.iva_items(); if (righeiva_items > 0) { //deve trasferire le righe iva rimaste dopo la sottrazione degli importi dovuti alle righe analitiche for (int m = 0; m < righeiva_items; m++) { const TRectype& riga = pn.iva(m); if (!riga.get_real(RMI_IMPOSTA).is_zero()) { const TBill uncle(riga); cur_rmoviva.curr() = riga; trasfilerighe->autoload(recrigheiva, cur_rmoviva); recrigheiva.add(uncle.tipo(), 6); //tipocf recrigheiva.add(uncle.descrizione().left(40), 8); //descrizione della riga iva = descrizione conto //procedura per ricavare la voce di spesa TString zio = uncle.string(0x8); const TString& vocespesa = get_vocespesa(zio); recrighe.add(vocespesa, 14); trasfilerighe->write(recrigheiva); } } } return true; } bool TInvioP::sottrai_iva(TMovimentoPN& pn, const TRectype& rigaiva) { const TBill zio(rigaiva); const real imposta = rigaiva.get_real(RMI_IMPOSTA); int k; //caso fortunato //scandisce gli elementi dell'array;se ne trova uno (k-esimo) con conto ed importo coincidenti.. //..con quelli passati al metodo, azzera l'importo di tale elemento dell'array for (k = 0; k < pn.iva_items(); k++) { TRectype& iva_k = pn.iva(k); const TBill conto_k(iva_k); const real imposta_k = iva_k.get_real(RMI_IMPOSTA); if (conto_k == zio && imposta_k == imposta) { iva_k.zero(RMI_IMPOSTA); return true; } } //caso sfortunato //in questo caso gli importi dell'elemento k-esimo dell'array e passato al metodo NON coincidono real residuo = imposta; int ultima_riga_buona = -1; for (k = 0; k < pn.iva_items() && !residuo.is_zero(); k++) { TRectype& iva_k = pn.iva(k); const TBill conto_k(iva_k); if (conto_k == zio) { const real imposta_k = iva_k.get_real(RMI_IMPOSTA); if (residuo >= imposta_k) { residuo -= imposta_k; iva_k.zero(RMI_IMPOSTA); } else { iva_k.put(RMI_IMPOSTA, imposta_k - residuo); residuo = ZERO; } ultima_riga_buona = k; } } //alla fine del ciclo sull'array resta un residuo non nullo.. if (!residuo.is_zero()) { if (ultima_riga_buona >= 0) { TRectype& iva_k = pn.iva(k); iva_k.put(RMI_IMPOSTA, -residuo); } } return true; } void TInvioP::stringa_grcosot(TRecord_text& recrighe, const TString& zio) { TString8 grcosot; long gcs = 0; gcs = atoi(zio.left(3)); grcosot.format("%d", gcs); recrighe.add(grcosot, 3); //gruppo gcs = atoi(zio.mid(3,3)); grcosot.format("%d", gcs); recrighe.add(grcosot, 4); //conto gcs = atoi(zio.mid(6,6)); grcosot.format("%d", gcs); recrighe.add(grcosot, 5); //sottoconto } // Calcola il totale del documento tenendo conto del segno della prima riga e di quella delle // ritenute sociali sulla causale real TInvioP::totale_documento(TMovimentoPN& pn, const bool includi_ritenute) const { //testata del movimento di prima nota const TRectype& mov = pn.curr(); real tot = mov.get_real(MOV_TOTDOC); // Legge totale //i conti sulle ritenute li deve fare solo se il movimento e' iva!! if (pn.iva_items() > 0) { if (includi_ritenute) { 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; } } } else //movimenti non iva; calcolo delle ritenute { TCausale caus(mov.get(MOV_CODCAUS)); const char sez = caus.sezione_clifo(); bool tot_is_zero = tot.is_zero(); TImporto totdoc(sez, tot); for (int i = 0; i < pn.cg_items(); i++) { const TRectype& rmov = pn.cg(i); const TBill conto(rmov); const TImporto importo(rmov.get_char(RMV_SEZIONE), rmov.get_real(RMV_IMPORTO)); if (tot_is_zero && rmov.get_char(RMV_TIPOC) > ' ') totdoc += importo; else { if (includi_ritenute && (cerca_fiscali(conto) || cerca_sociali(conto))) totdoc += importo; //valore da stampare nella colonna Tot.fattura con ritenute } } tot = totdoc.valore(); } return tot; } // Controlla sulla causale se il segno del totale documento (ritsoc=FALSE) // o quello delle ritenute sociali (ritsoc=TRUE) e' invertito rispetto al normale bool TInvioP::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; } bool TInvioP::cerca_conto(const TBill& bill, const TAssoc_array& assoc, const char tipoconto) const { TToken_string key(15); key.add(tipoconto); //il primo char della tokenstring e' il tipoconto (Fiscale o Sociale) 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 TInvioP::cerca_costo(const TBill& bill) const { return cerca_conto(bill, _costi, 'C') ? 1 : 0; } int TInvioP::cerca_pagamento(const TBill& bill) const { return cerca_conto(bill, _pagamenti, 'P') ? 2 : 0; } bool TInvioP::cerca_fiscali(const TBill& bill) const { if (bill.tipo() > ' ') //non si vogliono i conti tipo Cliente Fornitore return false; return cerca_conto(bill, _fiscali, 'F'); } bool TInvioP::cerca_sociali(const TBill& bill) const { if (bill.tipo() > ' ') //non si vogliono i conti tipo Cliente Fornitore return false; return cerca_conto(bill, _sociali, 'S'); } void TInvioP::lettura_conti(TAssoc_array& assoc, const char tipoconto) { TConfig conti("ca3600a.ini","Pdcc"); //paragrafo da scandire nell'ini 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); } } void TInvioP::calcola_imposte(const real& importo, const real& imposta, const TString& codind, real& iva_det, real& iva_ind) const { iva_det = imposta; iva_ind = ZERO; //esiste un codice di indetraibilita'? if (codind.full()) { real perc = ZERO; const TRectype& rec = cache().get("%DET", codind); if (rec.empty()) { if (strchr("139", codind[0]) != NULL) // Clausola di salvaguardia perc = CENTO; } else { if (rec.get_int("I0") > 0) perc = rec.get_real("R0"); } if (perc > ZERO) // C'è indetraibilità? { //valori delle varie ive if (perc < CENTO) { iva_ind = imposta * perc / CENTO; iva_ind.round(2); iva_det = imposta - iva_ind; } else { iva_ind = imposta; iva_det = ZERO; } } } } bool TInvioP::calcola_imponibile_totdoc(const long nreg, const TRectype& pag_rec, real& imponibile, real& totdoc, real& totpagato, real& iva_indetraibile) const { totpagato = pag_rec.get_real(PAGSCA_IMPORTO); TMovimentoPN pn; pn.curr().put(MOV_NUMREG, nreg); bool ok = nreg > 0 && pn.read() == NOERR; if (ok) { //percentuale di pagamento sul totale documento senza ritenute const real totdoc_no_rit = totale_documento(pn, false); const real perc_ritenute = totpagato / totdoc_no_rit; //Movimenti CON SALDACONTO //se movimento IVA.. if (pn.iva_items() > 0) { real imposta; const TRectype& movfat = pn.curr(); real ritfis = movfat.get_real(MOV_RITFIS); //ritenute sulla fattura: verranno pagate percentualmente if (perc_ritenute < UNO) { ritfis *= perc_ritenute; ritfis.round(2); } totpagato += pag_rec.get_real(PAGSCA_RITENUTE); //ritenute eventuali sul pagamento totpagato += ritfis; //Le ritenute sociali invece vanno testate con la test_swap.. real ritsoc = movfat.get_real(MOV_RITSOC); if (perc_ritenute < UNO) { ritsoc *= perc_ritenute; ritsoc.round(2); } ritsoc += pag_rec.get_real(PAGSCA_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; } for (int i = 0; i < pn.iva_items(); i++) { const TRectype& rmoviva = pn.iva(i); const TBill conto(rmoviva); if (conto.indicatore_bilancio() != 5) { const real importo = rmoviva.get_real(RMI_IMPONIBILE); const real iva = rmoviva.get_real(RMI_IMPOSTA); //trattamento delle ive indetraibili! const TString& codind = rmoviva.get(RMI_TIPODET); imponibile += importo; real iva_det, iva_ind; //calcola i valori dell'iva detraibile e delle ive indetraibili in diverse percentuali calcola_imposte(importo, iva, codind, iva_det, iva_ind); //se esiste un'iva indetraibile.. if (!iva_ind.is_zero()) { iva_indetraibile += iva_ind; imponibile += iva_ind; } //l'iva detraibile va sempre bene sommata alle imposte imposta += iva_det; } } totdoc = totale_documento(pn); //tot doc con ritenute fiscali + ritenute sociali } //if pn.iva_items().. else //NON iva { totdoc = totale_documento(pn); //tot doc con ritenute fiscali + ritenute sociali imponibile = totdoc; //nel caso di non iva TCausale caus(pn.curr().get(MOV_CODCAUS)); TImporto totpag(caus.sezione_clifo(), totpagato); for (int i = 0; i < pn.cg_items(); i++) { const TRectype& rmov = pn.cg(i); const TBill conto(rmov); if (cerca_fiscali(conto) || cerca_sociali(conto)) { real imp = rmov.get_real(RMV_IMPORTO); if (perc_ritenute < UNO) { imp *= perc_ritenute; imp.round(2); } const TImporto importo(rmov.get_char(RMV_SEZIONE), imp); totpag += importo; //valore da stampare nella colonna Tot.fattura con ritenute } } totpagato = totpag.valore(); } } //if (pn.read() == NOERR return ok; } real TInvioP::calcola_pagamento(TRectype& curpag_rec, real& iva_indetraibile) { //deve costruirsi la riga di partita che riguarda il documento di origine //per prima cosa crea tale riga a partire dal pagamento, che ha una chiave lunghissima... TToken_string key_part; key_part.add(curpag_rec.get(PAGSCA_TIPOC)); key_part.add(curpag_rec.get(PAGSCA_GRUPPO)); key_part.add(curpag_rec.get(PAGSCA_CONTO)); key_part.add(curpag_rec.get(PAGSCA_SOTTOCONTO)); key_part.add(curpag_rec.get(PAGSCA_ANNO)); key_part.add(curpag_rec.get(PAGSCA_NUMPART)); key_part.add(curpag_rec.get(PAGSCA_NRIGA)); //..ecco il record delle partite.. const TRectype& rec_partite = cache().get(LF_PARTITE, key_part); //..da cui prende nreg const long nreg = rec_partite.get_long(PART_NREG); //se nreg esiste... //dichiariamo una serie di simpatici real utilizzati in seguito real totdoc,imponibile,totpagato; if (calcola_imponibile_totdoc(nreg, curpag_rec, imponibile, totdoc, totpagato, iva_indetraibile)) { const real percentuale = totpagato /totdoc; //cerca se esiste una fattura da ricevere anteriore alla fattura da pagare const long fdr = calcola_fattura_originale(nreg); //se la trova deve tenerne conto in quanto la presente fattura (nreg) potrebbe pagare solo.. //..una parte della fdr originale if (fdr != nreg) { real imponibile_fdr, totdoc_fdr, totpagato_fdr, iva_indetraibile_fdr; //riutilizza la calcola_imponibile_totdoc per l'fdr;si fa notare che in questo caso gli.. //..ultimi due parametri del metodo sono del tutto inutili if (calcola_imponibile_totdoc(fdr, curpag_rec, imponibile_fdr, totdoc_fdr, totpagato_fdr, iva_indetraibile_fdr)) { const real rapporto_pagati = totdoc / totdoc_fdr; const real rapporto_imponibili = imponibile_fdr / imponibile; //la fattura con totdoc paga una parte di una precedente fdr con totdoc maggiore! //in questo caso totpagato e' quello della fattura e deve uscire senza ricalcolare.. //..percentuali e cazzi vari (funziona ststisticamente!) if (rapporto_pagati >= 0.7) imponibile = imponibile_fdr; if (rapporto_imponibili < 0.7 || rapporto_imponibili > 0.85) iva_indetraibile = ZERO; } } //if(fdr!=nreg.. else //se non esiste una fdr eventuali ive indetraibili non sussistono iva_indetraibile = ZERO; //calcolo finale del pagato totpagato = imponibile * percentuale; totpagato.round(2); } //if(calcola_imponibile_totdoc(nreg,... return totpagato; } long TInvioP::calcola_fattura_originale(long nreg) const { //prende il movimento del pagamento const TRectype& mov = cache().get(LF_MOV, nreg); TToken_string key; key.add(mov.get(MOV_DCODNUM)); key.add(mov.get(MOV_DANNO)); key.add(mov.get(MOV_DPROVV)); key.add(mov.get(MOV_DNDOC)); //crea il documento da cui deriva tale movimento (per il CSA e' in genere una fattura) TRecord_array doc(key, LF_RIGHEDOC); for (int i = 1; i <= doc.rows(); i++) { const TRectype& rdoc = doc.row(i); const TString& dacodnum = rdoc.get(RDOC_DACODNUM); if (dacodnum.full()) { const TRectype& num_rec = cache().get("%NUM", dacodnum); if (num_rec.get_bool("B3")) { key = rdoc.get(RDOC_DAPROVV); key.add(rdoc.get(RDOC_DAANNO)); key.add(dacodnum); key.add(rdoc.get(RDOC_DANDOC)); //cerca da quale documento deriva la fattura (la prima riga che trova e' ok) const TRectype& original_doc = cache().get(LF_DOC, key); //se trova il documento origine (per il CSA e' in genere una FDR) -> prende il suo nreg.. //..come nreg da ritornare (attenzione che se il doc originale non e' stato contabilizzato.. //..nreg diventa 0!) if (!original_doc.empty()) { nreg = original_doc.get_long(DOC_NUMREG); } } break; } } return nreg; } // oggetto che serve per memorizzare importo e flag acc/sal dei pagamenti.. //..(usato nel trasferimento pagamenti) struct TPay_info : public TObject { real _somma; char _as; }; bool TInvioP::i_proforma_pagamenti() { TInvioP_file* trasfilepag = apri_file("pagament"); TRectype da(LF_MOV); TRectype a(LF_MOV); da.put(MOV_DATAREG, _dataini); a.put(MOV_DATAREG, _datafin); TRelation rel(LF_MOV); rel.add(LF_CAUSALI, "CODCAUS==CODCAUS"); TCursor cur(&rel, "", 2, &da, &a); const long cur_items = cur.items(); if (cur_items != 0) { //se ha almeno un movimento carica lo sheet dei conti che gli servira' in seguito nel calcolo.. //..delle ritenute lettura_conti(_fiscali, 'F'); lettura_conti(_sociali, 'S'); lettura_conti(_costi, 'C'); lettura_conti(_pagamenti, 'P'); TProgress_monitor pi(cur_items, TR("Trasferimento pagamenti...")); cur.freeze(); TRectype& cur_rec = cur.curr(); for (cur = 0; cur.pos() < cur_items; ++(cur)) { if (!pi.set_status(cur.pos())) break; //pagamenti saldacontati! vedi l'else per quelli non saldacontati const tipo_movimento tipomov = (tipo_movimento)cur_rec.get_int(MOV_TIPOMOV); if (tipomov == tm_pagamento || tipomov == tm_nota_credito || tipomov == tm_pagamento_insoluto) { //attraverso le partite,noto il MOV_NUMREG,riesce a collegarsi al pagamento in LF_PAGSCA TRelation relpart(LF_PARTITE); TRectype da(LF_PARTITE); const long numreg = cur_rec.get_long(MOV_NUMREG); da.put(PART_NREG, numreg); #ifdef DBG if (numreg == 91653) int cazzone = 1; #endif TCursor curpart(&relpart, "", 2, &da, &da); const TRecnotype curpart_items = curpart.items(); //se trova la partita relativa al numreg... if (curpart_items > 0) { curpart.freeze(); TRectype& curpart_rec = curpart.curr(); TRelation relpag(LF_PAGSCA); TRectype da(LF_PAGSCA); //..collega i pagamenti filtrando con i parametri estratti dalle partite for (curpart = 0; curpart.pos() < curpart_items; ++(curpart)) { da.put(PAGSCA_TIPOC, curpart_rec.get(PART_TIPOCF)); da.put(PAGSCA_GRUPPO, curpart_rec.get(PART_GRUPPO)); da.put(PAGSCA_CONTO, curpart_rec.get(PART_CONTO)); da.put(PAGSCA_SOTTOCONTO, curpart_rec.get(PART_SOTTOCONTO)); da.put(PAGSCA_ANNO, curpart_rec.get(PART_ANNO)); da.put(PAGSCA_NUMPART, curpart_rec.get(PART_NUMPART)); const int nrigapart = curpart_rec.get_int(PART_NRIGA); TString80 filtro; filtro.format("NRIGP == %d", nrigapart); TCursor curpag(&relpag, filtro, 1, &da, &da); const TRecnotype curpag_items = curpag.items(); real iva_indet = ZERO; //valore dell'eventuale iva indetraibile //se trova i pagamenti,che sono alla fin fine cio' che cerca... if (curpag_items > 0) { TAssoc_array pagame; pagame.destroy(); curpag.freeze(); TRectype& curpag_rec = curpag.curr(); for (curpag = 0; curpag.pos() < curpag_items; ++(curpag)) { TString80 indice = curpag_rec.get(PAGSCA_ANNO); indice << '|' << curpag_rec.get(PAGSCA_NUMPART); indice << '|' << curpag_rec.get(PAGSCA_NRIGA); TPay_info* pi = (TPay_info*)pagame.objptr(indice); if (pi == NULL) { pi = new TPay_info; pi->_as = 'A'; pagame.add(indice, pi); } //ricava l'importo del pagamento e lo aggiunge al memorizzatore const real importo_pagato = calcola_pagamento(curpag_rec, iva_indet); pi->_somma += importo_pagato; if (curpag_rec.get_char(PAGSCA_ACCSAL) == 'S') pi->_as = 'S'; } // scrive i record risultanti for (TPay_info* pi = (TPay_info*)pagame.first_item(); pi != NULL; pi = (TPay_info*)pagame.succ_item()) { TToken_string keypart; keypart.add(curpart_rec.get(PART_TIPOCF)); keypart.add(curpart_rec.get(PART_GRUPPO)); keypart.add(curpart_rec.get(PART_CONTO)); keypart.add(curpart_rec.get(PART_SOTTOCONTO)); keypart.add(pagame.get_hashobj()->key()); const TRectype& fattura = cache().get(LF_PARTITE, keypart); _nregpag = cur_rec.get_long(MOV_NUMREG); //registrazione del movimento di pagamento //deve cercare la prima registrazione da cui deriva il pagamento.. const long nregfatt = fattura.get_long(PART_NREG); #ifdef DBG if (nregfatt == 91296) int cazzone = 1; #endif _nregcosto = calcola_fattura_originale(nregfatt); _importo = pi->_somma; //acconto/saldo in modo standard _accsal = pi->_as; //Casino plutonico dell'acconto-saldo in ottica CSA //Se il doc in esame discende da una FDR (fattura da ricevere) e' necessario.. //..cercare tutte le righe dei documenti che pagano tale FDR e sommare gli importi di tali.. //..rdocs con quello corrente; solo se tale somma risulatsse >= del totale delle righe.. //..della FDR originale il flag _accsal deve essere messo a saldo 'S' if (_nregcosto != nregfatt) { //deve risalire al documento FDR del movimento _nregcosto const TRectype& mov_fdr = cache().get(LF_MOV, _nregcosto); const TString8 fdr_codnum = mov_fdr.get(MOV_DCODNUM); const int fdr_anno = mov_fdr.get_int(MOV_DANNO); const char fdr_provv = mov_fdr.get_char(MOV_DPROVV); const long fdr_ndoc = mov_fdr.get_long(MOV_DNDOC); //adesso che ha la chiave del documento padre FDR, deve crearsi la query.. //..su RDOC alla ricerca di tutte le righe doc che discendono dall'FDR.. //..In pratica cerca le "sorelle" dell'attuale fattura nregfatt TString query; query << "USE RDOC KEY 4"; query << "\nFROM DACODNUM=" << fdr_codnum << " DAANNO=" << fdr_anno << " DAPROVV=" << fdr_provv << " DANDOC=" << fdr_ndoc; query << "\nTO DACODNUM=" << fdr_codnum << " DAANNO=" << fdr_anno << " DAPROVV=" << fdr_provv << " DANDOC=" << fdr_ndoc; TISAM_recordset recset(query); const int righe_delle_sorelle = recset.items(); TAssoc_array sorelle; TToken_string key; //cerco la mia data di fattura; const TDate datadoc_fattura = cache().get(LF_MOV, nregfatt, MOV_DATAREG); //dalle righe risale ai documenti di tali righe (che posssono essere meno) for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { key = recset.get(RDOC_PROVV).as_string(); key.add(recset.get(RDOC_ANNO).as_string()); key.add(recset.get(RDOC_CODNUM).as_string()); key.add(recset.get(RDOC_NDOC).as_string()); const TDate datadoc = cache().get(LF_DOC, key, DOC_DATADOC); //se non sono l'ultima fattura (sorella piu' giovane) allora e'.. //..sicuramente Acconto! Quindi esce dai cicli for e if if (datadoc > datadoc_fattura) { sorelle.destroy(); _accsal = 'A'; break; } //accresce l'array delle sorelle sorelle.add(key, key); } //tutto il casino s'ha da fare solo in caso ci sia piu' di una fattura.. //.."sorella" di quella in esame if (sorelle.items() > 1) { real importo_totale_sorelle; //giro su tutti i documenti delle sorelle FOR_EACH_ASSOC_OBJECT(sorelle, obj, chiave, itm) { TToken_string& ts = *(TToken_string*)itm; TDocumento sorella(ts.get_char(0), ts.get_int(1), ts.get(2), ts.get_long(3)); //per ogni documento deve cercare le righe discendenti dall'FDR for (int r = 1; r <= sorella.rows(); r++) { const TRiga_documento nipotina = sorella[r]; //servono solo le righe discendenti dall'FDR madre! if (nipotina.get(RDOC_DACODNUM) == fdr_codnum && nipotina.get_int(RDOC_DAANNO) == fdr_anno && nipotina.get_char(RDOC_DAPROVV) == fdr_provv && nipotina.get_long(RDOC_DANDOC) == fdr_ndoc) { const real importo_da_aggiungere = nipotina.importo(true, false); //importo scontato netto importo_totale_sorelle += importo_da_aggiungere; } } } //FOR_EACH_ASSOC.. //Se arriva fin qui la fattura in esame e' la sorella piu' giovane; adesso.. //..deve controllare se gli importi di tutte le sorelle sommati saldano.. //..o meno l'importo dell'originale mamma FDR... //intanto ha bisogno del totale documento FDR originale a partire dal movimento FDR... real totale_fdr = ZERO; TMovimentoPN movimento_fdr; movimento_fdr.curr().put(MOV_NUMREG, _nregcosto); if (movimento_fdr.read() == NOERR) totale_fdr = totale_documento(movimento_fdr, false); //non include ritenute real rimanenza = totale_fdr - importo_totale_sorelle; //arrotonda rimanenza.round(); //Se l'importo e' inferiore la FDR non e' ancora stata saldata (nasceranno.. //..una o piu' sorelle per saldare mamma FDR in futuro) if (rimanenza > ZERO) _accsal = 'A'; //Se l'importo e' >= -> la mamma e' saldata e non sono previste ulteriori.. //..sorelle (per la felicita' del papa'!) else _accsal = 'S'; } //if(sorelle.items()>1.. } //if(_nregcosto!=nregfatt.. //..e finalmente scrive 'sta minchia di riga TRecord_text recpag; recpag.set_type("G"); trasfilepag->autoload(recpag, curpag); trasfilepag->write(recpag); //se ha una riga di iva indetraibile dovuta al cambio regime fiscale 2005->2006.. //..deve aggiungere una ulteriore riga!! if (iva_indet > ZERO) { _nregcosto = nregfatt; _importo = iva_indet; _accsal = 'S'; recpag.set_type("G"); trasfilepag->autoload(recpag, curpag); trasfilepag->write(recpag); } } //for( }//if curpag_items.. }//for curpart =.. }//if curpart_items.. }//if tipomov ==.. if (tipomov == tm_nessuno) //tocca ai pagamenti NON saldacontati (procedura analoga a quella della stampa del pagato) { const long numregcg = cur_rec.get_long(MOV_NUMREG); //cerca un record di MOVANA che abbia numregcg = nreg;usa il nuovo metodo fighissimo.. //..con la isam query TString& query = get_tmp_string(); query << "USE MOVANA KEY 3\n"; query << "FROM NUMREGCG=" << numregcg << "\n"; query << "TO NUMREGCG=" << numregcg; TISAM_recordset movana(query); const TRecnotype items = movana.items(); if (items > 0) { if (items > 1) error_box(FR("Esiste più d'un movimento analitico collegato al movimento contabile %ld"), numregcg); movana.move_last(); //si posiziona sul record corretto //crea il movana legato al mov const TAnal_mov anal_mov(cur_rec); 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]; //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; default:break; } _nregpag = numregcg; _nregcosto = numregcg; _importo = imp.valore(); //deve stabilire adesso se acconto o saldo controllando gli importi _accsal = 'S'; //e finalmente aggiunge il record al file di esportazione TRecord_text recpag; recpag.set_type("G"); trasfilepag->autoload(recpag, *movana.cursor()); trasfilepag->write(recpag); } //if (tipo > 0.. } //for(j0... } //else if tipomov ==.. }//for cur =.. }//if cur_items.. chiudi_file(trasfilepag); return true; } bool TInvioP::i_proforma_clifor(char tipocf) { TInvioP_file* trasfile = NULL; TString progind_string = TR("Trasferimento "); if (tipocf == 'C') { trasfile = apri_file("clienti"); progind_string << TR("clienti"); } else { trasfile = apri_file("fornit"); progind_string << TR("fornitori"); } TString16 filtro; filtro.format("TIPOCF==\"%c\"", tipocf); TRelation rel(LF_CLIFO); rel.add(LF_COMUNI, "STATO==STATOCF|COM==COMCF", 1); TCursor cur(&rel, filtro); const long cur_items = cur.items(); if (cur_items != 0) { cur.freeze(); TRectype& cur_rec = cur.curr(); progind_string << "..."; TProgress_monitor pi(cur_items, progind_string); for (cur = 0; cur.pos() < cur_items; ++cur) { TRecord_text rec; rec.set_type("C"); trasfile->autoload(rec, cur); trasfile->write(rec); if (!pi.add_status()) break; } } chiudi_file(trasfile); return true; } //"metodo dei metodi":in base ai parametri della maschera esegue la procedura indicata void TInvioP::invio_proforma() { if (_msk->get_bool(F_MOVIMENTI)) i_proforma_movimenti(); if (_msk->get_bool(F_PAGAMENTI)) i_proforma_pagamenti(); if (_msk->get_bool(F_CLIENTI)) i_proforma_clifor(); if (_msk->get_bool(F_FORNITORI)) i_proforma_clifor('F'); if (_msk->get_bool(F_CONTI)) i_proforma_conti(); } bool TInvioP::create() { //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) return error_box(TR("Il programma funziona SOLO se in contabilità analitica si usa il piano dei conti contabile")); _msk = new TInvioP_mask(); _configfile = new TConfig("tc9100a.ini"); return TSkeleton_application::create(); } bool TInvioP::destroy() { if (_configfile != NULL) delete _configfile; if (_msk != NULL) delete _msk; return TSkeleton_application::destroy(); } void TInvioP::main_loop() { TFilename configname = "tc9100conf.ini"; //file configurazione della maschera configname.custom_path(); TConfig configfile(configname); _msk->set(F_DATAINI, configfile.get("DATA","OPZIONI")); _msk->set(F_DESTINAZIONE, configfile.get("PERCORSO","OPZIONI")); while (_msk->run()!=K_QUIT) { configfile.set("DATA", _msk->get_date(F_DATAFIN),"OPZIONI"); configfile.set("PERCORSO", _msk->get(F_DESTINAZIONE),"OPZIONI"); _dataini = _msk->get_date(F_DATAINI); _datafin = _msk->get_date(F_DATAFIN); const char tipoinvio = _msk->get(F_TIPOINVIO)[0]; if (tipoinvio == 'P') invio_proforma(); //dopo aver preso i parametri dalla maschera chiama il "metodo dei metodi" } } int tc9100(int argc, char **argv) { TInvioP a; a.run(argc, argv, TR("Invio dati contabilità a Proforma")); return 0; }