campo-sirio/ve/velib03.cpp

1339 lines
36 KiB
C++
Raw Normal View History

#include "velib.h"
#include "vepriv.h"
#include <clifo.h>
#ifndef __APPLICAT_H
#include <applicat.h>
#endif
#ifndef __VEUML_H
#include "veuml.h"
#endif
#ifndef __TABUTIL_H
#include <tabutil.h>
#endif
#ifndef __UTILITY_H
#include <utility.h>
#endif
#ifndef __VEINI_H
#include "veini.h"
#endif
#ifndef __MGLIB_H
#include "../mg/mglib.h"
#endif
#ifndef __SCONTI_H
#include "sconti.h"
#endif
#ifndef __MODAUT_H
#include <modaut.h>
#endif
#include "../mg/movmag.h"
///////////////////////////////////////////////////////////
// Movimento di magazzino
///////////////////////////////////////////////////////////
class TMov_mag_doc : public TMov_mag
{
const TDocumento * _doc;
protected:
virtual const char * codmag_rauto(int r) const;
public:
TMov_mag_doc(const TDocumento * d) : _doc(d) {}
virtual ~TMov_mag_doc() {}
};
const char * TMov_mag_doc::codmag_rauto(int r) const
{
const int rows = _doc->physical_rows();
const long num = get_long(MOVMAG_NUMREG);
for (int i = 1; r > 0 && i <= rows; i++)
if ((*_doc)[i].is_articolo() && num == (*_doc)[i].get_long("MOVMAG"))
r--;
i--;
if (i > rows)
return NULL;
const TString & codmag = (*_doc)[i].get("CODMAGC");
return codmag.empty() ? NULL : (const char *) codmag;
}
///////////////////////////////////////////////////////////
// Tipo documento
///////////////////////////////////////////////////////////
TAssoc_array TTipo_documento::_formule_documento;
TTipo_documento::TTipo_documento(const char* tipodoc)
: TRectype(LF_TABCOM)
{
settab("TIP");
if (tipodoc && *tipodoc)
read(tipodoc);
}
TTipo_documento::TTipo_documento(const TRectype& rec)
: TRectype(rec)
{
read_formule();
}
TTipo_documento::~TTipo_documento()
{ }
int TTipo_documento::read(const char* tipodoc)
{
TTable t("%TIP");
put("CODTAB", tipodoc);
int err = TRectype::read(t);
_formule = "";
if (err == NOERR)
read_formule();
else
yesnofatal_box("Tipo documento errato: %s", tipodoc);
return err;
}
void TTipo_documento::read_formule()
{
TFilename prof(profile_name());
prof.ext("ini");
TConfig profile(prof);
_formule = profile.get("CAMPICALC", "MAIN");
_formule.add(profile.get("CALCOLI", "MAIN"));
_totale = profile.get("TOTALE", "MAIN");
if (_totale.empty())
{
_totale = "TOTDOC";
if (_formule.find(_totale) < 0)
_formule.add("TOTDOC=IMPONIBILI()+IMPOSTE()");
}
_totale_netto = "_";
_totale_netto << _totale;
if (_totale.not_empty() && _formule.find(_totale) < 0)
{
error_box("Campo totale documento (%s) sconosciuto nel tipo documento %s", (const char *) _totale, (const char *) codice());
_totale.cut(0);
}
_basesconto = profile.get("BASESCONTO", "MAIN");
if (_basesconto.empty())
{
_basesconto = "BASESCONTO";
if (_formule.find(_basesconto) < 0)
_formule.add("BASESCONTO=SOMMA(\"IMPONIBILE()\", \"(TIPO() != 'S') && (TIPO() != 'C')\")");
}
if (_basesconto.not_empty() && _formule.find(_basesconto) < 0)
{
error_box("Campo sconto documento (%s) sconosciuto nel tipo documento %s", (const char *) _basesconto, (const char *) codice());
_basesconto.cut(0);
}
_spese = profile.get("SPESE", "MAIN");
if (_spese.empty())
{
_spese = "SPESE";
if (_formule.find(_spese) < 0)
_formule.add("SPESE=SOMMA(\"IMPONIBILE()\", \"TIPO() != 'S'\")");
}
if (_spese.not_empty() && _formule.find(_spese) < 0)
{
error_box("Campo spese (%s) sconosciuto nel tipo documento %s", (const char *) _spese, (const char *) codice());
_spese.cut(0);
}
}
bool TTipo_documento::stato_with_mov_mag(const TString & stato) const
{
if (!mov_mag())
return FALSE;
const TString16 stato_finale(stato_mov_finale());
if (stato_finale.not_empty() && stato > stato_finale)
return FALSE;
const TString16 stato_iniziale(stato_mov_iniziale());
return stato >= stato_iniziale;
}
TFormula_documento * TTipo_documento::succ_formula(bool restart)
{
if (restart)
_formule.restart();
const TString formula(_formule.get());
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;
}
else
return NULL;
}
///////////////////////////////////////////////////////////
// Documento per vendite
///////////////////////////////////////////////////////////
TAssoc_array TDocumento::_tipi;
TDocumento::TDocumento()
: TAuto_variable_rectype(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA"), _nuovo(TRUE),
_condv(NULL), _sconto(NULL), _esenzione(NULL)
{
_tipocf = new TRecfield(*this, "TIPOCF");
_codcf = new TRecfield(*this, "CODCF");
_cod_occas = new TRecfield(*this, "OCFPI");
set_memo_fld("G1");
for (int i = 3 ; i >= 0; i--) _liv_len[i] = 0;
}
TDocumento::TDocumento(const TDocumento & d)
: TAuto_variable_rectype(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA"), _nuovo(TRUE),
_condv(NULL), _sconto(NULL), _esenzione(NULL)
{
copy(d);
}
TDocumento::TDocumento(char provv, int anno, const char* codnum, long numdoc,
TCond_vendita * condv, TRelation * rel)
: TAuto_variable_rectype(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA"), _nuovo(TRUE),
_condv(condv), _sconto(NULL), _esenzione(NULL)
{
_tipocf = new TRecfield(*this, "TIPOCF");
_codcf = new TRecfield(*this, "CODCF");
_cod_occas = new TRecfield(*this, "OCFPI");
set_memo_fld("G1");
if (numdoc <= 0)
{
numdoc = 0;
set_key(*this, provv, anno, codnum, numdoc);
TRiga_documento* key = new TRiga_documento(this);
set_key(*key, provv, anno, codnum, numdoc);
_rows.set_key(key); // ok
}
else
read(provv, anno, codnum, numdoc);
for (int i = 3 ; i >= 0; i--) _liv_len[i] = 0;
}
TDocumento::TDocumento(const TRectype& rec, TCond_vendita * condv, TRelation * rel)
: TAuto_variable_rectype(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA"), _nuovo(FALSE),
_condv(condv), _sconto(NULL), _esenzione(NULL)
{
_tipocf = new TRecfield(*this, "TIPOCF");
_codcf = new TRecfield(*this, "CODCF");
_cod_occas = new TRecfield(*this, "OCFPI");
set_memo_fld("G1");
read(rec);
for (int i = 3 ; i >= 0; i--) _liv_len[i] = 0;
}
TDocumento::~TDocumento()
{
delete _tipocf;
delete _codcf;
delete _cod_occas;
if (_sconto != NULL) delete _sconto;
if (_esenzione != NULL) delete _esenzione;
}
real TDocumento::spese_incasso(real & imp, int ndec, TTipo_importo t) const
{
real imp_spese;
real percentuale = get_real("PERCSPINC");
static TArray spese_inc;
if (percentuale > ZERO)
{
if (spese_inc.objptr(_rim_dir) == NULL)
{
TConfig conf(CONFIG_STUDIO);
for (TTipo_pag p = _rim_dir; p < _nessun_pag; p = (TTipo_pag) ((int)p + 1))
{
real r(conf.get("IMPSPINC", "ve", p));
spese_inc.add(r, p);
}
}
TPagamento & pag = ((TDocumento *)this)->pagamento();
const int nrate = pag.n_rate();
for (int i = 0; i < nrate; i++)
{
const TTipo_pag p = (TTipo_pag) pag.tipo_rata(i);
imp_spese += (real &) spese_inc[p];
}
imp_spese *= percentuale / 100.0;
real cambio = get_real("CAMBIO");
if (cambio == ZERO)
cambio = 1.0;
static TString16 codiva;
static long firm = -1;
long new_firm = main_app().get_firm();
if (firm != new_firm)
{
TConfig conf(CONFIG_DITTA);
codiva = conf.get("SPINCODIVA", "ve");
firm = new_firm;
}
real iva_spese(iva(imp_spese, TRiga_documento::iva(codiva), ndec));
if (t == _lordo)
imp_spese += iva_spese;
else
if (t == _imposta)
imp_spese = iva_spese;
imp_spese /= cambio;
imp_spese.round(ndec);
}
return imp_spese;
}
real TDocumento::bolli(real & imp, int ndec, TTipo_importo t) const
{
real tot_bolli;
static TArray sca_bolli;
static TArray imp_bolli;
static int nscagl;
TLocalisamfile clifo(LF_CLIFO);
bool estero = 2;
if (get_bool("ADDBOLLI"))
{
real cambio = get_real("CAMBIO");
if (cambio == ZERO)
cambio = 1.0;
real importo = imp*cambio;
TPagamento & pag = ((TDocumento*)this)->pagamento();
const int nrate = pag.n_rate();
real old_bolli = -1.00;
real iva_bolli;
real imp_orig = imposta();
real sp_orig = spese();
for (int j = 0; j < 5 && tot_bolli != old_bolli; j++)
{
old_bolli = tot_bolli + iva_bolli;
const real imposte = imp_orig * cambio + iva_bolli;
const real imp_spese = sp_orig * cambio + tot_bolli - iva_bolli;
const real imponibile = importo - imposte - imp_spese;
tot_bolli = ZERO;
pag.set_total(imponibile, imposte, imp_spese);
pag.set_rate_auto();
for (int i = 0; i < nrate; i++)
{
const TTipo_pag p = (TTipo_pag) pag.tipo_rata(i);
real imp = pag.importo_rata(i);
switch (p)
{
case _ric_ban:
{
if (sca_bolli.objptr(0) == NULL)
{
TConfig conf(CONFIG_STUDIO);
for (nscagl = 0; nscagl < 7; nscagl++)
{
real s(conf.get("SPBOSCA", "ve", nscagl + 1));
real i(conf.get("SPBOIMP", "ve", nscagl + 1));
if (s == ZERO && i == ZERO)
break;
sca_bolli.add(s, nscagl);
imp_bolli.add(i, nscagl);
}
}
for (int i = 0; i < nscagl - 1; i++)
if ((real &) sca_bolli[i] >= imp)
break;
if (imp_bolli.items() > 0)
tot_bolli += (real &) imp_bolli[i];
}
break;
case _tratta:
case _tratta_acc:
{
if (estero == 2)
{
clifo.put("TIPOCF", get("TIPOCF"));
clifo.put("CODCF", get("CODCF"));
if (clifo.read() != NOERR)
clifo.zero();
const TString16 stato(clifo.get("STATOPAIV"));
estero = stato.not_empty() && stato != "IT";
if (!estero)
estero = clifo.get("STATOCF").not_empty() || clifo.get("COMCF")[0] == 'Z';
}
real r(imp);
r.ceil(-3);
if (estero)
r *= 0.009;
else
r *= 0.012;
r.round(-2);
tot_bolli += r;
}
break;
case _cessione:
case _paghero:
case _let_cred:
case _rim_dir:
case _rid:
case _bonfico:
default:
break;
}
}
static TString16 codiva;
static long firm = -1;
long new_firm = main_app().get_firm();
if (firm != new_firm)
{
TConfig conf(CONFIG_DITTA);
codiva = conf.get("SPBOCODIVA", "ve");
firm = new_firm;
}
iva_bolli = iva(tot_bolli, TRiga_documento::iva(codiva), ndec);
importo += (tot_bolli + iva_bolli - old_bolli);
}
if (t == _lordo)
tot_bolli += iva_bolli;
else
if (t == _imposta)
tot_bolli = iva_bolli;
tot_bolli /= cambio;
tot_bolli.round(ndec);
}
return tot_bolli;
}
// Funzione statica utile a tutti gli utenti di LF_DOC e LF_RIGHEDOC
void TDocumento::set_key(TRectype& rec, char provv, int anno, const char* codnum, long numdoc)
{
CHECK(provv == 'D' || provv == 'P', "Provvisorio o Definitivo?");
CHECKD(anno > 1900, "Anno non valido: ", anno);
CHECK(codnum && *codnum, "Codice numerazione nullo");
CHECKD(numdoc >= 0, "Numero documento non valido ", numdoc);
rec.put("PROVV", provv);
rec.put("ANNO", anno);
rec.put("CODNUM", codnum);
rec.put("NDOC", numdoc);
}
// Funzione statica utile a tutti gli utenti di LF_DOC e LF_RIGHEDOC
void TDocumento::copy_data(TRectype& dst, const TRectype& src)
{
// Memorizza tutti i campi chiave
const char provv = dst.get_char("PROVV");
const int anno = dst.get_int("ANNO");
const TString16 codnum = dst.get("CODNUM");
const long numdoc = dst.get_long("NDOC");
const int nriga = dst.num() == LF_RIGHEDOC ? dst.get_int("NRIGA") : 0;
// Copia tutto il record
dst = src;
// Ripristina tutti i campi chiave
set_key(dst, provv, anno, codnum, numdoc);
if (nriga > 0)
dst.put("NRIGA", nriga);
}
void TDocumento::copy_contents(const TDocumento & src)
{
copy_data(head(), src.head());
destroy_rows();
const int rows = src.physical_rows();
for (int i = 0; i < rows ; i++)
{
const TRiga_documento & s = src[i];
TRiga_documento & r = new_row(s.tipo().codice());
copy_data(r, s);
}
}
TRiga_documento& TDocumento::insert_row(int row, const char *tipo)
{
TRiga_documento * r = new TRiga_documento((const TRiga_documento &) _rows.key(), this); // ok
r->set_numero(row);
if (tipo)
r->set_tipo(tipo);
_rows.insert_row(r); // ok
return *r;
}
TRiga_documento& TDocumento::new_row(const char *tipo)
{
TRiga_documento & r = (TRiga_documento&)_rows.row(-1, TRUE); // ok
if (tipo)
r.set_tipo(tipo);
return r;
}
int TDocumento::read(TBaseisamfile& f, word op, word lockop)
{
TRiga_documento* key = new TRiga_documento(this);
TRectype rec(*this);
const char pr = tipo_numerazione();
const int an = anno();
const TString16 cn = numerazione();
const long nu = numero();
CHECK(nu > 0, "Numero documento nullo.");
set_key(*key, pr, an, cn, nu);
int err = TRectype::read(f);
_cli_for.zero();
_occas.zero();
if (err != NOERR && op == _isequal)
{
_nuovo = TRUE;
head() = rec;
destroy_rows();
_rows.set_key(key); // ok
}
else
{
_nuovo = FALSE;
_rows.read(key); //ok
}
set_riga_sconto();
if (is_fattura())
set_riga_esenzione();
return err;
}
int TDocumento::read(char provv, int anno, const char* codnum, long numdoc, word op, word lockop)
{
CHECK(numdoc > 0, "Numero documento nullo.");
set_key(*this, provv, anno, codnum, numdoc);
return read(op, lockop);
}
long TDocumento::renum(long numdoc)
{
if (numdoc <= 0)
{
const char tn = tipo_numerazione();
const int an = anno();
const TString16 nu = numerazione();
numdoc = get_next_key(tn, an, nu);
}
char num[16]; sprintf(num, "%ld", numdoc);
renum_key("NDOC", num); // Aggiorna testata
_rows.renum_key("NDOC", num); // Aggiorna righe ok
return numdoc;
}
void TDocumento::set_riga_sconto()
{
const TString80 sconto(get("SCONTOPERC"));
if (sconto.empty())
{
if(_sconto != NULL)
delete _sconto;
_sconto = NULL;
}
else
{
if (_sconto == NULL)
{
static TString _tipo_riga_sc;
if (_tipo_riga_sc.empty())
{
TConfig conf(CONFIG_STUDIO);
_tipo_riga_sc = conf.get("TRSCONTI", "ve");
}
_sconto = new TRiga_documento(this, _tipo_riga_sc);
_sconto->put("DESCR","Sconto");
}
_sconto->put("SCONTO", sconto);
}
}
void TDocumento::set_riga_esenzione()
{
TCli_for & c = clifor();
// const char tipo = get_char("TIPOCF");
// const long cod = get_long("CODCF");
// const TString80 occ(get("OCFPI"));
// c.load(tipo, cod, occ);
const TIVA codes(c.vendite().get(CFV_ASSFIS));
const TString16 v_esenzione(c.vendite().get(CFV_VSPROT));
const TString16 v_data_esenzione(c.vendite().get(CFV_VSDATAREG));
// const TString16 ufficio_IVA; ??
const TString16 n_registrazione(c.vendite().get(CFV_NSPROT));
const TString16 n_data_registrazione(c.vendite().get(CFV_NSDATAREG));
bool esente = codes.tipo().not_empty() && v_esenzione.not_empty() &&
v_data_esenzione.not_empty() && n_registrazione.not_empty() &&
n_data_registrazione.not_empty();
if (esente)
{
esente = FALSE;
const TString16 codiva(codes.codice());
for (int i = physical_rows(); !esente && i > 0; i--)
esente = codiva == row(i).get("CODIVA");
}
if (!esente)
{
if(_esenzione != NULL)
delete _esenzione;
_esenzione = NULL;
}
else
{
static TString _tipo_riga_es;
static real _bollo_es;
if (_tipo_riga_es.empty())
{
TConfig conf(CONFIG_STUDIO);
_tipo_riga_es = conf.get("TRESENZ", "ve");
_bollo_es = (real)conf.get("BOLLIES", "ve");
}
if (_esenzione == NULL)
_esenzione = new TRiga_documento(this, _tipo_riga_es);
TString d(256); d.format("Fattura non imponibile come da vostra dichiarazion");
_esenzione->put( "DESCR", d);
/* rilasciata dall' ufficio IVA di %s*/
d.format("e n. %s del %s da noi annotata al n. %s il %s. Marca da bollo da Lit. %s sull' originale.",
(const char *) v_esenzione, (const char *) v_data_esenzione,
/*(const char *) ufficio_IVA, */(const char *) n_registrazione,
(const char *) n_data_registrazione, _bollo_es.string("."));
_esenzione->put("DESCLUNGA", "X");
_esenzione->put("DESCEST", d);
}
}
void TDocumento::dirty_fields()
{
for (TDocumento_variable_field * f = (TDocumento_variable_field *) first_variable_field();
f != NULL; f = (TDocumento_variable_field *) succ_variable_field())
f->set_dirty();
for (int i = rows(); i > 0; i--)
{
TRiga_documento & r = (TRiga_documento &) row(i);
if (r.doc_dependent())
r.dirty_fields(FALSE);
}
}
int TDocumento::write_rewrite(TBaseisamfile & f, bool re) const
{
const bool nuovo = _nuovo || numero() <= 0; // E' nuovo di zecca!
const bool check_movmag = main_app().has_module(MGAUT, CHK_DONGLE) && tipo().mov_mag();
const TString16 stato_doc(get("STATO"));
const bool do_movmag = tipo().stato_with_mov_mag(stato_doc);
if (nuovo && re) // quindi ...
re = FALSE; // ... non fare la rewrite
if (tipo().spese_aut() && !get_bool("SPESEUPD"))
{
TString16 name("CODSP0");
TString_array spese;
TRectype & ven_rec = clifor().vendite();
for (int i = 1; i <= 4; i++)
{
name.rtrim(1); name << i;
const TString16 s(ven_rec.get(name));
if (s.not_empty())
spese.add(s);
}
((TDocumento *)this)->update_spese_aut(spese);
}
int err = NOERR;
long num = get_long("MOVMAG");
const int rows = physical_rows();
if (check_movmag)
{
TMov_mag_doc mov(this);
TLocalisamfile m(LF_MOVMAG);
mov.zero();
if (num == 0 && do_movmag)
{
num = atol(mov.get_next_key());
mov.put(MOVMAG_NUMREG, num);
while (mov.write(m) == _isreinsert)
{
num++;
mov.put(MOVMAG_NUMREG, num);
}
((TDocumento *)this)->put("MOVMAG", num);
}
if (num > 0)
{
mov.put(MOVMAG_NUMREG, num);
while (mov.read(m, _isequal, _testandlock) == _islocked)
message_box("Movimento di magazzino in uso da parte di un'altro utente");
if (do_movmag)
{
TRecord_array & b = mov.body();
const int mag_rows = mov.rows();
for (int i = mag_rows; i > 0; i--)
{
TRectype & r = b[i];
if (r.get_char(RMOVMAG_TIPORIGA) == riga_dadocumento)
{
b.destroy_row(i);
if (b.exist(i + 1) &&
b[i + 1].get_char(RMOVMAG_TIPORIGA) == riga_automatica)
b.destroy_row(i + 1);
}
}
b.pack();
TDate d(get("DATADOC"));
mov.put(MOVMAG_ANNOES, mov.codice_esercizio(d));
mov.put(MOVMAG_DATAREG, d);
mov.put(MOVMAG_DATACOMP, d);
mov.put(MOVMAG_DOCPROVV, get("PROVV"));
mov.put(MOVMAG_ANNODOC, get("ANNO"));;
mov.put(MOVMAG_CODNUM, get("CODNUM"));
const long numdoc = get_long("NDOC");
mov.put(MOVMAG_NUMDOC, numdoc);
mov.put(MOVMAG_CATVEN, get("CATVEN"));
mov.put(MOVMAG_CODLIST, get("CODLIST"));
mov.put(MOVMAG_CODCONT, get("CODCONT"));
mov.put(MOVMAG_CODCAMP, get("CODCAMP"));
mov.put(MOVMAG_CODCAUS, get("CAUSMAG"));
mov.put(MOVMAG_DESCR, format("%s n.ro %ld del %s", (const char *) tipo().get("S1"), numdoc, (const char *) d.string()));
mov.put(MOVMAG_TIPOCF, get("TIPOCF"));
mov.put(MOVMAG_CODCF, get("CODCF"));
int j = 1;
for (i = 1; i <= rows; i++)
{
TRiga_documento & r = ((TDocumento *)this)->row(i);
if (r.is_articolo())
{
long r_num = r.get_long("MOVMAG");
if (r_num == 0)
{
r_num = num;
r.put("MOVMAG", r_num);
}
if (r_num == num)
{
TRectype & rm = mov.insert_row(j++);
rm.put(RMOVMAG_CODMAG, r.get("CODMAG"));
rm.put(RMOVMAG_CODART, r.get("CODARTMAG"));
rm.put(RMOVMAG_LIVGIAC, r.get("LIVELLO"));
rm.put(RMOVMAG_UM, r.get("UMQTA"));
rm.put(RMOVMAG_QUANT, r.get("QTA"));
rm.put(RMOVMAG_PREZZO, r.get("PREZZO"));
rm.put(RMOVMAG_CODCAUS, r.get("CAUSMAG"));
rm.put(RMOVMAG_TIPORIGA, (char) riga_dadocumento);
}
}
}
mov.rewrite(m);
}
else
{
mov.remove(m);
for (int i = rows; i > 0; i--)
{
TRiga_documento & r = ((TDocumento *) this)->row(i);
long r_num = r.get_long("MOVMAG");
if (r_num == num)
r.zero("MOVMAG");
}
((TDocumento *)this)->zero("MOVMAG");
}
}
TLocalisamfile anamag(LF_ANAMAG);
TLocalisamfile codalt(LF_CODCORR);
codalt.setkey(2);
for (int i = rows; i > 0; i--)
{
TRiga_documento & r = ((TDocumento *) this)->row(i);
if (!r.is_checked())
{
const TString & codart = r.get("CODART");
anamag.put("CODART", codart);
if (anamag.read() == NOERR)
r.put("CODARTMAG", codart);
else
{
codalt.put("CODARTALT", codart);
if (codalt.read() == NOERR)
r.put("CODARTMAG", codalt.get("CODART"));
}
r.checked();
}
}
}
if (re)
{
err = _rows.write(re);
if (err == NOERR)
{
err = TRectype::rewrite(f);
if (err != NOERR)
err = TRectype::write(f);
}
}
else
{
if (nuovo)
{
TDocumento& myself = *(TDocumento*)this;
if (numero() <= 0)
myself.renum();
do
{
err = TRectype::write(f);
if (err == _isreinsert)
myself.renum();
} while (err == _isreinsert);
myself._nuovo = FALSE;
}
else
{
err = TRectype::write(f);
if (err != NOERR)
err = TRectype::rewrite(f);
}
if (err == NOERR)
err = _rows.write(re);
}
if (err == NOERR && clifor().occasionale())
{
if (get("OCFPI").not_empty())
{
TLocalisamfile o(LF_OCCAS);
TOccasionale & occ = occas();
err = occ.write(o);
if (err == _isreinsert)
err = occ.rewrite(o);
}
}
return err;
}
// eliminare anche il mov di mag. ??????
int TDocumento::remove(TBaseisamfile& f) const
{
int err = _rows.remove();
if (err == NOERR)
{
const bool check_movmag = main_app().has_module(MGAUT, CHK_DONGLE) && tipo().mov_mag();
if (check_movmag)
{
const long num = get_long("MOVMAG");
if (num > 0)
{
TMov_mag_doc mov(this);
TLocalisamfile m(LF_MOVMAG);
mov.put(MOVMAG_NUMREG, num);
while (mov.read(m, _isequal, _testandlock) == _islocked)
message_box("Movimento di magazzino in uso da parte di un'altro utente");
mov.remove(m);
}
}
err = TRectype::remove(f);
}
return err;
}
const bool TDocumento::in_valuta() const
{
const TString& val = valuta();
return (val.not_empty() && val != "LIT");
}
TRiga_documento & TDocumento::row(int index)
{
const int nrows = _rows.rows();
TRiga_documento * r = NULL;
if (index <= nrows)
r = &((TRiga_documento &) _rows.row(index, FALSE));
else
{
CHECKD((index == nrows + 1 && (_sconto != NULL || _esenzione != NULL)) || (index == nrows + 2 && _sconto != NULL && _esenzione != NULL),
"Riga documento non esistente ", index);
if (index == nrows + 1)
{
r = _sconto != NULL ? _sconto : _esenzione;
}
if (index == nrows + 2)
r = _esenzione;
}
return *r;
}
long TDocumento::get_next_key(char provv, int anno, const char* codnum) const
{
static long n = 0;
if (n == 0)
{
TLocalisamfile doc(LF_DOC);
TRectype& curr = doc.curr();
set_key(curr, provv, anno, codnum, 9999999L);
const int err = doc.read(_isgreat);
if (err != _isemptyfile)
{
if (err == NOERR)
doc.prev();
if (curr.get_char("PROVV") == provv &&
curr.get_int("ANNO") == anno &&
curr.get("CODNUM") == codnum)
n = curr.get_long("NDOC");
}
}
n++;
return n;
}
const TTipo_documento& TDocumento::tipo(const char * tipodoc)
{
CHECK(tipodoc && *tipodoc, "Tipo documento nullo");
TTipo_documento * o = (TTipo_documento*)_tipi.objptr(tipodoc);
if (o == NULL)
{
o = new TTipo_documento(tipodoc);
_tipi.add(tipodoc, o);
}
return *o;
}
const TTipo_documento& TDocumento::tipo() const
{
const TString16 tipodoc(get("TIPODOC"));
return tipo(tipodoc);
}
bool TDocumento::raggruppabile(const TDocumento& doc, TToken_string& campi) const
{
bool ok = raggruppabile() && doc.raggruppabile();
if (ok)
{
TString campo;
for (const char* c = campi.get(0); c && ok; c = campi.get())
{
campo = get(c);
ok &= campo == doc.get(c);
}
}
return ok;
}
void TDocumento::set_fields(TAuto_variable_rectype & rec)
{
if (tipo_valido())
{
TTipo_documento & tipo_doc = (TTipo_documento &) tipo();
const TString16 tot_doc(tipo_doc.totale_doc());
for (const TFormula_documento * f = tipo_doc.first_formula(); f; f = tipo_doc.succ_formula())
{
TExpr_documento * exp = f->expr();
if (tot_doc == f->name())
{
TString work_tot_doc(tot_doc);
work_tot_doc.insert("_");
TString netto_def(exp->string());
if (netto_def.find("IMPONIBILI") == -1)
{
if (netto_def.not_empty())
netto_def << "+";
netto_def << "IMPONIBILI()";
}
if (netto_def.find("IMPOSTE") == -1)
{
if (netto_def.not_empty())
netto_def << "+";
netto_def << "IMPOSTE()";
}
TExpr_documento * netto_exp = new TExpr_documento(netto_def, _numexpr, this);
add_field(new TDocumento_variable_field(work_tot_doc, netto_exp));
TExpr_documento * tot_exp = new TExpr_documento(
format("%s + _BOLLI(%s)", (const char *) work_tot_doc,
(const char *) work_tot_doc), _numexpr, this);
add_field(new TDocumento_variable_field(f->name(), tot_exp));
}
else
add_field(new TDocumento_variable_field(f->name(), exp));
if (exp)
exp->set_doc(this);
}
}
}
real TDocumento::imponibile(bool spese, int ndec) const
{
real val;
if (ndec > 99)
ndec = in_valuta() ? 3 : 0;
for (int i = rows(); i > 0; i--)
val += ((TRiga_documento &) ((TDocumento *)this)->row(i)).imponibile();
if (spese)
{
real tot_doc = val + imposta(FALSE, ndec);
val += spese_incasso(tot_doc, ndec, _netto);
tot_doc += spese_incasso(tot_doc, ndec);
val += bolli(tot_doc, ndec, _netto);
}
val.round(ndec);
return val;
}
real TDocumento::imposta(bool spese, int ndec) const
{
TAssoc_array ive;
if (ndec > 99)
ndec = in_valuta() ? 3 : 0;
for (int i = rows(); i > 0; i--)
{
TRiga_documento & r = ((TRiga_documento &) ((TDocumento *)this)->row(i));
real iva(r.imposta(FALSE));
const TString & cod_iva = r.get("CODIVA");
real * tot = (real *) ive.objptr(cod_iva);
if (tot == NULL)
ive.add(cod_iva, iva);
else
*tot += iva;
}
real val;
ive.restart();
for (real * iva = (real *) ive.get(); iva != NULL; iva = (real *) ive.get())
{
if (*iva < ZERO)
iva->floor(ndec);
else
iva->ceil(ndec);
val += *iva;
}
if (spese)
{
real tot_doc = val + imponibile(FALSE, ndec);
val += spese_incasso(tot_doc, ndec, _imposta);
tot_doc += spese_incasso(tot_doc, ndec);
val += bolli(tot_doc, ndec, _imposta);
}
val.round(ndec);
return val;
}
real TDocumento::totale_doc() const
{
const TString16 field(tipo().totale_doc());
if (field.not_empty())
return get_real(field);
else
{
real r = imponibile() + imposta();
r += spese_incasso(r, in_valuta() ? 3 : 0);
r += bolli(r, in_valuta() ? 3 : 0);
return r;
}
}
real TDocumento::totale_netto() const
{
const TString16 field(tipo().totale_netto());
if (field.not_empty())
return get_real(field);
else
return imponibile() + imposta();
}
real TDocumento::basesconto() const
{
const TString16 field(tipo().basesconto());
if (field.not_empty())
return get_real(field);
else
return ZERO;
}
real TDocumento::spese() const
{
const TString16 field(tipo().spese());
if (field.not_empty())
return get_real(field);
else
return ZERO;
}
TPagamento & TDocumento::pagamento()
{
const TString16 codpag(get("CODPAG"));
if (codpag != _pag.code())
{
_pag.set_code(codpag);
_pag.read();
}
return _pag;
}
void TDocumento::put_str(const char* fieldname, const char* val)
{
TString v(val);
if (strcmp(fieldname, "TIPODOC") == 0 && TRectype::get("TIPODOC") != v)
{
TAuto_variable_rectype::put_str(fieldname, v);
reset_fields(*this);
set_fields(*this);
}
else
{
if (strcmp(fieldname, "CODCF") == 0)
put("SPESEUPD", TRectype::get("CODCF") == v);
TAuto_variable_rectype::put_str(fieldname, v);
dirty_fields();
if (strcmp(fieldname, "SCONTOPERC") == 0)
set_riga_sconto();
}
}
void TDocumento::zero(const char * fieldname)
{
if (strcmp(fieldname, "TIPODOC") == 0)
reset_fields(*this);
TAuto_variable_rectype::zero(fieldname);
dirty_fields();
}
void TDocumento::zero(char c)
{
reset_fields(*this);
TAuto_variable_rectype::zero(c);
destroy_rows();
}
TCli_for & TDocumento::clifor() const
{
const char tipo = tipocf();
const long codice = codcf();
if (_cli_for.empty() || _cli_for.tipo() != tipo || _cli_for.codice() != codice)
((TDocumento *) this)->_cli_for.read(tipo, codice);
return (TCli_for &)_cli_for;
}
TOccasionale & TDocumento::occas() const
{
const TString80 occ_code(cod_occas());
if (_occas.empty() || strcmp(_occas.codice(), occ_code) != 0)
{
TLocalisamfile o(LF_OCCAS);
((TDocumento *) this)->_occas.zero();
((TDocumento *) this)->_occas.put(OCC_CFPI, occ_code);
TRectype oc(_occas);
if (((TDocumento *) this)->_occas.read(o) != NOERR)
((TDocumento *) this)->_occas = oc;
}
return (TOccasionale &) _occas;
}
TDocumento & TDocumento::copy(const TDocumento & d)
{
operator=((TRectype &)d);
_rows = d._rows;
for (int i = physical_rows(); i > 0; i--)
{
TRiga_documento & r = row(i);
r.set_doc(this);
}
for (i = 0; i < 3; i++)
_liv_len[i] = d._liv_len[i];
set_riga_sconto();
if (is_fattura())
set_riga_esenzione();
set_condv(d._condv);
_nuovo = d._nuovo;
return *this;
}
TRectype & TDocumento::operator =(const TRectype & r)
{
TRectype::operator=(r);
reset_fields(*this);
set_fields(*this);
return *this;
}
TRectype & TDocumento::operator =(const char * r)
{
TRectype::operator=(r);
reset_fields(*this);
set_fields(*this);
return *this;
}
void TDocumento::update_spese_aut(TString_array & spese_aut, bool preserve_old, TSheet_field * sh)
{
const bool updated = get_bool("SPESEUPD");
if (updated)
return;
const bool interactive = sh != NULL;
if (tipo().spese_aut())
{
const int nrows = _rows.rows();
for (int i = nrows; i > 0; i--)
{
TRiga_documento & r = row(i);
if (r.tipo().tipo() == RIGA_SPESEDOC && r.is_generata())
{
if (preserve_old)
return;
destroy_row(i, TRUE);
if (interactive)
sh->destroy(i - 1);
}
}
TString16 cod_iva_cli;
const int nspese = spese_aut.items();
if (nspese > 0)
{
TLocalisamfile cfven(LF_CFVEN);
cfven.put("TIPOCF", get("TIPOCF"));
cfven.put("CODCF", get("CODCF"));
if (cfven.read() == NOERR)
cod_iva_cli = cfven.get("ASSFIS");
for (i = 0; i < nspese; i++)
{
const TString & s = spese_aut.row(i);
TSpesa_prest sp(s);
TString16 tipo(sp.tipo_riga());
TRiga_documento & riga = new_row(tipo);
riga.put("CODART", s);
riga.generata();
riga.put("DESCR", sp.descrizione());
switch (sp.tipo())
{
case 'Q':
{
real qta = sp.qta();
if (qta == ZERO)
qta = 1.0;
riga.put("QTA", qta);
}
case 'V':
{
const real cambio = get_real("CAMBIO");
const TString16 valuta = get("CODVAL");
real prezzo = sp.prezzo();
sppr_calc(sp, valuta, cambio, prezzo);
riga.put("PREZZO", prezzo);
riga.put("UMQTA", sp.um());
}
break;
case 'P':
default:
break;
}
if (cod_iva_cli.empty())
riga.put("CODIVA", sp.cod_iva());
else
riga.put("CODIVA", cod_iva_cli);
if (interactive)
{
const int nrow = sh->insert(-1, FALSE);
riga.autoload(*sh);
sh->check_row(nrow);
}
}
}
}
put("SPESEUPD", TRUE);
}