From 695d69f859933a899178b53058d3a3e216cb605d Mon Sep 17 00:00:00 2001 From: mtollari Date: Wed, 8 Nov 2017 10:55:31 +0000 Subject: [PATCH] =?UTF-8?q?Patch=20level=20=20=20=20=20=20=20=20=20:=2012.?= =?UTF-8?q?0=20476=20Files=20correlati=20=20=20=20=20:=20li=20Commento=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20:=20Rivisitata=20completamente?= =?UTF-8?q?=20gestione=20lettere=20di=20intento=20(sviluppo=20non=20ancora?= =?UTF-8?q?=20completo):=20-=20Aggiunta=20possibilit=C3=A0=20di=20gestire?= =?UTF-8?q?=20pi=C3=B9=20lettere=20di=20intento=20aperte=20sullo=20stesso?= =?UTF-8?q?=20cliente=20-=20Aggiunte=20funzioni=20di=20consumo=20e=20incre?= =?UTF-8?q?mento=20plafond=20-=20Aggiunta=20funzione=20che=20dato=20un=20t?= =?UTF-8?q?otale=20documento=20restituisce=20l'utilizzo=20da=20scrivere=20?= =?UTF-8?q?nel=20campo=20memo=20-=20Aggiunte=20funzioni=20di=20controllo?= =?UTF-8?q?=20per=20il=20salvataggio,=20modifica=20di=20plafond=20gi=C3=A0?= =?UTF-8?q?=20aperti?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn://10.65.10.50/branches/R_10_00@24180 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- src/li/lilib01.cpp | 398 +++++++++++++++++++++++++++++++++++++++++---- src/li/lilib01.h | 63 +++++-- 2 files changed, 418 insertions(+), 43 deletions(-) diff --git a/src/li/lilib01.cpp b/src/li/lilib01.cpp index bb1ba23ce..7f0566868 100644 --- a/src/li/lilib01.cpp +++ b/src/li/lilib01.cpp @@ -1,5 +1,6 @@ #include "lilib01.h" #include +#include #define SOLUZIONE_UNICA 1 #define FINO_A_PLAFOND 2 @@ -19,38 +20,272 @@ void TLi_manager::elabTipiStati(TToken_string& tipi, TToken_string& stati) } } +const TString& TLi_manager::consPlaf(real& plafUsed, const bool write) +{ + TString& used = get_tmp_string(); + if(!validPlafond || plafUsed > getPlafond()) + { + used << "ERRORE NEL CALCOLO DEL PLAFOND"; + return used; + } + + bool close = false; + TToken_string thisPlaf("", ','); + while(plafUsed > ZERO) + { + // Calcolo quanto plafond ho usato + TString thisNumprot = plafondi.begin()->first; + real thisAmount = plafondi.begin()->second; + + real thisUtilizzato; + + if(plafUsed >= thisAmount) + { + close = true; + thisUtilizzato = thisAmount; + + // Rimuovo il plafond dalla lista, + plafondi.erase(thisNumprot); + + if(write) + { + // lo chiudo + changeStato(thisNumprot, true); + } + + // e diminuisco tutto + plafond -= thisAmount; + plafUsed -= thisAmount; + } + else + { + close = false; + thisUtilizzato = plafUsed; + + // e diminuisco tutto + plafond -= plafUsed; + plafondi[thisNumprot] -= plafUsed; + plafUsed = ZERO; + } + + // Segno di aver usato il plafond + used << thisNumprot << "|" << thisUtilizzato.string() << "|" << (close? "X" : "") << ","; + } + // Controllo di avere ancora plafond rimanente + if(plafond <= ZERO) + validPlafond = false; + + // Tolgo la virgola finale + used.cut(used.len()-1); + + return used; +} + +/* Aggiungo al plafond quello che trovo */ +const TString& TLi_manager::incrPlaf(TDocumento& d, real impNC, const bool write) +{ + TString& used = get_tmp_string(); + // 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")) + { + return used; + } + + 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],... + + if(lePlafs.items() == 0) + return used; + + // Controllo se non ho già ricevuto la quantità da stornare di plafond nella nota credito + if(impNC < ZERO) + { + impNC = -impNC; + } + else + { + // In caso negativo la calcolo + TAssoc_array tabIva = d.tabella_iva(true); + for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tabIva.get(); totali != NULL; totali = (TRiepilogo_iva *) tabIva.get()) + { + if(checkIva(totali->cod_iva().codice())) + { + impNC += -totali->imp_orig(); // +-+-+-+-+-+- + } + } + } + + // Controllo se ho del plafond da stornare + if(impNC <= ZERO) + return used; + + bool open = false; + TToken_string thisPlaf("", ','); // Sono abbastanza sicuro che non serve inizializzarlo + for(int i = lePlafs.items() - 1; i >= 0 && impNC > ZERO; i--) + { + lePlafs.get(i, thisPlaf); + + real importoPlaf = thisPlaf.get(_plimporto); + if(importoPlaf < impNC) + { + impNC -= importoPlaf; + } + else + { + importoPlaf = impNC; + impNC = ZERO; + } + + // Aggiungo a plafond + static TString key; key.cut(0) << thisPlaf.get(_planno) << "|" << thisPlaf.get(_plnumprot); + + if(plafondi.find(key) != plafondi.end()) + { + open = false; + // Incremento! + plafondi[key] += importoPlaf; + } + else + { + // Va aggiunto ex novo! + // Calcolo l'importo delle righe che rientrano nel plafond + open = true; + plafondi.insert(std::pair(key, importoPlaf)); + + // Se devo scrivere abilito il plafond + if(write) + { + changeStato(key, false); + } + } + // Segno di aver usato il plafond + used << key << "|" << importoPlaf.string() << "|" << (open? "X" : "") << ","; + } + return used; +} + +void TLi_manager::stornaDoc(TDocumento& d, const bool write) +{ + // Devo ricaricare le righe sui plafond che ho + TToken_string plafs(d.get("PLAFOND"), ','); + for(int i = 0; i < plafs.items(); i++) + { + TToken_string thisPlafond = plafs.get(i); + static TString key; key.cut(0) << thisPlafond.get(_planno) << "|" << thisPlafond.get(_plnumprot); + real thisImporto = thisPlafond.get(_plimporto); + TString asd = thisImporto.string(); + if(d.is_nota_credito()) + { + if(plafondi.find(key) != plafondi.end()) + { + if(thisImporto < plafondi[key]) + { + // Sottraggo + plafondi[key] -= thisImporto; + } + else + { + if(DEBUG_ENABLED) + { + if(thisImporto > plafondi[key]) + error_box("Importo maggiore del plafond rimanente"); + } + plafondi.erase(key); + } + } + else if(DEBUG_ENABLED) + { + error_box("Houston abbiamo un problema...perchè non trovo questo plafond attivo!?"); + } + } + 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); + } + } + } + } +} + + +/* Faccio un analisi di tutti i plafond aperti e li sommo salvandomeli in plafonds */ + 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()); // Creo un cursore ordinato e prelevo la prima riga non chiusa TCursor c_dicint(&letint, "", 2, &filtro, &filtro); validPlafond = false; - bool done = false; if(c_dicint.items() > 0) { - for(c_dicint = 0; c_dicint.pos() < c_dicint.items() && !done; ++c_dicint) + // Cerco finchè non arrivo alla fine o non trovo una soluzione + for(c_dicint = 0; c_dicint.pos() < c_dicint.items() && !soluzione; ++c_dicint) { TRectype row = c_dicint.curr(); + // Esco se raggiungo una data successiva al nostro documento + if(row.get_date("DAL") > finDicInt) + break; + if(!row.get_bool("CHIUSA")) { - if(iniDicInt.ok() && row.get_date("DAL") > iniDicInt) break; - done = true; if(row.get_int("TIPOOP") != FINO_A_PLAFOND && row.get_int("TIPOOP") != SOLUZIONE_UNICA) break; - if(row.get_int("TIPOOP") == SOLUZIONE_UNICA) soluzione = true; - iniDicInt = row.get_date("DAL"); - plafond = row.get_real("IMPORTO"); + if(row.get_int("TIPOOP") == SOLUZIONE_UNICA) + { + // Faccio un controllo in più per bloccare un utente con plafond di diverso tipo + if(validPlafond) + { + // ERRORE! Esiste già un plafond e ho trovato una soluzione unica! + validPlafond = false; + plafondi.clear(); + plafond = -UNO; + return; + } + soluzione = true; + } + if(!validPlafond) + iniDicInt = row.get_date("DAL"); + + // Aggiungo il plafond trovato all'elenco dei plafond + static TString key; + key.cut(0) << row.get("ANNO") << "|" << row.get("NUMPROT"); + plafondi.insert(std::pair(key, row.get_real("IMPORTO"))); + + // Aggiungo il valore del plafond al totale + plafond += row.get_real("IMPORTO"); validPlafond = true; } } @@ -76,8 +311,6 @@ const real TLi_manager::elabPlaRes(TToken_string tipi, TToken_string stati, TDat if(!validPlafond) return -UNO; - real resPlafond = plafond; - TLista_documenti din; // Legge tutti i documenti di input // Trovo tutti i documenti che mi interessano e sottraggo l'imponibile al plafond @@ -85,26 +318,82 @@ const real TLi_manager::elabPlaRes(TToken_string tipi, TToken_string stati, TDat for(int i = 0; i < din.items(); i++) { - TAssoc_array tabIva = din[i].tabella_iva(true); - for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tabIva.get(); totali != NULL; totali = (TRiepilogo_iva *) tabIva.get()) + TToken_string plaf(din[i].get("PLAFOND"), ','); + for(int i = 0; i < plaf.items(); i++) { - if(totali->cod_iva().codice() == codiva) + TToken_string thePla(plaf.get(i)); + static TString key; key.cut(0) << "," << thePla.get(_planno) << "|" << thePla.get(_plnumprot); + if(din[i].tipo().nota_credito()) { - resPlafond -= cache().get("%TIP", din[i].tipo().codice()).get_bool("B7") ? -totali->imp_orig() : totali->imp_orig(); + if(plafondi.find(key) != plafondi.end()) + { + plafondi[key] += (real)thePla.get(_plimporto); + } + else + { + // Va aggiunto ex novo! + // Calcolo l'importo delle righe che rientrano nel plafond + plafondi.insert(std::pair(key, (real)thePla.get(_plimporto))); + } + } + if(!din[i].tipo().nota_credito()) // thePla.get(_plchiusura) != "X" + { + if(plafondi.find(key) != plafondi.end()) + { + // La tolgo! Ma prima controllo che siano uguali + if(DEBUG_ENABLED) + { + if(plafondi[key] != (real)thePla.get(_plimporto)) + { + if(!yesno_box(TR("Questa lettera di intento è incongruente,\nTotale attivo: %s\nTotale da disattivare: %s\nContinuare?"), plafondi[key].string(), thePla.get(_plimporto))) + { + plafond = -UNO; + validPlafond = false; + return plafond; + } + } + } + plafondi.erase(key); + } + else + { + plafondi[key] -= (real)thePla.get(_plimporto); + } } } - - // Nel caso il plafond trovato fosse una soluzione unica e ho già trovato dei documenti vuol dire che il plafond non è più valido - if(soluzione) + /* + // Controllo se stiamo lavorando con una nota credito + if(din[i].tipo().nota_credito()) { - resPlafond = -UNO; - break; + incrPlaf(din[i]); } + else + { + TAssoc_array tabIva = din[i].tabella_iva(true); + for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tabIva.get(); totali != NULL; totali = (TRiepilogo_iva *) tabIva.get()) + { + if(checkIva(totali->cod_iva().codice())) + { + { + consPlaf(totali->imp_orig()); + } + } + } + // Nel caso il plafond trovato fosse una soluzione unica e ho già trovato dei documenti vuol dire che il plafond non è più valido + if(soluzione) + { + plafond = -UNO; + break; + } + } + */ } - return resPlafond; + return plafond; } + + const real TLi_manager::elabUtil(TToken_string tipi, TToken_string stati, TDate ad) { if(!validPlafond) @@ -121,10 +410,14 @@ 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()) { - if(totali->cod_iva().codice() == codiva) + if(checkIva(totali->cod_iva().codice())) { utilizzato += cache().get("%TIP", din[i].tipo().codice()).get_bool("B7") ? -totali->imp_orig() : totali->imp_orig(); } @@ -143,6 +436,8 @@ const real TLi_manager::elabUtil(TToken_string tipi, TToken_string stati, TDate 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(); @@ -155,10 +450,10 @@ bool TLi_manager::testPlafond(TLista_documenti dout, TLog_report& lerr) TAssoc_array tabIva = dout[i].tabella_iva(true); for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tabIva.get(); totali != NULL; totali = (TRiepilogo_iva *) tabIva.get()) { - if(totali->cod_iva().codice() == codiva) + if(checkIva(totali->cod_iva().codice())) { resPlafond -= totali->imp_orig(); - totFatt += totali->imp_orig(); + totFatt += totali->imp_orig(); } } } @@ -174,16 +469,59 @@ bool TLi_manager::testPlafond(TLista_documenti dout, TLog_report& lerr) return err; } -// TIPOCF, CODCLI, ANNO -TLi_manager::TLi_manager(const char t, const long c, TDate iniDic) - : tipocf(t), codcli(c), iniDicInt(iniDic), - tipidoc(ini_get_string(CONFIG_DITTA, "li", "TIPIDOC")), codiva(ini_get_string(CONFIG_DITTA, "li", "CODIVA")), - plafond(-UNO), validPlafond(false), soluzione(false) +int TLi_manager::checkEditability(TDocumento& d) { - elabPlafond(); + TToken_string tipi, stati; + elabTipiStati(tipi, stati); + TLista_documenti din; // Legge tutti i documenti di input + int ret = NOERR; + + // 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++) + { + if(d != din[i]) + ret = din[i].modificabile() ? ret : -1; + } + return ret; } -TLi_manager::~TLi_manager() // Perchè se lo sposto nel file .h il programma crasha? -{ +void TLi_manager::changeStato(const TString& key, const bool stato) +{ + TRectype Jean_Baptiste_Le_Rond_dAlembert = cache().get(LF_LETINT, key); // Che nome di classe! + Jean_Baptiste_Le_Rond_dAlembert.put("CHIUSA", stato); + Jean_Baptiste_Le_Rond_dAlembert.rewrite(TLocalisamfile(LF_LETINT)); + TString skey; skey << key << "|" << stato ? "" : "X"; // Ottimizzazione portami via... + modifiche.insert(std::pair(modifiche.size()+1, skey)); +} + +void TLi_manager::revertModifiche() +{ + if(!hasModifiche()) + return; + TLocalisamfile baguette(LF_LETINT); + + for(auto it = modifiche.begin(); it != modifiche.end(); ++it) + { + TToken_string key = it->second; + TRectype Jean_Baptiste_Le_Rond_dAlembert = cache().get(LF_LETINT, key.get(0)); // Che nome di classe! + Jean_Baptiste_Le_Rond_dAlembert.put("CHIUSA", key.get(1)); + Jean_Baptiste_Le_Rond_dAlembert.rewrite(baguette); + } + 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) +{ + elabPlafond(); } \ No newline at end of file diff --git a/src/li/lilib01.h b/src/li/lilib01.h index 4ace8eba7..6f199450b 100644 --- a/src/li/lilib01.h +++ b/src/li/lilib01.h @@ -17,6 +17,10 @@ #include #endif +#include + +enum plafStruct { _planno, _plnumprot, _plimporto, _plchiusura }; + class TLi_manager : TObject { bool validPlafond; @@ -25,31 +29,64 @@ class TLi_manager : TObject const long codcli; TDate iniDicInt; + TDate finDicInt; real plafond; const TToken_string tipidoc; - const TString codiva; + const TString codivaDef; + const TString codivaAlt; + // 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], ... public: // Getters - const real getPlafond() { return plafond; } // Ritorno il plafond - bool hasValidPlafond() { return validPlafond; } // Ritorno se il plafond è valido - bool isSoluzione() { return soluzione; } // Ritorna se è una dichiarazione di tipo soluzione + // Ritorno il plafond + const real getPlafond() { return plafond; } + // Ritorno se il plafond è valido + bool hasValidPlafond() { return validPlafond; } + // Ritorna se è una dichiarazione di tipo soluzione + bool isSoluzione() { return soluzione; } + + // "Consuma" il plafond + const TString& consPlaf(real& plafUsed, const bool write = false); + // Da una nota credito passata incremento il plafond + const TString& incrPlaf(TDocumento& d, real impNC = ZERO, const bool write = false); + // Storna un documento che riceve + void stornaDoc(TDocumento& d, const bool write = false); // Functions - void elabPlafond(); // Vado a estrapolare il plafond - bool testPlafond(TLista_documenti dout, TLog_report& lerr); // Testo se con i documenti passati supero il plafond - bool checkIva(TString cod) { return cod == codiva; } // Controllo se il codice iva è uguale a quello impostato per il calcolo del plafond - const real getPlaRes(); // Calcolo il rimanente del plafond - const real getPlaRes(TToken_string tipi, TToken_string stati); // Calcolo il rimanente del plafond su tipi e stati documento passati - const real elabPlaRes(TToken_string tipi, TToken_string stati, TDate ad = 0L); // Funzione che effettivamente effettua il calcolodalla data della dichiarazione alla data passata - const real elabUtil(TToken_string tipi, TToken_string stati, TDate ad = 0L); // Ritorna la quantità di plafond utilizzato dalla data della dichiarazione alla data passata + // Vado a estrapolare il plafond + void elabPlafond(); + // Testo se con i documenti passati supero il plafond + 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); + // 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); + // 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" + void changeStato(const TString& key, const bool stato); + // Controlla se ci sono delle modifiche da salvare nei plafonds + bool hasModifiche() { return !modifiche.empty(); } + // Annullo le modifiche + void revertModifiche(); + // Vuoto le modifiche + void clearModifiche() { modifiche.clear(); } // Costructors/Destructors - TLi_manager(const char t, const long c, TDate iniDic = 0L); - ~TLi_manager(); + TLi_manager(const char t, const long c, TDate iniDic = 0L, TDate finDic = 0L); + virtual ~TLi_manager() {} };