diff --git a/src/li/lilib01.cpp b/src/li/lilib01.cpp index ef0d5cf90..8d16a29d2 100644 --- a/src/li/lilib01.cpp +++ b/src/li/lilib01.cpp @@ -5,24 +5,60 @@ #define SOLUZIONE_UNICA 1 #define FINO_A_PLAFOND 2 -void TLi_manager::elabTipiStati(TToken_string& tipi, TToken_string& stati) +void TLi_manager::elabTipiStati() { - for(int i = 0; i < tipidoc.items(); i++) + if(tipi.blank() && stati.blank()) { - TString app(""); - tipidoc.get(i, app); - TToken_string statidoc(ini_get_string(CONFIG_DITTA, "li", app), ','); - for(int j = statidoc.get_int(0); j <= statidoc.get_int(1); j++) + for(int i = 0; i < tipidoc.items(); i++) { - tipi.add(app); - stati.add(j); + TString app(""); + tipidoc.get(i, app); + TToken_string statidoc(ini_get_string(CONFIG_DITTA, "li", app), ','); + for(int j = statidoc.get_int(0); j <= statidoc.get_int(1); j++) + { + tipi.add(app); + stati.add(j); + } } } } + +const TToken_string& TLi_manager::getUse(TDocumento& d, const bool write) +{ + static TToken_string& ret = get_tmp_string(); + TAssoc_array tabIva = d.tabella_iva(true); + + real plaUtil = ZERO; + + for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tabIva.get(); totali != NULL; totali = (TRiepilogo_iva *) tabIva.get()) + { + if(checkIva(totali->cod_iva().codice())) // Se l'iva del documento è diversa non mi interessa + { + plaUtil += totali->imp_orig(); + } + } + + if(plaUtil > ZERO) + { + if(d.is_nota_credito()) + { + ret.cut(0) << incrPlaf(d, plaUtil, write); + } + else + { + ret.cut(0) << consPlaf(plaUtil, write); + if(ret.starts_with("ERRORE")) + ret << " al documento " << d.numerazione() << " n." << d.numero() << "\nTotale plafond da consumare: " << plaUtil.string() << "\nTotale rimasto: " << getPlafond().string(); + } + } + + return ret; +} + const TToken_string& TLi_manager::consPlaf(real& plafUsed, const bool write) { - TToken_string& used(get_tmp_string()); used.separator(','); + static TToken_string used("", ','); used.cut(0); if(!validPlafond || plafUsed > getPlafond()) { used << "ERRORE NEL CALCOLO DEL PLAFOND"; @@ -88,7 +124,7 @@ const TToken_string& TLi_manager::consPlaf(real& plafUsed, const bool write) /* Aggiungo al plafond quello che trovo */ const TToken_string& TLi_manager::incrPlaf(TDocumento& d, real impNC, const bool write) { - TToken_string& used = get_tmp_string(); used.separator(','); + static TToken_string used("", ','); used.cut(0); // Controllo se questa nota credito si riferisce a un singolo documento, in quel caso aggiorno faccio un aggiornamento sulle lettere di intento // Se si rifà a più documenti o non è specificato salta, meglio stare bassi if(d.get("NUMDOCRIF").blank() || d.get("CODNUMRIF").blank() || d.get("ANNORIF").blank() || iniDicInt.year() != d.get_int("ANNORIF")) @@ -97,10 +133,9 @@ const TToken_string& TLi_manager::incrPlaf(TDocumento& d, real impNC, const bool } TDocumento ds('D', d.get_int("ANNORIF"), d.get("CODNUMRIF"), d.get_int("NUMDOCRIF")); - // Se il documento di riferimento non ha nulla inserito nel plafond esco, non mi interessa - TToken_string lePlafs(ds.get("PLAFOND"), ','); // [ANNO|NUMPROT|UTILIZZATO],... - + + // Se il documento di riferimento non ha nulla inserito nel plafond esco, non mi interessa if(lePlafs.items() == 0) return used; @@ -114,7 +149,6 @@ const TToken_string& TLi_manager::incrPlaf(TDocumento& d, real impNC, const bool if(checkIva(totali->cod_iva().codice())) { impNC += totali->imp_orig(); - message_box("Hey guarda il mio segno e dillo a Tolla! %s", totali->imp_orig().string()); } } } @@ -161,14 +195,14 @@ const TToken_string& TLi_manager::incrPlaf(TDocumento& d, real impNC, const bool { open = false; // Incremento! - plafondi[key] += importoPlaf; + plafondi[key] += rimanente; } else { // Va aggiunto ex novo! // Calcolo l'importo delle righe che rientrano nel plafond open = true; - plafondi.insert(std::pair(key, importoPlaf)); + plafondi.insert(std::pair(key, rimanente)); // Se devo scrivere abilito il plafond if(write) @@ -179,11 +213,16 @@ const TToken_string& TLi_manager::incrPlaf(TDocumento& d, real impNC, const bool // Segno di aver usato il plafond static TToken_string u; u.cut(0); u.add(key, _planno); - u.add(importoPlaf.string(), _plimporto); + u.add(rimanente.string(), _plimporto); u.add(open? "X" : "", _plchiusura); used.add(u); } + // Rigiro used, nelle note credito sono invertiti i plafond + static TToken_string usedApp("", ','); usedApp.cut(0); + for(int i = used.items(); i > 0; i--) + usedApp.add(used.get(used.items()-i), i-1); + // Sovrascrivo il documento ds.put("PLAFOND", lePlafs); ds.rewrite(); @@ -191,10 +230,11 @@ const TToken_string& TLi_manager::incrPlaf(TDocumento& d, real impNC, const bool // Tolgo la virgola finale used.cut(used.len()-1); - return used; + // Succedono cose in memoria, devo rimediare così + return usedApp; } - -void TLi_manager::stornaDoc(TDocumento& d, const bool write) +/* +void TLi_manager::stornaDoc(const TDocumento& d, const bool write) { // Devo ricaricare le righe sui plafond che ho TToken_string plafs(d.get("PLAFOND"), ','); @@ -249,7 +289,141 @@ void TLi_manager::stornaDoc(TDocumento& d, const bool write) } } +// Storna i documenti dopo a quello che riceve +void TLi_manager::stornaDocs(const TDocumento& d, const bool write) +{ + TLista_documenti din; // Legge tutti i documenti di input + // Trovo tutti i documenti che mi interessano + din.read('D', tipocf, codcli, iniDicInt.year(), tipi, stati, d.data(), finDicInt); + + for(int i = 0; i < din.items(); i++) + { + if(d.numero() < din[i].numero()) + { + stornaDoc(din[i], write); + } + } +} +*/ +const TToken_string& TLi_manager::stornaDoc(const TDocumento& d, real impDC, const bool write) +{ + static TToken_string used("", ','); used.cut(0); + // True se devo stornare tutto il Doc + bool totale = impDC.is_zero(); + bool ok = true; + // Devo ricaricare le righe sui plafond che ho + TToken_string plafs(d.get("PLAFOND"), ','); + for(int i = 0; i < plafs.items() && impDC > ZERO; i++) + { + TToken_string thisPlafond = plafs.get(i); + static TString key; key.cut(0) << thisPlafond.get(_planno) << "|" << thisPlafond.get(_plnumprot); + real thisImporto = thisPlafond.get(_plimporto); + if(totale) + { + if(thisImporto >= impDC) + { + thisImporto = impDC; + // Controllo se vado a stornare solo una parte o tutto, nel primo caso cambio la Token, nel secondo elimino normalmente + if(thisImporto > impDC) + { + thisPlafond.add(impDC, _plimporto); + plafs.add(thisPlafond, i); + } + else + plafs.destroy(i); + impDC = ZERO; + } + else + { + impDC -= thisImporto; + plafs.destroy(i); + } + } + TString asd = thisImporto.string(); + if(d.is_nota_credito()) + { + if(plafondi.find(key) != plafondi.end()) + { + if(thisImporto < plafondi[key]) + { + // Sottraggo + plafondi[key] -= thisImporto; + } + else + { + // Errore + used.cut(0) << "ERRORE: Non è presente abbastanza plafond rimanente per stornare la Nota Credito"; + return used; + } + } + else + { + // Errore + if(DEBUG_ENABLED) + error_box("Houston abbiamo un problema...perchè non trovo questo plafond attivo!?"); + used.cut(0) << "ERRORE: La lettera d'intento a cui si rifà questa Nota Credito non è aperta"; + return used; + } + } + else + { + if(plafondi.find(key) != plafondi.end()) + { + //Sommo + plafondi[key] += thisImporto; + } + else + { + // Aggiungo ai plafond + plafondi.insert(std::pair(key, thisImporto)); + // Se devo scrivere abilito il plafond + if(write) + { + changeStato(key, false); + } + } + } + } + used.cut(0) << plafs; + return used; +} + +// Where did you come from Cotton Eye Joe! + +/* +bool TLi_manager::recalcAfter(const TDocumento& d, TLog_report& lerr) +{ + TLista_documenti din; // Legge tutti i documenti di input + bool ok = true; + int first = -1; + // Trovo tutti i documenti che mi interessano + din.read('D', tipocf, codcli, iniDicInt.year(), tipi, stati, d.data(), finDicInt); + + for(int i = 0; i < din.items() && ok; i++) + { + if(d.numero() < din[i].numero()) + { + if(first == -1) first = i; + const TToken_string& use = getUse(din[i], true); + if(use.starts_with("ERRORE")) + { + ok = false; + lerr.log(2, use); + } + else + din[i].put("PLAFOND", use); + } + } + if(ok) + { + // Se va tutto bene scrivo tutti i documenti + for(; first < din.items(); first++) + din[first].rewrite(); + } + return ok; +} +*/ /* Faccio un analisi di tutti i plafond aperti e li sommo salvandomeli in plafonds */ void TLi_manager::elabPlafond() @@ -257,19 +431,7 @@ void TLi_manager::elabPlafond() TRelation letint(LF_LETINT); TRectype filtro(letint.curr()); filtro.add("CODCLI", codcli); - - // All'inizio passo in iniDicInt la data del documento QUINDI posso usarla come data limite, se non ho nulla metto l'ultimo dell'anno - TDate today(TODAY); - if(!iniDicInt.ok()) - { - filtro.add("ANNO", today.year()); - } - else - { - filtro.add("ANNO", iniDicInt.year()); - } - if(!finDicInt.ok()) - finDicInt = TDate(31, 12, iniDicInt.ok() ? iniDicInt.year() : today.year()); + filtro.add("ANNO", iniDicInt.year()); // Creo un cursore ordinato e prelevo la prima riga non chiusa TCursor c_dicint(&letint, "", 2, &filtro, &filtro); @@ -323,9 +485,7 @@ void TLi_manager::elabPlafond() const real TLi_manager::getPlaRes() { - TToken_string tipi, stati; - elabTipiStati(tipi, stati); - return elabPlaRes(tipi, stati); + return elabPlaRes(); } const real TLi_manager::getPlaRes(TToken_string tipi, TToken_string stati) @@ -333,8 +493,20 @@ const real TLi_manager::getPlaRes(TToken_string tipi, TToken_string stati) return elabPlaRes(tipi, stati); } -const real TLi_manager::elabPlaRes(TToken_string tipi, TToken_string stati, TDate ad) +const real TLi_manager::elabPlaRes(TToken_string t, TToken_string s, TDate ad) { + if(elabPR) + return plafond; + else + elabPR = true; + + if(t.full() && s.full()) + { + tipi = t; + stati = s; + } + if(!ad.ok()) + ad = finDicInt; plafond = -UNO; if(!validPlafond) return plafond; @@ -360,7 +532,7 @@ const real TLi_manager::elabPlaRes(TToken_string tipi, TToken_string stati, TDat { plafondi[key] = ZERO; } - plafondi[key] += (real)thePla.get(_plimporto); + plafondi[key] += static_cast(thePla.get(_plimporto)); } else { @@ -371,7 +543,7 @@ const real TLi_manager::elabPlaRes(TToken_string tipi, TToken_string stati, TDat return plafond; } // Calcolo l'importo delle righe che rientrano nel plafond - plafondi.insert(std::pair(key, (real)thePla.get(_plimporto))); + plafondi.insert(std::pair(key, static_cast(thePla.get(_plimporto)))); } } else @@ -380,7 +552,7 @@ const real TLi_manager::elabPlaRes(TToken_string tipi, TToken_string stati, TDat { if(chiusura == "X") { - if(DEBUG_ENABLED && plafondi[key] != (real)thePla.get(_plimporto) && + if(DEBUG_ENABLED && plafondi[key] != static_cast(thePla.get(_plimporto)) && !yesno_box(TR("Questa lettera di intento è incongruente,\nTotale attivo: %s\nTotale da disattivare: %s\nContinuare?"), plafondi[key].string(), thePla.get(_plimporto))) { validPlafond = false; @@ -390,7 +562,7 @@ const real TLi_manager::elabPlaRes(TToken_string tipi, TToken_string stati, TDat } else { - plafondi[key] -= (real)thePla.get(_plimporto); + plafondi[key] -= static_cast(thePla.get(_plimporto)); } } } @@ -423,10 +595,6 @@ const real TLi_manager::elabUtil(TToken_string tipi, TToken_string stati, TDate for(int i = 0; i < din.items(); i++) { - TRectype pollo = din[i].head(); - int ndoc = pollo.get_int("NDOC"); - TDate datadoc = pollo.get("DATADOC"); - TString tipodoc = pollo.get("TIPODOC"); TAssoc_array tabIva = din[i].tabella_iva(true); for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tabIva.get(); totali != NULL; totali = (TRiepilogo_iva *) tabIva.get()) { @@ -447,61 +615,65 @@ const real TLi_manager::elabUtil(TToken_string tipi, TToken_string stati, TDate return utilizzato; } -bool TLi_manager::testPlafond(TLista_documenti dout, TLog_report& lerr) +bool TLi_manager::testPlafond(TLista_documenti& dout, TLog_report& lerr) { - lerr.log(2, "Funzione da rifare"); - return true; bool err = false; - real resPlafond = getPlaRes(); - real testPlafond = getPlaRes(); - real totFatt; - int i = 0; - + static TToken_string& use = get_tmp_string(); // Faccio un ragionamento identico a getPlaRes, ma in input ho la lista di documenti appena elaborati - for(int i = 0; i < dout.items(); i++) + for(int i = 0; i < dout.items() && !err; i++) { - TAssoc_array tabIva = dout[i].tabella_iva(true); - for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tabIva.get(); totali != NULL; totali = (TRiepilogo_iva *) tabIva.get()) + use.cut(0) << getUse(dout[i], true); + if(use.starts_with("ERRORE")) { - if(checkIva(totali->cod_iva().codice())) - { - resPlafond -= totali->imp_orig(); - totFatt += totali->imp_orig(); - } + TString msgerr; + msgerr << "Superata dichiarazione di intento cliente N." << dout[i].codcf() << "\n" << use; + lerr.log(2, msgerr); + revertModifiche(); + clearModifiche(); + err = true; + } + else + { + dout[i].put("PLAFOND", use); } - } - if(resPlafond < 0) - { - err = true; // Alzo il flag dell'errore - - TString msgerr; - msgerr << "Superata dichiarazione di intento cliente N." << dout[i].codcf() << "\nPlafond rimanente: " << resPlafond + totFatt << "\nTotale fatture generate: " << totFatt << "\nSforato di: " << -resPlafond << "\n"; - lerr.log(2, msgerr); // 2 <- Errore } return err; } -int TLi_manager::checkEditability(TDocumento& d) +/* Per scelte implementative non ha una accuratezza del 100% */ +bool TLi_manager::checkUtilizzo(TDocumento& d, real impNC) { - TToken_string tipi, stati; - elabTipiStati(tipi, stati); - TLista_documenti din; // Legge tutti i documenti di input - int ret = NOERR; + TLista_documenti din; + bool ok; + TToken_string lePlafs(d.get("PLAFOND"), ','); - // Trovo tutti i documenti che mi interessano - din.read('D', tipocf, codcli, iniDicInt.year(), tipi, stati, iniDicInt, d.data()); - - // Oltre al mio documento c'è altro? - if(din.items() > 1) - ret = 1; - - for(int i = 0; i < din.items() && ret != -1; i++) + // Se me lo passa la funzione evito di calcolarlo + if(impNC.is_zero()) { - if(d != din[i]) - ret = din[i].modificabile() ? ret : -1; + for (TRiepilogo_iva * totali = (TRiepilogo_iva *) d.tabella_iva(true).get(); totali != NULL; totali = (TRiepilogo_iva *) d.tabella_iva(true).get()) + if(checkIva(totali->cod_iva().codice())) // Se l'iva del documento è diversa non mi interessa + impNC += totali->imp_orig(); } - return ret; + + /* Per sapere se non ho usato il plafond di questa NC controllo innanzitutto se c'è ne abbastanza + * rimasto per coprire la NC, non è il controllo della vita ma toglie già un po' di calcoli */ + ok = getPlaRes() > impNC; + + // Sucessivamente vado in dettaglio a verificare se sono sempre maggiori (getPlaRes() mi carica anche la variabile "plafondi" per gli altri calcoli) + for(int i = 0; i < lePlafs.items() && ok; i++) + { + TToken_string thisPlaf(lePlafs.get(i)); + static TString key; key.cut(0) << thisPlaf.get(_planno) << "|" << thisPlaf.get(_plnumprot); + if(plafondi.find(key) != plafondi.end()) + { + ok = plafondi[key] > static_cast(lePlafs.get(_plimporto)); + } + else + ok = false; + } + + return ok; } void TLi_manager::changeStato(const TString& key, const bool stato) @@ -530,11 +702,27 @@ void TLi_manager::revertModifiche() clearModifiche(); } -// TIPOCF, CODCLI, ANNO -TLi_manager::TLi_manager(const char t, const long c, TDate iniDic, TDate finDic) - : tipocf(t), codcli(c), iniDicInt(iniDic), finDicInt(finDic), - tipidoc(ini_get_string(CONFIG_DITTA, "li", "TIPIDOC")), codivaDef(ini_get_string(CONFIG_DITTA, "li", "CODIVA")), codivaAlt(ini_get_string(CONFIG_DITTA, "li", "CODIVALT")), - plafond(ZERO), validPlafond(false), soluzione(false) +TLi_manager::TLi_manager(const char t, const long c, TDate iniDic, TDate finDic) + : tipocf (t), codcli(c), iniDicInt(iniDic), finDicInt(finDic), + tipidoc(ini_get_string(CONFIG_DITTA, "li", "TIPIDOC")), + codivaDef(ini_get_string(CONFIG_DITTA, "li", "CODIVA")), + codivaAlt(ini_get_string(CONFIG_DITTA, "li", "CODIVALT")), + plafond(ZERO), validPlafond(false), soluzione(false), elabPR(false) { + elabTipiStati(); + elabPlafond(); +} + +TLi_manager::TLi_manager(const char t, const long c, TDate finDic) + : tipocf (t), codcli(c), finDicInt(finDic), + tipidoc(ini_get_string(CONFIG_DITTA, "li", "TIPIDOC")), + codivaDef(ini_get_string(CONFIG_DITTA, "li", "CODIVA")), + codivaAlt(ini_get_string(CONFIG_DITTA, "li", "CODIVALT")), + plafond(ZERO), validPlafond(false), soluzione(false), elabPR(false) +{ + iniDicInt.set_day(01); + iniDicInt.set_month(01); + iniDicInt.set_year(finDic.year()); + elabTipiStati(); elabPlafond(); } \ No newline at end of file diff --git a/src/li/lilib01.h b/src/li/lilib01.h index 8d03b5eef..237eaab08 100644 --- a/src/li/lilib01.h +++ b/src/li/lilib01.h @@ -23,9 +23,12 @@ enum plafStruct { _planno, _plnumprot, _plimporto, _plchiusura, _plNC }; class TLi_manager : TObject { + TToken_string tipi; + TToken_string stati; bool validPlafond; bool soluzione; - const char tipocf; + bool elabPR; + const char tipocf; const long codcli; TDate iniDicInt; @@ -38,8 +41,7 @@ class TLi_manager : TObject // Elenco di plafond con eventuale std::map plafondi; std::map modifiche; // Progressivo, TToken_string(chiave,stato); - - void elabTipiStati(TToken_string& tipi, TToken_string& stati); // Preparo due token string con le tipi[0] -> stati[0], ... + void elabTipiStati(); // Preparo due token string con tipi[0] -> stati[0], ... public: // Getters @@ -50,29 +52,37 @@ public: // Ritorna se è una dichiarazione di tipo soluzione bool isSoluzione() { return soluzione; } + // Funzione che unisce consPlaf e incrPlaf + const TToken_string& getUse(TDocumento& d, const bool write = false); // "Consuma" il plafond const TToken_string& consPlaf(real& plafUsed, const bool write = false); // Da una nota credito passata incremento il plafond const TToken_string& incrPlaf(TDocumento& d, real impNC = ZERO, const bool write = false); // Storna un documento che riceve - void stornaDoc(TDocumento& d, const bool write = false); + const TToken_string& stornaDoc(const TDocumento& d, real impDC = ZERO, const bool write = false); + // Storna i documenti dopo a quello che riceve + //void stornaDocs(const TDocumento& d, const bool write = false); + // Ricalcola i documenti dopo quello che riceve + //bool recalcAfter(const TDocumento& d, TLog_report& lerr); + // Functions // Vado a estrapolare il plafond void elabPlafond(); // Testo se con i documenti passati supero il plafond - bool testPlafond(TLista_documenti dout, TLog_report& lerr); + bool testPlafond(TLista_documenti& dout, TLog_report& lerr); // Controllo se il codice iva è uguale a quello impostato per il calcolo del plafond bool checkIva(TString cod) { return cod == codivaDef || cod == codivaAlt; } - // Controllo se il documento passato non ha successori con plafonds assegnati, in tal caso se ce ne sono definitivi - // 0 -> Tutto OK, -1 -> Avvistato documento definitivo!, 1-> Avvistati documenti ma non definitivi - int checkEditability(TDocumento& d); + + // Controllo se il plafond che la NC passata rilascia non è già stato utilizzato + bool checkUtilizzo(TDocumento& d, real impNC = ZERO); + // Calcolo il rimanente del plafond const real getPlaRes(); // Calcolo il rimanente del plafond su tipi e stati documento passati const real getPlaRes(TToken_string tipi, TToken_string stati); // Funzione che effettivamente effettua il calcolodalla data della dichiarazione alla data passata - const real elabPlaRes(TToken_string tipi, TToken_string stati, TDate ad = 0L); + const real elabPlaRes(TToken_string t = "", TToken_string s = "", TDate ad = 0L); // Ritorna la quantità di plafond utilizzato dalla data della dichiarazione alla data passata const real elabUtil(TToken_string tipi, TToken_string stati, TDate ad = 0L); // Modifica una lettera e salva la modifica in "modifiche" @@ -85,7 +95,8 @@ public: void clearModifiche() { modifiche.clear(); } // Costructors/Destructors - TLi_manager(const char t, const long c, TDate iniDic = 0L, TDate finDic = 0L); + TLi_manager(const char t, const long c, TDate iniDic, TDate finDic); + TLi_manager(const char t, const long c, TDate finDic); // Sets iniDicInt as 01/01/finDic.year() virtual ~TLi_manager() {} };