campo-sirio/ve/velib03a.cpp
guy 9ecc861e7b Patch level : 2.0 666
Files correlati     : ve0.exe ve6.exe
Ricompilazione Demo : [ ]
Commento            :

GF20114
Il paragrafo [DEFAULTS] dei profili dei documenti contiene la lista dei
valori di default da assegnare a certi campi della maschera di immissione.
Tale paragrafo nella versione a 32 bit viene completamente ignorato, mentre
nella precedente versione funzionava "quasi" sempre.

GF20115
Se si cerca di contabilizzare una fattura di vendita con calcolo al lordo e
con sconti "di testa",
la procedura tenta di generare un movimento sbilanciato e quindi fallisce.
Il problema sembra essere nel fatto che il totale documento e' corretto,
mentre imponibile e iva non tengono conto dello sconto.
Se si utilizzano gli sconti "di riga" o si toglie il calcolo al lordo, tutto
funziona bene.

GF20116
Nell'eventualità avessimo una causale contabile definita sull'anagrafica di
un nostro cliente/fornit bisogna fare in modo che se stiamo contabilizzando
una nota di credito la causale utilizzata non sia quella prevista in anagrafica,
ma bensì quella prevista nella tipologia del documento sul quale naturalmente
ci sarà la spunta di nota di credito/debito (questa appunto può essere la discriminante)


git-svn-id: svn://10.65.10.50/trunk@11704 c028cbd2-c16b-5b4b-a496-9718f37d4682
2004-01-12 08:48:58 +00:00

835 lines
21 KiB
C++
Executable File

#include <tabutil.h>
#include "velib.h"
#include "vepriv.h"
///////////////// //////////////////////////////////////////
// Tipo documento
///////////////////////////////////////////////////////////
TAssoc_array TTipo_documento::_formule_documento;
TTipo_documento::TTipo_documento(const char* tipodoc)
: TRectype(LF_TABCOM), _tipocf('\0')
{
settab("TIP");
if (tipodoc && *tipodoc)
read(tipodoc);
}
TTipo_documento::TTipo_documento(const TRectype& rec)
: TRectype(rec), _tipocf('\0')
{
read_formule();
}
TTipo_documento::~TTipo_documento()
{
}
int TTipo_documento::read(const char* tipodoc)
{
*this = cache().get("%TIP", tipodoc);
int err = empty() ? _iskeynotfound : NOERR;
_formule.cut(0);
if (err == NOERR)
read_formule();
else
yesnofatal_box("Tipo documento errato: %s", tipodoc);
return err;
}
const TFilename& TTipo_documento::profile_name(TFilename& profile) const
{
profile = get("S4");
profile.ext("ini");
return profile;
}
const char TTipo_documento::tipocf()
{
if (_tipocf == '\0')
{
TFilename pn; profile_name(pn);
TConfig prof(pn);
_tipocf = prof.get_char("TIPOCF", "MAIN");
}
return _tipocf;
}
const TString& TTipo_documento::riferimento(const TDocumento & doc, TString& rif) const
{
rif = get("S1");
int p = rif.find('{');
while (p >= 0)
{
const int last = rif.find('}');
const TString16 field_name(rif.sub(p + 1, last));
const TFieldref field(field_name, LF_DOC);
if (last < 0)
rif.cut(p);
else
{
const int len = rif.len() - last;
for (int i = 0; i <= len; i++)
rif[p + i] = rif[last + i + 1];
}
if (field.file() == LF_DOC)
rif.insert(field.read(doc), p);
else
{
TString16 key(doc.get(DOC_TIPOCF));
key << "|" << doc.get(DOC_CODCF);
const TRectype& rec = cache().get(field.file(), key);
rif.insert(field.read(rec), p);
}
p = rif.find('{');
}
return rif;
}
const TString_array& TTipo_documento::keys_descrs()
{
if (_keys_descrs.items() == 0)
{
TString16 var, tiporiga;
TFilename pn; profile_name(pn);
TConfig prof(pn);
const int numtr = prof.get_int( "NTIPIRIGA", "RIGHE" );
TTipo_riga_documento tr;
_keys_descrs.add("");
_keys_descrs.add("");
TToken_string& k = (TToken_string&)_keys_descrs[0];
TToken_string& d = (TToken_string&)_keys_descrs[1];
if (numtr > 0)
{
for ( int i = 1; i <= numtr; i ++ )
{
var.format("%d", i);
tiporiga = prof.get(var, "RIGHE");
tr.read(tiporiga);
k.add(tr.codice());
d.add(tr.descrizione());
}
}
else
{
TTable tri("%TRI");
for (int err = tri.first(); err == NOERR; err = tri.next())
{
k.add(tri.get("CODTAB"));
d.add(tri.get("S0"));
}
}
}
return _keys_descrs;
}
const TString_array& TTipo_documento::sheet_columns()
{
if (_sheet_columns.items() == 0)
{
TString16 col;
TFilename pn; profile_name(pn);
TConfig prof(pn, "SHEET");
int ncols = prof.get_int( "NCOLS", "SHEET" );
for (int i = 1; i <= ncols; i++)
{
col.format( "%d", i );
_sheet_columns.add(prof.get(col, "SHEET"));
}
}
return _sheet_columns;
}
const TString_array& TTipo_documento::handlers()
{
if (_handlers.items() == 0)
{
TString16 chiave;
TFilename pn; profile_name(pn);
TConfig prof(pn);
int numhandler = prof.get_int( "NHANDLER", "HANDLERS" ); // prof
for (int i = 1; i <= numhandler; i++)
{
chiave.format("%d", i);
_handlers.add(prof.get(chiave, "HANDLERS"));
}
}
return _handlers;
}
void TTipo_documento::set_defaults(TMask& m) const
{
if (_defaults.items() == 0) // Carica lo string_array con i defaults
{
TString4 chiave;
TFilename pn; profile_name(pn);
TConfig prof(pn, "DEFAULT");
const int ndefaults = prof.get_int("NDEFAULTS");
for(int i = 1; i <= ndefaults; i++)
{
chiave.format("%d", i);
((TTipo_documento*)this)->_defaults.add(prof.get(chiave));
}
}
// Setta i campi della maschera
FOR_EACH_ARRAY_ROW(_defaults, i, tt)
{
const short ncampo = tt->get_int(0);
if (m.id2pos(ncampo) >= 0)
m.set(ncampo, tt->get(), TRUE);
}
}
void TTipo_documento::add_formula_if_needed(TConfig& profile, TString& variable,
const char* varname, const char* formula)
{
variable = profile.get(varname, "MAIN");
if (variable.empty())
variable = varname;
const TRectype& trr = cache().get("%FRD", variable);
if (trr.empty() || trr.get("S1").empty())
_formule_documento.add(variable, new TFormula_documento(_documento, variable, formula), TRUE);
if (_formule.find(variable) < 0)
_formule.add(variable);
}
void TTipo_documento::read_formule()
{
TFilename profile; profile_name(profile);
TConfig prof(profile, "MAIN");
prof.write_protect(); // Altrimenti non si distrugge!!!
_formule = prof.get("CAMPICALC");
const TString& calcoli = prof.get("CALCOLI");
if (calcoli == "*")
{
TTable frd("%FRD");
for (int err = frd.first(); err == NOERR; err = frd.next())
{
const TString & formula = frd.get("CODTAB");
if (_formule.find(formula) < 0)
_formule.add(formula);
}
}
else
_formule.add(calcoli);
add_formula_if_needed(prof, _totale, "TOTALE", "IMPONIBILI()+IMPOSTE()");
if (_totale == "TOTALE")
_totale = "TOTDOC";
_totale_netto = "_"; _totale_netto << _totale;
add_formula_if_needed(prof, _basesconto, "BASESCONTO", "SOMMA(\"IMPONIBILE()\", \"(TIPO()!='S') && (TIPO()!='C')\")");
add_formula_if_needed(prof, _spese, "SPESE", "SOMMA(\"IMPONIBILE()\", \"TIPO() == 'S'\")");
add_formula_if_needed(prof, _totvalres, "TOTVALRES", "VALDOC(0)");
add_formula_if_needed(prof, _totvalore, "TOTVALORE", "VALDOC(1)");
if (provvigioni())
{
TString80 campo(prof.get("TOTPROVV"));
if (campo.empty())
campo = "TOTPROVV";
const TRectype& frd = cache().get("%FRD", campo);
_totprovv = "_";
_totprovv << campo;
TString80 expr(frd.get("S1"));
if (expr.empty())
expr = "SOMMA(\"PROVV()\")";
_formule_documento.add(_totprovv, new TFormula_documento(_documento, _totprovv, expr, TRUE));
if (_formule.find(campo) < 0)
_formule.add(campo);
_formule.add(_totprovv);
_formule_documento.add(campo, new TFormula_documento(_documento, campo, "TOTPROVV()"), TRUE);
}
_totale_cont = prof.get("TOTALECONT");
_cnt_prezzi = prof.get_bool("CONTROLLO_PREZZI");
_field_prezzo = prof.get(RDOC_PREZZO);
_field_qta = prof.get(RDOC_QTA, NULL, -1, RDOC_QTA);
_field_qtaevasa = prof.get(RDOC_QTAEVASA, NULL, -1, RDOC_QTAEVASA);
_check_qta = prof.get_char("CHECK_QTA", "MAIN");
_str_desc_doc = prof.get("DESCRIZIONE_DOC");
_str_desc_rdoc = prof.get("DESCRIZIONE_RDOC");
_show_evaded_lines = !prof.get_bool("NASCONDI_RIGHE_EVASE"); // Normalmente mostra anche evase
}
bool TTipo_documento::stato_with_mov_mag(const char stato) const
{
if (!mov_mag())
return FALSE;
const char stato_finale(stato_mov_finale());
if (stato_finale > ' ' && stato > stato_finale)
return FALSE;
const char stato_iniziale(stato_mov_iniziale());
return stato >= stato_iniziale;
}
TFormula_documento* TTipo_documento::succ_formula(bool restart)
{
if (restart)
_formule.restart();
TString formula = _formule.get();
while (formula.not_empty())
{
if (formula.blank())
formula = _formule.get();
else
break;
}
if (formula.not_empty())
{
char *expr = NULL;
const int p = formula.find('=');
if (p > 0)
{
expr = (char *) (const char *) formula + p;
*expr = '\0'; expr++;
}
TFormula_documento* o = (TFormula_documento*)_formule_documento.objptr(formula);
if (o == NULL)
{
o = new TFormula_documento(_documento, formula, expr);
_formule_documento.add(formula, o);
}
return o;
}
return NULL;
}
bool TTipo_documento::scarica_residuo() const
{
if (is_ordine() && !riporta_ordinato())
return TRUE;
return get_bool("B4");
}
///////////////////////////////////////////////////////////
// Espressione documento
///////////////////////////////////////////////////////////
TExpr_documento::TExpr_documento(const char* expression, TTypeexp type,
TDocumento * doc, TRiga_documento * row)
: TExpression(type), _doc(doc), _row(row)
{
if (!set(expression, type))
error_box("Wrong expression : '%s'", expression);
}
int TExpr_documento::parse_user_func(const char * name, int nparms) const
{
if (strcmp(name, "SOMMA") == 0)
return nparms > 0 || nparms < 3 ? _somma : -1;
if (strcmp(name, "BOLLI") == 0)
return nparms > 0 || nparms < 4 ? _bolli : -1;
if (strcmp(name, "_BOLLI") == 0)
return nparms > 0 || nparms < 3 ? _bolli_int : -1;
if (strcmp(name, "SPESEINC") == 0)
return nparms > 0 || nparms < 4 ? _spinc : -1;
if (strcmp(name, "PREZZO") == 0)
return nparms < 4 ? _prezzo : -1;
if (strcmp(name, "IMPORTO") == 0)
return nparms < 4 ? _importo : -1;
if (strcmp(name, "SCONTO") == 0)
return nparms < 2 ? _sconto : -1;
if (strcmp(name, "IMPONIBILE") == 0)
return nparms == 0 ? _imponibile : -1;
if (strcmp(name, "IVA") == 0)
return nparms == 0 ? _iva : -1;
if (strcmp(name, "PROVV") == 0)
return nparms < 2 ? _provv : -1;
if (strcmp(name, "QUANT") == 0)
return nparms < 2 ? _quant : -1;
if (strcmp(name, "QUANTEVASA") == 0)
return nparms < 2 ? _quantevasa : -1;
if (strcmp(name, "QTARES") == 0)
return nparms < 2 ? _qtares : -1;
if (strcmp(name, "VALDOC") == 0)
return nparms < 3 ? _valdoc : -1;
if (strcmp(name, "TIPO") == 0)
return nparms == 0 ? _tipo : -1;
if (strcmp(name, "IMPONIBILI") == 0)
return nparms < 3 ? _imponibili : -1;
if (strcmp(name, "IMPOSTE") == 0)
return nparms < 3 ? _imposte : -1;
if (strcmp(name, "TOTPROVV") == 0)
return nparms < 3 ? _totprovv : -1;
if (strcmp(name, "PSCONTOT") == 0)
return nparms < 1 ? _pscontot : -1;
if (strcmp(name, "RITENUTA") == 0)
return nparms < 3 ? _ritenuta : -1;
if (strcmp(name, "TIPORIT") == 0)
return nparms < 1 ? _tipo_ritenuta : -1;
return -1;
}
void TExpr_documento::evaluate_user_func(int index, int nparms, TEval_stack & stack, TTypeexp type) const
{
switch (index)
{
case _somma:
{
const TString cond(nparms == 2 ? stack.pop_string() : "STR(1)");
const TString & field = stack.pop_string();
real somma;
if (_doc != NULL)
{
TExpr_documento cond_expr(cond, _strexpr, _doc);
const int cond_nvars = cond_expr.numvar();
TExpr_documento expr(field, _numexpr, _doc);
const int nvars = expr.numvar();
const int nrows = _doc->rows();
for (int i = nrows; i > 0; i--)
{
TRiga_documento & riga = (TRiga_documento &) (*_doc)[i];
for (int j = cond_nvars - 1; j >= 0; j--)
{
const char* s = cond_expr.varname(j);
TFieldref f(s,0);
cond_expr.setvar(j, f.read(riga));
}
cond_expr.set_row(&riga);
if ((bool)cond_expr)
{
for (j = nvars - 1; j >= 0; j--)
{
const char* s = expr.varname(j);
TFieldref f(s,0);
expr.setvar(j, f.read(riga));
}
expr.set_row(&riga);
somma += expr.as_real();
}
}
}
stack.push(somma);
}
break;
case _spinc:
{
int ndec = AUTO_DECIMALS;
bool netto = FALSE;
if (nparms > 2)
ndec = (int) stack.pop_real().integer();
if (nparms > 1)
netto = !stack.pop_real().is_zero();
real & r = stack.peek_real();
if (_doc)
r = _doc->spese_incasso(r, ndec, netto ? _netto : _lordo);
else
r = ZERO;
}
break;
case _bolli:
{
int ndec = AUTO_DECIMALS;
bool netto = FALSE;
if (nparms > 2)
ndec = (int) stack.pop_real().integer();
if (nparms > 1)
netto = !stack.pop_real().is_zero();
real & r = stack.peek_real();
if (_doc)
{
r += _doc->spese_incasso(r, ndec);
r = _doc->bolli(r, ndec, netto ? _netto : _lordo);
}
else
r = ZERO;
}
break;
case _bolli_int:
{
int ndec = AUTO_DECIMALS;
if (nparms > 2)
ndec = (int) stack.pop_real().integer();
real & r = stack.peek_real();
if (_doc)
{
real r1 = _doc->spese_incasso(r, ndec);
r += r1;
r1 += _doc->bolli(r, ndec);
r = r1;
}
else
r = ZERO;
}
break;
case _prezzo:
{
int ndec = AUTO_DECIMALS;
bool lordo = FALSE;
bool scontato = FALSE;
if (nparms > 2)
ndec = (int) stack.pop_real().integer();
if (nparms > 1)
lordo = !stack.pop_real().is_zero();
if (nparms > 0)
scontato = !stack.peek_real().is_zero();
else
stack.push(ZERO);
real & val = stack.peek_real();
if (_row)
val = _row->prezzo(scontato, lordo, ndec);
else
val = ZERO;
}
break;
case _importo:
{
int ndec = AUTO_DECIMALS;
bool lordo = FALSE;
bool scontato = FALSE;
if (nparms > 2)
ndec = (int) stack.pop_real().integer();
if (nparms > 1)
lordo = !stack.pop_real().is_zero();
if (nparms > 0)
scontato = !stack.peek_real().is_zero();
else
stack.push(ZERO);
real & val = stack.peek_real();
if (_row)
val = _row->importo(scontato, lordo, ndec);
else
val = ZERO;
}
break;
case _imponibile:
{
real r;
if (_row)
r = _row->imponibile();
stack.push(r);
}
break;
case _sconto:
{
int ndec = AUTO_DECIMALS;
if (nparms > 0)
ndec = (int) stack.peek_real().integer();
else
stack.push(ZERO);
real & val = stack.peek_real();
if (_row)
{
if (_row->is_sconto())
val = -_row->importo(FALSE, FALSE, ndec);
else
val = _row->importo(FALSE, FALSE, ndec) - _row->importo(TRUE, FALSE, ndec);
}
else
val = ZERO;
}
break;
case _iva:
{
real r;
if (_row)
r = _row->imposta();
stack.push(r);
}
break;
case _provv:
{
int ndec = AUTO_DECIMALS;
if (nparms > 0)
ndec = (int) stack.peek_real().integer();
else
stack.push(ZERO);
real & val = stack.peek_real();
if (_row)
val = _row->provvigione(ndec);
else
val = ZERO;
}
break;
case _quant:
{
int ndec = AUTO_DECIMALS;
if (nparms > 0)
ndec = (int)stack.peek_real().integer();
else
stack.push(ZERO);
real& val = stack.peek_real();
if (_row)
val = _row->quantita();
else
val = ZERO;
}
break;
case _quantevasa:
{
int ndec = AUTO_DECIMALS;
if (nparms > 0)
ndec = (int)stack.peek_real().integer();
else
stack.push(ZERO);
real& val = stack.peek_real();
if (_row)
val = _row->qtaevasa();
else
val = ZERO;
}
break;
case _qtares:
{
int ndec = AUTO_DECIMALS;
if (nparms > 0)
ndec = (int) stack.peek_real().integer();
else
stack.push(ZERO);
real & val = stack.peek_real();
if (_row)
val = _row->qtaresidua();
else
val = ZERO;
}
break;
case _valdoc:
{
int ndec = AUTO_DECIMALS;
bool totale = TRUE; // Totale o residuo per documento
if (nparms > 1)
ndec = (int)stack.pop_real().integer();
if (nparms > 0)
totale = !stack.peek_real().is_zero();
else
stack.push(ZERO);
real & r = stack.peek_real();
if (_doc)
r = _doc->valore(totale, ndec);
else
r = ZERO;
}
break;
case _tipo:
{
TString s;
if (_row)
s << _row->tipo().tipo();
stack.push(s);
}
break;
case _imponibili:
{
int ndec = AUTO_DECIMALS;
bool spese = FALSE;
if (nparms > 1)
ndec = (int) stack.pop_real().integer();
if (nparms > 0)
spese = !stack.peek_real().is_zero();
else
stack.push(ZERO);
real & val = stack.peek_real();
val = _doc->imponibile(spese, ndec);
}
break;
case _imposte:
{
int ndec = AUTO_DECIMALS;
bool spese = FALSE;
if (nparms > 1)
ndec = (int) stack.pop_real().integer();
if (nparms > 0)
spese = !stack.peek_real().is_zero();
else
stack.push(ZERO);
real & val = stack.peek_real();
val = _doc->imposta(spese, ndec);
}
break;
case _totprovv:
{
int ndec = AUTO_DECIMALS;
if (nparms > 0)
ndec = (int) stack.peek_real().integer();
else
stack.push(ZERO);
real & val = stack.peek_real();
val = _doc->provvigione(ndec);
}
break;
case _pscontot:
{
real val;
TString80 s;
if (_doc && scontoexpr2perc(_doc->get(DOC_SCONTOPERC), FALSE, s, val) && val != ZERO)
val = 1 - val;
stack.push(val);
}
break;
case _ritenuta:
{
int ndec = AUTO_DECIMALS;
bool lordo = FALSE;
if (nparms > 1)
ndec = (int) stack.pop_real().integer();
if (nparms > 0)
lordo = !stack.peek_real().is_zero();
else
stack.push(ZERO);
real & val = stack.peek_real();
const bool spesa = _row->tipo().tipo() == 'S';
if (spesa)
{
const bool tipo_rit = _row->spesa().tipo_ritenuta() != 0;
if (tipo_rit != '\0')
{
((TSpesa_prest &)_row->spesa()).zero("S9");
_row->dirty_fields();
val = _row->importo(TRUE, lordo, ndec);
_row->dirty_fields();
((TSpesa_prest &)_row->spesa()).put("S9", (char)tipo_rit);
}
else
val = ZERO;
}
else
val = ZERO;
}
break;
case _tipo_ritenuta:
{
TString s;
if (_row && _row->tipo().tipo() == 'S')
s << _row->spesa().tipo_ritenuta();
stack.push(s);
}
break;
default:
TExpression::evaluate_user_func(index, nparms, stack, type);
break;
}
}
TObject* TExpr_documento::dup() const
{
TExpr_documento* o = new TExpr_documento(*this);
return o;
}
///////////////////////////////////////////////////////////
// Formula documento
///////////////////////////////////////////////////////////
TFormula_documento::TFormula_documento(TTipo_formula tipo, const char* codice, const char * expr, bool numexpr)
: TRectype(LF_TABCOM), _expr(NULL)
{
_tab = tipo == _documento ? "FRD" : "FRR";
settab(_tab);
_tab.insert("%");
if (codice && *codice)
read(codice, expr, numexpr);
}
TFormula_documento::TFormula_documento(const TRectype& rec)
: TRectype(rec), _expr(NULL)
{
_tab = "%";
_tab << rec.get("COD");
const TTypeexp et = expr_type();
_expr = new TExpr_documento(expr_string(), et);
}
TFormula_documento::~TFormula_documento()
{
if (_expr) delete _expr;
}
int TFormula_documento::read(const char* codice, const char * expr, bool numexpr)
{
if (_expr != NULL)
{
delete _expr;
_expr = NULL;
}
put("CODTAB", codice);
int err = NOERR;
if (expr && *expr)
{
put("S1", expr);
put("B0", numexpr ? "X" : "");
}
else
{
TTable t(_tab);
err = TRectype::read(t);
}
if (err == NOERR)
{
const TTypeexp et = expr_type();
const TString e = expr_string(); // Copio espressione proveniente da record
_expr = new TExpr_documento(e, et);
}
else
{
zero();
put("CODTAB", codice);
}
return err;
}