campo-sirio/src/li/lilib01.cpp

884 lines
25 KiB
C++
Raw Normal View History

#include "lilib01.h"
#include <recarray.h>
#include <utility.h>
#include <progind.h>
#define SOLUZIONE_UNICA 1
#define FINO_A_PLAFOND 2
const TString make_key(const int anno, const int numplaf)
{
static TString key;
key.cut(0).format("%04d|%06d", anno, numplaf);
return key;
}
void TLi_manager::elab_tipi_stati()
{
create_tipi_stati(_tipi, _stati);
}
const TToken_string& TLi_manager::get_use(TDocumento& d, const bool write)
{
static TToken_string& ret = get_tmp_string();
TAssoc_array tab_iva = d.tabella_iva(true);
TString4 num_doc = d.numerazione();
real pla_util = ZERO;
for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tab_iva.get(); totali != NULL; totali = (TRiepilogo_iva *) tab_iva.get())
{
if(check_iva(totali->cod_iva().codice())) // Se l'iva del documento <20> diversa non mi interessa
{
pla_util += totali->imp_orig();
}
}
if(pla_util > ZERO)
{
if(d.is_nota_credito())
{
ret.cut(0) << incr_plaf(d, pla_util, write);
}
else
{
ret.cut(0) << cons_plaf(pla_util, write);
if(ret.starts_with("ERRORE"))
ret << " al documento " << d.numerazione() << " n." << d.numero() << "\nTotale plafond da utilizzare: " << pla_util.string() << "\nTotale rimasto: " << get_plafond().string();
}
}
return ret;
}
const TToken_string& TLi_manager::cons_plaf(real& plaf_used, const bool write)
{
static TToken_string used("", ','); used.cut(0);
if(!_valid_plafond || plaf_used > get_plafond())
{
used << "ERRORE NEL CALCOLO DEL PLAFOND";
return used;
}
bool close = false;
TToken_string this_plaf("", ',');
while(plaf_used > ZERO)
{
// Calcolo quanto plafond ho usato
TString this_numprot = _plafondi.begin()->first;
real this_amount = _plafondi.begin()->second;
real this_utilizzato;
if(plaf_used >= this_amount)
{
close = true;
this_utilizzato = this_amount;
// Rimuovo il plafond dalla lista,
_plafondi.erase(this_numprot);
if(write)
{
// lo chiudo
change_stato(this_numprot, true);
}
// e diminuisco tutto
_plafond -= this_amount;
plaf_used -= this_amount;
}
else
{
close = false;
this_utilizzato = plaf_used;
// e diminuisco tutto
_plafond -= plaf_used;
_plafondi[this_numprot] -= plaf_used;
plaf_used = ZERO;
}
// Segno di aver usato il plafond
static TToken_string u; u.cut(0);
u.add(this_numprot, _planno);
u.add(this_utilizzato.string(), _plimporto);
u.add(close? "X" : "", _plchiusura);
used.add(u);
}
// Controllo di avere ancora plafond rimanente
if(_plafond <= ZERO)
_valid_plafond = false;
// Tolgo la virgola finale
used.cut(used.len()-1);
return used;
}
/* Aggiungo al plafond quello che trovo */
const TToken_string& TLi_manager::incr_plaf(TDocumento& d, real imp_nc, const bool write)
{
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<69> a pi<70> documenti o non <20> specificato salta, meglio stare bassi
if(d.get("NUMDOCRIF").blank() || d.get("CODNUMRIF").blank() || d.get("ANNORIF").blank() || _ini_dic_int.year() != d.get_int("ANNORIF"))
{
return used;
}
TDocumento ds('D', d.get_int("ANNORIF"), d.get("CODNUMRIF"), d.get_int("NUMDOCRIF"));
TToken_string le_plafs(ds.get("PLAFOND"), ','); // [ANNO|NUMPROT|UTILIZZATO],...
// Se il documento di riferimento non ha nulla inserito nel plafond esco, non mi interessa
if(le_plafs.items() == 0)
return used;
// Controllo se non ho gi<67> ricevuto la quantit<69> da stornare di plafond nella nota credito
if(imp_nc == ZERO)
{
// In caso negativo la calcolo
TAssoc_array tab_iva = d.tabella_iva(true);
for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tab_iva.get(); totali != NULL; totali = (TRiepilogo_iva *) tab_iva.get())
{
if(check_iva(totali->cod_iva().codice()))
{
imp_nc += totali->imp_orig();
}
}
}
// Controllo se ho del plafond da stornare
if(imp_nc <= ZERO)
return used;
bool open = false;
TToken_string this_plaf("", '|');
for(int i = le_plafs.items() - 1; i >= 0 && imp_nc > ZERO; i--)
{
le_plafs.get(i, this_plaf);
// Importo utilizzato del plafond
real importo_plaf = this_plaf.get(_plimporto);
// Importo gi<67> riaccreditato da altre NC
real importo_nc = this_plaf.get(_plNC);
// Importo possibile di plafond da stornare
real rimanente = importo_plaf - importo_nc;
if(rimanente == ZERO)
// This isn't the plafond you're looking for
continue;
if(rimanente < imp_nc)
{
imp_nc -= rimanente;
}
else
{
rimanente = imp_nc;
imp_nc = ZERO;
}
// Salvo la quantit<69> utilizzata nelle TToken_string
this_plaf.add(rimanente, _plNC);
le_plafs.add(this_plaf, i);
// Aggiungo a plafond
const TString key = make_key(this_plaf.get_int(_planno), this_plaf.get_int(_plnumprot));
if(_plafondi.find(key) != _plafondi.end())
{
open = false;
// Incremento!
_plafondi[key] += rimanente;
}
else
{
// Va aggiunto ex novo!
// Calcolo l'importo delle righe che rientrano nel plafond
open = true;
_plafondi.insert(std::pair<TString,real>(key, rimanente));
// Se devo scrivere abilito il plafond
if(write)
{
change_stato(key, false);
}
}
// Segno di aver usato il plafond
static TToken_string u; u.cut(0);
u.add(key, _planno);
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 used_app("", ','); used_app.cut(0);
for(int i = used.items(); i > 0; i--)
used_app.add(used.get(used.items()-i), i-1);
// Sovrascrivo il documento
ds.put("PLAFOND", le_plafs);
ds.rewrite();
// Tolgo la virgola finale
used.cut(used.len()-1);
// Succedono cose in memoria, devo rimediare cos<6F>
return used_app;
}
/*
void TLi_manager::stornaDoc(const 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<63> non trovo questo plafond attivo!?");
}
}
else
{
if(plafondi.find(key) != plafondi.end())
{
//Sommo
plafondi[key] += thisImporto;
}
else
{
// Aggiungo ai plafond
plafondi.insert(std::pair<TString, real>(key, thisImporto));
// Se devo scrivere abilito il plafond
if(write)
{
changeStato(key, false);
}
}
}
}
}
// 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::storna_doc(const TDocumento& d, real imp_dc, const bool write)
{
static TToken_string used("", ','); used.cut(0);
// True se devo stornare tutto il Doc
const bool totale = imp_dc.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() && imp_dc > ZERO; i++)
{
TToken_string this_plafond = plafs.get(i);
const TString key = make_key(this_plafond.get_int(_planno), this_plafond.get_int(_plnumprot));
real this_importo = this_plafond.get(_plimporto);
if(totale)
{
if(this_importo >= imp_dc)
{
this_importo = imp_dc;
// Controllo se vado a stornare solo una parte o tutto, nel primo caso cambio la Token, nel secondo elimino normalmente
if(this_importo > imp_dc)
{
this_plafond.add(imp_dc, _plimporto);
plafs.add(this_plafond, i);
}
else
plafs.destroy(i);
imp_dc = ZERO;
}
else
{
imp_dc -= this_importo;
plafs.destroy(i);
}
}
TString asd = this_importo.string();
if(d.is_nota_credito())
{
if(_plafondi.find(key) != _plafondi.end())
{
if(this_importo < _plafondi[key])
{
// Sottraggo
_plafondi[key] -= this_importo;
}
else
{
// Errore
used.cut(0) << "ERRORE: Non <20> presente abbastanza plafond rimanente per stornare la Nota Credito";
return used;
}
}
else
{
// Errore
if(DEBUG_ENABLED)
error_box("Houston abbiamo un problema...perch<63> non trovo questo plafond attivo!?");
used.cut(0) << "ERRORE: La lettera d'intento a cui si rif<69> questa Nota Credito non <20> aperta";
return used;
}
}
else
{
if(_plafondi.find(key) != _plafondi.end())
{
//Sommo
_plafondi[key] += this_importo;
}
else
{
// Aggiungo ai plafond
_plafondi.insert(std::pair<TString, real>(key, this_importo));
// Se devo scrivere abilito il plafond
if(write)
{
change_stato(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::elab_plafond()
{
_valid_plafond = false;
// Controllo preventivo per evitare di fare calcoli su anni precedenti al plafond
if(_ini_dic_int.year() < 2017)
return;
TRelation letint(LF_LETINT);
TRectype filtro(letint.curr());
filtro.add("CODCLI", _codcli);
filtro.add("ANNO", _ini_dic_int.year());
// Creo un cursore ordinato e prelevo la prima riga non chiusa
TCursor c_dicint(&letint, "", 2, &filtro, &filtro);
if(c_dicint.items() > 0)
{
// Cerco finch<63> 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") > _fin_dic_int)
break;
if(!row.get_bool("CHIUSA"))
{
if(row.get_int("TIPOOP") != FINO_A_PLAFOND && row.get_int("TIPOOP") != SOLUZIONE_UNICA) break;
if(row.get_int("TIPOOP") == SOLUZIONE_UNICA)
{
// Faccio un controllo in pi<70> per bloccare un utente con plafond di diverso tipo
if(_valid_plafond)
{
// ERRORE! Esiste gi<67> un plafond e ho trovato una soluzione unica!
_valid_plafond = false;
_plafondi.clear();
_plafond = -UNO;
return;
}
_soluzione = true;
}
if(!_valid_plafond)
_ini_dic_int = row.get_date("DAL");
// Aggiungo il plafond trovato all'elenco dei plafond
const TString key = make_key(row.get_int("ANNO"), row.get_int("NUMPROT"));
_plafondi.insert(std::pair<TString,real>(key, row.get_real("IMPORTO")));
// Aggiungo il valore del plafond al totale
_plafond += row.get_real("IMPORTO");
_valid_plafond = true;
}
}
}
if(!_valid_plafond)
_plafond = -UNO;
}
const real TLi_manager::get_pla_res()
{
return elab_pla_res();
}
const real TLi_manager::get_pla_res(TToken_string tipi, TToken_string stati)
{
return elab_pla_res(tipi, stati);
}
const real TLi_manager::elab_pla_res(TToken_string t, TToken_string s, TDate ad)
{
if(_elab_pr)
return _plafond;
else
_elab_pr = true;
if(t.full() && s.full())
{
_tipi = t;
_stati = s;
}
if(!ad.ok())
ad = _fin_dic_int;
_plafond = -UNO;
if(!_valid_plafond)
return _plafond;
TLista_documenti din; // Legge tutti i documenti di input
// Trovo tutti i documenti che mi interessano e sottraggo l'imponibile al _plafond
din.read('D', _tipocf, _codcli, _ini_dic_int.year(), _tipi, _stati, _ini_dic_int, ad);
for(int i = 0; i < din.items(); i++)
{
TToken_string plaf(din[i].get("PLAFOND"), ',');
for(int j = 0; j < plaf.items(); j++)
{
TToken_string the_pla(plaf.get(j));
const TString key = make_key(the_pla.get_int(_planno), the_pla.get_int(_plnumprot));
static TString chiusura; chiusura.cut(0) << the_pla.get(_plchiusura); // La get ritorna un const char*
if(din[i].tipo().nota_credito())
{
if(_plafondi.find(key) != _plafondi.end())
{
if(DEBUG_ENABLED && chiusura == "X" && yesno_box("Attenzione! La lettera con codice %s riferito alla nota credito %s, %d l'ho trovata ma dovevo aprirla adesso!\n Che faccio, azzero?", key, din[i].numerazione(), din[i].numero()))
{
_plafondi[key] = ZERO;
}
_plafondi[key] += static_cast<real>(the_pla.get(_plimporto));
}
else
{
// Va aggiunto ex novo!
if(DEBUG_ENABLED && chiusura != "X" && yesno_box("Attenzione! La lettera con codice %s riferito alla nota credito %s, %d non l'ho trovata ma doveva gi<67> essere aperta!\n Che faccio, annullo?", key, din[i].numerazione(), din[i].numero()))
{
_valid_plafond = false;
return _plafond;
}
// Calcolo l'importo delle righe che rientrano nel plafond
_plafondi.insert(std::pair<TString,real>(key, static_cast<real>(the_pla.get(_plimporto))));
}
}
else
{
if(_plafondi.find(key) != _plafondi.end())
{
if(chiusura == "X")
{
if(DEBUG_ENABLED && _plafondi[key] != static_cast<real>(the_pla.get(_plimporto)) &&
!yesno_box(TR("Questa lettera di intento <20> incongruente,\nTotale attivo: %s\nTotale da disattivare: %s\nContinuare?"), _plafondi[key].string(), the_pla.get(_plimporto)))
{
_valid_plafond = false;
return _plafond;
}
_plafondi.erase(key);
}
else
{
_plafondi[key] -= static_cast<real>(the_pla.get(_plimporto));
}
}
}
}
}
// Calcolo il totale da mappa scansionata
_plafond = ZERO;
for(auto it = _plafondi.begin(); it != _plafondi.end(); ++it)
_plafond += it->second;
return _plafond;
}
const real TLi_manager::elab_util(TToken_string tipi, TToken_string stati, TDate ad)
{
if(!_valid_plafond)
return -UNO;
if(tipi.items() == 0)
return ZERO;
real utilizzato = ZERO;
TLista_documenti din; // Legge tutti i documenti di input
// Trovo tutti i documenti che mi interessano e sottraggo l'imponibile al plafond
din.read('D', _tipocf, _codcli, _ini_dic_int.year(), tipi, stati, _ini_dic_int, ad);
for(int i = 0; i < din.items(); i++)
{
TAssoc_array tab_iva = din[i].tabella_iva(true);
for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tab_iva.get(); totali != NULL; totali = (TRiepilogo_iva *) tab_iva.get())
{
if(check_iva(totali->cod_iva().codice()))
{
utilizzato += cache().get("%TIP", din[i].tipo().codice()).get_bool("B7") ? -totali->imp_orig() : totali->imp_orig();
}
}
// Nel caso il plafond trovato fosse una soluzione unica e ho gi<67> trovato dei documenti vuol dire che il plafond non <20> pi<70> valido
if(_soluzione)
{
utilizzato = -UNO;
break;
}
}
return utilizzato;
}
bool TLi_manager::test_plafond(TLista_documenti& dout, TLog_report& lerr)
{
bool err = false;
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() && !err; i++)
{
use.cut(0) << get_use(dout[i], true);
if(use.starts_with("ERRORE"))
{
TString msgerr;
msgerr << "Superata dichiarazione di intento cliente N." << dout[i].codcf() << "\n" << use;
lerr.log(2, msgerr);
revert_modifiche();
clear_modifiche();
err = true;
}
}
return err;
}
/* Per scelte implementative non ha una accuratezza del 100% */
bool TLi_manager::check_utilizzo(TDocumento& d, real imp_nc)
{
bool ok = true;
TToken_string le_plafs(d.get("PLAFOND"), ',');
// Se me lo passa la funzione evito di calcolarlo
if(imp_nc.is_zero())
{
for (TRiepilogo_iva * totali = (TRiepilogo_iva *) d.tabella_iva(true).get(); totali != NULL; totali = (TRiepilogo_iva *) d.tabella_iva(true).get())
if(check_iva(totali->cod_iva().codice())) // Se l'iva del documento <20> diversa non mi interessa
imp_nc += totali->imp_orig();
}
/* Per sapere se non ho usato il plafond di questa NC controllo innanzitutto se c'<27> ne abbastanza
* rimasto per coprire la NC, non <EFBFBD> il controllo della vita ma toglie gi<EFBFBD> un po' di calcoli */
ok = get_pla_res() > imp_nc;
// 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 < le_plafs.items() && ok; i++)
{
TToken_string this_plaf(le_plafs.get(i));
const TString key = make_key(this_plaf.get_int(_planno), this_plaf.get_int(_plnumprot));
if(_plafondi.find(key) != _plafondi.end())
{
ok = _plafondi[key] > static_cast<real>(le_plafs.get(_plimporto));
}
else
ok = false;
}
return ok;
}
void TLi_manager::change_stato(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<int, TString>(_modifiche.size()+1, skey));
}
void TLi_manager::revert_modifiche()
{
if(!has_modifiche())
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);
}
clear_modifiche();
}
TLi_manager::TLi_manager(const char t, const long c, TDate iniDic, TDate finDic)
: _tipocf (t), _codcli(c), _ini_dic_int(iniDic), _fin_dic_int(finDic),
_codiva_def(ini_get_string(CONFIG_DITTA, "li", "CODIVA")),
_codiva_alt(ini_get_string(CONFIG_DITTA, "li", "CODIVALT")),
_plafond(ZERO), _valid_plafond(false), _soluzione(false), _elab_pr(false)
{
elab_tipi_stati();
elab_plafond();
}
TLi_manager::TLi_manager(const char t, const long c, TDate finDic)
: _tipocf (t), _codcli(c), _fin_dic_int(finDic),
_codiva_def(ini_get_string(CONFIG_DITTA, "li", "CODIVA")),
_codiva_alt(ini_get_string(CONFIG_DITTA, "li", "CODIVALT")),
_plafond(ZERO), _valid_plafond(false), _soluzione(false), _elab_pr(false)
{
_ini_dic_int.set_day(01);
_ini_dic_int.set_month(01);
_ini_dic_int.set_year(finDic.year());
elab_tipi_stati();
elab_plafond();
}
static void create_tipi_stati(TToken_string& tipi, TToken_string& stati)
{
static const TToken_string tipidoc(ini_get_string(CONFIG_DITTA, "li", "TIPIDOC"));
if(tipi.blank() && stati.blank())
{
for(int i = 0; i < tipidoc.items(); i++)
{
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);
}
}
}
}
bool genera_li_storico(const TDate& data_ini)
{
// Apro la tabella dei plafonds con chiave 2 (CODCLI+ANNO+NUMPROT) e per ogni cliente calcolo i plafond dal 2017
TRelation rletint(LF_LETINT);
TString filter = "DAL>="; filter << data_ini.date2ansi();
TCursor cletint(&rletint, filter, 2);
static TToken_string tipi, stati;
create_tipi_stati(tipi, stati);
static TString cod_ivap = ini_get_string(CONFIG_DITTA, "li", "CODIVA");
static TString cod_ivas = ini_get_string(CONFIG_DITTA, "li", "CODIVALT");
TProgress_monitor status(cletint.items(), "Aggiornamento plafond");
for(cletint = 0; cletint.pos() < cletint.items();) // Il cursore avanza sotto
{
if(!status.add_status())
break;
TRectype rletint = cletint.curr();
++cletint;
TRectype rletintn = cletint.curr();
// Controllo subuto che non sia una dichiarazione a tempo
if(rletint.get_int("TIPOOP") == 3)
continue;
// Date
TDate start_curr = rletint.get_date("DAL"), end_curr;
end_curr = rletint.get_int("CODCLI") == rletintn.get_int("CODCLI") ? --rletintn.get_date("DAL") : NULLDATE;
// Dati lettera
real imp_li = rletint.get_real("IMPORTO");
bool soluzione = rletint.get_int("TIPOOP") == SOLUZIONE_UNICA;
// Adesso che so le date apro tutti i documenti
TLista_documenti din;
din.read('D', 'C', rletint.get_long("CODCLI"), start_curr.year(), tipi, stati, start_curr, end_curr);
for(int i = 0; i < din.items(); i++)
{
#ifdef DBG
if(din[i].numero() == 1202 && din[i].anno() == 2017)
bool tolla = true;
#endif
real utilizzato = ZERO;
TAssoc_array tab_iva = din[i].tabella_iva(true);
for (TRiepilogo_iva * totali = (TRiepilogo_iva *) tab_iva.get(); totali != NULL; totali = (TRiepilogo_iva *) tab_iva.get())
{
if(totali->cod_iva().codice() == cod_ivap || totali->cod_iva().codice() == cod_ivas)
utilizzato += cache().get("%TIP", din[i].tipo().codice()).get_bool("B7") ? -totali->imp_orig() : totali->imp_orig();
}
if(utilizzato.is_zero())
{
if(DEBUG_ENABLED)
{
static bool erase = yesno_box("Vuoi resettare anche i documenti con utilizzo a zero?\nCi metter<65> pi<70> tempo");
din[i].put("PLAFOND", "");
din[i].rewrite();
}
continue;
}
// Controllo di non superare il plafond
if(imp_li >= utilizzato)
{
// Creo la chiave da scrivere e metto tutto dentro
const TString key = make_key(rletint.get_int("ANNO"), rletint.get_int("NUMPROT"));
din[i].put("PLAFOND", key);
din[i].rewrite();
}
else
{
// Error!
if(DEBUG_ENABLED)
warning_box("Superato plafond, si passa alla nuova lettera");
break;
}
// Solo per una lettera
if(soluzione)
break;
}
}
return true;
}
bool popola_plafond(TLista_documenti & din, const TDate& data_elab)
{
std::map<int, TLi_manager*> plafs;
TProgress_monitor m_doc(din.items(), "Generazione plafond nelle fatture");
bool ok = true;
for(int i = 0; i < din.items() && ok; i++)
{
if (!m_doc.add_status())
return false;
// Per ogni fattura richiamo il plafond dell'intestatario e faccio le mie elaborazioni
if (plafs.find(din[i].codcf()) == plafs.end())
{
TLi_manager* app = new TLi_manager(din[i].tipocf(), din[i].codcf(), data_elab);
plafs.insert(std::pair<int, TLi_manager*>(din[i].codcf(), app));
}
TLi_manager& this_pla = *plafs[din[i].codcf()]; // Forget about optimization!
if (!this_pla.has_valid_plafond()) continue;
// Calcolo quanto plafond sta utilizzando
real utilizzato = ZERO;
TAssoc_array tab_iva = din[i].tabella_iva(true);
for (TRiepilogo_iva * totali = (TRiepilogo_iva *)tab_iva.get(); totali != NULL; totali = (TRiepilogo_iva *)tab_iva.get())
{
if (this_pla.check_iva(totali->cod_iva().codice()))
utilizzato += cache().get("%TIP", din[i].tipo().codice()).get_bool("B7") ? -totali->imp_orig() : totali->imp_orig();
}
// Passo a un altro doc se non usa plafond
if (utilizzato.is_zero()) continue;
TToken_string used;
if (din[i].tipo().nota_credito())
{
used = this_pla.incr_plaf(din[i], utilizzato, true);
}
else
{
// Il controllo <20> andato bene, adesso mi segno i plafond che ho utilizzato nel memo del documento
used = this_pla.cons_plaf(utilizzato, true);
}
// Rincontrollo che l'utilizzo del pladond sia tutto ok, meglio una volta in pi<70> che una in meno!
if (used.starts_with("ERRORE"))
{
error_box("Errore! Superato l'utilizzo del plafond per il documento %s %d, del cli/fo %c%d, come <20> possibile?", din[i].tipo().codice(), din[i].numero(), din[i].tipocf(), din[i].codcf());
ok = false;
}
else
{
din[i].put("PLAFOND", used);
}
}
for (auto it = plafs.begin(); it != plafs.end(); ++it)
delete it->second;
return ok;
}