diff --git a/src/tf/tf0100.cpp b/src/tf/tf0100.cpp index 0baf0b49c..56dbc6334 100644 --- a/src/tf/tf0100.cpp +++ b/src/tf/tf0100.cpp @@ -1,21 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../ve/velib05.h" -#include "../cg/cglib03.h" - #include "tf0.h" -#include "tf0100a.h" +// Le definizioni sono qua +#include "tf0100b.h" + +#include // dongle() +#include // Oracle Recset -#include "../fe/felib.h" #include #include @@ -27,32 +16,113 @@ #include -///////////////////////////////////////////////////////////////////////////////////// -// Globals -///////////////////////////////////////////////////////////////////////////////////// - -static XVT_SQLDB _db = NULL; // TFF sqlite db -enum return_code -{ - found, // Trovato - movcustom, // Trovato in trasfatt - nextmov, // Trovato ma cambiato movimento - eof, // EOF rmoviva - eofm, // EOF mov - after // File mov su un movimento dopo rispetto a rmoviva -}; - -enum filter_fatt -{ - toSend, // Da inviare - sent, // Inviate - all // Tutte -}; ///////////////////////////////////////////////////////////////////////////////////// // Utilities ///////////////////////////////////////////////////////////////////////////////////// +// Le funzioni quelle belle +TString getTipoDoc(int id) +{ + TString ret; + switch(id) + { + case B_TIPO_AUTOFATT: + ret = "AF"; + break; + case B_TIPO_BOLLADOG: + ret = "BD"; + break; + case B_TIPO_CORRNINC: + ret = "CN"; + break; + case B_TIPO_CORR: + ret = "CR"; + break; + case B_TIPO_FATTACQ: + ret = "FA"; + break; + case B_TIPO_FATTFISC: + ret = "FF"; + break; + case B_TIPO_FATTSC: + ret = "FS"; + break; + case B_TIPO_FATTVEN: + ret = "FV"; + break; + case B_TIPO_NOTC: + ret = "NC"; + break; + case B_TIPO_NOTD: + ret = "ND"; + break; + case B_TIPO_RICFIS: + ret = "RF"; + break; + case B_TIPO_RICFISNI: + ret = "RN"; + break; + case B_TIPO_SCONT: + ret = "SC"; + break; + case B_TIPO_SCONTNI: + ret = "SN"; + break; + case B_TIPO_STORDOC: + ret = "ST"; + break; + } + return ret; +} + +int getTipoDoc(TString id) +{ + int ret = -1; + if(id == "AF") ret = B_TIPO_AUTOFATT; + else if(id == "BD") ret = B_TIPO_BOLLADOG; + else if(id == "CN") ret = B_TIPO_CORRNINC; + else if(id == "CR") ret = B_TIPO_CORR; + else if(id == "FA") ret = B_TIPO_FATTACQ; + else if(id == "FF") ret = B_TIPO_FATTFISC; + else if(id == "FS") ret = B_TIPO_FATTSC; + else if(id == "FV") ret = B_TIPO_FATTVEN; + else if(id == "NC") ret = B_TIPO_NOTC; + else if(id == "ND") ret = B_TIPO_NOTD; + else if(id == "RF") ret = B_TIPO_RICFIS; + else if(id == "RN") ret = B_TIPO_RICFISNI; + else if(id == "SC") ret = B_TIPO_SCONT; + else if(id == "SN") ret = B_TIPO_SCONTNI; + else if(id == "ST") ret = B_TIPO_STORDOC; + return ret; +} + +TRectype getTrasFatt(TString reg, TString codiva) +{ + TString key = reg; key << "|" << codiva; + return cache().get(LF_TRASFATT, key); +} + +TRectype getCli(TString tipocf, TString codcf) +{ + if(tipocf != "O") + { + TString key = tipocf; key << "|" << codcf; + return cache().get(LF_CLIFO, key); + } + // Cliente occasionale! + else + { + TRectype cli(LF_CLIFO); + TRectype occas = cache().get(LF_OCCAS, codcf); + cli.put("RAGSOC" , occas.get("RAGSOC")); + cli.put("CODRFSO" , ""); + cli.put("PAIV" , occas.get("PAIV")); + cli.put("COFI" , occas.get("COFI")); + return cli; + } +} + // Cerca una stringa all'interno di una SLIST (Potrebbe diventare una funzione di XVT.h) static SLIST_ELT xvt_slist_find_str(SLIST list, const char* str) { @@ -66,6 +136,7 @@ static SLIST_ELT xvt_slist_find_str(SLIST list, const char* str) return e; } +// Controlla se l'azienda ha un RFSO static bool haveRFSO(TString& codrfso) { codrfso = cache().get(LF_NDITTE, prefix().firm().codice(), "CODRFSO"); @@ -73,62 +144,123 @@ static bool haveRFSO(TString& codrfso) return true; } -static bool hasRFSO(TString tipocf, TString codcli, TString& codrfso) +/* Ritorno il tipo di documento + * TD01: Fattura + * TD04: Nota di credito + * TD05: Nota di debito + * NO-> TD07: Fattura semplificata + * NO-> TD08: NC semplificata + * TD10: Fatt di acquisto intra beni + * TD11: Fatt di acquisto intra servizi + */ +static const char* decodTipo(TToken_string* strarr) { - codrfso = cache().get(LF_CLIFO, tipocf << "|" << codcli, "CODRFSO"); - if(codrfso == "") return false; - return true; + TRectype mov = cache().get(LF_MOV, strarr->get(_numero)); + TCausale caus(mov.get("CODCAUS"), mov.get_int("ANNOIVA")); + switch(caus.tipomov()) + { + case tm_fattura: + // Potrebbe essere normale o intra + if(!caus.intra()) + return "TD01"; + else + { + // Controlliamo se è di beni o servizi + // Per capire se sono beni o servizi devo prendere il movimento, e trovare quale dei due ha un importo più alto + TAssoc_array intraval; + TRelation r_moviva(LF_RMOVIVA); + TRectype filter(r_moviva.curr()); filter.put("NUMREG", strarr->get(_numero)); + TCursor c_moviva(&r_moviva, "", 1, &filter, &filter); + for(c_moviva = 0; c_moviva.pos() < c_moviva.items(); ++c_moviva) + { + TRectype row = c_moviva.curr(); + real importo = row.get_real("IMPONIBILE"); + // La chiave deve essere formata da CODIVA, GRUPPO + CONTO + SOTTOCONTO + TString keyAssoc; keyAssoc << row.get("CODIVA") << "|" << row.get("GRUPPO") << "|" << row.get("CONTO") << "|" << row.get("SOTTOCONTO"); + if(intraval.is_key(keyAssoc)) + { + importo += *(real*)intraval.objptr(keyAssoc); + intraval.add(keyAssoc, importo, true); + } + else + { + intraval.add(keyAssoc, importo); + } + } + + // Adesso che ho tutti i totali divisi per CODIVA e GCS vado a pescare il valore maggiore + TString keyMax = ""; + real max = ZERO; + TString_array keys; + intraval.get_keys(keys); + for(int i = 0; i < keys.items(); i++) + { + TString key = *(TString*)keys.objptr(i); + real valItem = *(real*)intraval.objptr(key); + if(valItem > max) + { + keyMax = key; + max = valItem; + } + } + + // Una volta che ho trovato il nostro vincitore vado a prendere il tipo di fattura dal GCS + TString keyPCon = keyMax.ssub(keyMax.find('|') + 1); + if(cache().get(LF_PCON, keyPCon, "RICSER") == "1") + return "TD11"; + else + return "TD10"; + } + break; + case tm_nota_credito: + if(caus.tipodoc() == "NC") + return "TD04"; + else + return "TD05"; + break; + default: + return ""; + } } -// DA CONTROLLARE!!!!! -static const char* decodTipo(TDocumento& doc) +/* Salvo il record modificato in TFCustom */ +bool saveRec(TToken_string row, bool esportato) { - if(doc.is_fattura()) - return "TD01"; - if(doc.is_nota_credito()) - return "TD04"; - return "TD05"; + // Devo inserire la riga in trasfatt + TRectype rCust(LF_TRASFATT); + if(strcmp(row.get(_spedita), "X") == 0) // Controllo che non sia già stata spedita prima + { + TString key = row.get(_numero); key << "|"<< row.get(_aliquota); + rCust = cache().get(LF_TRASFATT, key); + } + else + { + rCust.put("NUMREG", row.get(_numero)); + } + rCust.put("TIPO", row.get(_tipocf)); + rCust.put("CODCF", row.get(_codcf)); + rCust.put("OCCAS", row.get(_occas)); + rCust.put("TIPODOC", row.get(_codnum)); + rCust.put("NUMDOC", row.get(_numdoc)); + rCust.put("DATAREG", row.get(_datareg)); + rCust.put("DATADOC", row.get(_datadoc)); + rCust.put("IMPONIBILE", row.get(_imponibile)); + rCust.put("IMPOSTA", row.get(_importoIVA)); + rCust.put("CODIVA", row.get(_aliquota)); + rCust.put("AUTOFATT", row.get(_autofatt)); + if(esportato) + { + rCust.put("TFINVIO", true); + rCust.put("TFDATA", TDate(TODAY)); + } + + return rCust.write_rewrite(TLocalisamfile(LF_TRASFATT)) == NOERR; } ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_record ///////////////////////////////////////////////////////////////////////////////////// -// Contenitore di campi di un record di database SQLite -class TTrFa_record : public TObject -{ - TString8 _table; - TToken_string _key; - TAssoc_array _fields; - -protected: - void copy(const TTrFa_record& rec) { _table = rec._table; _key = rec._key; _fields = rec._fields; } - const TString& var2str(const TString& fld, const TVariant& var) const; - -public: - void reset() { _fields.destroy(); } - void set(const char* fld, const TVariant& var); - void set(const char* fld, long var); - void set(const char* fld, const char* var); - void set(const char* fld, const real& var); - void set(const char* fld, const TString& var); - void set(const char* fld, const TDate& var); - void set(const char* fld, bool var); - const TVariant& get(const char* fld) const; - - bool insert(); - bool remove(); - bool search(); - bool search(const char* k1, const char* k2, const char* k3 = NULL); - - virtual TObject* dup() const { return new TTrFa_record(*this); } - virtual bool ok() const { return _table.not_empty(); } - - TTrFa_record& operator=(const TTrFa_record& rec) { copy(rec); return *this; } - TTrFa_record(const TTrFa_record& rec) { copy(rec); } - TTrFa_record(const char* table); -}; - // Imposta il valore di un campo variant void TTrFa_record::set(const char* fld, const TVariant& var) { @@ -347,254 +479,180 @@ TTrFa_record::TTrFa_record(const char* table) : _table(table), _key(15, ',') ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_cursors ///////////////////////////////////////////////////////////////////////////////////// -/* - * Classe per la gestione dei cursori RMOVIVA e MOV - */ -class TTrFa_cursors : TObject +TTrFa_cursors::~TTrFa_cursors() { - friend class TCursor; + if(c_rmoviva != NULL) + delete c_rmoviva; +} - TSorted_cursor* c_mov; - TCursor* c_moviva; - TCursor* c_trasfatt; - TRelation* r_mov; - TRelation* r_moviva; - TRelation* r_trasfatt; - - filter_fatt filFat; - - bool filOk(bool s) { return (filFat == all) || (filFat == sent && s) || (filFat == toSend && !s); } - int _next(bool init = false); // Si sposta avanti di un elemento - -public: - TTrFa_cursors(); - ~TTrFa_cursors() { delete c_mov, c_moviva, r_mov, r_moviva, r_trasfatt, c_trasfatt; }; - long int getMovItems() { return c_mov->items(); } - long int getIvaItems() { return c_moviva->items(); } - long int getMovPos() { return c_mov->pos(); } - long int getIvaPos() { return c_moviva->pos(); } - TRectype getMov() { return c_mov->curr(); } - TRectype getIva() { return c_moviva->curr(); } - TRectype getTrasfatt() { return c_trasfatt->curr(); } - int next(TAssoc_array& recimposte); // Legge tutto il prossimo movimento, in importi mette per ogni codiva la somma - - int updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, TAssoc_array& recimposte, int cod = toSend); -}; - -TTrFa_cursors::TTrFa_cursors() : filFat(all) +int TTrFa_cursors::next(TAssoc_array& recimposte, bool& ok, TString& tipocf, TString& codcf) { - r_mov = new TRelation(LF_MOV); - r_moviva = new TRelation(LF_RMOVIVA); - r_trasfatt = new TRelation(LF_TRASFATT); - c_mov = new TSorted_cursor(r_mov, "NUMREG"); - c_moviva = new TCursor(r_moviva); - c_trasfatt = new TCursor(r_trasfatt); -}; - -int TTrFa_cursors::next(TAssoc_array& recimposte) -{ - int err = _next(true); + // Azzero recimposte + recimposte.destroy(); + // Return code + return_code err; + // Record + TRectype record = _next(err, tipocf, codcf); + if(record.get("NUMREG") == "42094") + bool tolla = true; while(err < nextmov) { - TRectype mov = getMov(), miva = getIva(), cust = getTrasfatt(); - if(recimposte.is_key(miva.get("CODIVA"))) + // Se ho trovato un record custom o non trovo il suo codiva tra i record custom lo salvo + if(recimposte.is_key(record.get("CODIVA"))) { // Prelevo il record salvato - TRectype app = *(TRectype*)recimposte.objptr(miva.get("CODIVA")); + TRectype app = *(TRectype*)recimposte.objptr(record.get("CODIVA")); // Aggiorno i valori - app.put("IMPONIBILE", app.get_real("IMPONIBILE") + (err == movcustom ? cust.get_real("IMPONIBILE") : miva.get_real("IMPONIBILE"))); - app.put("IMPOSTA", app.get_real("IMPOSTA") + (err == movcustom ? cust.get_real("IMPOSTA") : miva.get_real("IMPOSTA"))); + app.put("IMPONIBILE", app.get_real("IMPONIBILE") + record.get_real("IMPONIBILE")); + app.put("IMPOSTA", app.get_real("IMPOSTA") + record.get_real("IMPOSTA")); // Lo reinserisco - recimposte.add(miva.get("CODIVA"), app, true); + recimposte.add(record.get("CODIVA"), app, true); } else // Inserisco per la prima volta { - // Creo un record di tipo tabella trasmissione fatture, tanto conterrebbe tutti i dati necessari - TRectype app(LF_TRASFATT); - // Inserisco i dati - if(err == movcustom) - { - app.put("NUMREG", cust.get("NUMREG")); - app.put("TIPO", cust.get("TIPO")); - app.put("COD", cust.get("CODCF")); - app.put("TIPODOC", cust.get("TIPODOC")); - app.put("NUMDOC", cust.get("NUMDOC")); - app.put("DATADOC", cust.get("DATADOC")); - app.put("IMPONIBILE", cust.get("IMPONIBILE")); - app.put("IMPOSTA", cust.get("IMPOSTA")); - app.put("CODIVA", cust.get("CODIVA")); - } - else - { - app.put("NUMREG", mov.get("NUMREG")); - app.put("TIPO", mov.get("TIPO")); - app.put("COD", mov.get("CODCF")); - app.put("TIPODOC", mov.get("TIPODOC")); - app.put("NUMDOC", mov.get("NUMDOC")); - app.put("DATADOC", mov.get("DATADOC")); - app.put("IMPONIBILE", miva.get("IMPONIBILE")); - app.put("IMPOSTA", miva.get("IMPOSTA")); - app.put("CODIVA", miva.get("CODIVA")); - } // Salvo il record nell'array - recimposte.add(app.get("CODIVA"), app); + recimposte.add(record.get("CODIVA"), record); } - err = _next(); + record = _next(err, tipocf, codcf); } + ok = err != eof; return err; } /* - * Questa funzione si sposta sui due cursori trovando la prossima riga, se le righe sono finite si posiziona sul prossimo movimento o ritorna EOF + * Questa funzione precarica un array associativo con il movimento diviso per codiva e lo ritorna */ -int TTrFa_cursors::_next(bool init) +TRectype TTrFa_cursors::_next(return_code& code, TString& tipocf, TString& codcf) { - bool isNextMov = false; - if(c_moviva->pos() == c_moviva->items()) - return eof; // A noi interessa solo rmoviva - else + TString numMov = c_rmoviva->get("23.NUMREG").as_string(); + // Record di ritorno + TRectype retRec(LF_TRASFATT); + // Controllo che non sia il primo record del movimento + if(_newMov) { - TRectype rigaMov = c_mov->curr(), rigaIva = c_moviva->curr(), rigaTF = c_trasfatt->curr(); - bool first = true; - bool checkOk = false; - // Posso capitare movimenti aggiunti dopo che non rientrano nel periodo che ci interessa, applico un controllino - while(first || rigaMov.get_long("NUMREG") > rigaIva.get_long("NUMREG") || !filOk(checkOk)) + _newMov = false; + // Se è un cliente occasionale passo "O" + if(c_rmoviva->get("23.OCFPI").as_string() != "") { - first = false; - - // Stratagemma terribile per evitare di saltare il primo record - if(!init) - { - if(!c_moviva->next_match(0)) - return eof; - } - else init = false; - - rigaMov = c_mov->curr(); - rigaIva = c_moviva->curr(); - rigaTF = c_trasfatt->curr(); - - while(rigaMov.get_long("NUMREG") < rigaIva.get_long("NUMREG")) - { - isNextMov = true; // Vale la pena fare un controllo aggiuntivo per questo? Il while verrà eseguito max 2 volte - - if (!c_mov->next_match(0)) - return eofm; - rigaMov = c_mov->curr(); - } - - // Mi muovo finchè le righe non sono le stesse - while(rigaTF.get_long("NUMREG") <= rigaIva.get_long("NUMREG") && rigaTF.get_long("NUMRIG") < rigaIva.get_long("NUMRIG") && c_trasfatt->pos() != c_trasfatt->items()) - { - if(!c_mov->next_match(0)) // Non mi interessa se raggiungo la fine di questa tabella - break; - rigaTF = c_trasfatt->curr(); - } - if(rigaTF.get_long("NUMREG") == rigaIva.get_long("NUMREG") && rigaTF.get_long("NUMRIG") == rigaIva.get_long("NUMRIG")) - checkOk = rigaTF.get_bool("TFINVIO"); - else - checkOk = rigaIva.get_bool("TFINVIO"); - - } - - if(isNextMov) - { - if(rigaTF.get_long("NUMREG") == rigaIva.get_long("NUMREG") && rigaTF.get_long("NUMRIG") == rigaIva.get_long("NUMRIG")) - return movcustom; - else - return nextmov; + tipocf = "O"; + codcf = c_rmoviva->get("23.OCFPI").as_string(); } else - return found; + { + tipocf = c_rmoviva->get("23.TIPO").as_string(); + codcf = c_rmoviva->get("23.CODCF").as_string(); + } } + else + { + TString codiva; + do + { + // Se ritorna false ho finito i records + if(!c_rmoviva->move_next()) + { + code = eof; + return retRec; + } + else + { + // Controllo se ho cambiato movimento + _newMov = numMov != c_rmoviva->get("23.NUMREG").as_string(); + codiva = c_rmoviva->get("25.CODIVA").as_string(); + } + } // Ciclo finchè non trovo un nuovo movimento o trovo cod IVA già presi da cust + while(TCodiceIVA(codiva).tipo() == "NS" || (!_newMov && _alqCust.get_pos(codiva) > -1)); + } + + + // Se ho cambiato movimento ritorno, leggerò poi al prossimo giro + if(_newMov) + { + _alqCust.cut(0); + code = nextmov; + return retRec; + } + else + code = found; + + // Controllo dell'esistenza di un record custom in tasfatt + retRec = getTrasFatt(c_rmoviva->get("23.NUMREG").as_string(), c_rmoviva->get("25.CODIVA").as_string()); + if(retRec.empty()) + { + code = found; + // Carico il record + retRec.put("NUMREG", c_rmoviva->get("23.NUMREG").as_int()); + retRec.put("TIPO", c_rmoviva->get("23.TIPO").as_string()); + retRec.put("CODCF", c_rmoviva->get("23.CODCF").as_string()); + retRec.put("OCCAS", c_rmoviva->get("23.OCFPI").as_string()); + retRec.put("TIPODOC", c_rmoviva->get("23.TIPODOC").as_string()); + retRec.put("NUMDOC", c_rmoviva->get("23.NUMDOC").as_int()); + retRec.put("DATAREG", c_rmoviva->get("23.DATAREG").as_date()); + retRec.put("DATADOC", c_rmoviva->get("23.DATADOC").as_date()); + retRec.put("IMPONIBILE", c_rmoviva->get("25.IMPONIBILE").as_real()); + retRec.put("IMPOSTA", c_rmoviva->get("25.IMPOSTA").as_real()); + retRec.put("CODIVA", c_rmoviva->get("25.CODIVA").as_string()); + retRec.put("TIPODET", c_rmoviva->get("25.TIPODET").as_string()); + } + else + { + _alqCust.add(c_rmoviva->get("25.CODIVA").as_string()); + code = foundcust; + } + return retRec; } -int TTrFa_cursors::updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, TAssoc_array& recimposte, int cod) +int TTrFa_cursors::updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, int cod) { - filFat = (filter_fatt)cod; + TString query = "USE RMOVIVA\n"; + query << "SELECT (23.REG!=\"\")&&BETWEEN(23.DATAREG,#DADATAREG,#ADATAREG)&&(23.TIPO=\"" << tipocf << "\")"; + + if(codcf > 0) + query<<"&&STR((23.CODCF=#CODCF))"; - TRectype filMov(r_mov->curr()); - int movKey = 1; + switch(cod) + { + case toSend: + query<<"&&(23.TFINVIO!=\"X\")"; + break; + case sent: + query<<"&&(23.TFINVIO=\"X\")"; + break; + default: + break; + } - TString filter; + query << "\nJOIN MOV INTO NUMREG==NUMREG\n"; + c_rmoviva = new TISAM_recordset(query); if(dal.empty()) dal = "20170101"; // Data in cui questo modulo è diventato valido if(al.empty()) al = TODAY; - filter << "&&(BETWEEN(DATADOC," << dal.date2ansi() << ',' << al.date2ansi() << "))"; - - if(tipocf != 'T') + + c_rmoviva->set_var("#DADATAREG", dal); + c_rmoviva->set_var("#ADATAREG", al); + + if(codcf > 0) + c_rmoviva->set_var("#CODCF", codcf); + + + if(c_rmoviva->items() > ZERO) { - movKey = 3; - filMov.put("TIPO", tipocf); - // Se è selezionato un cliente specifico - if(codcf > 0) - filMov.put("CODCF", codcf); + _newMov = true; + return c_rmoviva->items(); } - else - filMov = 0; - - // Risetto mov - delete c_mov; - c_mov = new TSorted_cursor(r_mov, "NUMREG", TString("REG!=\"\"")<items(); - c_mov->first_item(); - - // Preparo c_moviva - TRectype filIva(r_moviva->curr()); - filIva.put("NUMREG", TRectype(c_mov->curr()).get_long("NUMREG")); - - // Resetto rmoviva - delete c_moviva; - c_moviva = new TCursor(r_moviva, "", 1, &filIva); - c_moviva->first_item(); - - // Preparo c_moviva - TRectype filTF(r_trasfatt->curr()); - filTF.put("NUMREG", TRectype(c_mov->curr()).get_long("NUMREG")); - - // Resetto trasfatt - delete c_trasfatt; - c_trasfatt = new TSorted_cursor(r_trasfatt, "NUMREG", "", 1, &filIva); - c_trasfatt->first_item(); - - - // Mi posiziono sullo stesso Numero di registrazione - if(c_mov->items() > 0 && c_moviva->items() > 0) - { - return next(recimposte); - } - - return eof; + return -1; } ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_mask ///////////////////////////////////////////////////////////////////////////////////// -class TTrFa_mask : public TAutomask -{ - friend class TTrFa_cursors; - - TMaskmode _mode; - bool _sheet_dirty; - bool _filter_changed; - -protected: - virtual void next_page(int p); - const char * natura(const TString& codiva) const; - real get_IVA(const TString& codiva) const; - char revCharge(TString codcaus) const; - TString findDetraib(TString codiva) const; - - virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); - //void fill(); - //void init(); - -public: - void setFilterChanged() { _filter_changed = true; } - void load_sheet(); - TTrFa_mask(TString msk) : TAutomask(msk), _filter_changed(true) {} -}; +TTrFa_mask::~TTrFa_mask() +{ + TSheet_field& sheet = sfield(F_RIGHE); + if(!sheet.empty()) + sheet.destroy(); +} void TTrFa_mask::next_page(int p) { @@ -624,18 +682,6 @@ bool TTrFa_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) if (e == fe_init) o.set(TDate(TODAY)); break; - case F_TIPOCF: - if(get(F_TIPOCF) != "T") - { - enable(F_CODCF); - enable(F_RAGSOC); - } - else - { - disable(F_CODCF); - disable(F_RAGSOC); - } - break; case DLG_ALL: if (e == fe_button) { @@ -652,6 +698,195 @@ bool TTrFa_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) } } break; + case F_RIGHE: + if (e == se_notify_add) + { + TSheet_field& s = (TSheet_field&)o; + TToken_string& row = s.row(jolly); + row.add(nuovo_progr(), s.cid2index(A_NUMERO)); + } else + if (e == se_query_del) + { + TSheet_field& s = (TSheet_field&)o; + TToken_string& row = s.row(jolly); + const TRecnotype progr = row.get_long(0); + return progr >= MOV_CUSTOM; + } + break; + case A_DATAREG: + { + // Mi interessa solo fe_edit + if(e != fe_modify) break; + // Controllo che la data sia < della data documento e l'esercizio sia quello richiesto + TDate datareg = o.get(), datadoc = o.mask().get(A_DATADOC); + if(datareg >= get_date(F_DATAINI) && datareg <= get_date(F_DATAFIN)) + { + // Controllo la data del documento + if(datadoc.ok()) + { + if(datadoc > datareg) + { + error_box("La data del documento è antecedente a quella di registrazione"); + o.set(""); + } + } + } + else + { + error_box("La data di registrazione non appartiene al periodo corrente"); + o.set(""); + } + } + break; + case A_DATADOC: + { + // Mi interessa solo fe_edit + if(e != fe_modify) break; + TDate datareg = o.mask().get(A_DATAREG), datadoc = o.get(); + // Controllo la data di registrazione + if(datareg.ok()) + { + if(datadoc > datareg) + { + error_box("La data del documento è antecedente a quella di registrazione"); + o.set(""); + } + } + } + break; + case A_AUTOFATT: + if(e == fe_modify) + { + TString piva, cofi; + // Se ha impostato un autofattura metto cf e piva dell'azienda + if(o.get() == "X") + { + TString key; key << prefix().firm().get("TIPOA") << "|" << prefix().firm().get("CODANAGR"); + piva = cache().get(LF_ANAG, key, "PAIV"); + cofi = cache().get(LF_ANAG, key, "COFI"); + } + // Altrimenti provo a prenderli da clifo + else + { + TString tipocf, codcf; + // Controllo se è un cliente occasionale + tipocf = "O"; + codcf = o.mask().get(A_OCFPI); + if(codcf.empty()) + { + tipocf = o.mask().get(A_TIPOCF); + codcf = o.mask().get(A_CODCF); + } + TRectype app = getCli(tipocf, codcf); + piva = app.get("PAIV"); + cofi = app.get("COFI"); + } + o.mask().set(A_PAIV, piva); + o.mask().set(A_COFI, cofi); + } + break; + case A_ALIQUOTA: + if(e == fe_modify) + { + // Calcolo la natura + o.mask().set(A_NATURA, natura(o.get())); + // Se esiste un imponibile calcolo l'imposta + real imponibile = o.mask().get(A_IMPONIBILE), imposta = ZERO; + if(imponibile > 0) + { + imposta = imponibile * real(cache().get("%IVA", o.get(), "R0")) / 100; + o.mask().set(A_IMPOSTA, imposta.round(2).string()); + } + } + break; + case A_IMPONIBILE: + if(e == fe_modify) + { + // Se esiste l'iva calcolo l'imposta + real imponibile = o.get(), imposta = ZERO; + TString codiva = o.mask().get(A_ALIQUOTA); + if(codiva != "") + { + imposta = imponibile * real(cache().get("%IVA", codiva, "R0")) / 100; + o.mask().set(A_IMPOSTA, imposta.round(2).string()); + } + } + break; + case A_IMPOSTA: + if(e == fe_modify) + { + // Controllo dell'esistenza sia di codiva che dell'imponibile e verifico che l'importo immesso sia corretto + real imponibile = o.mask().get(A_IMPONIBILE), imposta = ZERO; + TString codiva = o.mask().get(A_ALIQUOTA); + if(codiva != "" && imponibile > ZERO) + { + imposta = imponibile * real(cache().get("%IVA", codiva, "R0")) / 100; imposta = imposta.round(2); + // Controllo che l'aliquota calcolata sia == a quella che ho qua + real impostaInserita = o.get(); + if(impostaInserita != imposta) + { + TString msg; + msg << "Attenzione!! Il valore immesso " << impostaInserita.string() << "€ non è corretto!\n"; + msg << "Valore corretto: " << imposta.string() << "€\nVuoi proseguire?"; + if(!yesno_box(msg)) + { + o.set(imposta.string()); + } + } + } + } + case A_TIPOCF: + case A_CODCF: + case A_OCFPI: + { + if(e != fe_modify) break; + TString tipocf, codcf; + // Controllo se è un cliente occasionale + tipocf = "O"; + codcf = o.mask().get(A_OCFPI); + if(codcf.empty()) + { + tipocf = o.mask().get(A_TIPOCF); + codcf = o.mask().get(A_CODCF); + } + TRectype app = getCli(tipocf, codcf); + o.mask().set(A_RAGSOC, app.get("RAGSOC")); + o.mask().set(A_RFSO, app.get("CODRFSO")); + o.mask().set(A_RAGSOCRFSO, getRFSO(app.get("CODRFSO"))); + o.mask().set(A_PAIV, app.get("PAIV")); + o.mask().set(A_COFI, app.get("COFI")); + + // Controllo autofattura + TString key; key << prefix().firm().get("TIPOA") << "|" << prefix().firm().get("CODANAGR"); + TString piva = cache().get(LF_ANAG, key, "PAIV"); + if(piva == app.get("PAIV")) + { + // Autofattura! + o.mask().set(A_AUTOFATT, "X"); + } + } + case DLG_SAVEREC: + if(e == fe_button) + saveAll(); + break; + case DLG_ARCHIVE: + if(e == fe_button) + checkAll(); + break; + case DLG_EDIT: + if(e == fe_button) + { + TSheet_field& sheet = sfield(F_RIGHE); + if(sheet.items() > 0) + { + sheet.esporta(); + } + else + { + warning_box("Impossibile esportare una griglia vuota"); + } + } + break; default: break; } @@ -659,25 +894,196 @@ bool TTrFa_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) const short id = o.dlg(); if (e == fe_modify && jolly == 1) { - if (id >= A_NUMERO && id < A_COFI && id != A_FORZATA) + if (id >= START_SHEET && id < END_SHEET && id != A_FORZATA) { o.mask().set(A_FORZATA, true); } } if (e == fe_modify && jolly == 0) { - if (id >= F_DATAINI && id <= F_FATTSEL) + if (id >= START_MASK && id <= END_MASK) { setFilterChanged(); } + if(id >= START_BOOLEAN && id <= END_BOOLEAN) + saveConfig(); } return true; } +void TTrFa_mask::loadConfig() +{ + // Rilevo i tipi scelti + TToken_string tipidoc(ini_get_string(CONFIG_DITTA, "tf", "TIPIDOC")); + // Potrei fare un for su TToken_string ma non darebbe la possibilità di flaggare tutto in caso di prima installazione + for(int pos = 0; pos < tipidoc.items(); pos++) + { + set(getTipoDoc(tipidoc.get(pos)), "X"); + } +} +void TTrFa_mask::saveConfig() +{ + TToken_string tipidoc; + for(int id = START_BOOLEAN; id <= END_BOOLEAN; id++) + { + if(get_bool(id)) + { + tipidoc.add(getTipoDoc(id)); + } + } + ini_set_string(CONFIG_DITTA, "tf", "TIPIDOC", tipidoc); +} + +/* salvo tutti i record modificati */ +bool TTrFa_mask::saveAll() +{ + TSheet_field& sheet = sfield(F_RIGHE); + //TString_array& strarr = sheet.rows_array(); + TString mod = ""; + FOR_EACH_SHEET_ROW(sheet, r, strarr) + { + strarr->get(_forzata, mod); + if(mod == "X") + { + bool ok, retry = false; + do + { + ok = saveRec(*strarr); + if(!ok) + { + TString msg = "Errore durante il salvataggio del movimento "; + msg << "alla riga " << r << "\nRitentare?"; + retry = yesno_box(msg); + } + } while(retry && !ok); + if(!ok) + return false; + } + } + return true; +} + +bool TTrFa_mask::checkAll() +{ + // Controllo di avere uno sheet pieno + if(!checkNotEmpty()) return true; + + if(yesno_box("Controllare tutti i C.F. P.IVA?")) + { + TExternal_app servizio("cg1 -2 L"); + servizio.run(); + } + static TPrinter stampa; + stampa.reset(); + stampa.open(); + TPrintrow riga; + riga.put(TR("------------------ Controllo Errori TF -------------------"), 30); + stampa.setheaderline(1, riga); + riga.reset(); + riga.put("N.Registrazione", 0); + riga.put("N.Documento", 20); + riga.put("Tipo errore", 40); + stampa.setheaderline(3, riga); + riga.reset(); + riga.put(TR("Tutti i record errati sono stati segnati con il codice \"Errore\" e non verranno inviati"), 0); + stampa.setheaderline(2, riga); + riga.reset(); + stampa.setheaderline(4, riga); + TSheet_field& sheet = sfield(F_RIGHE); + FOR_EACH_SHEET_ROW(sheet, r, strarr) + { + checkRec(&stampa, *strarr); + } + stampa.close(); + return true; +} + +inline void printError(TPrinter* stampa, TString movimento, TString documento, TString msgerr) +{ + TPrintrow riga; + riga.put(movimento, 0); + riga.put(documento, 20); + riga.put(msgerr, 40); + stampa->print(riga); +} + +bool TTrFa_mask::checkRec(TPrinter* stampa, TToken_string rec) +{ + + bool ok = true; + TString numMov = rec.get(_numero), numDoc = rec.get(_numdoc); + TString msgerr; + TString coderr; + // Controllo date *********************************************************************************** + TDate reg = rec.get(_datareg), doc = rec.get(_datadoc); + if(reg < doc) + { + ok = false; + msgerr.cut(0) << "Data registrazione precedente alla data del documento"; + printError(stampa, numMov, numDoc, msgerr); + coderr << "1;"; + } + + // Controllo aliquota, imponibile e imposta ********************************************************* + TCodiceIVA codiva(rec.get(_aliquota)); + TString nat = rec.get(_natura), realNat(natura(rec.get(_aliquota))); + nat.ltrim(); // Se vuoto arriva con uno spazio + real imponibile = rec.get(_imponibile), imposta = rec.get(_importoIVA); + if(nat != realNat) + { + msgerr.cut(0) << "Natura del movimento errata, valore dichiarato: " << nat << " valore corretto: " << realNat; + printError(stampa, numMov, numDoc, msgerr); + coderr << "2;"; + } + + real realImp = imponibile * codiva.percentuale() / CENTO; + realImp.round(2); + if(imposta != realImp) + { + msgerr.cut(0) << "Imposta errata, valore dichiarato: " << imposta.string() << " valore corretto: " << realImp.string(); + printError(stampa, numMov, numDoc, msgerr); + coderr << "3;"; + } + + // Controllo Stato *********************************************************************************** + /* + TRectype clifo = getCli(rec.get(_tipocf), rec.get(_codcf)); + if(clifo.get("STATOCF") == "" && + */ + // Flaggo il record con i messaggi di errore + if(!ok) + { + rec.add("E", _invio); + rec.add(coderr, _coderr); + } + + return ok; +} + +bool TTrFa_mask::checkNotEmpty() +{ + TSheet_field& sheet = sfield(F_RIGHE); + TString msg("La tabella dei movimenti è vuota, vuoi caricarla con i filtri selezionati?"); + if(sheet.empty() && yesno_box(msg)) + { + load_sheet(); + } + return sheet.full(); +} + +TRecnotype TTrFa_mask::nuovo_progr() const +{ + static TRectype app(LF_TRASFATT); + app.last(TLocalisamfile(LF_TRASFATT)); + // Lo inizializzo solo la prima volta poi incremento + static TRecnotype numreg = app.get_long("NUMREG") > MOV_CUSTOM ? app.get_long("NUMREG") : MOV_CUSTOM; + numreg++; + return numreg; +} void TTrFa_mask::load_sheet() { - const char tipocf = get(F_TIPOCF)[0]; - const long codcf = get_long(F_CODCF); + const char tipo = get(F_TIPOCF)[0]; + const long codice = get_long(F_CODCF); TDate dal = get_date(F_DATAINI), al = get_date(F_DATAFIN); //TString key; key << "TIPOA=" << prefix().firm().get("TIPOA")<< ",CODANAGR=" << prefix().firm().get("CODANAGR"); TString key; key << prefix().firm().get("TIPOA") << "|" << prefix().firm().get("CODANAGR"); @@ -688,87 +1094,83 @@ void TTrFa_mask::load_sheet() TSheet_field& sheet = sfield(F_RIGHE); TString_array& strarr = sheet.rows_array(); - + sheet.hide(); // Nascondo lo sheet per guadagnare un 20% di velocità di caricamento, le ottimizzazioni da PRO! - sheet.destroy(); + if(!sheet.empty()) + sheet.destroy(); TAssoc_array recimposte; - int next = c.updateFilters(tipocf, codcf, dal, al, recimposte, get_int(F_FATTSEL)); - while(next < eof) + int items = c.updateFilters(tipo, codice, dal, al, get_int(F_FATTSEL)); + for(bool ok = true; items > 0 && ok;) { - TRectype mov(c.getMov()), miva(c.getIva()), mcust(c.getTrasfatt()); - TToken_string* row = new TToken_string; - + TString tipocf, codcf; + int err = c.next(recimposte, ok, tipocf, codcf); // Carico i clienti - TRelation r_cli(LF_CLIFO); - TRectype filCli(r_cli.curr()); - filCli.put("TIPOCF", mov.get("TIPO")); - filCli.put("CODCF", mov.get("CODCF")); - TCursor c_cli(&r_cli, "", 1, &filCli, &filCli); c_cli.items(); - c_cli = 0; - TRectype cli(c_cli.curr()); + TRectype cli = getCli(tipocf, codcf); FOR_EACH_ASSOC_OBJECT(recimposte, h, iva, rec) { + TToken_string* row = new TToken_string; TRectype movimento = *(TRectype*)rec; - row->add(next == movcustom ? mcust.get("TFINVIO") : miva.get("TFINVIO"), 0); //Forzo la posizione - row->add(row[0] == "X"? "" : "X"); // Se è già stata spedita la riga non viene preselezionata - row->add(next == movcustom ? "X" : ""); - row->add(movimento.get_long("NUMREG")); - row->add(miva.get_long("NUMRIG")); - row->add(cli.get("TIPOCF")); - row->add(cli.get("CODCF")); - row->add(cli.get_bool("OCCAS") ? "X" : ""); - row->add(cli.get("RAGSOC")); - row->add(cli.get("CODRFSO")); - row->add(movimento.get("TIPODOC")); // Tipo documento - row->add(movimento.get_long("NUMDOC")); // Numero documento - row->add(movimento.get_date("DATADOC")); // Data documento - row->add(natura(iva)); // NATURA! - row->add(get_IVA(iva)); // Aliquota! - row->add(findDetraib(iva)); // Detraibilità - row->add(movimento.get_real("IMPONIBILE")); // Imponibile - row->add(movimento.get_real("IMPOSTA")); // Imposta - row->add(revCharge(mov.get("CODCAUS"))); // Rev.Charge - row->add(pivaDitta == cli.get("PAIV") ? 'X' : '\0'); // AutoFatt - if(strcmp(row->get(19), "X") == 0) // Se è un autofattura + // Controllo che sia un tipo documento da leggere + if(!get_bool(getTipoDoc(movimento.get("TIPODOC")))) continue; + + /* Siccome mi cambiano l'ordine ogni volta e non ho voglia di cambiare tutto ovunque + * basta settare i valori negli enum e lo sheet + */ + TRectype isCust = getTrasFatt(movimento.get("NUMREG"), iva); + + row->add(isCust.get_bool("TFINVIO") ? "X" : "", _spedita); // Spedita + row->add("X"); // Da spedire, sempre! + row->add(isCust.full() ? "X" : "", _forzata); // Modificato + row->add(movimento.get_long("NUMREG"), _numero); // Numero registrazione + row->add(movimento.get_date("DATAREG"), _datareg); // Data Registrazione + row->add(movimento.get("TIPO"), _tipocf); // Tipo Cli/For + row->add(movimento.get("CODCF"), _codcf); // Codice Cli/For + row->add(movimento.get("OCCAS"), _occas); // Codice Occasionale + row->add(cli.get("RAGSOC"), _ragsoc); // Ragione sociale + row->add(cli.get("CODRFSO"), _rfso); // Codice RF/SO + row->add(getRFSO(cli.get("CODRFSO")), _ragsocrfso); // Ragione Sociale RF/SO + row->add(movimento.get("TIPODOC"), _codnum); // Tipo documento + row->add(movimento.get_long("NUMDOC"), _numdoc); // Numero documento + row->add(movimento.get_date("DATADOC"), _datadoc); // Data documento + row->add(natura(iva), _natura); // NATURA! + row->add(iva, _aliquota); // Codice aliquota! + row->add(findDetraib(movimento.get("TIPODET")), _detraibile); // Detraibilità + row->add(movimento.get_real("IMPONIBILE"), _imponibile); // Imponibile + row->add(movimento.get_real("IMPOSTA"), _importoIVA); // Imposta + row->add(revCharge(movimento.get("NUMREG")), _reverse); // Rev.Charge + + /* + * Possono esistere movimenti custom dove il cliente ha una partita IVA propria + * ma è stato flaggato l'autofattura, quindi in trasfat è presente il codice cliente con PIVA e CODFIS della ditta. + * Controllo sia il movimento che il cliente + */ + if(movimento.get("AUTOFATT") == "X" || pivaDitta == cli.get("PAIV")) // Se è un autofattura { - row->add(pivaDitta); - row->add(cofiDitta); + row->add("X", _autofatt); // AutoFatt + row->add(pivaDitta, _paiv); // P.IVA + row->add(cofiDitta, _codfis); // Codice Fiscale } else { - row->add(cli.get("PAIV")); - row->add(cli.get("COFI")); + row->add("", _autofatt); // AutoFatt + row->add(cli.get("PAIV"), _paiv); // P.IVA + row->add(cli.get("COFI"), _codfis); // Codice Fiscale } strarr.add(row); } recimposte.destroy(); - next = c.next(recimposte); } sheet.force_update(); sheet.show(); } -TString TTrFa_mask::findDetraib(TString codiva) const +TString TTrFa_mask::findDetraib(TString tipodet) const { - // Mi creo un cursore per i valori di indetraibilità, così facendo mi risparmio operazioni lente dopo - static TRelation r_indetr(LF_TABCOM); - static TRectype f_indetr(r_indetr.curr()); f_indetr.put("COD", "DET"); - static TCursor c_indetr(&r_indetr, "", 1, &f_indetr, &f_indetr); - - TString codtab = cache().get("%IVA", codiva, "S4"); - if(codtab.full()) - { - for(c_indetr = 0; c_indetr.pos() < c_indetr.items(); ++c_indetr) - { - TRectype row = c_indetr.curr(); - if(codtab == row.get("CODTAB")) - return (CENTO - row.get_real("R0")).stringa(6,2); - } - } - return "0.00"; + real perc = cache().get("%DET", tipodet, "R0"); + return perc.stringa(6,2); } const char * TTrFa_mask::natura(const TString& codiva) const @@ -809,57 +1211,28 @@ real TTrFa_mask::get_IVA(const TString& codiva) const return ai.get_real("R0"); } -char TTrFa_mask::revCharge(TString codcaus) const +TString TTrFa_mask::revCharge(TString numreg) const { - const TRectype& caus = cache().get(LF_CAUSALI, codcaus); - const int reg_spec = caus.get_int(CAU_REGSPIVA); - if (reg_spec == 13 || reg_spec == 50 || reg_spec == 51) // reverse charge - return 'X'; - return '\0'; + TString key = numreg; key << "|1"; + return cache().get(LF_RMOV, key).empty() ? "X" : ""; +} + +TString TTrFa_mask::getRFSO(TString codrfso) const +{ + TString key; key << codrfso[0] << "|" << codrfso.mid(1); + return cache().get(LF_ANAG, key, "RAGSOC"); +} + +TTrFa_mask::TTrFa_mask(TString msk) + : TAutomask(msk), _filter_changed(true) +{ + loadConfig(); } ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_app ///////////////////////////////////////////////////////////////////////////////////// -class TTrFa_app : public TSkeleton_application -{ - TAnagrafica _ditta; - TString16 _cofi; - TFilename _dbname; - TLog_report* _log; - TString _logTFF; - enum { _spedita, _invio, _forzata, _numero, _numriga, _tipocf, _codcf, _ocfpi, _ragsoc, _rfso, _codnum, _numdoc, _datadoc, - _natura, _aliquota, _detraibile, _imponibile, _imposta, _reverse, _autofatt, _paiv, _codfis }; - -private: - int parse_line(const TString& line, TString& var, TString& val) const; - bool create_table(TScanner& TFF, const TString& table); - bool addDT(TString8& hfatt, TString20& bfatt, TToken_string* strarr); - bool setEsportato(TToken_string* strarr); - //const TRectype* find_parent_row(const TRectype& rdoc) const; - //int find_ancestors(const TRiga_documento& rdoc, TArray& ancestors) const; - -protected: - //const char* descrizione(const TRiga_documento& rdoc) const; - //const TRectype& cco(const TRectype& doc) const; // Contratto/Convenzione/Offerta - - void log(int severity, const char* msg); - bool show_log(); - void set_IVA(const TString& codiva, TTrFa_record& TFF) const; - void set_IVA(const TRiga_documento& rdoc, TTrFa_record& TFF) const; - bool syncronizeDB(); - bool createDB(); - -public: - virtual bool create(); - virtual bool destroy(); - virtual void main_loop(); - bool send(TTrFa_mask* msk); - - TTrFa_app() : _log(NULL) {} -}; - void TTrFa_app::log(int severity, const char* msg) { if (severity < 0) @@ -1027,7 +1400,7 @@ bool TTrFa_app::create() _dbname = prefix().get_studio(); // base direcotry _dbname.add("sql"); make_dir(_dbname); - TString16 d; d.format("TR%05ld.db", prefix().get_codditta()); + TString16 d; d.format("TF%05ld.db", prefix().get_codditta()); _dbname.add(d); bool create = !_dbname.exist(); @@ -1081,105 +1454,223 @@ bool TTrFa_app::createDB() bool TTrFa_app::send(TTrFa_mask* msk) { + // Controllo se è la prima esecuzione, in caso positivo chiedo se vuole controllare p.iva e cf + bool first = ini_get_bool(CONFIG_DITTA, "tf", "FirstExec", true); + if(first) + { + if(yesno_box("Stai eseguendo il programma per la prima volta,\nvuoi controllare di avere tutti i Codici Fiscali e Partite IVA corrette?")) + { + TExternal_app checkApp("cg1 -2 L"); + checkApp.run(); + } + ini_set_bool(CONFIG_DITTA, "tf", "FirstExec", false); + } // Mi carico i miei dati - TSheet_field& sheet = msk->sfield(F_RIGHE); - bool ok; + // Booleano per appendere i record nel db + _append = false; + // Controllo che non ci sia già una esportazione in attesa + TString query; query << "SELECT * FROM TFF0100F WHERE P1_KEYPRGINVIO='" << DTE_PROVV << "' OR P1_KEYPRGINVIO='" << DTR_PROVV << "';"; + TODBC_recordset testProv(query); + if(testProv.items() > 0) + { + + TString msg; + if(get_hostname() == "GIARDINI") + msg << "Gentilissima Ilaria, Il tuo fantastico programmatore di quartiere ci tiene a farti notare che sono già presenti dei record provvisori da esportare, cosa vorresti fare?"; + else + msg << "Sono già presenti dei record da esportare, cosa vuoi fare?"; + _append = custom_box(msg, "Aggiungi", "Sovrascrivi", NULL) == 1; + + if(!_append) + { + // Elimino la roba + warning_box("Va che non hai implementato l'eliminazione della roba nel db"); + } + } + + /*********************************************************************************************** + * Esporto + ***********************************************************************************************/ + xvt_sql_begin(_db); + // Testata + if(!_append) + tff0100(sheet); // Se devo appendere vuol dire che c'è già! + // Anagrafica + tff0400(sheet); + // Documenti + tff0700(sheet); + + if(false) + { + log(-1, "WTF!?"); + xvt_sql_rollback(_db); + //return false; + } + if(xvt_sql_commit(_db)) + { + // Imposto l'esportazione + setEsportato(sheet); + } + TProgress_monitor p(sheet.items(),"Esportazione fatture"); FOR_EACH_SHEET_ROW(sheet, r, strarr) { - //if(!p.add_status()) - //return false; + if(!p.add_status()) + return false; if(strcmp(strarr->get(_invio), "X") != 0) continue; // Non mi interessa se non è selezionata - - TString8 hfatt; // Codice univoco di 6 caratteri dell'ufficio P.A. - TString20 bfatt; // Codice univoco di 20 caratteri del documento - - hfatt.cut(0) << strarr->get(_tipocf) << "_" << strarr->get(_codcf); - bfatt.cut(0) << TDate(strarr->get(_datadoc)).year() << "|" << strarr->get(_codnum) << "|" << strarr->get(_numdoc) << "|" << strarr->get(_numriga); - - log(-1, bfatt); - - // Preparo l'esportazione - xvt_sql_begin(_db); - - ok = addDT(hfatt, bfatt, strarr); - - // Controllo in caso di errore - if(!ok) - { - log(-1, "WTF!?"); - xvt_sql_rollback(_db); - //return false; - } - else - { - xvt_sql_commit(_db); - // Imposto l'esportazione - setEsportato(strarr); - } } return true; } -bool TTrFa_app::addDT(TString8& hfatt, TString20& bfatt, TToken_string* strarr) +TString TTrFa_app::getKey(TToken_string* strarr) +{ + return strarr->get_char(_tipocf) == 'C' ? DTE_PROVV : DTR_PROVV; +} + +TString TTrFa_app::getHeader(TToken_string* strarr) +{ + /* + // Chiave header (20): TIPOCF(1) + NANANANANA(10) + CODCF(6) + TString header; header.format("%c3753N4108E%06ld", strarr->get_char(_tipocf), strarr->get_int(_codcf)); + return header; + */ + + /* Devo crearmi una struttura dove immagazzino delle strutture di clienti e all'interno ci metto i numeratori che mi chiedono + * Così facendo mando a puttane persino l'append che potevo tranquillamente implementare prima e creare fastidiose query per capire dove cazzo sto + */ + // Chiave header (20): TIPOCF(1) + CODCF(6) + IDHEADER(10) + static long int idHeader = 0L; + + // Cerco/Aggiungo il Clifo all'std::map + TString keyMap; keyMap << strarr->get_char(_tipocf) << strarr->get_int(_codcf); + clifoDoc app; + // Non è presente e lo inserisco + if(mCliDoc.find(keyMap) == mCliDoc.end()) + { + idHeader++; + app.contCliFo = idHeader; + app.countDoc = 0L; + mCliDoc.insert(std::pair(keyMap, app)); + } + // É presente lo prendo + else + { + app = mCliDoc[keyMap]; + } + TString header; header.format("%c%06ld%010ld", strarr->get_char(_tipocf), strarr->get_int(_codcf), app.contCliFo); + // Ritorno l'header + return header; +} + +TString TTrFa_app::getBody(TToken_string* strarr) +{ + /* + // Chiave body (20): TIPODOC(2) + DATADOC[YEAR](4) + NUMDOC(7) + AAA(3) + CODALIQUOTA(4) + TDate datadoc(strarr->get(_datadoc)); + TString body; body.format("%02s%04d%07s%04s", strarr->get(_codnum), datadoc.year(), strarr->get(_numdoc), strarr->get(_aliquota)); + return body; + */ + + /* Sembra che utilizzare identificatori chiari e sensati in questo mondo non è concesso, quindi adesso vi sbatto un bell'ID numerico + * Ok per OGNI cliente devo assegnarli un identificativo del numero della fattura + */ + TString keyMap; keyMap << strarr->get_char(_tipocf) << strarr->get_int(_codcf); + + clifoDoc app = mCliDoc[keyMap]; + app.countDoc += 1; + mCliDoc[keyMap] = app; + + TString body; body.format("%010d%010d", app.contCliFo, app.countDoc); + return body; +} + +bool TTrFa_app::tff0100(TSheet_field& sheet) { const char* const paese = "IT"; static const TFirm& firm = prefix().firm(); - // - TTrFa_record tff0100f("TFF0100F"); - tff0100f.set("P1_KEYHEADERFATT", hfatt); - tff0100f.set("P1_KEYBODYFATT", bfatt); - - tff0100f.set("P1_TRASMITTPAESE", paese); - tff0100f.set("P1_TRASMITTCOD", _cofi); - tff0100f.set("P1_PRGINVIO", ""); // Ci pensa SiAggTF - - tff0100f.set("P1_CODDEST", hfatt); + // Controllo la presenza di clienti e fornitori + // Scandisco in maniera ignorante sperando di beccare subito un cliente e un fornitore + bool cli = false, fo = false; + FOR_EACH_SHEET_ROW(sheet, r, strarr) + { + if(strarr->get_char(_tipocf) == 'C') + cli = true; + else + fo = true; + if(cli & fo) break; + } + // Metto qua il numero di telefono per dopo TString80 tel; tel << firm.get(NDT_PTEL) << firm.get(NDT_TEL); - tff0100f.set("P1_TELEFONO", tel); - tff0100f.set("P1_MAIL", firm.get(NDT_MAIL)); - tff0100f.set("P1_GESTIONE", "D"); - tff0100f.insert(); + bool ok = true; + if(cli) + { + TTrFa_record dte("TFF0100F"); + dte.set("P1_KEYPRGINVIO", DTE_PROVV); + dte.set("P1_TRASMITTPAESE", paese); + dte.set("P1_TRASMITTCOD", _cofi); + dte.set("P1_TIPOINVIO", "DTE"); + dte.set("P1_TELEFONO", tel); + dte.set("P1_MAIL", firm.get(NDT_MAIL)); + dte.set("P1_GESTIONE", ""); + ok = dte.insert(); + if(!ok) return false; + ok = tff0200(DTE_PROVV); + if(!ok) return false; + } + if(fo) + { + TTrFa_record dtr("TFF0100F"); + dtr.set("P1_KEYPRGINVIO", DTR_PROVV); + dtr.set("P1_TRASMITTPAESE", paese); + dtr.set("P1_TRASMITTCOD", _cofi); + dtr.set("P1_TIPOINVIO", "DTR"); + dtr.set("P1_TELEFONO", tel); + dtr.set("P1_MAIL", firm.get(NDT_MAIL)); + dtr.set("P1_GESTIONE", ""); + ok = dtr.insert(); + if(!ok) return false; + ok = tff0200(DTR_PROVV); + if(!ok) return false; + } + return ok; +} - // - +bool TTrFa_app::tff0200(TString key) +{ /******************************************************************************************************************** - * CessionarioCommit * + * Cedeprest * ********************************************************************************************************************/ - // TTrFa_record tff0200f("TFF0200F"); - tff0200f.set("P2_KEYHEADERFATT", hfatt); - tff0200f.set("P2_KEYBODYFATT", bfatt); - tff0200f.remove(); + tff0200f.set("P2_KEYPRGINVIO", key); if (_ditta.partita_IVA().full()) { - tff0200f.set("P2_FISCIVAPAESE", paese); // Sempre IT - tff0200f.set("P2_FISCIVACOD", _ditta.partita_IVA()); + tff0200f.set("P2_FISCIVAPAESE", _ditta.stato_partita_IVA()); // Sempre IT + tff0200f.set("P2_FISCIVACOD", _ditta.partita_IVA()); } - tff0200f.set("P2_CODFISCALE", _ditta.codice_fiscale()); + tff0200f.set("P2_CODFISCALE", _ditta.codice_fiscale()); if (_ditta.fisica()) { - tff0200f.set("P2_ANANOME", _ditta.nome()); - tff0200f.set("P2_ANACOGNOME", _ditta.cognome()); + tff0200f.set("P2_ANANOME", _ditta.nome()); + tff0200f.set("P2_ANACOGNOME", _ditta.cognome()); } else { - tff0200f.set("P2_ANADENOMIN", _ditta.ragione_sociale()); + tff0200f.set("P2_ANADENOMIN", _ditta.ragione_sociale()); } // DatiSede - tff0200f.set("P2_SEDEIND", _ditta.via_residenza()); - tff0200f.set("P2_SEDENRCIVICO", _ditta.civico_residenza()); - tff0200f.set("P2_SEDECAP", _ditta.CAP_residenza()); - tff0200f.set("P2_SEDECOMUNE", _ditta.comune_residenza()); - tff0200f.set("P2_SEDEPROV", _ditta.provincia_residenza()); - tff0200f.set("P2_SEDENAZ", paese); + tff0200f.set("P2_SEDEIND", _ditta.via_residenza()); + tff0200f.set("P2_SEDENRCIVICO", _ditta.civico_residenza()); + tff0200f.set("P2_SEDECAP", _ditta.CAP_residenza()); + tff0200f.set("P2_SEDECOMUNE", _ditta.comune_residenza()); + tff0200f.set("P2_SEDEPROV", _ditta.provincia_residenza()); + tff0200f.set("P2_SEDENAZ", _ditta.localita_residenza()); - TString myrfso; + myrfso = ""; if(haveRFSO(myrfso)) { TRectype r_ana = cache().get(LF_ANAG, TString(myrfso[0]) << myrfso.sub(1)); @@ -1196,93 +1687,199 @@ bool TTrFa_app::addDT(TString8& hfatt, TString20& bfatt, TToken_string* strarr) } else // Rappresentante Fiscale { - TTrFa_record tff0300f("TFF0300F"); - tff0300f.set("P3_KEYHEADERFATT", hfatt); - tff0300f.set("P3_KEYBODYFATT", bfatt); - tff0300f.remove(); - tff0300f.set("P3_FISCIVAPAESE", paese); // Io italiano posso avere un rappresentante fiscale italiano - tff0300f.set("P3_FISCIVACODICE", r_ana.get("PAIV")); + bool ok = tff0300(key, r_ana); + if(!ok) return false; + } + } + tff0200f.set("P2_GESTIONE", ""); + return tff0200f.insert(); +} +bool TTrFa_app::tff0300(TString key, TRectype r_ana) +{ + TTrFa_record tff0300f("TFF0300F"); + tff0300f.set("P3_KEYPRGINVIO", key); + TString stato = r_ana.get("STATOPAIV") == "" ? "IT" : r_ana.get("STATOPAIV"); + tff0300f.set("P3_FISCIVAPAESE", stato); + tff0300f.set("P3_FISCIVACODICE", r_ana.get("PAIV")); - if(r_ana.get_char("TIPOA") == 'G') - { - tff0300f.set("P3_ANADENOMI", r_ana.get("RAGSOC")); - } - else - { - TString nomCom = r_ana.get("RAGSOC"); - tff0300f.set("P3_ANANOME", nomCom.sub(30)); - tff0300f.set("P3_ANACOGNOME", nomCom.sub(0,30)); - } - tff0300f.set("P3_GESTIONE", "D"); - tff0300f.insert(); - } - } - - tff0200f.set("P2_GESTIONE", "D"); - - tff0200f.insert(); - - /******************************************************************************************************************** - * Cedeprest * - ********************************************************************************************************************/ - - // - - TAnagrafica cedeprest(LF_CLIFO, strarr->get_char(_tipocf), strarr->get_long(_codcf)); - TRectype r_cedeprest = cache().get(LF_CLIFO, TString(strarr->get_char(_tipocf)) << "|" << strarr->get_long(_codcf)); - TString statocli = cache().get("%STA", r_cedeprest.get("STATOCF"), "S2"); - // - - TTrFa_record tff0400f("TFF0400F"); - tff0400f.set("P4_KEYHEADERFATT", hfatt); - tff0400f.set("P4_KEYBODYFATT", bfatt); - tff0400f.remove(); - - // Autofattura - if(strcmp(strarr->get(_autofatt),"X") == 0) + if(r_ana.get_char("TIPOA") == 'G') { - tff0400f.set("P4_FISCIVAPAESE", paese); - tff0400f.set("P4_FISCIVACOD", _ditta.partita_IVA()); - tff0400f.set("P4_CODFISC", _ditta.codice_fiscale()); - } - else // Fattura normale - { - if (cedeprest.stato_partita_IVA().full() && cedeprest.partita_IVA().full()) - { - tff0400f.set("P4_FISCIVAPAESE", cedeprest.stato_partita_IVA()); - tff0400f.set("P4_FISCIVACOD", cedeprest.partita_IVA()); - } - else - tff0400f.set("P4_CODFISC", cedeprest.codice_fiscale()); - } - - if (cedeprest.fisica()) - { - tff0400f.set("P4_ANANOME", cedeprest.nome()); - tff0400f.set("P4_ANACOGNOME", cedeprest.cognome()); + tff0300f.set("P3_ANADENOMI", r_ana.get("RAGSOC")); } else { - tff0400f.set("P4_ANADENOM", cedeprest.ragione_sociale()); - } - // DatiSede - tff0400f.set("P4_SEDEIND", cedeprest.via_residenza()); - tff0400f.set("P4_SEDENRCIVICO", cedeprest.civico_residenza()); - tff0400f.set("P4_SEDECAP", cedeprest.CAP_residenza()); - tff0400f.set("P4_SEDECOMUNE", cedeprest.comune_residenza()); - tff0400f.set("P4_SEDEPROV", cedeprest.provincia_residenza()); - tff0400f.set("P4_SEDENAZ", statocli); - tff0400f.set("P4_GESTIONE", "D"); - tff0400f.insert(); - - TString rfso; - if(hasRFSO(strarr->get_char(_tipocf), strarr->get_long(_codcf), rfso)) + TString nomCom = r_ana.get("RAGSOC"); + tff0300f.set("P3_ANANOME", nomCom.sub(30)); + tff0300f.set("P3_ANACOGNOME", nomCom.sub(0,30)); + } + tff0300f.set("P3_GESTIONE", "D"); + return tff0300f.insert(); +} + +bool TTrFa_app::tff0400(TSheet_field& sheet) +{ + // Siccome non siamo in grado di fare delle join devo in qualche modo evitare di caricare clienti già caricati quindi mi salvo tutto in un bel TToken_string e controllo + // Era troppo complicato fare una join codice cliente con i documenti per prendere solo quelli valorizzati. + TToken_string clifoSent = ""; + bool ok = true; + TProgress_monitor p(sheet.items(),"Caricamento Clienti/Fornitori"); + FOR_EACH_SHEET_ROW(sheet, r, strarr) { - TRectype r_ana = cache().get(LF_ANAG, TString(myrfso[0]) << rfso.sub(1)); + if(!p.add_status()) + return false; + if(strcmp(strarr->get(_invio), "X") != 0) continue; // Non mi interessa se non è selezionata + + // Controllo il clifo, se non c'è lo aggiungo altrimenti salto sto giro + TString checkClifo; checkClifo << strarr->get_char(_tipocf) << strarr->get_long(_codcf); + if(clifoSent.get_pos(checkClifo) < 0) + clifoSent.add(checkClifo); + else + continue; + + TAnagrafica cedeprest(LF_CLIFO, strarr->get_char(_tipocf), strarr->get_long(_codcf)); + TRectype r_cedeprest = cache().get(LF_CLIFO, TString(strarr->get_char(_tipocf)) << "|" << strarr->get_long(_codcf)); + TString statocli = cache().get("%STA", r_cedeprest.get("STATOCF"), "S2"); + + TTrFa_record tff0400f("TFF0400F"); + tff0400f.set("P4_KEYPRGINVIO", getKey(strarr)); + tff0400f.set("P4_KEYHEADERFATT", getHeader(strarr)); + + // Autofattura + if(strcmp(strarr->get(_autofatt),"X") == 0) + { + tff0400f.set("P4_FISCIVAPAESE", _ditta.stato_partita_IVA()); + tff0400f.set("P4_FISCIVACOD", _ditta.partita_IVA()); + tff0400f.set("P4_CODFISC", _ditta.codice_fiscale()); + } + else // Fattura normale + { + if (cedeprest.stato_partita_IVA().full() && cedeprest.partita_IVA().full()) + { + tff0400f.set("P4_FISCIVAPAESE", cedeprest.stato_partita_IVA()); + tff0400f.set("P4_FISCIVACOD", cedeprest.partita_IVA()); + } + else + { + tff0400f.set("P4_CODFISC", cedeprest.codice_fiscale()); + } + } + + if (cedeprest.fisica()) + { + tff0400f.set("P4_ANANOME", cedeprest.nome()); + tff0400f.set("P4_ANACOGNOME", cedeprest.cognome()); + } + else + { + tff0400f.set("P4_ANADENOM", cedeprest.ragione_sociale()); + } + // DatiSede + tff0400f.set("P4_SEDEIND", cedeprest.via_residenza()); + tff0400f.set("P4_SEDENRCIVICO", cedeprest.civico_residenza()); + tff0400f.set("P4_SEDECAP", cedeprest.CAP_residenza()); + tff0400f.set("P4_SEDECOMUNE", cedeprest.comune_residenza()); + tff0400f.set("P4_SEDEPROV", cedeprest.provincia_residenza()); + tff0400f.set("P4_SEDENAZ", statocli); + tff0400f.set("P4_GESTIONE", "D"); + ok = tff0400f.insert(); + + // Controllo dopo l'inserimento del tff0400 + if(!ok) return false; + + TString rfso = strarr->get(_rfso); + if(rfso.full()) + { + TRectype r_ana = cache().get(LF_ANAG, TString(myrfso[0]) << rfso.sub(1)); + ok = tff3100(strarr, r_ana); + } + + // E dopo l'inserimento del tff3100 + if(!ok) return false; + } + return ok; +} + +bool TTrFa_app::tff0700(TSheet_field& sheet) +{ + + /******************************************************************************************************************** + * Fattura * + ********************************************************************************************************************/ + // Mentre per i clienti è una porcata per le fatture non posso fare altrimenti, potrebbe essere che i clienti mettono righe in fondo customizzate spezzando fatture + TToken_string fattSent = ""; + bool ok = true; + TProgress_monitor p(sheet.items(),"Caricamento Fatture"); + FOR_EACH_SHEET_ROW(sheet, r, strarr) + { + if(!p.add_status()) + return false; + if(strcmp(strarr->get(_invio), "X") != 0) continue; // Non mi interessa se non è selezionata + + + TString checkFatt; checkFatt << strarr->get_char(_tipocf) << strarr->get_long(_codcf) << strarr->get(_numdoc); + if(fattSent.get_pos(checkFatt) < 0) + { + fattSent.add(checkFatt); + + // + TTrFa_record tff0700f("TFF0700F"); + tff0700f.set("P7_KEYPRGINVIO", getKey(strarr)); + tff0700f.set("P7_KEYHEADERFATT", getHeader(strarr)); + tff0700f.set("P7_KEYBODYFATT", getBody(strarr)); + + tff0700f.set("P7_TIPODOC", decodTipo(strarr)); + tff0700f.set("P7_DATA", strarr->get(_datadoc)); + tff0700f.set("P7_NUMERO", strarr->get(_numdoc)); + + tff0700f.set("P7_GESTIONE", ""); + ok = tff0700f.insert(); + + // Controllo dopo l'inserimento del tff0700f + if(!ok) return false; + } + // In qualsiasi caso va messa la riga + ok = tff2200(strarr); + + // E dopo l'inserimento del tff2200 + if(!ok) return false; + } + return ok; +} + +bool TTrFa_app::tff2200(TToken_string* strarr) +{ + TTrFa_record tff2200f("TFF2200F"); + tff2200f.set("PL_KEYPRGINVIO", getKey(strarr)); + tff2200f.set("PL_KEYHEADERFATT", getHeader(strarr)); + tff2200f.set("PL_KEYBODYFATT", getBody(strarr)); + + tff2200f.set("PL_IMPONIBILE", strarr->get(_imponibile)); + tff2200f.set("PL_IMPOSTA", strarr->get(_importoIVA)); + tff2200f.set("PL_ALIQUOTAIVA", strarr->get(_aliquota)); + tff2200f.set("PL_NATURA", strarr->get(_natura)); + real det(strarr->get(_detraibile)); + // Nella conversione la vigola viene persa e 100,00 diventa 10.000 quindi divido + det /= CENTO; + if(det > ZERO) + { + tff2200f.set("PL_DETRAIBILE", det.stringa(6,2)); + } + else if(false) // Sempre disabilitato! + { + tff2200f.set("PL_DEDUCIBILE", "SI"); + } + + tff2200f.set("PL_GESTIONE", "D"); + return tff2200f.insert(); +} + +bool TTrFa_app::tff3100(TToken_string* strarr, TRectype r_ana) +{ TTrFa_record tff3100f("TFF3100F"); - tff3100f.set("PH_KEYHEADERFATT", hfatt); - tff3100f.set("PH_KEYBODYFATT", bfatt); - tff3100f.remove(); + tff3100f.set("PH_KEYPRGINVIO", getKey(strarr)); + tff3100f.set("PH_KEYHEADERFATT", getHeader(strarr)); + if(_append) + tff3100f.remove(); if(r_ana.get_char("TIPORFSO") == 'S') // Stabile Organizzazione { @@ -1298,7 +1895,8 @@ bool TTrFa_app::addDT(TString8& hfatt, TString20& bfatt, TToken_string* strarr) { // La P.IVA del rappresentante fiscale deve essere in AT quindi non faccio alcun controllo, // se il valore nullo perchè Extra CEE non è un errore di campo (Anche perchè che senso ha un RF extra CEE?) - tff3100f.set("PH_FISCIVAPAESE", r_ana.get("STATOPAIV") == "" ? "IT" : r_ana.get("STATOPAIV")); + TString stato = r_ana.get("STATOPAIV") == "" ? "IT" : r_ana.get("STATOPAIV"); + tff3100f.set("PH_FISCIVAPAESE", stato); tff3100f.set("PH_FISCIVACODICE", r_ana.get("PAIV")); if(r_ana.get_char("TIPOA") == 'G') @@ -1313,82 +1911,33 @@ bool TTrFa_app::addDT(TString8& hfatt, TString20& bfatt, TToken_string* strarr) } } tff3100f.set("PH_GESTIONE", "D"); - tff3100f.insert(); - } - - // - - /******************************************************************************************************************** - * Fattura * - ********************************************************************************************************************/ - - // - TTrFa_record tff0700f("TFF0700F"); - tff0700f.set("P7_KEYHEADERFATT", hfatt); - tff0700f.set("P7_KEYBODYFATT", bfatt); - tff0700f.remove(); - - tff0700f.set("P7_GESTIONE", "D"); - tff0700f.insert(); - - TTrFa_record tff2200f("TFF2200F"); - tff2200f.set("PL_KEYHEADERFATT", hfatt); - tff2200f.set("PL_KEYBODYFATT", bfatt); - tff2200f.remove(); - - tff2200f.set("PL_IMPONIBILE", strarr->get(_imponibile)); - tff2200f.set("PL_IMPOSTA", strarr->get(_imposta)); - tff2200f.set("PL_ALIQUOTAIVA", strarr->get(_aliquota)); - tff2200f.set("PL_NATURA", strarr->get(_natura)); - if(strcmp(strarr->get(_detraibile), "0.00") != 0) - { - tff2200f.set("PL_DETRAIBILE", strarr->get(_detraibile)); - } - else if(false) // Sempre disabilitato! - { - tff2200f.set("PL_DEDUCIBILE", "SI"); - } - - tff2200f.set("PL_GESTIONE", "D"); - tff2200f.insert(); - - return true; + return tff3100f.insert(); } -bool TTrFa_app::setEsportato(TToken_string* strarr) +bool TTrFa_app::setEsportato(TSheet_field& sheet) { - if(strcmp(strarr->get(_forzata), "X") == 0) + bool ok = true; + TProgress_monitor p(sheet.items(),"Segno l'esportazione sui records"); + FOR_EACH_SHEET_ROW(sheet, r, strarr) { - // Devo inserire la riga in trasfatt - TRectype row(LF_TRASFATT); - if(strcmp(strarr->get(_spedita), "X") == 0) // Controllo che non sia già stata spedita prima + if(!p.add_status()) + return false; + if(strcmp(strarr->get(_invio), "X") != 0) continue; // Non mi interessa se non è selezionata + if(strcmp(strarr->get(_forzata), "X") == 0) { - row = cache().get(LF_TRASFATT, TString(strarr->get(_numero))<<"|"<<(strarr->get(_numriga))); + ok = saveRec(*strarr, true); + if(!ok) return false; } else { - row.put("NUMREG", strarr->get(_numero)); - row.put("NUMRIG", strarr->get(_numriga)); + TRectype row = cache().get(LF_RMOV, TString(strarr->get(_numero))); + row.put("TFINVIO", "X"); + row.put("TFDATA", TDate(TODAY)); + ok = row.rewrite(TLocalisamfile(LF_RMOV)) == NOERR; + if(!ok) return false; } - row.put("TIPODOC", strarr->get(_codnum)); - row.put("NDOC", strarr->get(_numdoc)); - row.put("DATADOC", strarr->get(_datadoc)); - row.put("IMPONIBILE", strarr->get(_imponibile)); - row.put("IMPOSTA", strarr->get(_imposta)); - row.put("REVCHARGE", strarr->get(_reverse)); - row.put("AUTOFATT", strarr->get(_autofatt)); - row.put("TFINVIO", "X"); - row.put("TFDATA", TDate(TODAY)); - - return row.write_rewrite(TLocalisamfile(LF_TRASFATT)) == NOERR; - } - else - { - TRectype row = cache().get(LF_RMOVIVA, TString(strarr->get(_numero))<<"|"<<(strarr->get(_numriga))); - row.put("TFINVIO", "X"); - row.put("TFDATA", TDate(TODAY)); - return row.rewrite(TLocalisamfile(LF_RMOVIVA)) == NOERR; } + return ok; } void TTrFa_app::main_loop() @@ -1397,14 +1946,8 @@ void TTrFa_app::main_loop() while (msk.run() == K_ENTER) { - TSheet_field& sheet = msk.sfield(F_RIGHE); - TString msg("La tabella dei movimenti è vuota, vuoi caricarla con i filtri selezionati?"); - if(sheet.empty() && yesno_box(msg)) - { - msk.load_sheet(); - } - - send(&msk); + if(msk.checkNotEmpty()) + send(&msk); } } diff --git a/src/tf/tf0100a.h b/src/tf/tf0100a.h index 727732333..d47b8d8a0 100644 --- a/src/tf/tf0100a.h +++ b/src/tf/tf0100a.h @@ -1,31 +1,61 @@ -#define F_DATAINI 401 -#define F_DATAFIN 402 -#define F_TIPOCF 403 -#define F_CODCF 404 -#define F_RAGSOC 405 -#define F_FATTSEL 406 +#define START_MASK 401 -#define F_RIGHE 300 +#define F_DATAINI 401 +#define F_DATAFIN 402 +#define F_TIPOCF 403 +#define F_CODCF 404 +#define F_RAGSOC 405 +#define F_FATTSEL 406 +/* Campi booleani documento */ +#define START_BOOLEAN 407 -#define A_SPEDITA 101 -#define A_INVIO 102 -#define A_FORZATA 103 -#define A_NUMERO 104 -#define A_NUMRIGA 105 -#define A_TIPOCF 106 -#define A_CODCF 107 -#define A_OCFPI 108 -#define A_RAGSOC 109 -#define A_RFSO 110 -#define A_TIPODOC 111 -#define A_NUMDOC 112 -#define A_DATADOC 113 -#define A_NATURA 114 -#define A_ALIQUOTA 115 -#define A_DETRAIB 116 -#define A_IMPONIBILE 117 -#define A_IMPOSTA 118 -#define A_REVERSE 119 -#define A_AUTOFATT 120 -#define A_PAIV 121 -#define A_COFI 122 \ No newline at end of file +#define B_TIPO_AUTOFATT 407 +#define B_TIPO_BOLLADOG 408 +#define B_TIPO_CORRNINC 409 +#define B_TIPO_CORR 410 +#define B_TIPO_FATTACQ 411 +#define B_TIPO_FATTFISC 412 +#define B_TIPO_FATTSC 413 +#define B_TIPO_FATTVEN 414 +#define B_TIPO_NOTC 415 +#define B_TIPO_NOTD 416 +#define B_TIPO_RICFIS 417 +#define B_TIPO_RICFISNI 418 +#define B_TIPO_SCONT 419 +#define B_TIPO_SCONTNI 420 +#define B_TIPO_STORDOC 421 + +#define END_BOOLEAN 421 + +#define END_MASK 421 + +#define F_RIGHE 301 // Sheet righe tf + +#define START_SHEET 101 + +#define A_DATAREG 101 +#define A_TIPODOC 102 +#define A_NUMDOC 103 +#define A_DATADOC 104 +#define A_ALIQUOTA 105 +#define A_IMPONIBILE 106 +#define A_IMPOSTA 107 +#define A_NATURA 108 +#define A_DETRAIB 109 +#define A_TIPOCF 110 +#define A_CODCF 111 +#define A_OCFPI 112 +#define A_RAGSOC 113 +#define A_RFSO 114 +#define A_RAGSOCRFSO 115 +#define A_PAIV 116 +#define A_COFI 117 +#define A_REVERSE 118 +#define A_AUTOFATT 119 +#define A_SPEDITA 120 +#define A_INVIO 121 +#define A_FORZATA 122 +#define A_NUMERO 123 +#define A_CODERR 124 + +#define END_SHEET 124 \ No newline at end of file diff --git a/src/tf/tf0100a.uml b/src/tf/tf0100a.uml index 4af536cf6..cceb318c6 100644 --- a/src/tf/tf0100a.uml +++ b/src/tf/tf0100a.uml @@ -1,6 +1,30 @@ #include "tf0100a.h" TOOLBAR "topbar" 0 0 0 2 +BUTTON DLG_RECALC 2 2 +BEGIN + PROMPT 1 1 "Carica" + PICTURE TOOL_CONVERT +END + +BUTTON DLG_ARCHIVE 2 2 +BEGIN + PROMPT 2 1 "Controlla" + PICTURE TOOL_SMILE +END + +BUTTON DLG_SAVEREC 2 2 +BEGIN + PROMPT 3 1 "Salva" + PICTURE TOOL_SAVEREC +END + +BUTTON DLG_EDIT 10 2 +BEGIN + PROMPT 3 1 "E~xcel" + PICTURE TOOL_EXCEL +END + #include ENDPAGE @@ -8,20 +32,19 @@ PAGE "Impostazioni" 0 2 0 0 DATE F_DATAINI BEGIN - PROMPT 1 0 "Data iniziale:" + PROMPT 1 1 "Data iniziale:" CHECKTYPE REQUIRED END DATE F_DATAFIN BEGIN - PROMPT 40 0 "Data Finale: " + PROMPT 40 1 "Data Finale: " CHECKTYPE REQUIRED END RADIOBUTTON F_TIPOCF 15 BEGIN PROMPT 1 2 "Tipo C/F" - ITEM "T|Tutti" ITEM "C|Cliente" ITEM "F|Fornitore" END @@ -41,7 +64,7 @@ BEGIN OUTPUT F_RAGSOC RAGSOC CHEKTYPE NORMAL GROUP 1 - FLAGS "D" + FLAGS "" END STRING F_RAGSOC 50 49 @@ -57,7 +80,7 @@ BEGIN COPY OUTPUT F_CODCF ADD RUN CG0 -1 GROUP 1 - FLAGS "D" + FLAGS "" END @@ -69,35 +92,121 @@ BEGIN ITEM "2|Tutti" END +GROUPBOX DLG_NULL 65 6 +BEGIN + PROMPT 30 7 "Tipi documento selezionati" +END + +BOOLEAN B_TIPO_AUTOFATT +BEGIN + PROMPT 31 8 "Autofattura" + FLAGS "" +END +BOOLEAN B_TIPO_BOLLADOG +BEGIN + PROMPT 45 8 "Bolla dog" + FLAGS "" +END +BOOLEAN B_TIPO_CORRNINC +BEGIN + PROMPT 60 8 "Corr non inc" + FLAGS "" +END +BOOLEAN B_TIPO_CORR +BEGIN + PROMPT 75 8 "Corrispettivo" + FLAGS "" +END +BOOLEAN B_TIPO_FATTACQ +BEGIN + PROMPT 31 9 "Fatt d'Acq" + FLAGS "" +END +BOOLEAN B_TIPO_FATTFISC +BEGIN + PROMPT 45 9 "Fatt Fisc" + FLAGS "" +END +BOOLEAN B_TIPO_FATTSC +BEGIN + PROMPT 60 9 "Fatt Scontr" + FLAGS "" +END +BOOLEAN B_TIPO_FATTVEN +BEGIN + PROMPT 75 9 "Fatt Ven" + FLAGS "" +END +BOOLEAN B_TIPO_NOTC +BEGIN + PROMPT 31 10 "Nota Cred" + FLAGS "" +END +BOOLEAN B_TIPO_NOTD +BEGIN + PROMPT 45 10 "Nota Deb" + FLAGS "" +END +BOOLEAN B_TIPO_RICFIS +BEGIN + PROMPT 60 10 "Ric fis" + FLAGS "" +END +BOOLEAN B_TIPO_RICFISNI +BEGIN + PROMPT 75 10 "Ric Fis NI" + FLAGS "" +END +BOOLEAN B_TIPO_SCONT +BEGIN + PROMPT 31 11 "Scontrino" + FLAGS "" +END +BOOLEAN B_TIPO_SCONTNI +BEGIN + PROMPT 45 11 "Scontrino NI" + FLAGS "" +END +BOOLEAN B_TIPO_STORDOC +BEGIN + PROMPT 60 11 "Storno Doc" + FLAGS "" +END + + + + ENDPAGE PAGE "Trasferimento Fatture" 0 2 0 0 SPREADSHEET F_RIGHE BEGIN - PROMPT 0 0 "" - ITEM "Spedita@3F" - ITEM "Invio@3F" - ITEM "Mod.@3F" - ITEM "N.\nRegistraz.@7F" - ITEM "N.Riga@3F" - ITEM "C/F@2F" - ITEM "Codice@6F" - ITEM "Occas.@3" - ITEM "Ragione Sociale@35" - ITEM "RF/SO@6" - ITEM "Tipo\nDocum.@2" - ITEM "Numero\nDocum.@5" + PROMPT 0 0 "Righe movimenti" + ITEM "Data\n Reg.@8F" + ITEM "Tipo\nDocum.@2F" + ITEM "Numero\nDocum.@5F" ITEM "Data\nDocum.@10" - ITEM "Natura\nIVA@4" ITEM "Aliquota@4" - ITEM "% Detr.@6" ITEM "Imponibile@10" ITEM "Imposta@10" - ITEM "Rev.\nCharge@4" - ITEM "Auto\nfatt.@3" + ITEM "Natura\nIVA@4" + ITEM "% Detr.@6" + ITEM "C/F@2" + ITEM "Codice@6" + ITEM "Occas.@16" + ITEM "Ragione Sociale@35" + ITEM "RF/SO@16" + ITEM "Rag. Soc. RF/SO@35" ITEM "Partita IVA@11" ITEM "Codice Fiscale@15" + ITEM "Rev.\nCharge@4" + ITEM "Auto\nfatt.@3" + ITEM "Spedita@5" + ITEM "Invio@3" + ITEM "Mod.@3" + ITEM "N.\nRegistraz.@10" + ITEM "Codici Errori@10" DEFAULT "*" // Impedisce il salvataggio su profilo .ini END @@ -105,53 +214,54 @@ ENDPAGE ENDMASK -PAGE "Riga" -1 -1 69 10 +PAGE "Riga" -1 -1 -1 -1 BOOLEAN A_SPEDITA BEGIN - PROMPT 40 9 "Gia' spedita" + PROMPT 52 10 "Gia' spedita" FIELD SPEDITA FLAGS "D" END -BOOLEAN A_INVIO +LIST A_INVIO 1 10 BEGIN - PROMPT 40 9 "Da inviare" + PROMPT 1 10 "Da inviare" + ITEM "X|Da Inviare" + ITEM "E|Errore" FIELD INVIO END BOOLEAN A_FORZATA BEGIN - PROMPT 40 9 "Forzatura manuale" + PROMPT 25 10 "Forzatura manuale" FIELD FORZATURA END -NUMBER A_NUMERO 7 +NUMBER A_NUMERO 10 BEGIN PROMPT 1 0 "N.Movimento" FLAGS "D" FIELD PROGR END -NUMBER A_NUMRIGA 3 +DATE A_DATAREG BEGIN - PROMPT 25 0 "N.Riga" - FLAGS "D" - FIELD PROGR + PROMPT 26 0 "Data reg." + FIELD DATAREG + CHEKTYPE REQUIRED END LIST A_TIPOCF 1 10 BEGIN - PROMPT 1 2 "Tipo C/F" + PROMPT 1 1 "Tipo C/F " ITEM "C|Cliente" ITEM "F|Fornitore" FIELD TIPOCF - FLAGS "D" END NUMBER A_CODCF 6 BEGIN - PROMPT 23 2 "Cod. C/F" + PROMPT 26 1 "Cod. C/F" USE LF_CLIFO INPUT TIPOCF A_TIPOCF SELECT INPUT CODCF A_CODCF @@ -160,16 +270,18 @@ BEGIN DISPLAY "Occasionale@C" OCCAS DISPLAY "Partita IVA" PAIV DISPLAY "Codice fiscale@16" COFI - OUTPUT A_CODCF CODCF - CHEKTYPE REQUIRED + OUTPUT A_CODCF CODCF + OUTPUT A_RAGSOC RAGSOC + OUTPUT A_PAIV PAIV + OUTPUT A_COFI COFI ADD RUN cg0 -1 FIELD CODCF - FLAGS "DG" + FLAGS "G" END STRING A_OCFPI 16 BEGIN - PROMPT 43 2 "Occas." + PROMPT 44 1 "Occas." USE LF_OCCAS INPUT CFPI A_OCFPI DISPLAY "Codice@16" CFPI @@ -177,51 +289,72 @@ BEGIN DISPLAY "Partita IVA" PAIV DISPLAY "Codice fiscale@16" COFI OUTPUT A_OCFPI CFPI + OUTPUT A_RAGSOC RAGSOC + OUTPUT A_PAIV PAIV + OUTPUT A_COFI COFI CHEKTYPE NORMAL GROUP 3 ADD RUN cg0 -6 FIELD OCFPI - FLAGS "DG" + FLAGS "G" END STRING A_RAGSOC 50 47 BEGIN FIELD RAGSOC - PROMPT 1 3 "Ragione Sociale " + PROMPT 1 2 "Ragione Sociale" FLAGS "D" END STRING A_RFSO 6 BEGIN FIELD RFSO - PROMPT 30 16 "Codice RF/SO:" + PROMPT 1 4 "Codice RF/SO: " HELP "Codice Rappresentante Fiscale o Stabile Organizzazione" FLAGS "D" END +STRING A_RAGSOCRFSO 50 47 +BEGIN + FIELD RAGSOCRFSO + PROMPT 1 5 "Rag. Soc. RF/SO" + HELP "Ragione Sociale RF/SO" + FLAGS "D" +END + STRING A_TIPODOC 2 BEGIN - PROMPT 23 5 "Tipo doc. " - FLAGS "U" + PROMPT 23 6 "Tipo doc. " FIELD TIPODOC + USE %TPD + INPUT CODTAB A_TIPODOC + DISPLAY "Tipo " CODTAB + DISPLAY "Descrizione @50" S0 + OUTPUT A_TIPODOC CODTAB + WARNING "Tipo documento errato" + CHECKTYPE REQUIRED + FLAGS "U" + ADD NONE END STRING A_NUMDOC 7 BEGIN - PROMPT 23 5 "Num. doc. " + PROMPT 42 6 "Num. doc. " FLAGS "U" FIELD NUMDOC + CHEKTYPE REQUIRED END DATE A_DATADOC BEGIN - PROMPT 1 5 "Data doc. " + PROMPT 1 6 "Data doc." FIELD DATADOC + CHEKTYPE REQUIRED END LIST A_NATURA 1 35 BEGIN - PROMPT 1 6 "Natura IVA" + PROMPT 20 7 "Natura IVA" ITEM "|IVA ordinaria" ITEM "N1|N1 - IVA esclusa ex art 15" ITEM "N2|N2 - IVA non soggetta" @@ -233,16 +366,30 @@ BEGIN FIELD S12 END -NUMBER A_ALIQUOTA 6 2 +STRING A_ALIQUOTA 4 BEGIN - PROMPT 25 7 "Aliquota " - HELP "Percentuale di imposta" - FLAGS "D" + PROMPT 1 7 "Aliquota " + HELP "Codice aliquota" + FIELD CODTAB + KEY 1 + USE %IVA + FLAGS "U" + INPUT CODTAB A_ALIQUOTA + DISPLAY "Codice" CODTAB + DISPLAY "Descrizione@50" S0 + DISPLAY "Tipo" S1 + DISPLAY "%@5" R0 + DISPLAY "Vent." S6 + DISPLAY "Sospeso" B2 + OUTPUT A_ALIQUOTA CODTAB + HELP "Codice IVA" + CHECKTYPE REQUIRED + VALIDATE ZEROFILL_FUNC 2 END STRING A_DETRAIB 6 BEGIN - PROMPT 25 7 "% Detraibilita' " + PROMPT 1 8 "% Detraibilita'" HELP "Percentuale di detraibilita'" FLAGS "D" END @@ -250,13 +397,14 @@ END CURRENCY A_IMPONIBILE 12 BEGIN - PROMPT 1 7 "Imponibile" + PROMPT 42 8 "Imponibile" FIELD IMPORTO + CHEKTYPE REQUIRED END CURRENCY A_IMPOSTA 12 BEGIN - PROMPT 45 7 "Imposta" + PROMPT 42 9 "Imposta " FIELD IMPOSTA END @@ -274,13 +422,19 @@ END STRING A_PAIV 12 BEGIN - PROMPT 1 4 "Partita IVA " + PROMPT 1 3 "Partita IVA " FLAGS "D" END STRING A_COFI 16 BEGIN - PROMPT 33 4 "Codice Fiscale " + PROMPT 33 3 "Codice Fiscale" + FLAGS "D" +END + +STRING A_CODERR 10 +BEGIN + PROMPT -1 -1 "Codice Fiscale" FLAGS "D" END @@ -293,12 +447,6 @@ BEGIN PROMPT 1 1 "" END -BUTTON DLG_USER 2 2 -BEGIN - PROMPT 2 1 "Collega" - PICTURE TOOL_LINK -END - BUTTON DLG_CANCEL 2 2 BEGIN PROMPT 4 1 "" diff --git a/src/tf/tf0100b.h b/src/tf/tf0100b.h new file mode 100644 index 000000000..61c293a38 --- /dev/null +++ b/src/tf/tf0100b.h @@ -0,0 +1,267 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // std::map + +#include "../ve/velib05.h" +#include "../cg/cglib03.h" +#include "../fe/felib.h" + +#include "tf0100a.h" +///////////////////////////////////////////////////////////////////////////////////// +// Globals +///////////////////////////////////////////////////////////////////////////////////// + +static XVT_SQLDB _db = NULL; // TFF sqlite db +enum return_code +{ + found, // Trovato + foundcust, // Trovato in trasfatt + nextmov, // Trovato ma cambiato movimento + eof, // EOF rmoviva + eofm, // EOF mov + after // File mov su un movimento dopo rispetto a rmoviva +}; + +enum filter_fatt +{ + toSend, // Da inviare + sent, // Inviate + all // Tutte +}; + +#define MOV_CUSTOM 10000000 +#define SHEET_GAP 101 +#define DTE_PROVV "DTE0000001" +#define DTR_PROVV "DTR0000001" + +/* Così facendo basta modificare la maschera (e le dichiarazioni di conseguenza) + * per avere l'inserimento nello sheet corretto */ +enum spesometroFields{ + _spedita = A_SPEDITA - SHEET_GAP, + _invio = A_INVIO - SHEET_GAP, + _forzata = A_FORZATA - SHEET_GAP, + _numero = A_NUMERO - SHEET_GAP, + _datareg = A_DATAREG - SHEET_GAP, + _tipocf = A_TIPOCF - SHEET_GAP, + _codcf = A_CODCF - SHEET_GAP, + _occas = A_OCFPI - SHEET_GAP, + _ragsoc = A_RAGSOC - SHEET_GAP, + _rfso = A_RFSO - SHEET_GAP, + _ragsocrfso = A_RAGSOCRFSO - SHEET_GAP, + _codnum = A_TIPODOC - SHEET_GAP, + _numdoc = A_NUMDOC - SHEET_GAP, + _datadoc = A_DATADOC - SHEET_GAP, + _natura = A_NATURA - SHEET_GAP, + _aliquota = A_ALIQUOTA - SHEET_GAP, + _detraibile = A_DETRAIB - SHEET_GAP, + _imponibile = A_IMPONIBILE - SHEET_GAP, + _importoIVA = A_IMPOSTA - SHEET_GAP, // Imposta è già preso + _reverse = A_REVERSE - SHEET_GAP, + _autofatt = A_AUTOFATT - SHEET_GAP, + _paiv = A_PAIV - SHEET_GAP, + _codfis = A_COFI - SHEET_GAP, + _coderr = A_CODERR - SHEET_GAP +}; + +///////////////////////////////////////////////////////////////////////////////////// +// Utilities +///////////////////////////////////////////////////////////////////////////////////// + +// Da un id ritorna il tipo doc corrispondente +TString getTipoDoc(int id); +int getTipoDoc(TString id); +// Ritorna il record custom +TRectype getTrasFatt(TString reg, TString codiva); +// Ritorna il cliente in un record di $clifo, con tipocf = "O" lo cerca in $occas +TRectype getCli(TString tipocf, TString codcf); +// Cerca una stringa all'interno di una SLIST (Potrebbe diventare una funzione di XVT.h) +static SLIST_ELT xvt_slist_find_str(SLIST list, const char* str); +// Controlla se l'azienda ha un RFSO +static bool haveRFSO(TString& codrfso); +// Decodifica il tipo di documento per il trasferimento fatture +static const char* decodTipo(TToken_string* strarr); +// Salvo un singolo record +bool saveRec(TToken_string row, bool esportato = false); + +///////////////////////////////////////////////////////////////////////////////////// +// TTrFa_record +///////////////////////////////////////////////////////////////////////////////////// + +// Contenitore di campi di un record di database SQLite +class TTrFa_record : public TObject +{ + TString8 _table; + TToken_string _key; + TAssoc_array _fields; + +protected: + void copy(const TTrFa_record& rec) { _table = rec._table; _key = rec._key; _fields = rec._fields; } + const TString& var2str(const TString& fld, const TVariant& var) const; + +public: + void reset() { _fields.destroy(); } + void set(const char* fld, const TVariant& var); + void set(const char* fld, long var); + void set(const char* fld, const char* var); + void set(const char* fld, const real& var); + void set(const char* fld, const TString& var); + void set(const char* fld, const TDate& var); + void set(const char* fld, bool var); + const TVariant& get(const char* fld) const; + + bool insert(); + bool remove(); + bool search(); + bool search(const char* k1, const char* k2, const char* k3 = NULL); + + virtual TObject* dup() const { return new TTrFa_record(*this); } + virtual bool ok() const { return _table.not_empty(); } + + TTrFa_record& operator=(const TTrFa_record& rec) { copy(rec); return *this; } + TTrFa_record(const TTrFa_record& rec) { copy(rec); } + TTrFa_record(const char* table); +}; + +///////////////////////////////////////////////////////////////////////////////////// +// TTrFa_cursors +///////////////////////////////////////////////////////////////////////////////////// + +/* + * Classe per la gestione di RMOVIVA, MOV, TFCUST + */ +class TTrFa_cursors : TObject +{ + friend class TCursor; + TISAM_recordset* c_rmoviva; + filter_fatt filFat; + bool _newMov; + // Se trovo un record custom devo saltare tutti quelli che trovo successivamente, per fare ciò utilizzo una TToken_string + TToken_string _alqCust; + + bool filOk(bool alreadySent) { return (filFat == all) || (filFat == sent && alreadySent) || (filFat == toSend && !alreadySent); } + TRectype _next(return_code& code, TString& tipocf, TString& codcf); // Si sposta avanti di un elemento + +public: + TTrFa_cursors() : filFat(all) {}; + ~TTrFa_cursors(); + long int getIvaItems() { return c_rmoviva->items(); } + long int getIvaPos() { return c_rmoviva->cursor()->pos(); } + TRectype getIva() { return c_rmoviva->cursor()->curr(); } + int next(TAssoc_array& recimposte, bool& ok, TString& tipocf, TString& codcf); // Legge tutto il prossimo movimento, in importi mette per ogni codiva la somma + + int updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, int cod = toSend); +}; + +///////////////////////////////////////////////////////////////////////////////////// +// TTrFa_mask +///////////////////////////////////////////////////////////////////////////////////// + +class TTrFa_mask : public TAutomask +{ + friend class TTrFa_cursors; + + TMaskmode _mode; + bool _sheet_dirty; + bool _filter_changed; + +protected: + virtual void next_page(int p); + const char * natura(const TString& codiva) const; + real get_IVA(const TString& codiva) const; + TString findDetraib(TString tipodet) const; + TString revCharge(TString numreg) const; + TString getRFSO(TString codrfso) const; + TRecnotype nuovo_progr() const; + + virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); + +public: + void setFilterChanged() { _filter_changed = true; } + void load_sheet(); + TTrFa_mask(TString msk); + ~TTrFa_mask(); + // Carico i tipi documento all'inizio + void loadConfig(); + // Salvo i tipi documento + void saveConfig(); + // Salvo tutti i records + bool saveAll(); + // Controllo tutti i records + bool checkAll(); + // Testo validità record + bool checkRec(TPrinter* stampa, TToken_string rec); + // Controllo che siano presenti records + bool checkNotEmpty(); +}; +// Funzione inline di stampa +inline void printError(TPrinter* stampa, TString movimento, TString documento, TString msgerr); + +///////////////////////////////////////////////////////////////////////////////////// +// TTrFa_app +///////////////////////////////////////////////////////////////////////////////////// + +struct clifoDoc +{ + long contCliFo; + long countDoc; +}; + +class TTrFa_app : public TSkeleton_application +{ + TAnagrafica _ditta; + TString16 _cofi; + TFilename _dbname; + TLog_report* _log; + TString _logTFF; + bool _append; + TString myrfso; + static long header; + // Solitamente nei programmi di campo cerco di sfruttare le classi interne ma per mancanza di tempo sono costretto a usare l'std::vector + std::map mCliDoc; + +private: + int parse_line(const TString& line, TString& var, TString& val) const; + bool create_table(TScanner& TFF, const TString& table); + TString getKey(TToken_string* strarr); + TString getHeader(TToken_string* strarr); + TString getBody(TToken_string* strarr); + bool tff0100(TSheet_field& sheet); // Header esportazione + bool tff0200(TString key); // Anagrafica ditta + bool tff0300(TString key, TRectype r_ana); // Rappresentante fiscale ditta + bool tff0400(TSheet_field& sheet); // Anagrafica clifo + bool tff0700(TSheet_field& sheet); // Testata documento + bool tff2200(TToken_string* strarr); // Riepilogo aliquote + bool tff3100(TToken_string* strarr, TRectype r_ana); // Rappresentante fiscale clifo + bool setEsportato(TSheet_field& sheet); + //const TRectype* find_parent_row(const TRectype& rdoc) const; + //int find_ancestors(const TRiga_documento& rdoc, TArray& ancestors) const; + +protected: + //const char* descrizione(const TRiga_documento& rdoc) const; + //const TRectype& cco(const TRectype& doc) const; // Contratto/Convenzione/Offerta + + void log(int severity, const char* msg); + bool show_log(); + void set_IVA(const TString& codiva, TTrFa_record& TFF) const; + void set_IVA(const TRiga_documento& rdoc, TTrFa_record& TFF) const; + bool syncronizeDB(); + bool createDB(); + +public: + virtual bool create(); + virtual bool destroy(); + virtual void main_loop(); + bool send(TTrFa_mask* msk); + + TTrFa_app() : _log(NULL) {} +}; \ No newline at end of file diff --git a/src/tf/tf0200.cpp b/src/tf/tf0200.cpp index ff9baee34..cc7c15714 100644 --- a/src/tf/tf0200.cpp +++ b/src/tf/tf0200.cpp @@ -344,12 +344,6 @@ bool ComLiqPerIva_mask::on_field_event(TOperable_field& o, TField_event e, long real creprec = ZERO; real appcreaprec; calcolaCreditoPrec(creprec, appcreaprec, mensile, get_int(F_ANNO), get_int(F_MESE)); creaprec = appcreaprec + creaprec; - // Controllo che il credito non sia sforato sotto 0 - if (creaprec < ZERO) - { - TString msg = "Attenzione! Capienza del credito dell'anno precedente esaurita di "; msg << (creaprec * - UNO).stringa(0,2) << "€"; - warning_box(msg); - } } real credito = get_real(F_IVADOVC) + get_real(F_CREPREC) + creaprec + get_real(F_VEAUE) + get_real(F_CREIMP) + get_real(F_ACCDOV); diff --git a/src/tf/tff.ini b/src/tf/tff.ini index 5aa1415f7..17bae17dc 100644 --- a/src/tf/tff.ini +++ b/src/tf/tff.ini @@ -1,70 +1,65 @@ [TFF0100F] -P1_KEYHEADERFATT = CHAR(20) -P1_KEYBODYFATT = CHAR(20) +P1_KEYPRGINVIO = CHAR(10) +P1_TRASMITTPAESE = CHAR(2) +P1_TRASMITTCOD = CHAR(28) +P1_TIPOINVIO = CHAR(4) +P1_FMTTRASMISS = CHAR(5) +P1_CODDEST = CHAR(7) +P1_TELEFONO = CHAR(12) +P1_MAIL = CHAR(256) +P1_GESTIONE = CHAR(1) +P1_CODFISCDICH = CHAR(16) +P1_CODCARICADICH = CHAR(2) +P1_PROTOCOLLO = CHAR(18) +P1_ERRINT = CHAR(1) +P1_ERREST = CHAR(1) -P1_TRASMITTPAESE = CHAR(2) -P1_TRASMITTCOD = CHAR(28) -P1_PRGINVIO = CHAR(10) -P1_FMTTRASMISS = CHAR(5) -P1_CODDEST = CHAR(6) -P1_TELEFONO = CHAR(12) -P1_MAIL = CHAR(256) - -P1_GESTIONE = CHAR(1) -P1_ERRINT = CHAR(1) -P1_ERREST = CHAR(1) - -INDEX_1 = P1_KEYHEADERFATT,P1_KEYBODYFATT +INDEX_1 = P1_KEYPRGINVIO [TFF0200F] -P2_KEYHEADERFATT = CHAR(20) -P2_KEYBODYFATT = CHAR(20) +P2_KEYPRGINVIO = CHAR(20) +P2_FISCIVAPAESE = CHAR(2) +P2_FISCIVACOD = CHAR(28) +P2_CODFISCALE = CHAR(16) +P2_ANADENOMIN = CHAR(80) +P2_ANANOME = CHAR(60) +P2_ANACOGNOME = CHAR(60) +P2_ANATITOLO = CHAR(10) +P2_ANACODEORI = CHAR(17) +P2_ALBOPROFESS = CHAR(60) +P2_PROVALBO = CHAR(2) +P2_NRISCRIZALBO = CHAR(60) +P2_DTISCRIZEALBO = DATE +P2_REGFISCALE = CHAR(4) +P2_SEDEIND = CHAR(60) +P2_SEDENRCIVICO = CHAR(8) +P2_SEDECAP = NUMERIC(5, 0) +P2_SEDECOMUNE = CHAR(60) +P2_SEDEPROV = CHAR(2) +P2_SEDENAZ = CHAR(2) +P2_STABORGIND = CHAR(60) +P2_STABORGNRCIVICO = CHAR(8) +P2_STABORGCAP = NUMERIC(5, 0) +P2_STABORGCOMUNE = CHAR(60) +P2_STABORGPROV = CHAR(2) +P2_STABORGNAZ = CHAR(2) +P2_ISCRREAUFF = CHAR(2) +P2_ISCRREANUM = CHAR(20) +P2_ISCRREACAP = VARNUMERIC(15, 2) +P2_ISCRREASOCIOU = CHAR(2) +P2_ISCRREASLIQUID = CHAR(2) +P2_CONTATTITELEF = CHAR(12) +P2_CONTATTIFAX = CHAR(12) +P2_CONTATTIMAIL = CHAR(256) +P2_RIFAMMINISTR = CHAR(20) +P2_GESTIONE = CHAR(1) +P2_ERRINT = CHAR(1) +P2_ERREST = CHAR(1) -P2_FISCIVAPAESE = CHAR(2) -P2_FISCIVACOD = CHAR(28) -P2_CODFISCALE = CHAR(16) -P2_ANADENOMIN = CHAR(80) -P2_ANANOME = CHAR(60) -P2_ANACOGNOME = CHAR(60) -P2_ANATITOLO = CHAR(10) -P2_ANACODEORI = CHAR(17) -P2_ALBOPROFESS = CHAR(60) -P2_PROVALBO = CHAR(2) -P2_NRISCRIZALBO = CHAR(60) -P2_DTISCRIZEALBO = DATE -P2_REGFISCALE = CHAR(4) -P2_SEDEIND = CHAR(60) -P2_SEDENRCIVICO = CHAR(8) -P2_SEDECAP = NUMERIC(5, 0) -P2_SEDECOMUNE = CHAR(60) -P2_SEDEPROV = CHAR(2) -P2_SEDENAZ = CHAR(2) -P2_STABORGIND = CHAR(60) -P2_STABORGNRCIVICO = CHAR(8) -P2_STABORGCAP = NUMERIC(5, 0) -P2_STABORGCOMUNE = CHAR(60) -P2_STABORGPROV = CHAR(2) -P2_STABORGNAZ = CHAR(2) -P2_ISCRREAUFF = CHAR(2) -P2_ISCRREANUM = CHAR(20) -P2_ISCRREACAP = VARNUMERIC(15, 2) -P2_ISCRREASOCIOU = CHAR(2) -P2_ISCRREASLIQUID = CHAR(2) -P2_CONTATTITELEF = CHAR(12) -P2_CONTATTIFAX = CHAR(12) -P2_CONTATTIMAIL = CHAR(256) -P2_RIFAMMINISTR = CHAR(20) - -P2_GESTIONE = CHAR(1) -P2_ERRINT = CHAR(1) -P2_ERREST = CHAR(1) - -INDEX_1 = P2_KEYHEADERFATT,P2_KEYBODYFATT +INDEX_1 = P2_KEYPRGINVIO [TFF0300F] -P3_KEYHEADERFATT = CHAR(20) -P3_KEYBODYFATT = CHAR(20) - +P3_KEYPRGINVIO = CHAR(10) P3_FISCIVAPAESE = CHAR(2) P3_FISCIVACODICE = CHAR(28) P3_CODFISC = CHAR(16) @@ -73,16 +68,15 @@ P3_ANANOME = CHAR(60) P3_ANACOGNOME = CHAR(60) P3_ANATITOLO = CHAR(10) P3_ANACODEORI = CHAR(17) - P3_GESTIONE = CHAR(1) P3_ERRINT = CHAR(1) P3_ERREST = CHAR(1) -INDEX_1 = P3_KEYHEADERFATT,P3_KEYBODYFATT +INDEX_1 = P3_KEYPRGINVIO [TFF0400F] +P4_KEYPRGINVIO = CHAR(10) P4_KEYHEADERFATT = CHAR(20) -P4_KEYBODYFATT = CHAR(20) P4_FISCIVAPAESE = CHAR(2) P4_FISCIVACOD = CHAR(28) P4_CODFISC = CHAR(16) @@ -91,71 +85,68 @@ P4_ANANOME = CHAR(60) P4_ANACOGNOME = CHAR(60) P4_ANATITOLO = CHAR(10) P4_ANACODEORI = CHAR(17) - P4_SEDEIND = CHAR(60) P4_SEDENRCIVICO = CHAR(8) P4_SEDECAP = CHAR(5) P4_SEDECOMUNE = CHAR(60) P4_SEDEPROV = CHAR(2) P4_SEDENAZ = CHAR(2) +P4_GESTIONE = CHAR(1) +P4_ERRINT = CHAR(1) +P4_ERREST = CHAR(1) -P4_GESTIONE = CHAR(1) -P4_ERRINT = CHAR(1) -P4_ERREST = CHAR(1) - -INDEX_1 = P4_KEYHEADERFATT,P4_KEYBODYFATT +INDEX_1 = P4_KEYPRGINVIO,P4_KEYHEADERFATT [TFF0700F] -P7_KEYHEADERFATT = CHAR(20) -P7_KEYBODYFATT = CHAR(20) -P7_TIPODOC = CHAR(4) -P7_DIVISA = CHAR(3) -P7_DATA = DATE -P7_NUMERO = CHAR(20) +P7_KEYPRGINVIO = CHAR(10) +P7_KEYHEADERFATT = CHAR(20) +P7_KEYBODYFATT = CHAR(20) +P7_PROGRESSIVO = NUMERIC(7,0) +P7_TIPODOC = CHAR(4) +P7_DIVISA = CHAR(3) +P7_DATA = DATE +P7_NUMERO = CHAR(20) +P7_TIPORITENUTA = CHAR(4) +P7_IMPORTORIT = NUMERIC(15,2) +P7_ALIQUOTARIT = NUMERIC(6,2) +P7_CAUSPAGAM = CHAR(1) +P7_NUMEROBOLLO = CHAR(14) +P7_IMPORTOBOLLO = NUMERIC(15,2) +P7_GESTIONE = CHAR(1) +P7_ERRINT = CHAR(1) +P7_ERREST = CHAR(1) +P7_DATAREG = DATE +P7_NUMEROREG = NUMERIC(20,0) +P7_TIPOREG = CHAR(6) +P7_PROTOCOLLO = CHAR(18) +P7_POSIZIONE = NUMERIC(7,0) -P7_TIPORITENUTA = CHAR(4) -P7_IMPORTORIT = NUMERIC(15, 2) -P7_ALIQUOTARIT = NUMERIC(6, 2) -P7_CAUSPAGAM = CHAR(1) -P7_NUMEROBOLLO = CHAR(14) -P7_IMPORTOBOLLO = NUMERIC(15, 2) +INDEX_1 = P7_KEYPRGINVIO,P7_KEYHEADERFATT,P7_KEYBODYFATT -P7_DATAREG = DATE -P7_NUMEROREG = NUMERIC(20, 0) -P7_TIPOREG = CHAR(6) -P7_PROTOCOLLO = CHAR(18) -P7_POSIZIONE = NUMERIC(4, 0) - -P7_GESTIONE = CHAR(1) -P7_ERRINT = CHAR(1) -P7_ERREST = CHAR(1) - -INDEX_1 = P7_KEYHEADERFATT,P7_KEYBODYFATT [TFF2200F] -PL_KEYHEADERFATT = CHAR(20) -PL_KEYBODYFATT = CHAR(20) +PL_KEYPRGINVIO = CHAR(10) +PL_KEYHEADERFATT = CHAR(20) +PL_KEYBODYFATT = CHAR(20) +PL_ALIQUOTAIVA = NUMERIC(6,2) +PL_NATURA = CHAR(2) +PL_SPESEACCESS = NUMERIC(15,2) +PL_ARROTONDAM = NUMERIC(15,2) +PL_IMPONIBILE = NUMERIC(15,2) +PL_IMPOSTA = NUMERIC(15,2) +PL_ESIGIVA = CHAR(1) +PL_RIFNORMATIVO = CHAR(100) +PL_DETRAIBILE = NUMERIC(6, 2) +PD_DEDUCIBILE = CHAR(2) +PL_GESTIONE = CHAR(1) +PL_ERRINT = CHAR(1) +PL_ERREST = CHAR(1) -PL_ALIQUOTAIVA = NUMERIC(6,2) -PL_NATURA = CHAR(2) -PL_SPESEACCESS = NUMERIC(15,2) -PL_ARROTONDAM = NUMERIC(15,2) -PL_IMPONIBILE = NUMERIC(15,2) -PL_IMPOSTA = NUMERIC(15,2) -PL_ESIGIVA = CHAR(1) -PL_RIFNORMATIVO = CHAR(100) -PL_DETRAIBILE = NUMERIC(6, 2) -PD_DEDUCIBILE = CHAR(2) - -PL_GESTIONE = CHAR(1) -PL_ERRINT = CHAR(1) -PL_ERREST = CHAR(1) - -INDEX_1 = PL_KEYHEADERFATT,PL_KEYBODYFATT +INDEX_1 = PL_KEYPRGINVIO,PL_KEYHEADERFATT,PL_KEYBODYFATT [TFF3100F] +PH_KEYPRGINVIO = CHAR(10) PH_KEYHEADERFATT = CHAR(20) -PH_KEYBODYFATT = CHAR(20) PH_STABORGIND = CHAR(60) PH_STABORGNRCIVICO = CHAR(8) PH_STABORGCAP = NUMERIC(5) @@ -171,4 +162,4 @@ PH_GESTIONE = CHAR(1) PH_ERRINT = CHAR(1) PH_ERREST = CHAR(1) -INDEX_1 = PH_KEYHEADERFATT,PH_KEYBODYFATT \ No newline at end of file +INDEX_1 = PH_KEYPRGINVIO,PH_KEYHEADERFATT \ No newline at end of file