Files correlati : li0.exe f154.dir f154.trr li0200a.msk li0300a.msk li0400a.msk limenu.men Commento : Ristrutturato modulo li
616 lines
14 KiB
C++
616 lines
14 KiB
C++
#include "lilib01.h"
|
|
#include "letint.h"
|
|
#include <doc.h>
|
|
#include "sqlset.h"
|
|
#include <modaut.h>
|
|
#include <utility.h>
|
|
#include <progind.h>
|
|
|
|
#ifndef __VELIB04_H
|
|
#include "../ve/velib04.h"
|
|
#endif
|
|
|
|
#define INIZIO_LETINT 2017
|
|
|
|
// ritorna il codice iva del plafond
|
|
const TString & iva_plafond()
|
|
{
|
|
static TString codiva_plafond_def("*");
|
|
static TString codiva_plafond_alt;
|
|
|
|
if (codiva_plafond_def == "*")
|
|
{
|
|
codiva_plafond_def = ini_get_string(CONFIG_DITTA, "li", "CODIVA");
|
|
codiva_plafond_alt = ini_get_string(CONFIG_DITTA, "li", "CODIVALT");
|
|
}
|
|
if (codiva_plafond_def.full())
|
|
return codiva_plafond_def;
|
|
if (codiva_plafond_alt.full())
|
|
return codiva_plafond_alt;
|
|
return EMPTY_STRING;
|
|
}
|
|
|
|
// Controllo se il codice iva è uguale a quello impostato per il calcolo del plafond
|
|
bool check_iva_plafond(const TString& cod)
|
|
{
|
|
return cod == iva_plafond();
|
|
}
|
|
|
|
const TString & make_key(const int anno, const int numplaf)
|
|
{
|
|
TString & key = get_tmp_string(20);
|
|
|
|
key.format("%04d|%06d", anno, numplaf);
|
|
return key;
|
|
}
|
|
|
|
static TToken_string __tipidoc;
|
|
static TToken_string __statidoc;
|
|
|
|
void get_tipi_stati()
|
|
{
|
|
if (__tipidoc.blank())
|
|
{
|
|
TToken_string tipidoc = (TToken_string &)ini_get_string(CONFIG_DITTA, "li", "TIPIDOC");
|
|
|
|
for (const char * tipo = tipidoc.get(0); tipo && *tipo; tipo = tipidoc.get())
|
|
{
|
|
TToken_string statidoc(ini_get_string(CONFIG_DITTA, "li", tipo), ',');
|
|
const int stato_ini = statidoc.get_int(0);
|
|
const int stato_fin = statidoc.get_int();
|
|
|
|
for (int i = stato_ini; i <= stato_fin; i++)
|
|
{
|
|
__tipidoc.add(tipo);
|
|
__statidoc.add(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TToken_string & tipi()
|
|
{
|
|
if (__tipidoc.blank())
|
|
get_tipi_stati();
|
|
return __tipidoc;
|
|
}
|
|
|
|
TToken_string & stati()
|
|
{
|
|
if (__statidoc.blank())
|
|
get_tipi_stati();
|
|
return __statidoc;
|
|
}
|
|
|
|
#define LINT_MSG 0
|
|
#define LINT_ERROR 1
|
|
#define LINT_CONDITIONAL_ERROR 2
|
|
#define LINT_FATAL 3
|
|
|
|
static TToken_string __lint_msg("", '\n');
|
|
static bool __lint_batch = false;
|
|
|
|
void lint_batch(const bool on) { __lint_batch = on; }
|
|
|
|
bool lint_add_msg(const char * msg, const int msg_type = LINT_MSG, const char * question = "")
|
|
{
|
|
TString m(msg);
|
|
bool ok = msg_type == LINT_MSG;
|
|
|
|
if (msg_type > LINT_MSG)
|
|
m.insert(TR("Errore : "));
|
|
if (msg_type == LINT_FATAL)
|
|
fatal_box(m);
|
|
if (__lint_batch)
|
|
__lint_msg.add(m);
|
|
else
|
|
{
|
|
switch (msg_type)
|
|
|
|
{
|
|
case LINT_MSG :
|
|
message_box(m);
|
|
break;
|
|
case LINT_ERROR:
|
|
error_box(m);
|
|
break;
|
|
case LINT_CONDITIONAL_ERROR:
|
|
m << ' ' << question << " ?";
|
|
yesnocancel_box (m);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void lint_reset_msg() { __lint_msg.cut(0); }
|
|
const TToken_string & lint_get_msg() { return __lint_msg; }
|
|
|
|
void TLi_manager::set_anno(const int anno)
|
|
{
|
|
if (_anno != anno)
|
|
{
|
|
_anno = anno;
|
|
read();
|
|
}
|
|
}
|
|
|
|
void genera_li_storico(const int anno, const long from_cli, const long to_cli, const char tipocf)
|
|
{
|
|
// Apro la tabella dei plafonds con chiave 2 (CODCLI+ANNO+NUMPROT) e per ogni cliente calcolo i plafond dal 2017
|
|
const TDate dal(1, 1, anno);
|
|
TRelation rletint(LF_LETINT);
|
|
TRectype * from_let = nullptr;
|
|
TRectype * to_let = nullptr;
|
|
|
|
if (from_cli > 0L)
|
|
{
|
|
from_let = new TRectype(rletint.file().curr());
|
|
from_let->put(LETINT_CODCLI, from_cli);
|
|
}
|
|
if (to_cli > 0L)
|
|
{
|
|
to_let = new TRectype(rletint.file().curr());
|
|
to_let->put(LETINT_CODCLI, to_cli);
|
|
}
|
|
TString filter = LETINT_DAL ; filter << ">=" << dal.date2ansi();
|
|
TCursor letint(&rletint, filter , 2, from_let, to_let);
|
|
const int items = letint.items();
|
|
TAssoc_array cli;
|
|
bool ok = true;
|
|
TString msg(TR("Ricostruzione plafond dal "));
|
|
|
|
msg << dal.string();
|
|
|
|
TProgress_monitor status(items, msg);
|
|
TString16 curr_codcli;
|
|
|
|
lint_reset_msg();
|
|
lint_batch();
|
|
for (letint = 0; ok && letint.pos() < items; ++letint)
|
|
{
|
|
if (ok = status.add_status())
|
|
{
|
|
const TString16 codcli = letint.curr().get(LETINT_CODCLI);
|
|
TBit_array * years = nullptr;
|
|
|
|
if (codcli != curr_codcli)
|
|
{
|
|
curr_codcli = codcli;
|
|
cli.add(curr_codcli, years = new TBit_array);
|
|
|
|
}
|
|
if (years != nullptr)
|
|
years->set(letint.curr().get_int(LETINT_ANNO) - INIZIO_LETINT);
|
|
}
|
|
}
|
|
|
|
TString_array keys;
|
|
|
|
cli.get_keys(keys);
|
|
keys.sort();
|
|
|
|
const int cli_items = keys.items();
|
|
|
|
for (int i = 0; i < cli_items; i++)
|
|
{
|
|
const TString & codcli = keys[i];
|
|
const TBit_array & years = (const TBit_array &)cli[codcli];
|
|
|
|
if (years.some_one())
|
|
{
|
|
const int last = years.last_one();
|
|
|
|
for (int y = years.first_one(); y <= last; y++)
|
|
{
|
|
const int anno = INIZIO_LETINT + y;
|
|
TLi_manager li('C', atol(codcli), anno);
|
|
|
|
li.rebuild_plafond(true, anno);
|
|
}
|
|
}
|
|
}
|
|
const TString messages = lint_get_msg();
|
|
|
|
if (messages.full())
|
|
message_box(messages);
|
|
lint_batch(false);
|
|
}
|
|
|
|
void TLi_manager::read(const TRectype & filter)
|
|
{
|
|
TCursor c(new TRelation(LF_LETINT), "", 2, &filter, &filter);
|
|
const int items = c.items();
|
|
|
|
_plafonds.destroy();
|
|
for (c = 0L; c.pos() < items; ++c)
|
|
_plafonds.add(c.curr());
|
|
_valid_plafond = items > 0;
|
|
}
|
|
|
|
int TLi_manager::flush()
|
|
{
|
|
int err = NOERR;
|
|
|
|
if (_dirty)
|
|
{
|
|
TLocalisamfile letint(LF_LETINT);
|
|
const int rows = _plafonds.items();
|
|
|
|
for (int r = 0; r < rows; r++)
|
|
{
|
|
TRectype & row = (TRectype &)_plafonds[r];
|
|
|
|
int err = row.rewrite(letint);
|
|
}
|
|
_dirty = false;
|
|
}
|
|
return err;
|
|
}
|
|
TRectype & TLi_manager::get_lint(const int numprot)
|
|
{
|
|
const int rows = _plafonds.items();
|
|
static TRectype nullrec(LF_LETINT); // orrible static record for errors
|
|
|
|
for (int r = 0; r < rows; r++)
|
|
{
|
|
TRectype & rec = (TRectype &) _plafonds[r];
|
|
if (numprot == rec.get_int(LETINT_NUMPROT))
|
|
return rec;
|
|
}
|
|
nullrec.put(LETINT_CODCLI, _codcli);
|
|
nullrec.put(LETINT_ANNO, _anno);
|
|
nullrec.put(LETINT_NUMPROT, numprot);
|
|
return nullrec;
|
|
}
|
|
|
|
void TLi_manager::add2lint(TRectype & reclint, const real & utilizzo, const bool add)
|
|
{
|
|
TLocalisamfile letint(LF_LETINT);
|
|
const real valore = add ? utilizzo : -utilizzo;
|
|
|
|
reclint.add(LETINT_UTILIZZATO, valore);
|
|
|
|
const bool soluzione_unica = reclint.get_bool(LETINT_TIPOOP) == SOLUZIONE_UNICA;
|
|
const real utilizzato = reclint.get_real(LETINT_UTILIZZATO);
|
|
const real importo = reclint.get_real(LETINT_IMPORTO);
|
|
const bool chiusa = (soluzione_unica && (utilizzato) != ZERO) || (utilizzato >= importo);
|
|
|
|
reclint.put(LETINT_CHIUSA, chiusa);
|
|
_dirty = true;
|
|
}
|
|
|
|
bool TLi_manager::utilizza_plafond(const TDocumento & d, TToken_string & plafs, const real importo)
|
|
{
|
|
bool ok = true;
|
|
|
|
TDate dal(1, 1, _anno);
|
|
real imp_plafond = importo;
|
|
const TDate datadoc = d.get_date(DOC_DATADOC);
|
|
const int day = datadoc - dal;
|
|
TToken_string & letints = _days[day];
|
|
const int letitems = letints.items();
|
|
|
|
if (d.is_nota_credito())
|
|
{
|
|
if (d.get(DOC_PLAFOND).empty())
|
|
{
|
|
TString8 codnumdocrif = d.get(DOC_CODNUMRIF);
|
|
int annodocrif = d.get_int(DOC_ANNORIF);
|
|
const long numdocrif = d.get_long(DOC_NUMDOCRIF);
|
|
|
|
if (codnumdocrif.blank())
|
|
codnumdocrif = d.get(DOC_CODNUM);
|
|
if (annodocrif == 0)
|
|
annodocrif = d.get_int(DOC_ANNO);
|
|
|
|
TDocumento docrif('D', annodocrif, codnumdocrif, numdocrif);
|
|
|
|
if (!docrif.empty())
|
|
{
|
|
plafs = docrif.get(DOC_PLAFOND);
|
|
|
|
const int items = plafs.items();
|
|
|
|
for (int k = 0; k < items; k++)
|
|
{
|
|
TToken_string plaf = plafs.get(k);
|
|
|
|
plaf.add(ZERO, _plimporto);
|
|
plafs.add(plaf, k);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const int plafsitems = plafs.items();
|
|
|
|
if (plafsitems < letitems)
|
|
{
|
|
TToken_string new_plafs("", ',');
|
|
|
|
for (int j = 0; j < letitems; j++)
|
|
{
|
|
TRectype & rec = (TRectype &)_plafonds[letints.get_int(j)];
|
|
bool chiusa = rec.get_bool(LETINT_CHIUSA);
|
|
const int numprot = rec.get_int(LETINT_NUMPROT);
|
|
const int tipo = rec.get_int(LETINT_TIPOOP);
|
|
TToken_string new_plaf;
|
|
|
|
new_plaf.add(_anno, _planno);
|
|
new_plaf.add(numprot, _plnumprot);
|
|
real utilizzo;
|
|
for (int k = 0; utilizzo == ZERO && k < plafsitems; k++)
|
|
{
|
|
TToken_string plaf(plafs.get(k));
|
|
|
|
if (plaf.get_int(_plnumprot) == numprot)
|
|
utilizzo = plaf.get_real(_plimporto);
|
|
}
|
|
new_plaf.add(utilizzo, _plimporto);
|
|
new_plafs.add(new_plaf);
|
|
}
|
|
plafs = new_plafs;
|
|
}
|
|
|
|
const bool storna = imp_plafond < ZERO;
|
|
|
|
for (int k = storna ? letitems - 1 : 0; imp_plafond != ZERO && (storna ? k >= 0: k < letitems); storna ? k-- : k++)
|
|
{
|
|
TRectype & rec = (TRectype &) _plafonds[letints.get_int(k)];
|
|
bool chiusa = rec.get_bool(LETINT_CHIUSA);
|
|
|
|
if (!chiusa || storna)
|
|
{
|
|
real utilizzo = imp_plafond;
|
|
const real let_importo = rec.get_real(LETINT_IMPORTO);
|
|
const real totale_utilizzato = rec.get_real(LETINT_UTILIZZATO);
|
|
TToken_string plaf = plafs.get(k);
|
|
const real disponibile = let_importo - totale_utilizzato;
|
|
const real totale = totale_utilizzato + utilizzo;
|
|
const real utilizzo_plaf = plaf.get_real(_plimporto);
|
|
|
|
if (d.is_nota_credito())
|
|
{
|
|
if (utilizzo > ZERO)
|
|
{
|
|
if (utilizzo + utilizzo_plaf > ZERO)
|
|
utilizzo = -utilizzo_plaf;
|
|
}
|
|
if (totale < ZERO)
|
|
utilizzo -= totale;
|
|
}
|
|
else
|
|
{
|
|
if (totale > let_importo)
|
|
utilizzo = disponibile;
|
|
if (totale < ZERO)
|
|
utilizzo += totale;
|
|
}
|
|
imp_plafond -= utilizzo;
|
|
plaf.add(utilizzo + utilizzo_plaf, _plimporto);
|
|
plafs.add(plaf, k);
|
|
add2lint(rec, utilizzo);
|
|
}
|
|
}
|
|
if (imp_plafond > ZERO)
|
|
{
|
|
TString msg(TR("Attenzione il plafond del cliente "));
|
|
|
|
msg << _codcli << ' ' << TR("il plafond per l'anno ") << _anno << ' ' <<
|
|
TR("è stato superato di € ") << imp_plafond;
|
|
lint_add_msg(msg, LINT_ERROR);
|
|
ok = false;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void TLi_manager::clear_letint()
|
|
{
|
|
const int rows = _plafonds.items();
|
|
|
|
for (int r = 0; r < rows; r++)
|
|
{
|
|
TRectype & row = (TRectype &) _plafonds[r];
|
|
|
|
row.zero(LETINT_UTILIZZATO);
|
|
row.zero(LETINT_CHIUSA);
|
|
}
|
|
_dirty = true;
|
|
flush();
|
|
}
|
|
|
|
void TLi_manager::rebuild_plafond(bool update_docs, const int anno)
|
|
{
|
|
TLista_documenti din;
|
|
TDate dal; dal.set_start_year(anno);
|
|
TDate al; al.set_end_year(anno);
|
|
|
|
set_anno(anno);
|
|
din.read('D', 'C', _codcli, anno, tipi(), stati(), dal, al);
|
|
|
|
const int items = din.items();
|
|
|
|
if (_valid_plafond)
|
|
{
|
|
TProgress_monitor status(items, "Aggiornamento plafond : Ricostuzione");
|
|
bool ok = true;
|
|
|
|
clear_letint();
|
|
for (int i = 0; ok && i < items; i++)
|
|
{
|
|
if (ok = status.add_status())
|
|
{
|
|
TToken_string plafs("", ',');
|
|
|
|
din[i].zero(DOC_PLAFOND);
|
|
if (update_docs)
|
|
din[i].rewrite();
|
|
else
|
|
utilizza_plafond(din[i], plafs, din[i].importo_plafond());
|
|
}
|
|
}
|
|
flush();
|
|
}
|
|
else
|
|
{
|
|
bool has_plafond = false;
|
|
|
|
for (int i = 0; !has_plafond && i < items; i++)
|
|
has_plafond = din[i].importo_plafond() != ZERO;
|
|
|
|
if (has_plafond)
|
|
{
|
|
TString msg(TR("Attenzione il cliente "));
|
|
|
|
msg << _codcli << TR(" per l'anno") << dal.year() << TR("ha documenti con esenzione plafond ma non ha plafond registrati");
|
|
lint_add_msg(msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TLi_manager::read(const char t, const long c, TDate inidic, TDate findic)
|
|
{
|
|
TRectype reclint(LF_LETINT);
|
|
|
|
flush();
|
|
_plafond = ZERO;
|
|
_dirty = false;
|
|
_days.destroy();
|
|
TDate inizio_anno; inizio_anno.set_start_year(_anno);
|
|
TDate fine_anno; fine_anno.set_end_year(_anno);
|
|
const int last_day = fine_anno - inizio_anno;
|
|
|
|
for (int d = 0; d <= last_day; d++)
|
|
_days.add(new TToken_string);
|
|
if (t != ' ')
|
|
_tipocf = t;
|
|
if (c != 0)
|
|
_codcli = c;
|
|
if (_anno == 0)
|
|
_anno = TDate(TODAY).year();
|
|
reclint.put(LETINT_CODCLI, _codcli);
|
|
reclint.put(LETINT_ANNO, _anno);
|
|
read(reclint);
|
|
|
|
const int rows = _plafonds.items();
|
|
|
|
for (int r = 0; r < rows; r++)
|
|
{
|
|
const TRectype & row = (const TRectype &)_plafonds[r];
|
|
const real & importo = row.get_real(LETINT_IMPORTO);
|
|
const real & utilizzato = row.get_real(LETINT_UTILIZZATO);
|
|
|
|
_plafond += importo;
|
|
_utilizzato += utilizzato;
|
|
|
|
TDate inizio = row.get_date(LETINT_DAL);
|
|
TDate fine = row.get_date(LETINT_AL);
|
|
|
|
if (!inizio.ok())
|
|
inizio = inizio_anno;
|
|
if (!fine.ok())
|
|
fine = fine_anno;
|
|
|
|
const int from_day = inizio - inizio_anno;
|
|
const int to_day = fine - inizio_anno;
|
|
|
|
for (int d = from_day; d <= to_day; d++)
|
|
{
|
|
TToken_string & list = _days[d];
|
|
|
|
list.add(r);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TLi_manager::doc_ok(const TDocumento & doc) const
|
|
{
|
|
const TString8 tipodoc = doc.tipo().codice();
|
|
const TString4 stato = doc.get(DOC_STATO);
|
|
|
|
return (tipi().find(tipodoc) >= 0) && (stati().find(stato) >= 0);
|
|
}
|
|
|
|
bool TLi_manager::plafond_write(TDocumento& d)
|
|
{
|
|
bool ok = true;
|
|
real importo_plafond = d.importo_plafond();
|
|
|
|
if (doc_ok(d) && has_valid_plafond()) // Se il cliente non mi interessa
|
|
{
|
|
if (importo_plafond != ZERO)
|
|
{
|
|
TToken_string plafs("", ',');
|
|
|
|
// Il controllo è andato bene, adesso mi segno i plafond che ho utilizzato nel memo del documento
|
|
ok = utilizza_plafond(d, plafs, importo_plafond);
|
|
d.put(DOC_PLAFOND, plafs);
|
|
flush();
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TLi_manager::plafond_rewrite(TDocumento& d)
|
|
{
|
|
bool ok = true;
|
|
TToken_string plafs(d.get(DOC_PLAFOND), ',');
|
|
const TString8 tipodoc = d.tipo().codice();
|
|
const TString4 stato = d.get(DOC_STATO);
|
|
real diff = (doc_ok(d) && has_valid_plafond() ? d.importo_plafond() : ZERO) - d.importo_plafond_salvato();
|
|
|
|
// Calcolo le differenze tra il plafond attuale da verificare e quello precedente
|
|
if (diff != ZERO)
|
|
{
|
|
ok = utilizza_plafond(d, plafs, diff);
|
|
d.put(DOC_PLAFOND, plafs);
|
|
flush();
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TLi_manager::write_rewrite(TDocumento& d, bool rewrite)
|
|
{
|
|
bool ok = true;
|
|
|
|
// Aggiunte per il controllo plafond
|
|
if (main_app().has_module(LIAUT, CHK_DONGLE) && _valid_plafond)
|
|
{
|
|
if (rewrite)
|
|
ok = plafond_rewrite(d);
|
|
else
|
|
ok = plafond_write(d);
|
|
}
|
|
else
|
|
d.zero(DOC_PLAFOND);
|
|
return ok;
|
|
}
|
|
|
|
bool TLi_manager::remove(TDocumento& d)
|
|
{
|
|
bool ok = true;
|
|
TToken_string plafs(d.get(DOC_PLAFOND), ',');
|
|
|
|
if (main_app().has_module(LIAUT, CHK_DONGLE) && has_valid_plafond() && plafs.full())
|
|
{
|
|
ok = utilizza_plafond(d, plafs, -d.importo_plafond());
|
|
flush();
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
TLi_manager::TLi_manager(const char t, const long c, const int anno)
|
|
: _tipocf(t), _codcli(c), _anno(anno), _plafond(),
|
|
_utilizzato(), _valid_plafond(false),
|
|
_dirty(false), _plafonds()
|
|
{
|
|
read();
|
|
}
|
|
|
|
TLi_manager::~TLi_manager()
|
|
{
|
|
flush();
|
|
} |