diff --git a/tc/tc0701.cpp b/tc/tc0701.cpp index 31b690a1e..8257179a7 100755 --- a/tc/tc0701.cpp +++ b/tc/tc0701.cpp @@ -286,7 +286,8 @@ TTS_textset::TTS_textset(const char* query) TString80 field; // dati iva - for (int i=0; i<8; i++) + int i; + for (i = 0; i < 8; i++) { field.format("TRF-IMPONIB_%d", i); add_field("0", field, 12, n, 475+(31*i)); // imponibile @@ -304,7 +305,7 @@ TTS_textset::TTS_textset(const char* query) add_field("0", "TRF-TOT-FATT", 12, n, 723); // totale fattura // conti di ricavo/costo - for (i=0; i<8; i++) + for (i = 0; i < 8; i++) { field.format("TRF-CONTORIC_%d", i); add_field("0", field, 7, n, 735+(19*i)); // codice conto di ricavo/costo @@ -319,7 +320,7 @@ TTS_textset::TTS_textset(const char* query) add_field("0", "TRF-CAU-AGG-2-PAGAM", 34, an, 939); // ulteriore descrizione aggiuntiva // altri movimenti - for (i=0; i<80; i++) + for (i = 0; i < 80; i++) { field.format("TRF-CONTO_%d", i); add_field("0", field, 7, n, 973+(64*i)); // codice conto @@ -338,7 +339,7 @@ TTS_textset::TTS_textset(const char* query) } // ratei e risconti - for (i=0; i<10; i++) + for (i = 0; i < 10; i++) { field.format("TRF-RIFER-TAB_%d", i); add_field("0", field, 1, an, 6093+(19*i)); // tabella di riferimento @@ -358,7 +359,7 @@ TTS_textset::TTS_textset(const char* query) add_field("0", "TRF-AN-TIPO-SOGG", 1, n, 6290); // tipo soggetto ritenuta di acconto // ulteriori dati ev. pagamento o movimenti diversi - for (i=0; i<80; i++) + for (i = 0; i < 80; i++) { field.format("TRF-EC-PARTITA-SEZ-PAG_%d", i); add_field("0", field, 2, n, 6291+(2*i)); // numero sezionale partita estratto conto @@ -374,13 +375,13 @@ TTS_textset::TTS_textset(const char* query) add_field("0", "TRF-RIT-4", 12, n, 6526); // 4 // ulteriori dati per unita' produttive ricavi - for (i=0; i<8; i++) + for (i = 0; i < 8; i++) { field.format("TRF-UNITA-RICAVI_%d", i); add_field("0", field, 2, n, 6538+(2*i)); // } // ulteriori dati per unita' produttive pagamenti - for (i=0; i<80; i++) + for (i = 0; i < 80; i++) { field.format("TRF-UNITA-PAGAM_%d", i); add_field("0", field, 2, n, 6554+(2*i)); // diff --git a/tc/tc9.cpp b/tc/tc9.cpp index 6e4d29eb6..29b1a063d 100755 --- a/tc/tc9.cpp +++ b/tc/tc9.cpp @@ -7,8 +7,8 @@ int main(int argc, char** argv) const int op = argc < 2 ? 0 : argv[1][1]-'0'; switch (op) { - case 0: tc9100(argc,argv); break; // esiste sulla 4.0 Invio a Proforma - case 1: tc9200(argc,argv); break; // esiste dalla 4.0 Invio a Sispac/Cosmo + case 0: tc9100(argc,argv); break; // Invio a Proforma + case 1: tc9200(argc,argv); break; // Invio a Sispac/Cosmo default: tc9100(argc,argv); break; } exit(0); diff --git a/tc/tc9100.cpp b/tc/tc9100.cpp index 1673b64b7..4846ae79d 100755 --- a/tc/tc9100.cpp +++ b/tc/tc9100.cpp @@ -1,7 +1,1626 @@ -//NON riportare nulla!!!! Esiste dalla 4.0; qui e' solo un segnaposto +#include +#include +#include +#include +#include +#include + #include "tc9.h" +#include "tc9100a.h" + +#include +#include + +#include "../cg/cg2101.h" +#include "../cg/cg2103.h" +#include "../cg/cgsaldac.h" + +#include "../ca/calib01.h" +#include "../ca/movana.h" +#include "../ca/rmovana.h" +#include "../ve/velib.h" + +#include +#include + + +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); + virtual ~TInvioP_file() { } +}; + +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); + + const TString tipocf = pn.curr().get(MOV_TIPO); + recrighe.add(tipocf, 6); //tipocf + + //procedura per stringare il codice clifo + if (tipocf > ' ') + { + const long codcf = pn.curr().get_long(MOV_CODCF); + TString cf; + cf.format("%ld", codcf); + recrighe.add(cf, 7); //codcf + } + else + { + recrighe.add("", 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 +{ + if (cerca_conto(bill, _costi, 'C')) + return 1; + else + return 0; +} + +int TInvioP::cerca_pagamento(const TBill& bill) const +{ + if (cerca_conto(bill, _pagamenti, 'P')) + return 2; + else + return 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"); + } + //valori delle varie ive + iva_ind = imposta * perc / CENTO; + iva_ind.round(2); + iva_det = imposta - iva_ind; + } +} + +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 != 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'); + + TProgind pi(cur_items, "Trasferimento pagamenti...", true, true); + + cur.freeze(); + TRectype& cur_rec = cur.curr(); + for (cur = 0; cur.pos() < cur_items; ++(cur)) + { + if (!pi.addstatus(1)) + 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); + da.put(PART_NREG, cur_rec.get(MOV_NUMREG)); + TCursor curpart(&relpart, "", 2, &da, &da); + const long 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 long 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); + _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(TR("Esiste piu' di 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 = "Trasferimento "; + + if (tipocf == 'C') + { + trasfile = apri_file("clienti"); + progind_string << "clienti"; + } + else + { + trasfile = apri_file("fornit"); + progind_string << "fornitori"; + } + + TString80 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) + { + progind_string << "..."; + TProgind pi(cur_items, progind_string, 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("C"); + trasfile->autoload(rec, cur); + trasfile->write(rec); + } + } + 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() +{ + _msk = new TInvioP_mask(); + _configfile = new TConfig("tc9100a.ini"); + return TSkeleton_application::create(); +} + +bool TInvioP::destroy() +{ + if (_configfile != NULL) + delete _configfile; + delete _msk; + + return TSkeleton_application::destroy(); +} + +void TInvioP::main_loop() +{ + //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; + } + + 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) { - return 0; + TInvioP a; + a.run(argc, argv, "Invio dati contabilità a Proforma"); + + return 0; } diff --git a/tc/tc9100a.h b/tc/tc9100a.h index dbc9d777a..4f35bf6a5 100755 --- a/tc/tc9100a.h +++ b/tc/tc9100a.h @@ -1,15 +1,23 @@ // invio dati ad altra procedura (Proforma) -#define F_CODDITTA 101 -#define F_RAGSOC 102 -#define F_MOVIMENTI 103 -#define F_CLIENTI 104 -#define F_FORNITORI 105 -#define F_CONTI 106 -#define F_PAGAMENTI 107 -#define F_TIPOINVIO 108 -#define F_DESTINAZIONE 109 -#define F_DATAINI 110 -#define F_DATAFIN 111 -#define F_RIPRISTINA 112 -#define F_DATARIPRISTINO 113 +#define F_CODDITTA 301 +#define F_RAGSOC 302 +#define F_MOVIMENTI 303 +#define F_CLIENTI 304 +#define F_FORNITORI 305 +#define F_CONTI 306 +#define F_PAGAMENTI 307 +#define F_TIPOINVIO 308 +#define F_DESTINAZIONE 309 +#define F_DATAINI 310 +#define F_DATAFIN 311 +#define F_RIPRISTINA 312 +#define F_DATARIPRISTINO 313 + +#define F_PDCC 315 + +#define S_TIPO 101 +#define S_GRUPPO 102 +#define S_CONTO 103 +#define S_SOTTOCONTO 104 +#define S_DESCRIZIONE 105 diff --git a/tc/tc9100a.ini b/tc/tc9100a.ini index 0ed66a8db..892943b26 100755 --- a/tc/tc9100a.ini +++ b/tc/tc9100a.ini @@ -7,3 +7,426 @@ SKIPLINES = 0 TYPEFIELD = -1 TYPELEN = -1 TYPEPOS = -1 + +[TYPE STRINGA] +ALIGN = L +DATA = S +DECIMAL = 0 +FILLER = ' ' +LENGTH = 0 +PICTURE = + +[TYPE NUMERO] +ALIGN = R +DATA = N +DECIMAL = 0 +FILLER = '0' +PICTURE = + +[TYPE DATA] +ALIGN = +DATA = D +DECIMAL = 0 +FILLER = '0' +LENGTH = 8 +PICTURE = 1444 + +[TYPE IMPORTO] +ALIGN = R +DATA = N +DECIMAL = 2 +FILLER = '0' +LENGTH = 14 +PICTURE = @@@@@@@@@,@@ + +[RECORD T] + +NAME(0) = ID REGISTRAZIONE +TYPE(0) = NUMERO +POSITION(0) = 0 +LENGTH(0) = 10 +FIELD(0) = NUMREG + +NAME(1) = DATA REGISTRAZIONE +TYPE(1) = DATA +POSITION(1) = 10 +LENGTH(1) = 8 +FIELD(1) = DATAREG + +NAME(2) = CODICE CAUSALE +TYPE(2) = STRINGA +POSITION(2) = 18 +LENGTH(2) = 3 +FIELD(2) = CODCAUS + +NAME(3) = DESCRIZIONE CAUSALE +TYPE(3) = STRINGA +POSITION(3) = 21 +LENGTH(3) = 40 +FIELD(3) = 26->DESCR[1,40] + +NAME(4) = DESCRIZIONE TESTATA +TYPE(4) = STRINGA +POSITION(4) = 61 +LENGTH(4) = 240 +FIELD(4) = DESCR[1,40] + +NAME(5) = DATA DOCUMENTO +TYPE(5) = DATA +POSITION(5) = 301 +LENGTH(5) = 8 +FIELD(5) = DATADOC + +NAME(6) = NUMERO DOCUMENTO +TYPE(6) = STRINGA +POSITION(6) = 309 +LENGTH(6) = 6 +FIELD(6) = NUMDOC + +NAME(7) = TIPO DOCUMENTO +TYPE(7) = STRINGA +POSITION(7) = 315 +LENGTH(7) = 30 + +NAME(8) = CODICE CLIFOR +TYPE(8) = STRINGA +POSITION(8) = 345 +LENGTH(8) = 10 +FIELD(8) = CODCF + +NAME(9) = TOTALE IMPONIBILE +TYPE(9) = IMPORTO +POSITION(9) = 355 + +NAME(10) = TOTALE IVA +TYPE(10) = IMPORTO +POSITION(10) = 369 + +NAME(11) = TOTALE DOCUMENTO +TYPE(11) = IMPORTO +POSITION(11) = 383 +FIELD(11) = TOTDOC + +NAME(12) = DATA PAGAMENTO +TYPE(12) = DATA +POSITION(12) = 397 +LENGTH(12) = 8 + +NAME(13) = TIPO PAGAMENTO +TYPE(13) = STRINGA +POSITION(13) = 405 +LENGTH(13) = 20 +FIELD(13) = CODPAG + +NAME(14) = DATA COMPETENZA +TYPE(14) = DATA +POSITION(14) = 425 +LENGTH(14) = 8 +FIELD(14) = DATACOMP + +NAME(15) = NUMERO PROTOCOLLO +TYPE(15) = STRINGA +POSITION(15) = 433 +LENGTH(15) = 10 +FIELD(15) = PROTIVA + +NAME(16) = VALUTA +TYPE(16) = STRINGA +POSITION(16) = 443 +LENGTH(16) = 1 +MESSAGE(16)=_FISSO,!1 + +[RECORD R] + +NAME(0) = ID REGISTRAZIONE +TYPE(0) = NUMERO +POSITION(0) = 0 +LENGTH(0) = 10 +FIELD(0) = 23->NUMREG + +NAME(1) = FLAG RIGA IVA +TYPE(1) = STRINGA +POSITION(1) = 10 +LENGTH(1) = 1 +MESSAGE(1) = _FISSO,!N + +NAME(2) = FLAG DARE/AVERE +TYPE(2) = STRINGA +POSITION(2) = 11 +LENGTH(2) = 1 +FIELD(2) = SEZIONE + +NAME(3) = CODICE MASTRO +TYPE(3) = STRINGA +POSITION(3) = 12 +LENGTH(3) = 5 + +NAME(4) = CODICE CONTO +TYPE(4) = STRINGA +POSITION(4) = 17 +LENGTH(4) = 5 + +NAME(5) = CODICE SOTTOCONTO +TYPE(5) = STRINGA +POSITION(5) = 22 +LENGTH(5) = 5 + +NAME(6) = FLAG CLIFOR +TYPE(6) = STRINGA +POSITION(6) = 27 +LENGTH(6) = 1 + +NAME(7) = CODICE CLIFOR +TYPE(7) = STRINGA +POSITION(7) = 28 +LENGTH(7) = 10 + +NAME(8) = DESCRIZIONE RIGA +TYPE(8) = STRINGA +POSITION(8) = 38 +LENGTH(8) = 40 +FIELD(8) = DESCR[1,40] + +NAME(9) = IMPORTO SOTTOCONTO +TYPE(9) = IMPORTO +POSITION(9) = 78 +FIELD(9) = IMPORTO + +NAME(10) = IMPONIBILE +TYPE(10) = IMPORTO +POSITION(10) = 92 + +NAME(11) = CODICE IVA +TYPE(11) = STRINGA +POSITION(11) = 106 +LENGTH(11) = 4 + +NAME(12) = CP INDED +TYPE(12) = STRINGA +POSITION(12) = 110 +LENGTH(12) = 15 + +NAME(13) = COMMESSA +TYPE(13) = STRINGA +POSITION(13) = 125 +LENGTH(13) = 20 +FIELD(13) = CODCMS + +NAME(14) = SOTTOPROGETTO +TYPE(14) = STRINGA +POSITION(14) = 145 +LENGTH(14) = 20 + +NAME(15) = EDIZIONE +TYPE(15) = STRINGA +POSITION(15) = 165 +LENGTH(15) = 20 + +NAME(16) = VOCE DI SPESA +TYPE(16) = STRINGA +POSITION(16) = 185 +LENGTH(16) = 10 + +[RECORD I] + +NAME(0) = ID REGISTRAZIONE +TYPE(0) = NUMERO +POSITION(0) = 0 +LENGTH(0) = 10 +FIELD(0) = NUMREG + +NAME(1) = FLAG RIGA IVA +TYPE(1) = STRINGA +POSITION(1) = 10 +LENGTH(1) = 1 +MESSAGE(1) = _FISSO,!S + +NAME(3) = CODICE MASTRO +TYPE(3) = STRINGA +POSITION(3) = 12 +LENGTH(3) = 5 +FIELD(3) = GRUPPO + +NAME(4) = CODICE CONTO +TYPE(4) = STRINGA +POSITION(4) = 17 +LENGTH(4) = 5 +FIELD(4) = CONTO + +NAME(5) = CODICE SOTTOCONTO +TYPE(5) = STRINGA +POSITION(5) = 22 +LENGTH(5) = 5 +FIELD(5) = SOTTOCONTO + +NAME(6) = FLAG CLIFOR +TYPE(6) = STRINGA +POSITION(6) = 27 +LENGTH(6) = 1 +FIELD(6) = TIPOC + +NAME(7) = CODICE CLIFOR +TYPE(7) = STRINGA +POSITION(7) = 28 +LENGTH(7) = 10 + +NAME(8) = DESCRIZIONE RIGA +TYPE(8) = STRINGA +POSITION(8) = 38 +LENGTH(8) = 40 + +NAME(9) = IMPORTO SOTTOCONTO +TYPE(9) = IMPORTO +POSITION(9) = 78 + +NAME(10) = IMPONIBILE +TYPE(10) = IMPORTO +POSITION(10) = 92 +FIELD(10) = IMPONIBILE + +NAME(11) = CODICE IVA +TYPE(11) = STRINGA +POSITION(11) = 106 +LENGTH(11) = 4 +FIELD(11) = CODIVA + +NAME(12) = CP INDED +TYPE(12) = STRINGA +POSITION(12) = 110 +LENGTH(12) = 15 + +NAME(13) = COMMESSA +TYPE(13) = STRINGA +POSITION(13) = 125 +LENGTH(13) = 20 + +NAME(14) = SOTTOPROGETTO +TYPE(14) = STRINGA +POSITION(14) = 145 +LENGTH(14) = 20 + +NAME(15) = EDIZIONE +TYPE(15) = STRINGA +POSITION(15) = 165 +LENGTH(15) = 20 + +NAME(16) = VOCE DI SPESA +TYPE(16) = STRINGA +POSITION(16) = 185 +LENGTH(16) = 10 + + +[RECORD C] + +NAME(0) = CODICE +TYPE(0) = STRINGA +POSITION(0) = 0 +LENGTH(0) = 10 +FIELD(0) = 20->CODCF + +NAME(1) = RAGIONE SOCIALE +TYPE(1) = STRINGA +POSITION(1) = 11 +LENGTH(1) = 40 +MESSAGE(1) = _RAGSOC +FIELD(1) = 20->RAGSOC + +NAME(2) = PARTITA IVA +TYPE(2) = STRINGA +POSITION(2) = 50 +LENGTH(2) = 12 +FIELD(2)=20->PAIV + +NAME(3) = CODICE FISCALE +TYPE(3) = STRINGA +POSITION(3) = 62 +LENGTH(3) = 16 +FIELD(3) = 20->COFI + +NAME(4) = INDIRIZZO +TYPE(4) = STRINGA +POSITION(4) = 78 +LENGTH(4) = 40 +FIELD(4) = 20->INDCF + +NAME(5) = CAP DI RESIDENZA +TYPE(5) = STRINGA +POSITION(5) = 118 +LENGTH(5) = 5 +FIELD(5)=20->CAPCF + +NAME(6) = COMUNE DI RESIDENZA +TYPE(6) = STRINGA +POSITION(6) = 123 +LENGTH(6) = 23 +FIELD(6) = 13->DENCOM[1,40] + +NAME(7) = PROVINCIA DI RESIDENZA +TYPE(7) = STRINGA +POSITION(7) = 163 +LENGTH(7) = 2 +FIELD(7) = 13->PROVCOM + +NAME(8) = TELEFONO +TYPE(8) = STRINGA +POSITION(8) = 165 +LENGTH(8) = 20 +FIELD(8) = 20->TEL +MESSAGE(8) = _TELEFONO + +[RECORD P] + +NAME(0) = CODICE MASTRO +TYPE(0) = STRINGA +POSITION(0) = 0 +LENGTH(0) = 5 +FIELD(0)=19->GRUPPO + +NAME(1) = CODICE CONTO +TYPE(1) = STRINGA +POSITION(1) = 5 +B LENGTH(1) = 5 +FIELD(1)=19->CONTO + +NAME(2) = CODICE SOTTOCONTO +TYPE(2) = STRINGA +POSITION(2) = 10 +LENGTH(2) = 5 +FIELD(2)=19->SOTTOCONTO + +NAME(3) = DESCRIZIONE +TYPE(3) = STRINGA +POSITION(3) = 15 +LENGTH(3) = 80 +FIELD(3)=19->DESCR + +[RECORD G] + +NAME(0) = ID REGISTRAZIONE PAGAMENTO +TYPE(0) = NUMERO +POSITION(0) = 0 +LENGTH(0) = 10 +MESSAGE(0) = _NREGPAG + +NAME(1) = ID REGISTRAZIONE COSTO +TYPE(1) = NUMERO +POSITION(1) = 10 +LENGTH(1) = 10 +MESSAGE(1) = _NREGCOSTO + +NAME(2) = IMPORTO +TYPE(2) = IMPORTO +POSITION(2) = 20 +MESSAGE(2) = _IMPORTO + +NAME(3) = FLAG ACCONTO/SALDO +TYPE(3) = STRINGA +POSITION(3) = 34 +LENGTH(3) = 1 +MESSAGE(3) = _FLAG + +NAME(4) = VALUTA +TYPE(4) = STRINGA +POSITION(4) = 35 +LENGTH(4) = 1 +MESSAGE(4)=_FISSO,!1 diff --git a/tc/tc9100a.uml b/tc/tc9100a.uml index 0577d476f..4e0113027 100755 --- a/tc/tc9100a.uml +++ b/tc/tc9100a.uml @@ -1,5 +1,19 @@ #include "tc9100a.h" +TOOLBAR "" 0 -2 0 2 + +BUTTON DLG_OK 10 2 +BEGIN + PROMPT -12 -11 "" +END + +BUTTON DLG_QUIT 10 2 +BEGIN + PROMPT -22 -11 "" +END + +ENDPAGE + PAGE "Invio dati contabilita'" -1 -1 78 20 GROUPBOX DLG_NULL 76 3 @@ -31,70 +45,188 @@ END BOOLEAN F_MOVIMENTI BEGIN PROMPT 3 5 "Movimenti contabili" - MESSAGE TRUE,ENABLE F_DATAFIN + MESSAGE FALSE CLEAR,F_PAGAMENTI|DISABLE,F_DATAFIN + MESSAGE TRUE ENABLE,F_PAGAMENTI|ENABLE,F_DATAFIN END BOOLEAN F_CLIENTI BEGIN - PROMPT 3 6 "Clienti" + PROMPT 3 6 "Clienti" END BOOLEAN F_FORNITORI BEGIN - PROMPT 3 7 "Fornitori" + PROMPT 3 7 "Fornitori" END BOOLEAN F_CONTI BEGIN - PROMPT 3 8 "Piano dei conti" + PROMPT 3 8 "Piano dei conti" END BOOLEAN F_PAGAMENTI BEGIN - PROMPT 40 5 "Pagamenti" + PROMPT 40 5 "Pagamenti" END LISTBOX F_TIPOINVIO 20 BEGIN - PROMPT 2 10 "Invio a " - ITEM "P|Proforma" + PROMPT 2 10 "Invio a " + ITEM "P|Proforma" END STRING F_DESTINAZIONE 20 BEGIN - PROMPT 2 11 "Destinazione " + PROMPT 2 11 "Destinazione " END DATE F_DATAINI BEGIN - PROMPT 2 12 "Data iniziale " + PROMPT 2 12 "Data iniziale " END DATE F_DATAFIN BEGIN - PROMPT 40 12 "Data finale " + PROMPT 40 12 "Data finale " END -BUTTON F_RIPRISTINA 20 +BUTTON F_RIPRISTINA 20 2 BEGIN - PROMPT 2 14 "Annulla invio" - MESSAGE SHOW,F_DATARIPRISTINO|ENABLE,F_DATARIPRISTINO + PROMPT 2 14 "Annulla invio" + MESSAGE SHOW,F_DATARIPRISTINO|ENABLE,F_DATARIPRISTINO END DATE F_DATARIPRISTINO BEGIN - PROMPT 25 14 "Annulla invio fino al " - FLAGS "HD" + PROMPT 25 14 "Annulla invio fino al " + FLAGS "HD" END -BUTTON DLG_OK 9 2 +ENDPAGE + +PAGE "Conti" -1 -1 78 20 + +TEXT -1 BEGIN - PROMPT -12 -1 "" + PROMPT 1 1 "@bPiano dei conti contabile" END -BUTTON DLG_QUIT 9 2 +SPREADSHEET F_PDCC 78 -6 BEGIN - PROMPT -22 -1 "" + PROMPT 1 2 "Pdcc" + ITEM "Tipo" + ITEM "Gruppo" + ITEM "Conto" + ITEM "Sottoconto" + ITEM "Descrizione@50" +END + +TEXT -1 +BEGIN + PROMPT 1 17 "Inserire conti di tipo F per ritenute Fiscali" +END + +TEXT -1 +BEGIN + PROMPT 1 18 "S per ritenute Sociali, C per Costi, P per Pagamenti" +END + +BUTTON DLG_SAVEREC 12 2 +BEGIN + PROMPT -11 19 "" + PICTURE BMP_SAVEREC + PICTURE BMP_SAVERECDN +END + +ENDPAGE + +ENDMASK + +//-------------------------------------------------------------------- +// Riga dello sheet dei conti +//-------------------------------------------------------------------- + +PAGE "Riga Piano dei conti contabile" -1 -1 78 8 + +LIST S_TIPO 1 18 +BEGIN + PROMPT 1 1 "Tipo " + ITEM "C|Costi" + ITEM "P|Pagamenti" + ITEM "F|Ritenute fiscali" + ITEM "S|Ritenute sociali" +END + +NUMBER S_GRUPPO 3 +BEGIN + PROMPT 1 2 "Gruppo " + USE LF_PCON KEY 1 SELECT CONTO="" + INPUT GRUPPO S_GRUPPO + DISPLAY "Gruppo" GRUPPO + DISPLAY "Descrizione@50" DESCR + OUTPUT S_GRUPPO GRUPPO + CHECKTYPE REQUIRED +END + +NUMBER S_CONTO 3 +BEGIN + PROMPT 1 3 "Conto " + USE LF_PCON KEY 1 SELECT ((CONTO!="")&&(SOTTOCONTO="")) + COPY INPUT S_GRUPPO + INPUT CONTO S_CONTO + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Descrizione@50" DESCR + OUTPUT S_GRUPPO GRUPPO + OUTPUT S_CONTO CONTO + CHECKTYPE NORMAL + VALIDATE REQIF_FUNC 1 S_SOTTOCONTO +END + +NUMBER S_SOTTOCONTO 6 +BEGIN + PROMPT 1 4 "Sottoconto " + USE LF_PCON KEY 1 SELECT SOTTOCONTO!="" + COPY INPUT S_CONTO + INPUT SOTTOCONTO S_SOTTOCONTO + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Sottoconto" SOTTOCONTO + DISPLAY "Descrizione@50" DESCR + OUTPUT S_SOTTOCONTO SOTTOCONTO + OUTPUT S_CONTO CONTO + OUTPUT S_GRUPPO GRUPPO + OUTPUT S_DESCRIZIONE DESCR + CHECKTYPE NORMAL +END + +STRING S_DESCRIZIONE 50 +BEGIN + PROMPT 1 5 "Descrizione " + KEY 2 + USE LF_PCON KEY 2 + INPUT DESCR S_DESCRIZIONE + DISPLAY "Descrizione@50" DESCR + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Sottoconto" SOTTOCONTO + COPY OUTPUT S_SOTTOCONTO + CHECKTYPE REQUIRED +END + +BUTTON DLG_OK 10 2 +BEGIN + PROMPT -13 -1 "" +END + +BUTTON DLG_DELREC 10 2 +BEGIN + PROMPT -23 -1 "" +END + +BUTTON DLG_CANCEL 10 2 +BEGIN + PROMPT -33 -1 "" END ENDPAGE diff --git a/tc/tc9100conf.ini b/tc/tc9100conf.ini index 139597f9c..a30989f60 100755 --- a/tc/tc9100conf.ini +++ b/tc/tc9100conf.ini @@ -1,2 +1,5 @@ - +[OPZIONI] +CONFSTRINGA = +DATA = +PERCORSO = diff --git a/tc/tc9200.cpp b/tc/tc9200.cpp index 656cf5018..13366dbf7 100755 --- a/tc/tc9200.cpp +++ b/tc/tc9200.cpp @@ -1,7 +1,385 @@ -//NON riportare nulla!!!! Esiste dalla 4.0; qui e' solo un segnaposto -#include "tc9.h" +#include +#include +#include + +#include "tc0.h" +#include "tc9200a.h" + +#include +#include +#include +#include + +#define ALIAS_REG 100 + +class TInvioS_file: public TFile_text +{ +protected: + virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str); + +public: + TInvioS_file(const TString& file_name); + virtual ~TInvioS_file() { } +}; + +TInvioS_file::TInvioS_file(const TString& file_name) + : TFile_text(file_name, "tc9200a.ini") +{ +} + +class TInvioS_mask : public TAutomask +{ +protected: + bool on_field_event(TOperable_field& o, TField_event e, long jolly); +public: + + TInvioS_mask(); + + virtual ~TInvioS_mask(){}; +}; + +TInvioS_mask::TInvioS_mask() :TAutomask ("tc9200a") +{ +} + +bool TInvioS_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; + default: + break; + } + return TRUE; +} + +class TInvioS : public TSkeleton_application +{ + TCursor* _cur; + TInvioS_mask* _msk; + TInvioS_file* _trasfile; + TConfig* _configfile; + TDate _dataini, _datafin; + +protected: + virtual bool create(void); + virtual bool destroy(void); + virtual void main_loop() ; + void invio_sispac(); + long i_sispac_clifor(const char* tipocf, const bool invio = TRUE); + long i_sispac_movcont(const bool invio = TRUE); + long i_sispac_moviva(const bool invio = TRUE); + +public: + TInvioS_file* apri_file(const char* nome); + void chiudi_file(TInvioS_file* trasfile); + TConfig& config() {return *_configfile;}; + TInvioS() {} ; + virtual ~TInvioS() {} ; +}; + +// restituisce un riferimento all' applicazione +inline TInvioS& app() { return (TInvioS&) main_app();} + +// gestione dei messaggi estesi nei campi +void TInvioS_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 == "_TIPORIGA") + { + valore = str.empty() ? " " : "S"; + } + else if (code == "_CODPAG") + { + valore = app().config().get(str, "PAGAMENTI"); + } + else if (code == "_OPZIONI") + { + TString in(s.get()); + valore = app().config().get(in, "OPZIONI"); + } + else if (code == "_IMPORTO") + { + real importo(str); + valore = importo.string(0,2); + valore.strip("-"); + valore.strip("+"); + valore.strip("."); + } + else if (code == "_IMPORTORIGAIVA") + { + real imponibile = cur.curr(LF_RMOVIVA).get_real(RMI_IMPONIBILE);; + real imposta = cur.curr(LF_RMOVIVA).get_real(RMI_IMPOSTA);; + imponibile += imposta; + valore = imposta.string(0,2); + valore.strip("-"); + valore.strip("+"); + valore.strip("."); + } + else if (code == "_INDIR") + { + valore = cur.curr(LF_CLIFO).get(CLI_INDCF); + valore << ' ' << cur.curr(LF_CLIFO).get(CLI_CIVCF); + valore.cut(40); + } + else if (code == "_GIUFIS") + { + const char c = str[0]; + valore = (c == 'F') ? "S" : "N"; + } + else if (code == "_TITOLARE") + { + valore = (str.empty() ? "N" : "S"); + } + else if (code == "_TIPODET") + { + valore = (str.empty() ? " " : "100"); + } + else if (code == "_CONTO") + { + int gruppo = cur.curr(LF_CLIFO).get_int(CLI_GRUPPO); + if (gruppo == 10) + gruppo = 0; + int conto = cur.curr(LF_CLIFO).get_int(CLI_CONTO); + long codice = cur.curr(LF_CLIFO).get_int(CLI_CODCF); + valore.format("%03d%03d%06ld", gruppo, conto, codice); + } + else if (code == "_CONTOMOV") + { + int gruppo = cur.curr(LF_RMOV).get_int(RMV_GRUPPO); + if (gruppo == 10) + gruppo = 0; + int conto = cur.curr(LF_RMOV).get_int(RMV_CONTO); + long codice = cur.curr(LF_RMOV).get_int(RMV_SOTTOCONTO); + valore.format("%03d%03d%06ld", gruppo, conto, codice); + } + else if (code == "_CONTOMOVIVA") + { + int gruppo = cur.curr(LF_RMOVIVA).get_int(RMI_GRUPPO); + if (gruppo == 10) + gruppo = 0; + int conto = cur.curr(LF_RMOVIVA).get_int(RMI_CONTO); + long codice = cur.curr(LF_RMOVIVA).get_int(RMI_SOTTOCONTO); + valore.format("%03d%03d%06ld", gruppo, conto, codice); + } + else NFCHECK("Macro non definita: %s", (const char *)code); + str = valore; +} + +TInvioS_file* TInvioS::apri_file(const char* nome) +{ + TFilename filename = _msk->get(F_DESTINAZIONE); + filename.add(nome); + filename.ext("txt"); + if (filename.exist()) + remove(filename); + TInvioS_file* trasfile = new TInvioS_file(filename); + trasfile->open(filename,'w'); + trasfile->force_record_separator(); + return trasfile; +} + +void TInvioS::chiudi_file(TInvioS_file* trasfile) +{ + trasfile->close(); + delete trasfile; +} + +long TInvioS::i_sispac_movcont(const bool invio) +{ + TRectype da(LF_MOV); + TRectype a(LF_MOV); + TDate dataini = _msk->get_date(F_DATAINI); + TDate datafin = _msk->get_date(F_DATAFIN); + if (dataini.ok()) + da.put(MOV_DATAREG, dataini); + if (datafin.ok()) + a.put(MOV_DATAREG, datafin); + TRelation rel(LF_MOV); + rel.add(LF_RMOV, "NUMREG==NUMREG", 1); + rel.add(LF_CLIFO, "TIPOCF==TIPO|CODCF==CODCF", 1); + TCursor cur(&rel, "", 2, &da, &a); + const long cur_items = cur.items(); + if (cur_items != 0) + { + cur.freeze(); + TRectype& cur_rec = cur.curr(); + for (cur = 0; cur.pos() < cur_items; ++(cur)) + { + const long numreg = cur.curr().get_long(MOV_NUMREG); + bool continua = TRUE; + while (continua) + { + const long numregrig = cur.curr(LF_RMOV).get_long(RMV_NUMREG); + if (numreg == numregrig) + { + if (invio) + { + TRectype& cur_rec_righe = cur.curr(LF_RMOV); + TRecord_text recrighe; + recrighe.set_type("R"); + _trasfile->autoload(recrighe, cur); + _trasfile->write(recrighe); + } + } + continua = cur.next_match(LF_RMOV, "NUMREG"); + } + } + } + return 0; +} + + +long TInvioS::i_sispac_moviva(const bool invio) +{ + 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_RMOVIVA, "NUMREG==NUMREG", 1); + rel.add("REG", "CODTAB[1,4]==ANNOIVA|CODTAB[5,7]==REG", 1); + rel.add(LF_CLIFO, "TIPOCF==TIPO|CODCF==CODCF", 1); + TCursor cur(&rel, "", 2, &da, &a); + const long cur_items = cur.items(); + if (cur_items != 0) + + { + cur.freeze(); + TRectype& cur_rec = cur.curr(); + for (cur = 0; cur.pos() < cur_items; ++(cur)) + { + const long numreg = cur.curr().get_long(MOV_NUMREG); + bool continua = TRUE; + while (continua) + { + const long numregrig = cur.curr(LF_RMOVIVA).get_long(RMI_NUMREG); + if (numreg == numregrig) + { + if (invio) + { + TRectype& cur_rec_righe = cur.curr(LF_RMOVIVA); + TRecord_text recrighe; + recrighe.set_type("I"); + _trasfile->autoload(recrighe, cur); + _trasfile->write(recrighe); + } + } + continua = cur.next_match(LF_RMOVIVA, "NUMREG"); + } + } + } + return 0; +} + +long TInvioS::i_sispac_clifor(const char* tipocf, const bool invio) +{ + TString80 nomefile = "FILE"; + nomefile << tipocf; + TInvioS_file* trasfilecf = apri_file(_configfile->get(nomefile, "OPZIONI")); + TRelation rel(LF_CLIFO); + rel.add(LF_COMUNI, "STATO==STATOCF|COM==COMCF", 1); + rel.add(LF_ANAGFIS,"CODANAGR==CODANAGPER", 1); + rel.add(LF_ANAG,"TIPOA==TIPOPERS|CODANAGR==CODANAGPER", 1); + TString80 filtro; + filtro = "20->TIPOCF == \""; + filtro << tipocf; + filtro << "\""; + TCursor cur(&rel); + cur.setfilter(filtro, TRUE); + const long cur_items = cur.items(); + if (cur_items != 0 && invio) + { + cur.freeze(); + TRectype& cur_rec = cur.curr(); + for (cur = 0; cur.pos() < cur_items; ++(cur)) + { + TRecord_text rec; + rec.set_type(tipocf); + trasfilecf->autoload(rec, cur); + trasfilecf->write(rec); + } + } + chiudi_file(trasfilecf); + return 0; +} + +//metodone globale che chiama, come un menu, i vari sottometodi in base alle scelte sulla maschera +void TInvioS::invio_sispac() +{ + if (_msk->get_bool(F_CLIFOR)) + { + i_sispac_clifor("C"); + i_sispac_clifor("F"); + } + if (_msk->get_bool(F_MOVCONT)) + { + TString80 filename = _configfile->get("FILEM", "OPZIONI"); + _trasfile = apri_file(filename); + i_sispac_movcont(); + i_sispac_moviva(); + chiudi_file(_trasfile); + } +} + +bool TInvioS::create() +{ + _msk = new TInvioS_mask(); + TFilename configname = "tc9200conf.ini"; + configname.custom_path(); + _configfile = new TConfig(configname); + return TSkeleton_application::create(); +} + +bool TInvioS::destroy() +{ + delete _configfile; + delete _msk; + return TSkeleton_application::destroy(); +} + +void TInvioS::main_loop() +{ + _msk->set(F_NUMEROINVIO, _configfile->get_int("NUMEROINVIO","OPZIONI")+1); + _msk->set(F_DATAINI, _configfile->get("DATA","OPZIONI")); + _msk->set(F_DESTINAZIONE, _configfile->get("PERCORSO","OPZIONI")); + while (_msk->run() != K_QUIT) + { + _configfile->set("NUMEROINVIO", _msk->get(F_NUMEROINVIO),"OPZIONI"); + _configfile->set("DATA", _msk->get_date(F_DATAFIN),"OPZIONI"); + _configfile->set("PERCORSO", _msk->get(F_DESTINAZIONE),"OPZIONI"); + _configfile->set_paragraph("PAGAMENTI"); + _dataini = _msk->get_date(F_DATAINI); + _datafin = _msk->get_date(F_DATAFIN); + const char tipoinvio = _msk->get(F_TIPOINVIO)[0]; + if (tipoinvio == 'S') + invio_sispac(); + } +} int tc9200(int argc, char **argv) { - return 0; + TInvioS a; + a.run(argc, argv, "Invio dati contabilità Sispac/Cosmo"); + return 0; } + diff --git a/tc/tcmenu.men b/tc/tcmenu.men index d3f8cda2d..0bb4b0a72 100755 --- a/tc/tcmenu.men +++ b/tc/tcmenu.men @@ -5,6 +5,8 @@ Module = 27 Flags = "" Item_01 = "TeamSystem", [TCMENU_002] Item_02 = "Zucchetti", "tc1 -0", "" +Item_03 = "Proforma", "tc9 -0", "" +Item_04 = "Sispac/Cosmo", "tc9 -1", "" [TCMENU_002] Caption = "TeamSystem"