#include "tf0.h" // Le definizioni sono qua #include "tf0100b.h" #include // dongle() #include // Oracle Recset #include #include #include #include #include #include #include #include ///////////////////////////////////////////////////////////////////////////////////// // Utilities ///////////////////////////////////////////////////////////////////////////////////// // Le funzioni quelle belle TString getTipoDoc(int id) { TString ret; switch(id) { case B_TIPO_AUTOFATT: ret = "AF"; break; case B_TIPO_FATTACQ: ret = "FA"; break; case B_TIPO_FATTFISC: ret = "FF"; 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_STORDOC: ret = "ST"; 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_FATTSC: ret = "FS"; 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; */ default: ret = "ERR"; 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) { SLIST_ELT e = NULL; for (e = xvt_slist_get_first(list); e; e = xvt_slist_get_next(list, e)) { const char* val = xvt_slist_get(list, e, NULL); if (xvt_str_compare_ignoring_case(str, val) == 0) break; } return e; } // Controlla se l'azienda ha un RFSO static bool haveRFSO(TString& codrfso) { codrfso = cache().get(LF_NDITTE, prefix().firm().codice(), "CODRFSO"); if(codrfso == "") return false; return true; } /* 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) { TRectype mov = cache().get(LF_MOV, strarr->get(_numero)); TCausale caus(mov.get("CODCAUS"), mov.get_int("ANNOIVA")); TString tipodoc; tipodoc << strarr->get(_codnum); // Le autofatture possono essere solo di tipo TDO1 e le bolle doganali nel dubbio pure if(tipodoc == "AF" || tipodoc == "BD") return "TD01"; else if(tipodoc == "FA" || tipodoc == "FV") { // 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"; } } else if(tipodoc == "NC") return "TD04"; else if(tipodoc == "ND") return "TD05"; else return tipodoc; } /* Salvo il record modificato in TFCustom */ bool saveRec(TToken_string row, bool esportato) { static TLocalisamfile trasfatt(LF_TRASFATT); // 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); } // Controllo non si sa mai if(rCust.empty()) { 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(trasfatt) == NOERR; } ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_record ///////////////////////////////////////////////////////////////////////////////////// // Imposta il valore di un campo variant void TTrFa_record::set(const char* fld, const TVariant& var) { CHECK(fld && *fld, "Null field name"); if (var.is_null()) { _fields.remove(fld); } else { TVariant* obj = (TVariant*)_fields.objptr(fld); if (obj != NULL) *obj = var; else _fields.add(fld, new TVariant(var)); } } // Imposta il valore di un campo intero void TTrFa_record::set(const char* fld, long val) { const TVariant var(val); set(fld, var); } // Imposta il valore di un campo stringa void TTrFa_record::set(const char* fld, const char* val) { if (val == NULL) set(fld, NULL_VARIANT); else { const TVariant var(val); set(fld, var); } } // Imposta il valore di un campo stringa void TTrFa_record::set(const char* fld, const TString& val) { const TVariant var(val); set(fld, var); } // Imposta il valore di un campo numerico void TTrFa_record::set(const char* fld, const real& val) { const TVariant var(val); set(fld, var); } // Imposta il valore di un campo data in formato ISO void TTrFa_record::set(const char* fld, const TDate& val) { if (val.ok()) { const TVariant var(val); set(fld, var); } else set(fld, ""); } // Imposta il valore di un campo booleano void TTrFa_record::set(const char* fld, bool var) { set(fld, var ? "SI" : "NO"); } // Legge il valore di un campo variant const TVariant& TTrFa_record::get(const char* fld) const { const TVariant* var = (const TVariant*)_fields.objptr(fld); return var ? *var : NULL_VARIANT; } // Converte un variant in una stringa valida per SQLite const TString& TTrFa_record::var2str(const TString& fldname, const TVariant& var) const { const TFieldtypes vt = var.type(); if (vt == _realfld) { const TCurrency v(var.as_real(), "", ZERO, fldname.find("IMPONIBILE")>0 || fldname.find("IMPOSTA")>0); TString& tmp = get_tmp_string(); tmp << '\'' << v.string() << '\''; tmp.replace(',','.'); return tmp; } if (vt == _datefld) { TString& tmp = get_tmp_string(); tmp << '\'' << var.as_date().string(full, '-', full, full, amg_date) << '\''; return tmp; } const TString& str = var.as_string(); bool apici = vt == _alfafld; if (apici && str[0] != '0' && real::is_natural(str)) apici = false; if (!apici) return str; TString& tmp = get_tmp_string(); tmp = str; for (int a = str.rfind('\''); a >= 0; a--) { if (tmp[a] == '\'') tmp.insert("'", a); } tmp.insert("'", 0); tmp << '\''; return tmp; } // Elimina il record in base ai campi chiave bool TTrFa_record::remove() { TString256 query; query << "DELETE FROM " << _table << " WHERE "; int nkf = 0; FOR_EACH_TOKEN(_key, fld) { const TVariant& var = get(fld); if (!var.is_null()) { if (nkf++ > 0) query << " AND "; query << fld << '=' << var2str(fld, var) ; } } CHECKS(nkf >= 2, "Can't remove partial key on table ", (const char*)_table); query << ';'; return xvt_sql_execute(_db, query, NULL, 0L) > 0; } // Callback per la sottostante funzione search() static int tff_search_record(void* jolly, int cols, char** values, char** names) { TTrFa_record& rec = *(TTrFa_record*)jolly; for (int i = 0; i < cols; i++) rec.set(names[i], values[i]); return 0; } // Carica un record in base ai campi chiave bool TTrFa_record::search() { CHECKS(_fields.items() >= _key.items(), "Can't search partial key on table ", _table); TString256 query; query << "SELECT * FROM " << _table << " WHERE "; FOR_EACH_TOKEN(_key, fld) { const TVariant& var = get(fld); if (!var.is_null()) query << fld << '=' << var2str(fld, var) << " AND "; } query.rtrim(5); query << ';'; return xvt_sql_execute(_db, query, tff_search_record, this) == 1; } // Carica un record in base ad un massimo di 3 campi chiave bool TTrFa_record::search(const char* k1, const char* k2, const char* k3) { _fields.destroy(); set(_key.get(0), k1); if (k2 && *k2) set(_key.get(1), k2); if (k3 && *k3) set(_key.get(2), k3); return search(); } // Aggiunge un record al db bool TTrFa_record::insert() { CHECKS(_fields.items() > _key.items(), "Can't insert empty record on table ", _table); TString query, values; query << "INSERT INTO " << _table << "\n("; FOR_EACH_ASSOC_OBJECT(_fields, obj, fld, itm) { const TVariant& var = get(fld); if (!var.is_null()) { query << fld << ','; values << var2str(fld, var) << ','; } } query.rtrim(1); values.rtrim(1); query << ")\nVALUES (" << values << ");"; return xvt_sql_execute(_db, query, NULL, 0L) == 1; } // Crea un record della tabella data ed imposta i nomi dei campi chiave TTrFa_record::TTrFa_record(const char* table) : _table(table), _key(15, ',') { _key = ini_get_string("./tff.ini", table, "INDEX_1"); if (_key.empty()) { // Cerco di costruire i nomi della chiave cercando la K, come in P1_KEYHEADERFATT TConfig cfg("tff.ini", table); TAssoc_array& fields = cfg.list_variables(); FOR_EACH_ASSOC_STRING(fields, obj, key, str) { if (key[3] == 'K') _key.add(key); } } CHECKS(!_key.empty_items(), "Invalid primary key for table ", table); } ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_cursors ///////////////////////////////////////////////////////////////////////////////////// TTrFa_cursors::~TTrFa_cursors() { if(c_rmoviva != NULL) delete c_rmoviva; if(c_trasfatt != NULL) delete c_trasfatt; } int TTrFa_cursors::next(TAssoc_array& recimposte, bool& ok, TString& tipocf, TString& codcf) { // Azzero recimposte recimposte.destroy(); // Return code return_code err; // Record TRectype record = _next(err, tipocf, codcf); if(err == eof) { record = _nextCust(err, tipocf, codcf); } while(err < nextmov) { // 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(record.get("CODIVA")); // Aggiorno i valori 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(record.get("CODIVA"), app, true); } else // Inserisco per la prima volta { // Salvo il record nell'array recimposte.add(record.get("CODIVA"), record); } if(err == foundidcust) break; record = _next(err, tipocf, codcf); } ok = err != eofcust; return err; } /* * Questa funzione precarica un array associativo con il movimento diviso per codiva e lo ritorna */ TRectype TTrFa_cursors::_next(return_code& code, TString& tipocf, TString& codcf) { 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) { _newMov = false; // Se è un cliente occasionale passo "O" if(c_rmoviva->get("23.OCFPI").as_string() != "") { tipocf = "O"; codcf = c_rmoviva->get("23.OCFPI").as_string(); } else { 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(); } } // Ciclo finchè non trovo un nuovo movimento o trovo cod IVA già presi da cust while(!checkRecord(c_rmoviva) || (!_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_string()); 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; } TRectype TTrFa_cursors::_nextCust(return_code& code, TString& tipocf, TString& codcf) { bool ok; // Preparo il nuovo cursore if(_newCust) { ok = c_trasfatt->move_first(); _newCust = false; } else { ok = c_trasfatt->move_next(); } tipocf = c_trasfatt->get("TIPO").as_string(); codcf = c_trasfatt->get("CODCF").as_string(); code = ok ? foundidcust : eofcust; return c_trasfatt->cursor()->curr(); } /* Utilizzo questa funzione per filtrare al meglio i record, tutti i casi che devo omettere verranno rilevati e ritorneranno false * Nota bene: viene sfruttato un puntatore di TISA_Recordset per non creare nuovi oggetti e velocizzare la chiamata * a questo punto il programma non ha ancora creato un record di $trasfatt con i dati che mi interessano */ bool TTrFa_cursors::checkRecord(TISAM_recordset* rec) { TString codiva = rec->get("25.CODIVA").as_string(); // Tolgo i non soggetti TCodiceIVA cod(codiva); if(cod.tipo() == "NS") return false; // Clienti if(rec->get("23.TIPO").as_string() == "C") { // Tolgo tutti i movimenti di sola IVA e in reverse charge o di tipo 3 (Acquisto di beni e servizi di soggetti non residenti) TCausale caus(rec->get("23.CODCAUS").as_string()); if(caus.soloiva() && (caus.reverse_charge() || caus.regime_speciale() == 3)) return false; } return true; } int TTrFa_cursors::updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, int cod) { TString query = "USE RMOVIVA\n", queryCust = "USE TRASFATT\n"; query << "SELECT (23.REG!=\"\")&&BETWEEN(23.DATAREG,#DADATAREG,#ADATAREG)&&(23.TIPO=\"" << tipocf << "\")"; queryCust << "SELECT BETWEEN(DATAREG,#DADATAREG,#ADATAREG)&&(TIPO=\"" << tipocf << "\")"; if(codcf > 0) { query << "&&STR((23.CODCF=#CODCF))"; queryCust << "&&STR((CODCF=#CODCF))"; } /* switch(cod) { case toSend: query<<"&&(23.TFINVIO!=\"X\")"; break; case sent: query<<"&&(23.TFINVIO=\"X\")"; break; default: break; } */ query << "\nJOIN MOV INTO NUMREG==NUMREG\n"; queryCust << "\nFROM NUMREG=" << MOV_CUSTOM; c_rmoviva = new TISAM_recordset(query); c_trasfatt= new TISAM_recordset(queryCust); if(dal.empty()) dal = "20170101"; // Data in cui questo modulo è diventato valido if(al.empty()) al = TODAY; c_rmoviva->set_var("#DADATAREG", dal); c_rmoviva->set_var("#ADATAREG", al); c_trasfatt->set_var("#DADATAREG", dal); c_trasfatt->set_var("#ADATAREG", al); if(codcf > 0) { c_rmoviva->set_var("#CODCF", codcf); c_trasfatt->set_var("#CODCF", codcf); } int items = c_rmoviva->items() + c_trasfatt->items(); if(items > 0) { _newMov = true; _newCust = true; return items; } return -1; } ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_mask ///////////////////////////////////////////////////////////////////////////////////// TTrFa_mask::~TTrFa_mask() { TSheet_field& sheet = sfield(F_RIGHE); if(!sheet.empty()) sheet.destroy(); } void TTrFa_mask::next_page(int p) { TAutomask::next_page(p); if (_filter_changed) { TSheet_field & sf = sfield(F_RIGHE); if (curr_win() == sf.parent()) { load_sheet(); sf.force_update(); _filter_changed = false; } } } bool TTrFa_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_DATAINI: if (e == fe_init) o.set(ini_get_string(CONFIG_DITTA, "tf", "LastSend", "01-01-2017")); break; case F_DATAFIN: if (e == fe_init) o.set(TDate(TODAY)); break; case DLG_ALL: if (e == fe_button) { TSheet_field& docs = sfield(F_RIGHE); TString_array& sht = docs.rows_array(); const int items = sht.items(); if (items > 0) { const TString4 select = *(sht.row(0).get(0)) == 'X' ? "" : "X"; for (int i = 0; i < items; i++) sht.row(i).add(select, 0); docs.force_update(); } } 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; } else if(e == se_enter) { //primaNota(o,e); } 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_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; case DLG_RECALC: if(e == fe_button) next_page(1); break; case DLG_USER: if (e == fe_button || e == fe_init) { const long numreg = o.mask().get_long(A_NUMERO); const bool enab = (numreg > 0) && (numreg < MOV_CUSTOM); if (e == fe_button && enab) { o.disable(); // Tecnica anti doppio click! TRectype mov(LF_MOV); mov.put(MOV_NUMREG, numreg); mov.edit(); o.enable(); } else o.enable(enab); } break; case DLG_DELREC: if (e == fe_button && o.active()) { const long progr = o.mask().get_long(A_NUMERO); TString codalq = o.mask().get(A_ALIQUOTA); TString key; key << progr << "|" << codalq; if (progr >= MOV_CUSTOM) { if(cache().get(LF_TRASFATT, key).full()) { TLocalisamfile trasfat(LF_TRASFATT); trasfat.put("NUMREG", progr); trasfat.put("CODIVA", codalq); const int err = trasfat.remove(); if (err != NOERR) return error_box(FR("Errore di cancellazione: %d"), err); } // In qualsiasi caso elimino sta riga TSheet_field& s = o.mask().sfield(F_RIGHE); TToken_string& row = s.row(jolly); row.destroy(jolly); } else return error_box(TR("Riga non cancellabile")); } break; default: break; } const short id = o.dlg(); if (e == fe_modify && jolly == 1) { if (id >= START_SHEET && id < END_SHEET && id != A_FORZATA) { // Se ho modificato l'impostazione dell'invio non va segnata la modifica MA devo togliere o mettere il flag a tutti quelli con movimento uguale if(id != A_INVIO) o.mask().set(A_FORZATA, true); else { changeInvio(o.mask().get(A_TIPOCF), o.mask().get(A_CODCF), o.mask().get(A_NUMDOC), o.mask().get(A_INVIO)); } } } if (e == fe_modify && jolly == 0) { 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++) { int field = getTipoDoc(tipidoc.get(pos)); if(field != -1) set(field, "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); stampa.print(riga); TSheet_field& sheet = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(sheet, r, strarr) { checkRec(&stampa, *strarr); } riga.reset(); riga.put(TR("------------------ Fine controllo! ------------------"), 30); stampa.print(riga); 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 + TOLLARANZA || imposta < realImp - TOLLARANZA) { msgerr.cut(0) << "Imposta errata, valore dichiarato: " << imposta.string() << " valore \"potenzialmente\" 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; if(sheet.empty()) msg = "La tabella dei movimenti è vuota, vuoi caricarla con i filtri selezionati?"; else if(_filter_changed) msg = "I filtri sono stati cambiati, vuoi ricaricare la tabella con i nuovi filtri selezionati?"; if(msg.full() && yesno_box(msg)) { _filter_changed = false; 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; } // Dato un cliente e il suo numero documento imposto il nuovo flag di invio su tutti i campi void TTrFa_mask::changeInvio(TString tipocf, TString codcf, TString numdoc, TString invio) const { TSheet_field& sheet = sfield(F_RIGHE); TString rtipo, rcod, rnum; FOR_EACH_SHEET_ROW(sheet, r, strarr) { // Ricevo i parametri della riga rtipo.cut(0); rtipo << strarr->get_char(_tipocf); rcod.cut(0); rcod << strarr->get_int(_codcf); rnum.cut(0); rnum << strarr->get(_numdoc); if(tipocf == rtipo && codcf == rcod && rnum == numdoc) { strarr->add(invio, _invio); } } } void TTrFa_mask::load_sheet() { 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"); const TString pivaDitta = cache().get(LF_ANAG, key, "PAIV"); const TString cofiDitta = cache().get(LF_ANAG, key, "COFI"); TTrFa_cursors c; 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! if(!sheet.empty()) sheet.destroy(); TAssoc_array recimposte; int items = c.updateFilters(tipo, codice, dal, al, get_int(F_FATTSEL)); for(bool ok = true; items > 0 && ok;) { TString tipocf, codcf; int err = c.next(recimposte, ok, tipocf, codcf); // Carico i clienti TRectype cli = getCli(tipocf, codcf); FOR_EACH_ASSOC_OBJECT(recimposte, h, iva, rec) { TToken_string* row = new TToken_string; TRectype movimento = *(TRectype*)rec; // 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("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("X", _autofatt); // AutoFatt row->add(pivaDitta, _paiv); // P.IVA row->add(cofiDitta, _codfis); // Codice Fiscale } else { 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(); } sheet.force_update(); sheet.show(); } TString TTrFa_mask::findDetraib(TString tipodet) const { real perc = cache().get("%DET", tipodet, "R0"); return perc.stringa(6,2); } const char * TTrFa_mask::natura(const TString& codiva) const { const TRectype& ai = cache().get("%IVA", codiva); TString & natura = get_tmp_string(4); natura = ai.get("S12"); return natura; } real TTrFa_mask::get_IVA(const TString& codiva) const { const TRectype& ai = cache().get("%IVA", codiva); return ai.get_real("R0"); } TString TTrFa_mask::revCharge(TString numreg) const { // Controllo se la causale ha il reverse charge, se il cliente non l'ha impostata giusta sono ARAZZI suoi TString key = numreg; TCausale caus(cache().get(LF_MOV, key, "CODCAUS")); return caus.reverse_charge() ? "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 ///////////////////////////////////////////////////////////////////////////////////// void TTrFa_app::log(int severity, const char* msg) { if (severity < 0) { _logTFF = msg; } else if (_log == NULL) { _log = new TLog_report; if (_logTFF.full()) { TString txt; txt << _logTFF << ": " << msg; _log->log(severity, txt); } else _log->log(severity, msg); } } bool TTrFa_app::show_log() { bool ok = true; if (_log) { _log->preview(); delete _log; _log = NULL; ok = noyes_box(TR("Si desidera procedere con la generazione file xml?")); } return ok; } int TTrFa_app::parse_line(const TString& line, TString& var, TString& val) const { if (line.blank()) return 0; if (line[0] == '[') { var = line.mid(1); var.rtrim(1); val.cut(0); return 1; } const int equal = line.find('='); if (equal < 6) return 0; var = line.left(equal); var.trim(); val = line.mid(equal+1); val.trim(); return 2; } bool TTrFa_app::create_table(TScanner& tff, const TString& table) { TString query, var, val; if (xvt_sql_table_exists(_db, table)) { SLIST fields = xvt_sql_list_fields(_db, table); while (!tff.eof()) { const TString& line = tff.line(); const int n = parse_line(line, var, val); if (n <= 0) break; if (var.starts_with("INDEX_")) break; if (xvt_slist_find_str(fields, var) == NULL) { query.cut(0) << "ALTER TABLE " << table << " ADD COLUMN " << var << ' ' << val << " NOT NULL"; if (val.find("INT") >= 0 || val.find("NUM") >= 0) query << " DEFAULT 0"; else query << " DEFAULT ''"; query << ";"; xvt_sql_execute(_db, query, NULL, NULL); // Create table } } xvt_slist_destroy(fields); } else { query << "CREATE TABLE " << table << " ("; while (!tff.eof()) { const TString& line = tff.line(); const int n = parse_line(line, var, val); if (n <= 0) break; if (n == 1) { tff.push(line); break; } if (var.starts_with("INDEX_")) { query.rtrim(1); // toglie ultima , query << ");"; xvt_sql_execute(_db, query, NULL, NULL); // Create table query.cut(0); query << "CREATE UNIQUE INDEX " << table << "_1 ON " << table << " (" << val << ");"; xvt_sql_execute(_db, query, NULL, NULL); // Create index break; } else { query << "\n " << var << ' ' << val << " NOT NULL"; if (val.find("INT") >= 0 || val.find("NUM") >= 0) query << " DEFAULT 0"; else query << " DEFAULT ''"; query << ","; } } } return true; } bool TTrFa_app::create() { open_files(LF_MOV, LF_RMOV, LF_RMOVIVA, LF_TABCOM, LF_ANAG, LF_CLIFO, LF_OCCAS, LF_CFVEN, LF_NDITTE, 0); // Controllo preventivo dell'avvenuta conversione del tracciato record TRectype rmoviva(LF_RMOVIVA); //if (rmoviva.type("TFINVIO") != _boolfld) //return error_box(TR("Database non convertito per il Trasferimento Elettronico")); _ditta.init(LF_NDITTE, prefix().get_codditta()); _dbname = prefix().get_studio(); // base direcotry _dbname.add("sql"); make_dir(_dbname); TString16 d; d.format("TF%05ld.db", prefix().get_codditta()); _dbname.add(d); bool create = !_dbname.exist(); _db = xvt_sql_open(_dbname, user(), "", _dbname.path()); if (_db == NULL) return false; if(create) { createDB(); } return TSkeleton_application::create(); } // Sincronizzo il DB SQL con quello di campo bool TTrFa_app::syncronizeDB() { //xvt_sql_begin(_db); return true; } bool TTrFa_app::createDB() { const TFilename ini = "tff.ini"; bool ok = ini.exist(); if (ok) { xvt_sql_begin(_db); TScanner TFF(ini); while (ok && !TFF.eof()) { const TString& p = TFF.line(); if (p.starts_with("[TF") && p.ends_with("F]")) { TString16 table = p; table.strip("[]"); ok = create_table(TFF, table); } } if(ok) { // Aggiungo il valore di default in TFNUM TTrFa_record tfnum("TFNUM00F"); tfnum.set("PJNKEY", "00001"); tfnum.set("PJNINV", "0000000000"); ok = tfnum.insert(); } if (ok) xvt_sql_commit(_db); else xvt_sql_rollback(_db); } else return cantread_box(ini); return true; } 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); // Booleano per appendere i record nel db /*********************************************************************************************** * Esporto ***********************************************************************************************/ xvt_sql_begin(_db); bool ok; // Testata ok = tff0100(sheet); if(ok) { // Anagrafica ok = tff0400(sheet); if(ok) // Documenti ok = tff0700(sheet); } if(!ok) { log(-1, "WTF!?"); xvt_sql_rollback(_db); return false; } if(xvt_sql_commit(_db)) { message_box("Ho esportato correttamente!"); // Imposto l'esportazione if(yesno_box("Vuoi segnare i record esportati?")) setEsportato(sheet); } else message_box("Errore durante il salvataggio delle modifiche"); return true; } 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) 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 per la chiave body if(mCliDoc.find(keyMap) == mCliDoc.end()) { idHeader++; app.contCliFo = idHeader; app.countDoc = 0L; mCliDoc.insert(std::pair(keyMap, app)); } TString header; header.format("%c%06ld", strarr->get_char(_tipocf), strarr->get_int(_codcf)); // Ritorno l'header return header; } TString TTrFa_app::getBody(TToken_string* strarr, bool add) { /* // 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]; if(add) 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(); // 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); bool ok = true; if(cli) { TTrFa_record dte("TFF0100F"); // Controllo la presenza di un caricamento in attesa if(dte.search(DTE_PROVV)) { bool sent = dte.get("P1_KEYPRGINVIO").as_string() == DTE_PROVV; if(sent) { TString msg = "É presente un'altra esportazione non ancora elaborata vuoi eliminarla?"; if(yesno_box(msg)) { if(!emptyTables(DTE_PROVV)) { error_box("Fallita eliminazione record!!!"); return false; } } else return false; } } 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"); // Controllo la presenza di un caricamento in attesa if(dtr.search(DTR_PROVV)) { bool sent = dtr.get("P1_KEYPRGINVIO").as_string() == DTR_PROVV; TString msg = "É presente un'altra esportazione non ancora elaborata vuoi eliminarla?"; if(sent) { if(yesno_box(msg)) { if(!emptyTables(DTE_PROVV)) { error_box("Fallita eliminazione record!!!"); return false; } } else return false; } } 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) { /******************************************************************************************************************** * Cedeprest * ********************************************************************************************************************/ // TTrFa_record tff0200f("TFF0200F"); tff0200f.set("P2_KEYPRGINVIO", key); if (_ditta.partita_IVA().full()) { tff0200f.set("P2_FISCIVAPAESE", _ditta.stato_partita_IVA()); // Sempre IT tff0200f.set("P2_FISCIVACOD", _ditta.partita_IVA()); } tff0200f.set("P2_CODFISCALE", _ditta.codice_fiscale()); if (_ditta.fisica()) { tff0200f.set("P2_ANANOME", _ditta.nome()); tff0200f.set("P2_ANACOGNOME", _ditta.cognome()); } else { 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()); if(_ditta.italiano()) // Campo ritornerebbe "EE" se estero tff0200f.set("P2_SEDEPROV", _ditta.provincia_residenza()); tff0200f.set("P2_SEDENAZ", _ditta.stato_residenzaISO()); myrfso = ""; if(haveRFSO(myrfso)) { TRectype r_ana = cache().get(LF_ANAG, TString(myrfso[0]) << myrfso.sub(1)); if(r_ana.get_char("TIPORFSO") == 'S') // Stabile Organizzazione { tff0200f.set("P2_STABORGIND", r_ana.get("INDRES")); tff0200f.set("P2_STABORGNRCIVICO", r_ana.get("CIVRES")); tff0200f.set("P2_STABORGCAP", r_ana.get("CAPRES")); TRectype r_comune = cache().get(LF_COMUNI, TString("|") << r_ana.get("COMRES")); tff0200f.set("P2_STABORGCOMUNE", r_comune.get("DENCOM")); tff0200f.set("P2_STABORGPROV", r_comune.get("PROVCOM")); tff0200f.set("P2_STABORGNAZ", "IT"); } else // Rappresentante Fiscale { 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"); 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) { 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)); TString keyCedPrest; keyCedPrest << strarr->get_char(_tipocf) << "|" << strarr->get_long(_codcf); TRectype r_cedeprest = cache().get(LF_CLIFO, keyCedPrest); TString statocli = cache().get("%STA", r_cedeprest.get("STATOCF"), "S10"); // Se rimane vuoto è italiano if(statocli == "") statocli = "IT"; 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"); TString oldKey = ""; int numRiga; 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", toDate(strarr->get(_datadoc))); tff0700f.set("P7_NUMERO", strarr->get(_numdoc)); tff0700f.set("P7_DATAREG", toDate(strarr->get(_datareg))); // Obbligatoria nei DTR tff0700f.set("P7_GESTIONE", ""); ok = tff0700f.insert(); // Controllo dopo l'inserimento del tff0700f if(!ok) return false; } // In qualsiasi caso va messa la riga ma prima elaboro il numero della riga! TString newKey = getBody(strarr, false); if(oldKey != newKey) { numRiga = 1; oldKey = newKey; } else numRiga++; ok = tff2200(strarr, numRiga); // E dopo l'inserimento del tff2200 if(!ok) return false; } return ok; } bool TTrFa_app::tff2200(TToken_string* strarr, int nriga) { TTrFa_record tff2200f("TFF2200F"); tff2200f.set("PL_KEYPRGINVIO", getKey(strarr)); tff2200f.set("PL_KEYHEADERFATT", getHeader(strarr)); tff2200f.set("PL_KEYBODYFATT", getBody(strarr, false)); TString numriga; numriga.format("%020d", nriga); tff2200f.set("PL_KEYBODYDETT", numriga); tff2200f.set("PL_IMPONIBILE", real(strarr->get(_imponibile))); // Se li converto in real una volta passati vengono parsati da var2str nel formato che vuole l'agenzia delle entrate tff2200f.set("PL_IMPOSTA", real(strarr->get(_importoIVA))); real aliquota = cache().get("%IVA", strarr->get(_aliquota), "R0"); tff2200f.set("PL_ALIQUOTAIVA", 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); } 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_KEYPRGINVIO", getKey(strarr)); tff3100f.set("PH_KEYHEADERFATT", getHeader(strarr)); if(_append) tff3100f.remove(); if(r_ana.get_char("TIPORFSO") == 'S') // Stabile Organizzazione { tff3100f.set("PH_STABORGIND", r_ana.get("INDRES")); tff3100f.set("PH_STABORGNRCIVICO", r_ana.get("CIVRES")); tff3100f.set("PH_STABORGCAP", r_ana.get("CAPRES")); TRectype r_comune = cache().get(LF_COMUNI, TString("|") << r_ana.get("COMRES")); tff3100f.set("PH_STABORGCOMUNE", r_comune.get("DENCOM")); tff3100f.set("PH_STABORGPROV", r_comune.get("PROVCOM")); tff3100f.set("PH_STABORGNAZ", "IT"); } else // Rappresentante Fiscale { // 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?) 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') { tff3100f.set("PH_ANADENOMI", r_ana.get("RAGSOC")); } else { TString nomCom = r_ana.get("RAGSOC"); tff3100f.set("PH_ANANOME", nomCom.sub(30)); tff3100f.set("PH_ANACOGNOME", nomCom.sub(0,30)); } } tff3100f.set("PH_GESTIONE", "D"); return tff3100f.insert(); } bool TTrFa_app::setEsportato(TSheet_field& sheet) { bool ok = true; TProgress_monitor p(sheet.items(),"Segno l'esportazione sui records"); 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 if(strcmp(strarr->get(_forzata), "X") == 0) { ok = saveRec(*strarr, true); if(!ok) return false; } else { TRectype row = cache().get(LF_MOV, TString(strarr->get(_numero))); row.put("TFINVIO", "X"); row.put("TFDATA", TDate(TODAY).string()); ok = row.rewrite(TLocalisamfile(LF_MOV)) == NOERR; if(!ok) return false; } } return ok; } bool TTrFa_app::emptyTables(TString key) { TString query; query << "DELETE FROM TFF0100F WHERE P1_KEYPRGINVIO = '" << key << "';\n"; query << "DELETE FROM TFF0200F WHERE P2_KEYPRGINVIO = '" << key << "';\n"; query << "DELETE FROM TFF0300F WHERE P3_KEYPRGINVIO = '" << key << "';\n"; query << "DELETE FROM TFF0400F WHERE P4_KEYPRGINVIO = '" << key << "';\n"; query << "DELETE FROM TFF0700F WHERE P7_KEYPRGINVIO = '" << key << "';\n"; query << "DELETE FROM TFF2200F WHERE PL_KEYPRGINVIO = '" << key << "';\n"; query << "DELETE FROM TFF3100F WHERE PH_KEYPRGINVIO = '" << key << "';\n"; return xvt_sql_execute(_db, query, NULL, NULL) >= 0; } void TTrFa_app::main_loop() { TTrFa_mask msk("tf0100a"); while (msk.run() == K_ENTER) { if(msk.checkNotEmpty()) send(&msk); } } bool TTrFa_app::destroy() { if (_cofi.full()) ini_set_string(CONFIG_DITTA, "pa", "TRASMITTCOD", _cofi); xvt_sql_close(_db); _db = NULL; return TSkeleton_application::destroy(); } int tf0100(int argc, char* argv[]) { TTrFa_app t2t; t2t.run(argc, argv, TR("Trasferimento Fatture Elettroniche")); return 0; }