campo-sirio/ce/ce4400.cpp
luca 545e047be5 Patch level :10.0 806
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
sistemato problema datareg/datacalc nella contabilizzazione cespiti


git-svn-id: svn://10.65.10.50/branches/R_10_00@20881 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-09-20 11:06:18 +00:00

1563 lines
50 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <automask.h>
#include <dongle.h>
#include <modaut.h>
#include <progind.h>
#include <recarray.h>
#include <reprint.h>
#include <reputils.h>
#include "../ca/calib01.h"
#include "../ca/calib02.h"
#include "../ca/movana.h"
#include "../ca/rmovana.h"
#include "../cg/cg2101.h"
#include "../cg/cglib02.h"
#include "celib.h"
#include "ce2101.h"
#include "ce4400a.h"
#include "ammce.h"
#include "cespi.h"
#include "movam.h"
#include "movce.h"
#include "salcecms.h"
//===============================================================================================
//maschera
class TContabilizza_ce_mask: public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TContabilizza_ce_mask():TAutomask("ce4400a") { ditta_cespiti().init_mask(*this); }
};
bool TContabilizza_ce_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_PROVDEF:
if (e == fe_modify)
{
const char definitivo = o.get()[0];
if (definitivo == 'X')
{
TEsercizi_contabili esc;
int anno = get_int(F_ESERCIZIO);
TDate dal, al;
if (esc.code2range(anno, dal, al))
{
set(F_DATACALC, al);
disable(F_DATACALC);
}
else
return error_box("Esercizio non corretto!");
}
else
{
enable(F_DATACALC);
const TDate today(TODAY);
set(F_DATACALC, today);
}
}
break;
case F_DATACALC:
if (e == fe_close)
{
const TDate data_fine_es = get(F_FINE_ES);
const TDate data_ini_es = get(F_INIZIO_ES);
TDate datacalc = o.get();
if (datacalc < data_ini_es)
return error_box("La data di calcolo deve essere pari o successiva alla data inizio dell'esercizio selezionato");
if (!datacalc.ok())
{
datacalc = data_fine_es;
o.set(datacalc.string());
}
if (datacalc < data_ini_es || datacalc > data_fine_es)
return error_box(TR("La data di calcolo deve appartenere all'esercizio selezionato!"));
}
break;
case F_DATAREG:
if (e == fe_modify || e == fe_close)
{
const int ese = get_int(F_ESERCIZIO);
TDate datalim;
TEsercizi_contabili esc;
const int nesen = esc.next(ese);
if (nesen > 0)
{
datalim = esc[nesen].fine();
}
else
{
datalim = esc[ese].fine();
datalim.addyear(1);
}
TDate datareg = o.get();
if (datareg > datalim)
return error_box(FR("La data registrazione deve essere inferiore al %s"), datalim.string());
//solo in caso di trasferimento definitivo, senn<6E>, se si sceglie una datareg nel futuro rispetto alla data di sistema,..
//..il movimento contabile generato non si pu<70> aprire con Campo in CG a meno di cambiare la data si sistema operativo
if (datareg < get_date(F_DATACALC) && get_bool(F_PROVDEF))
return error_box("La data di registrazione non puo' essere inferiore alla data di calcolo");
}
default: break;
}
return true;
}
//==============================================================================================
// Metodi static che servono in giro
static long get_new_numreg_CG()
{
TLocalisamfile mov(LF_MOV);
mov.last();
//primo numero libero da usare come numreg
return mov.curr().get_long(MOV_NUMREG) + 1;
}
static long get_new_numreg_CA()
{
TLocalisamfile movana(LF_MOVANA);
movana.last();
return movana.curr().get_long(MOVANA_NUMREG) + 1;
}
static void fill_head(TRectype& head, const TDate& datacomp, const TDate& datareg,
const long numreg, const TString& codcaus, const bool definitivo,
const TString& numdoc, const TString& tipodoc, const TDate& datadoc)
{
TEsercizi_contabili esc;
const int codes = esc.date2esc(datacomp);
head.put(MOV_ANNOES, codes);
head.put(MOV_NUMREG, numreg);
head.put(MOV_DATAREG, datareg);
head.put(MOV_DATACOMP, datacomp);
head.put(MOV_CODCAUS, codcaus);
//campi dei soli movimenti di vendita/eliminazione
head.put(MOV_NUMDOC, numdoc);
head.put(MOV_TIPODOC, tipodoc);
head.put(MOV_DATADOC, datadoc);
if (!definitivo)
head.put(MOV_PROVVIS, 'C');
}
//===============================================================================================
//Rectype da utilizzare per la creazione delle righe movimento contabili. Deriva da LF_RMOV ma ha..
//..3 valori in piu' (gruppo,specie,categoria) che servono per gli ordinamenti in fase di generazione..
//..movimenti contabili
class TRigamov : public TRectype
{
TString4 _spc;
int _grp, _cat;
public:
virtual int compare(const TSortable& s) const;
const TRectype& categoria() const;
const TString& descr_categoria() const;
TRigamov(const int grp, const TString& spc, const int cat, bool is_anal = false)
: TRectype(is_anal ? LF_RMOVANA : LF_RMOV) { _grp = grp; _spc = spc; _cat = cat; }
};
const TRectype& TRigamov::categoria() const
{
return ditta_cespiti().categoria(_grp, _spc, _cat, true);
}
const TString& TRigamov::descr_categoria() const
{
TString& wrkstring = get_tmp_string();
wrkstring << _grp << ' ' << _spc << ' ' << _cat << ' ' ;
wrkstring << ditta_cespiti().categoria(_grp, _spc, _cat, false).get("S0");
return wrkstring;
}
//confrontatore di saldi_per_codice
int TRigamov::compare(const TSortable& s) const
{
int cmp = 0;
const TRigamov& sc = (const TRigamov&)s;
cmp = _grp - sc._grp;
if (cmp == 0)
{
cmp = _spc.compare(sc._spc);
if (cmp == 0)
cmp = _cat - sc._cat;
}
return cmp;
}
//===============================================================================================
//Struct che serve per avere ammortamenti per categoria (Codcat|Qamm_tot|Qperse_tot)
struct TSaldo_per_codice : public TSortable
{
TString4 _spc;
int _grp, _cat;
TString16 _idcespite;
TAnal_bill _conto;
real _qnor, _qant, _qacc;//, _qperse;
void add(const TRectype& rec_ammce);
bool use_pdcc() const;
virtual int compare(const TSortable& s) const;
const TRectype& categoria() const;
const TString& descr_categoria() const;
int trova_quota_e_conto_CG(const int tipo, real& quota, TBill& zio, TLog_report& log) const;
int trova_quota_e_conto_CA(const int tipo, real& quota, TAnal_bill& zio, TLog_report& log) const;
int compila_rmov_CG(const int tipo, const int riga_nor, TArray& righe_mov, TLog_report& log, const int movdett) const;
int genera_righe_CG(TArray& righe_mov, TLog_report& log, const int movdett) const;
int compila_rmovana_CA(const int tipo, const int riga_nor, TArray& righe_movana, TLog_report& log,
const int movdett) const;
int genera_righe_CA(TArray& righe_movana, TLog_report& log, const int movdett) const;
TSaldo_per_codice(const int grp, const TString& spc, const int cat, const char* idcespite = "")
: _grp(grp),_spc(spc), _cat(cat), _idcespite(idcespite) {}
};
bool TSaldo_per_codice::use_pdcc() const
{
static char _use_pdcc = ' ';
if (_use_pdcc == ' ')
{
TConfig cfg = ca_config();
_use_pdcc = cfg.get_bool("UsePdcc");
}
return _use_pdcc != '\0';
}
void TSaldo_per_codice::add(const TRectype& rec_ammce)
{
//valore totale degli ammortamenti del cespite di tipo qnor,qant,qacc che trova in AMMCE
const real qnor = rec_ammce.get_real(AMMCE_QNOR);
const real qant = rec_ammce.get_real(AMMCE_QANT);
const real qacc = rec_ammce.get_real(AMMCE_QACC);
//valore totale delle qperse del cespite che trova in AMMCE
//const real qperse = rec_ammce.get_real(AMMCE_QPERSE);
_qnor += qnor;
_qant += qant;
_qacc += qacc;
// _qperse += qperse;
}
//confrontatore di saldi_per_codice
int TSaldo_per_codice::compare(const TSortable& s) const
{
int cmp = 0;
const TSaldo_per_codice& sc = (const TSaldo_per_codice&)s;
cmp = _grp - sc._grp;
if (cmp == 0)
{
cmp = _spc.compare(sc._spc);
if (cmp == 0)
{
cmp = _cat - sc._cat;
if (cmp == 0)
cmp = _idcespite.compare(sc._idcespite);
}
}
return cmp;
}
const TRectype& TSaldo_per_codice::categoria() const
{
//viene chiamato il metodo standard della ditta_cespiti con l'ultimo parametro true in modo che usi solo...
//...le categorie valide per il collegamento alla contabilita' (tabella CCC)
return ditta_cespiti().categoria(_grp, _spc, _cat, true);
}
const TString& TSaldo_per_codice::descr_categoria() const
{
TString& wrkstring = get_tmp_string();
wrkstring << _grp << ' ' << _spc << ' ' << _cat << ' ' ;
wrkstring << ditta_cespiti().categoria(_grp, _spc, _cat, false).get("S0");
return wrkstring;
}
bool str2bill(const TString& stringona, const int pos, TBill& zio)
{
const int gr = atoi(stringona.mid(pos, 3));
const int co = atoi(stringona.mid(pos + 3, 3));
if (co <= 0)
return false;
const long so = atoi(stringona.mid(pos + 6, 6));
zio.set(gr, co, so);
return true;
}
int TSaldo_per_codice::trova_quota_e_conto_CG(int tipo, real& quota, TBill& zio,
TLog_report& log) const
{
int pos = 0;
const char* field = "S1";
switch (tipo)
{
case 1: quota = _qnor; pos = 24; break;
case 2: quota = _qant; pos = 36; break;
case 3: quota = _qacc; pos = 48; break;
default: break;
}
if (quota <= ZERO)
return 0;
const TRectype& rec_ccc = categoria();
const TString& stringona = rec_ccc.get(field);
if (!str2bill(stringona, pos, zio))
{
pos = 24;
if (tipo == 1 || !str2bill(stringona, pos, zio))
{
TString msg;
msg << TR("Manca il conto per le quote ammortamento normali della categoria ") << descr_categoria();
log.log(2, msg);
return 0;
}
else
tipo = 1;
}
return tipo;
}
int TSaldo_per_codice::trova_quota_e_conto_CA(int tipo, real& quota, TAnal_bill& zio, TLog_report& log) const
{
//caso CA con use_pdcc
TString80 stringona;
if (use_pdcc())
{
int pos = 0;
const char* field = "S1";
switch (tipo)
{
case 1: quota = _qnor; pos = 24; break;
case 2: quota = _qant; pos = 36; break;
case 3: quota = _qacc; pos = 48; break;
default: break;
}
if (quota <= ZERO)
return 0;
const TRectype& rec_ccc = categoria();
stringona = rec_ccc.get(field).mid(pos, 12);
zio.set_conto(stringona);
if (stringona.blank())
{
pos = 24;
stringona = rec_ccc.get(field).mid(pos, 12);
if (tipo == 1 || stringona.blank())
{
TString msg;
msg << TR("Manca il conto per le quote ammortamento normali della categoria ") << descr_categoria();
log.log(2, msg);
return 0;
}
else
tipo = 1;
}
}
else //caso CA con use_pconana
{
char* field;
switch (tipo)
{
case 1: quota = _qnor; field = "S3"; break;
case 2: quota = _qant; field = "S4"; break;
case 3: quota = _qacc; field = "S5"; break;
default: break;
}
if (quota <= ZERO)
return 0;
const TRectype& rec_ccc = categoria();
stringona = rec_ccc.get(field);
if (stringona.blank())
{
stringona = rec_ccc.get("S3");
if (tipo == 1 || stringona.blank())
{
TString msg;
msg << TR("Manca il conto analitico per le quote ammortamento normali della categoria ") << descr_categoria();
log.log(2, msg);
return 0;
}
else
tipo = 1;
}
}
if (tipo > 0)
zio.set_conto(stringona);
return tipo;
}
//metodi per contabilit<69> generale CG
//-----------------------------------
int TSaldo_per_codice::compila_rmov_CG(const int tipo, const int riga_nor, TArray& righe_mov, TLog_report& log,
const int movdett) const
{
real quota;
TBill zio;
const int tipo_trovato = trova_quota_e_conto_CG(tipo, quota, zio, log);
if (tipo_trovato <= 0)
return -1;
if (tipo_trovato == 1 && riga_nor >= 0)
{
TRectype& rmovnor = (TRectype&)righe_mov[riga_nor];
rmovnor.add(RMV_IMPORTO, quota);
return riga_nor;
}
TRigamov* rmov = new TRigamov(_grp, _spc, _cat);
rmov->put(RMV_SEZIONE, "D");
rmov->put(RMV_IMPORTO, quota);
//conto e descrizione dipendono dal livello di dettaglio stabilito nella configurazione del collegamento CG/CE
switch (movdett)
{
case 0: //dettaglio per categoria
rmov->put(RMV_DESCR, rmov->descr_categoria());
break;
case 1: //dettaglio per cespite
{
const TRectype& rec_cespi = cache().get(LF_CESPI, _idcespite);
rmov->put(RMV_DESCR, rec_cespi.get(CESPI_DESC));
}
break;
case 2: //dettaglio per cespite con sottoconto=idcespite (idcespite numerico e di 6 cifre max!)
{
const TRectype& rec_cespi = cache().get(LF_CESPI, _idcespite);
rmov->put(RMV_DESCR, rec_cespi.get(CESPI_DESC));
bool ok = real::is_natural(_idcespite);
if (ok)
{
const long sottoc = atol(_idcespite);
ok = sottoc > 0 && sottoc < 1000000;
if (ok)
{
zio.set(zio.gruppo(), zio.conto(), sottoc);
ok = zio.find();
}
}
if (!ok)
{
TString msg;
msg.format(FR("Il codice cespite %s non e' un sottoconto valido"), (const char*)_idcespite);
log.log(2, msg);
}
}
break;
default:
break;
}
zio.put(*rmov);
return righe_mov.add(rmov);
}
//metodo di alto livello per la compilazione delle righe contabili;chiama il metodo di basso livello..
//..compila_rmov con i parametri caso x caso
int TSaldo_per_codice::genera_righe_CG(TArray& righe_mov, TLog_report& log, const int movdett) const
{
const int righe_prima = righe_mov.items();
const int riga_nor = compila_rmov_CG(1, -1, righe_mov, log, movdett);
const int riga_ant = compila_rmov_CG(2, riga_nor, righe_mov, log, movdett);
const int riga_acc = compila_rmov_CG(3, riga_nor, righe_mov, log, movdett);
//const int riga_persa = compila_rmov_CG(4, -1, righe_mov, log, movdett);
const int righe_dopo = righe_mov.items();
return righe_dopo - righe_prima; //messo qui tanto per poter compilare
}
//metodi per analitica CA
//-------------------------
int TSaldo_per_codice::compila_rmovana_CA(const int tipo, const int riga_nor, TArray& righe_movana, TLog_report& log,
const int movdett) const
{
real quota;
TAnal_bill zio;
const int tipo_trovato = trova_quota_e_conto_CA(tipo, quota, zio, log);
if (tipo_trovato <= 0)
return -1;
if (tipo_trovato == 1 && riga_nor >= 0)
{
TRectype& rmovananor = (TRectype&)righe_movana[riga_nor];
rmovananor.add(RMOVANA_IMPORTO, quota);
return riga_nor;
}
TRigamov* rmovana = new TRigamov(_grp, _spc, _cat, true);
rmovana->put(RMOVANA_SEZIONE, "D");
rmovana->put(RMOVANA_IMPORTO, quota);
//conto e descrizione dipendono dal livello di dettaglio stabilito nella configurazione del collegamento CG/CE
switch (movdett)
{
case 0: //dettaglio per categoria
rmovana->put(RMOVANA_DESCR, rmovana->descr_categoria());
break;
case 1: //dettaglio per cespite
{
const TRectype& rec_cespi = cache().get(LF_CESPI, _idcespite);
rmovana->put(RMOVANA_DESCR, rec_cespi.get(CESPI_DESC));
}
break;
case 2: //dettaglio per cespite con sottoconto=idcespite (idcespite numerico e di 6 cifre max!)
{
const TRectype& rec_cespi = cache().get(LF_CESPI, _idcespite);
rmovana->put(RMOVANA_DESCR, rec_cespi.get(CESPI_DESC));
bool ok = real::is_natural(_idcespite);
if (ok)
{
const long sottoc = atol(_idcespite);
ok = sottoc > 0 && sottoc < 1000000;
if (ok)
{
TString16 stringona = zio.conto().left(6);
stringona << _idcespite.right(6);
zio.set_conto(stringona);
ok = zio.ok();
}
}
if (!ok)
{
TString msg;
msg.format(FR("Il codice cespite %s non e' un sottoconto valido"), (const char*)_idcespite);
log.log(2, msg);
}
}
break;
default:
break;
}
rmovana->put(RMOVANA_CODCONTO, zio.conto());
rmovana->put(RMOVANA_CODCCOSTO, _conto.costo());
rmovana->put(RMOVANA_CODCMS, _conto.commessa());
rmovana->put(RMOVANA_CODFASE, _conto.fase());
return righe_movana.add(rmovana);
}
int TSaldo_per_codice::genera_righe_CA(TArray& righe_movana, TLog_report& log, const int movdett) const
{
const int righe_prima = righe_movana.items();
const int riga_nor = compila_rmovana_CA(1, -1, righe_movana, log, movdett);
const int riga_ant = compila_rmovana_CA(2, riga_nor, righe_movana, log, movdett);
const int riga_acc = compila_rmovana_CA(3, riga_nor, righe_movana, log, movdett);
const int righe_dopo = righe_movana.items();
return righe_dopo - righe_prima;
}
//===============================================================================================
//TMovimentoPN_CE
class TMovimentoPN_CE : public TMovimentoPN
{
TSaldo_agg _sagg;
protected:
void salda_rmov(const bool add);
public:
virtual int read(TIsamop op = _isequal, TReclock lockop = _nolock);
virtual int write(bool force = true);
virtual int rewrite(bool force = true);
virtual int remove();
TRectype& nuova_riga();
TRectype& nuova_riga(const TRectype& row);
};
void TMovimentoPN_CE::salda_rmov(const bool add)
{
_sagg.set_anno_es(curr().get_int(MOV_ANNOES));
_sagg.set_movprovv(curr().get_char(MOV_PROVVIS) > ' ');
_sagg.set_movimentato(true);
TBill zio;
TImporto imp;
for (int i = 0; i < cg_items(); i++)
{
const TRectype& rmov = cg(i); //riga i-esima corrente
zio.get(rmov);
imp.set(rmov.get_char(RMV_SEZIONE), rmov.get_real(RMV_IMPORTO));
_sagg.aggiorna(zio, imp, add);
}
}
int TMovimentoPN_CE::read(TIsamop op, TReclock lockop)
{
int err = TMovimentoPN::read(op, lockop);
if (err == NOERR)
{
_sagg.reset();
salda_rmov(false);
}
return err;
}
int TMovimentoPN_CE::remove()
{
int err = TMovimentoPN::remove();
if (err == NOERR)
{
_sagg.registra();
_sagg.reset();
}
return err;
}
int TMovimentoPN_CE::write(bool force)
{
int err = TMovimentoPN::write(force);
if (err == NOERR)
{
salda_rmov(true);
_sagg.set_num_ulmov(curr().get_long(MOV_NUMREG));
_sagg.set_data_ulmov(curr().get_date(MOV_DATAREG));
_sagg.registra();
}
return err;
}
int TMovimentoPN_CE::rewrite(bool force)
{
int err = TMovimentoPN::rewrite(force);
if (err == NOERR)
{
salda_rmov(true);
_sagg.registra();
}
return err;
}
//nuova riga fondo
TRectype& TMovimentoPN_CE::nuova_riga()
{
TRectype& riga = cg(-1);
riga.put(RMV_NUMRIG, cg_items());
riga.put(RMV_ANNOES, curr().get(MOV_ANNOES));
return riga;
}
//nuova riga normale
TRectype& TMovimentoPN_CE::nuova_riga(const TRectype& row)
{
TRectype& riga = cg(-1);
riga = row;
riga.put(RMV_NUMRIG, cg_items());
riga.put(RMV_ANNOES, curr().get(MOV_ANNOES));
//resettatore del saldo ad ogni nuovo movimento (righe tot presenti 1 = nuovo movimento)
if (cg_items() == 1)
_sagg.reset();
return riga;
}
//===============================================================================================
//TAmmortamento_per_cespite
class TPlus_minus : public TSaldo_per_codice
{
TArray _ammmv, _movam, _movce;
public:
void genera_mov_elim_ven(const TDate& datareg, const TDate& datacomp, const bool definitivo, TLog_report& log) const;
TPlus_minus(const int gruppo, const TString& specie, const int categoria,
const TArray& ammmv, const TArray& movam, const TArray& movce)
: TSaldo_per_codice(gruppo, specie, categoria), _ammmv(ammmv), _movam(movam), _movce(movce) {}
};
//metodo per la generazione dei movimenti dovuti a plus/minus
void TPlus_minus::genera_mov_elim_ven(const TDate& datareg, const TDate& datacomp, const bool definitivo, TLog_report& log) const
{
//Parametri dalla maschera
//parametri da utilizzare piu' volte
TString4 codcaus;
//conti fondo, immobilizzo, sopravenienza passiva, plusvalenza, minusvalenza cespite
const TString& stringona = categoria().get("S1");
TBill zio_fondo;
str2bill(stringona, 12, zio_fondo);
if (!zio_fondo.find())
{
TString msg;
msg << TR("Conto del fondo errato o mancante per la categoria ") << descr_categoria();
log.log(2, msg);
return;
}
TBill zio_immobilizzo;
str2bill(stringona, 0, zio_immobilizzo);
if (!zio_immobilizzo.find())
{
TString msg;
msg << TR("Conto di immobilizzo errato o mancante per la categoria ") << descr_categoria();
log.log(2, msg);
return;
}
//Riempie i campi della testata movimento
long numreg = get_new_numreg_CG();
//attenzione!! ci possono essere piu' movimenti per lo stesso cespite!!! -> ciclo sui movce.items()
for (int i = 0; i < _movce.items(); i++)
{
const TRectype& movce = (const TRectype&)_movce[i];
const TRectype& movam = (const TRectype&)_movam[i];
//causale movimento
const real impven = movce.get_real(MOVCE_IMPVEN);
const bool eliminazione = impven == ZERO;
//estremi documento di vendita
const TString& numdoc = movce.get(MOVCE_NDOC);
const TString& tipodoc = movce.get(MOVCE_TPDOC);
const TDate& datadoc = movce.get_date(MOVCE_DTDOC);
TConfig config_ditta_ce(CONFIG_DITTA, "ce");
if (eliminazione)
codcaus = config_ditta_ce.get("COAUEL");
else
codcaus = config_ditta_ce.get("COAUCH");
if (codcaus.empty())
{
TString msg;
msg << TR("Causale di vendita o eliminazione mancante");
log.log(2, msg);
return;
}
//movimento contabile
TMovimentoPN_CE pn;
TRectype& head = pn.curr();
fill_head(head, datacomp, datareg, numreg, codcaus, definitivo, numdoc, tipodoc, datadoc);
head.put(MOV_DESCR, movce.get(MOVCE_DESC));
numreg ++; //incrementa il numreg per l'eventuale testata successiva
//Aggiunge le righe
//le prime 2 righe sono comuni a tutti i tipi di movimento (esistono solo con importo non nullo)
//riga 1: fondo
const real val_fondo_cesp = movam.get_real(MOVAM_QNOR) + movam.get_real(MOVAM_QANT) + movam.get_real(MOVAM_QACC);
if (!val_fondo_cesp.is_zero())
{
TRectype& riga_fondo = pn.nuova_riga();
riga_fondo.put(RMV_SEZIONE, 'D');
riga_fondo.put(RMV_IMPORTO, val_fondo_cesp); //somma qnor+qant+qacc in movam);
zio_fondo.put(riga_fondo);
riga_fondo.put(RMV_DESCR, TR("Fondo"));
}
//riga 2: immobilizzo
const real val_imm_cesp = movce.get_real(MOVCE_CSTO);
if (!val_imm_cesp.is_zero())
{
TRectype& riga_immobilizzo = pn.nuova_riga();
riga_immobilizzo.put(RMV_SEZIONE, 'A');
riga_immobilizzo.put(RMV_IMPORTO, val_imm_cesp);
zio_immobilizzo.put(riga_immobilizzo);
riga_immobilizzo.put(RMV_DESCR, TR("Immobilizzo"));
}
//le successive righe dipendono dai parametri del config_ditta_ce e dalla differenza di importi riga2-riga1
const real val_sopravv_pass = val_imm_cesp - val_fondo_cesp;
if (eliminazione) //caso di ELIMINAZIONE cespite:
{
//riga 3: sopravenienza passiva (SOLO se movimento sbilanciato!)
if (!val_sopravv_pass.is_zero())
{
TRectype& riga_sopravv = pn.nuova_riga();
riga_sopravv.put(RMV_SEZIONE, 'D');
riga_sopravv.put(RMV_IMPORTO, val_sopravv_pass);
TBill zio_sopravv(config_ditta_ce.get_int("GRCOTELI"), config_ditta_ce.get_int("COCOTELI"),
config_ditta_ce.get_long("SOCOTELI"));
if (!zio_sopravv.find())
{
TString msg;
msg << TR("Conto di sopravvenienza errato o mancante");
log.log(2, msg);
return;
}
zio_sopravv.put(riga_sopravv);
riga_sopravv.put(RMV_DESCR, TR("Sopravenienza passiva"));
}
}
else //caso di VENDITA cespite:
{
//riga 3: vendita; parte comune (anche questa, come le altre, deve avere importo non nullo)
if (!impven.is_zero())
{
TRectype& riga_ven = pn.nuova_riga();
riga_ven.put(RMV_SEZIONE, 'D');
riga_ven.put(RMV_IMPORTO, impven);
const bool tiposcrit = config_ditta_ce.get_bool("COR5PM");
if (tiposcrit) //tipo scrittura per vendita: su conto cespite (conto in categoria CCC)
{
zio_immobilizzo.put(riga_ven);
riga_ven.put(RMV_DESCR, TR("Vendita su conto cespite"));
}
else //tipo scrittura per vendita: su conto vendita (conto in configurazione ditta)
{
TBill zio_vendita(config_ditta_ce.get_int("GRCOTVEN"), config_ditta_ce.get_int("COCOTVEN"),
config_ditta_ce.get_long("SOCOTVEN"));
if (!zio_vendita.find())
{
TString msg;
msg << TR("Conto di vendita cespite errato o mancante");
log.log(2, msg);
return;
}
zio_vendita.put(riga_ven);
riga_ven.put(RMV_DESCR, TR("Vendita su conto vendita"));
}
} //if(!impven.is_zero...
//riga 4: plus/minus-valenza
TImporto imp_fondo('D', val_fondo_cesp);
TImporto imp_immobilizzo('A', val_imm_cesp);
TImporto imp_ven('D', impven);
TImporto imp_valenza = imp_fondo;
imp_valenza += imp_immobilizzo;
imp_valenza += imp_ven;
if (!imp_valenza.is_zero()) //SOLO se movimento sbilanciato dopo le prime 3 righe, ovvero come le precedenti
{
imp_valenza.swap_section();
imp_valenza.normalize();
TRectype& riga_valenza = pn.nuova_riga();
const char sezione_valenza = imp_valenza.sezione();
riga_valenza.put(RMV_SEZIONE, sezione_valenza);
riga_valenza.put(RMV_IMPORTO, imp_valenza.valore());
if (sezione_valenza == 'A') //plusvalenza
{
TBill zio_plus(config_ditta_ce.get_int("GRCOTPLU"), config_ditta_ce.get_int("COCOTPLU"),
config_ditta_ce.get_long("SOCOTPLU"));
if (!zio_plus.find())
{
TString msg;
msg << TR("Conto di plusvalenza errato o mancante");
log.log(2, msg);
return;
}
zio_plus.put(riga_valenza);
riga_valenza.put(RMV_DESCR, TR("Plusvalenza"));
}
else //minusvalenza
{
TBill zio_minus(config_ditta_ce.get_int("GRCOTMIN"), config_ditta_ce.get_int("COCOTMIN"),
config_ditta_ce.get_long("SOCOTMIN"));
if (!zio_minus.find())
{
TString msg;
msg << TR("Conto di minusvalenza errato o mancante");
log.log(2, msg);
return;
}
zio_minus.put(riga_valenza);
riga_valenza.put(RMV_DESCR, TR("Minusvalenza"));
}
} //if(!imp_valenza.is_zero...
} //else di if(eliminazione...
//finalmente scrive sul file qesti movimenti...
int err = pn.write();
if (err != NOERR)
{
TString msg;
msg << TR("Impossibile registrare il movimento ") << numreg << "\n";
log.log(2, msg);
}
else
{
TString msg;
msg << TR("Registrato movimento ") << numreg << TR(" da movimento cespite ") << movce.get_long(MOVCE_IDMOV) << "\n";
log.log(0, msg);
}
} //for(int i=0;... (ciclo sui movimenti di un cespite)
}
//===============================================================================================
//Applicazione
class TContabilizza_ce : public TSkeleton_application
{
TContabilizza_ce_mask* _mask;
TConfig* _config_ditta_ce;
bool _has_ca;
protected:
virtual void main_loop();
virtual bool create();
virtual bool destroy();
void elabora(); //metodo di alto livello per la gestione ordinata del casino
long contabilizza_CG(TAssoc_array& quote_per_codice, TLog_report& cont_cesp_log); //contabilizza ammortamenti in CG
void contabilizza_CA(const long first_numreg_CG, TAssoc_array& anal_quote_per_codice, TLog_report& cont_cesp_log); //contabilizza ammortamenti in CA
long genera_mov_CG(TArray& righe_mov, TLog_report& log); //genera movimenti CG
void genera_movana_CA(const long first_numreg_CG, TArray& righe_movana, TLog_report& log); //genera movimenti CA
void delete_old_movs(const TDate& ini_es); //accoppa i movimenti provvisori (sia i CG che i CA collegati)
void ordina_saldi(TAssoc_array& quote, TArray& saldi_ordinati); //prende quote e restituisce saldi_ordinati sortato
void fill_salcecms_default(const TString& idcespite, const int codes, TRectype& rec_salcecms) const;
public:
};
//eliminatore dei movimenti CG e CA eventualmente collegati
void TContabilizza_ce::delete_old_movs(const TDate& ini_es)
{
TMovimentoPN_CE pn;
TRectype darec(LF_MOV);
darec.put(MOV_DATAREG, ini_es);
TString filtro;
filtro.format("(PROVVIS==\"C\")");
TCursor cur_mov (&pn, filtro, 2, &darec);
const long items = cur_mov.items();
cur_mov.freeze();
TProgind progind(items, "Eliminazione movimenti provvisori cespiti...", false, true);
for (cur_mov = 0; cur_mov.pos() < items; ++cur_mov)
{
progind.addstatus(1);
pn.read();
TRectype& head = pn.curr();
const long numreg = head.get_long(MOV_NUMREG);
int err = pn.remove();
//rimuove anche l'eventuale movana collegato
if (_has_ca)
{
TString query;
query << "USE MOVANA KEY 3";
query << "\nFROM NUMREGCG=#NUMREGCG";
query << "\nTO NUMREGCG=#NUMREGCG";
TISAM_recordset recset(query);
recset.set_var("#NUMREGCG", numreg);
if (recset.items() > 0)
{
TAnal_mov movana(recset.cursor()->curr(LF_MOVANA));
movana.remove(recset.cursor()->file());
}
} //if(_has_ca)...
}
}
//metodo per la generazione di movimenti contabili con righe per categoria
long TContabilizza_ce::genera_mov_CG(TArray& righe_mov, TLog_report& log)
{
//Parametri config ditta cespiti
const TString4 codcaus = _config_ditta_ce->get("COAUQU");
const int movdett = _config_ditta_ce->get_int("MOVDETT");
//Parametri maschera
const TDate fine_es = _mask->get_date(F_FINE_ES);
const TDate datareg = _mask->get_date(F_DATAREG);
const TDate datacomp = min(fine_es, datareg);
const bool definitivo = _mask->get_bool(F_PROVDEF);
//Riempie i campi della testata movimento
const long first_numreg = get_new_numreg_CG();
long numreg = first_numreg;
TMovimentoPN_CE pn;
TRectype& head = pn.curr();
fill_head(head, datacomp, datareg, numreg, codcaus, definitivo, "", "", NULLDATE);
head.put(MOV_DESCR, TR("Rilevazione quote amm. cespiti per categoria"));
//massimo numero consentito di righe per movimento
const int max_cg_rows = _has_ca ? 995 : 95;
//Procedura di inserimento delle righe del movimento
TImporto fondo;
//aggiunge all'array con tutte le righe mov determinate con il calcolo una riga senza gr/sp/cat
righe_mov.add(new TRigamov(0, EMPTY_STRING, 0));
//Ciclo su tutte le righe dell'array delle righe mov. Ad ogni cambio di categoria dovra' inserire la riga..
//..fondo per bilanciare la categoria, quindi scrivere sul movimento le righe ammortamento (da 1 a 3, ovvero..
//..qnor,qant,qacc) e la riga fondo di quella categoria, quindi passare alla categoria successiva.
for (int i = 0; i < righe_mov.items(); i++)
{
//record di righe_mov
const TRigamov& rigamov = (const TRigamov&)righe_mov[i];
//Controllo dell'eventuale cambio di categoria. Lo fa confrontando la riga iesima appena caricata con..
//..la riga i-1esima (la precedente,insomma)
//Se la categoria e' cambiata...
if (i > 0 && (rigamov.compare((const TRigamov&)righe_mov[i-1]) != 0 || pn.cg_items() > max_cg_rows))
{
//crea una nuova riga per metterci il fondo;in questo momento la riga e' aggiunta ma va riempita!!
TRectype& riga_fondo = pn.nuova_riga();
//Inverte la sezione del fondo calcolato per il bilancamento
fondo.swap_section(); //inverte la sezione
fondo.normalize(); //normalizza il segno
riga_fondo.put(RMV_SEZIONE, fondo.sezione()); //inserisce nella riga fondo le sezione..
riga_fondo.put(RMV_IMPORTO, fondo.valore()); //..ed il valore
//Deve mettere nella riga fondo gr/co/sot che stanno nella categoria in CCC
//Serve la categoria precedente, perche' in questo momento l'ha cambiata! Quindi [i-1]
const TRigamov& prev_riga_mov = (const TRigamov&)righe_mov[i-1];
const TString& stringone = prev_riga_mov.categoria().get("S1");
riga_fondo.put(RMV_GRUPPO, stringone.mid(12,3));
riga_fondo.put(RMV_CONTO, stringone.mid(15,3));
riga_fondo.put(RMV_SOTTOCONTO, stringone.mid(18,6));
const TString descat = prev_riga_mov.descr_categoria();
riga_fondo.put(RMV_DESCR, descat);
//se il movimento supera le 95 righe va salvato sul file MOV, poi distrutto per poter costruirne uno nuovo..
//..con le righe di righe_mov che sono rimaste
if (pn.cg_items() > 95 || i == righe_mov.last() || movdett > 0)
{
if (movdett > 0) //se va per cespite la descrizione cambia per ogni movimento in base alla categoria
{
TString desc;
desc << TR("Quote amm. ") << descat;
desc.cut(50);
head.put(MOV_DESCR, desc);
}
int err = pn.write(); //scrive il movimento sul file
if (err != NOERR)
{
TString msg;
msg << TR("Impossibile registrare il movimento ") << numreg << "\n";
log.log(2, msg);
}
else
{
TString msg;
msg << TR("Registrato movimento ") << numreg << TR(" categoria ") << descat << "\n";
log.log(0, msg);
}
pn.destroy_rows(numreg); //ne elimina le righe per poter ricominciare
head.put(MOV_NUMREG, ++numreg); //nuova testata per nuovo movimento
}
//azzera il valore del fondo in modo da ricominciare a calcolarlo con la nuova categoria
fondo.reset();
} //if i>0&&rigamov.compare...
//Se la categoria non e' cambiata crea normalmente la nuova riga
//Aggiorna l'importo del fondo che e' pari alla somma di tutte le righe della stessa categoria
TImporto imp_riga(rigamov.get_char(RMV_SEZIONE), rigamov.get_real(RMV_IMPORTO));
fondo += imp_riga;
pn.nuova_riga(rigamov);
} //for(inti=0;...
return first_numreg;
}
void TContabilizza_ce::genera_movana_CA(const long first_numreg_CG, TArray& righe_movana, TLog_report& log)
{
//generazione dei movimenti analitci (collegati a quelli contabili)
//Parametri config ditta cespiti
const TString4 codcaus = _config_ditta_ce->get("COAUQU");
const int movdett = _config_ditta_ce->get_int("MOVDETT");
//Parametri maschera
const int annoes = _mask->get_int(F_ESERCIZIO);
const TDate fine_es = _mask->get_date(F_FINE_ES);
const TDate datareg = _mask->get_date(F_DATAREG);
const TDate datacomp = min(fine_es, datareg);
const bool definitivo = _mask->get_bool(F_PROVDEF);
//Riempie i campi della testata movimento analitico
long numregcg = first_numreg_CG;
long numregca = get_new_numreg_CA();
//movimento analitico che sar<61> generato
TAnal_mov movana;
movana.put(MOVANA_NUMREG, numregca);
movana.put(MOVANA_ANNOES, annoes);
movana.put(MOVANA_DATAREG, datareg);
movana.put(MOVANA_DATACOMP, datacomp);
movana.put(MOVANA_DATAFCOMP, datacomp);
movana.put(MOVANA_DESCR, TR("Rilevazione quote amm. cespiti per categoria"));
movana.put(MOVANA_TIPOMOV, "");
movana.put(MOVANA_CODCAUS, codcaus);
movana.put(MOVANA_NUMREGCG, numregcg); //primo movana corrispondente al primo mov
righe_movana.add(new TRigamov(0, EMPTY_STRING, 0, true));
TImporto totale_movana;
//Ciclo su tutte le righe dell'array delle righe movana.
for (int i = 0; i < righe_movana.items(); i++)
{
const TRigamov& rmovana = (const TRigamov&)righe_movana[i];
//Controllo dell'eventuale cambio di categoria. Lo fa confrontando la riga iesima appena caricata con..
//..la riga i-1esima (la precedente,insomma)
//Se la categoria e' cambiata...
if (i > 0 && (rmovana.compare((const TRigamov&)righe_movana[i-1]) != 0))
{
//la descrizione viene dalla categoria precedente, visto che l'ha appena cambiata
const TRigamov& prev_rmovana = (const TRigamov&)righe_movana[i-1];
const TString descat = prev_rmovana.descr_categoria();
if (i == righe_movana.last() || movdett > 0)
{
if (movdett > 0) //se va per cespite la descrizione cambia per ogni movimento in base alla categoria
{
TString desc;
desc << TR("Quote amm. ") << descat;
desc.cut(50);
movana.put(MOVANA_DESCR, desc);
}
//prepara l'importo totale
totale_movana.normalize();
movana.put(MOVANA_SEZIONE, totale_movana.sezione());
movana.put(MOVANA_TOTDOC, totale_movana.valore());
totale_movana.reset();
//scrive il movana
TLocalisamfile fmovana(LF_MOVANA);
int err = movana.write(fmovana);
if (err != NOERR)
{
TString msg;
msg << TR("Impossibile registrare il movimento analitico ") << numregca << "\n";
log.log(2, msg);
}
else
{
TString msg;
msg << TR("Registrato movimento analitico ") << numregca << TR(" categoria ") << descat << "\n";
log.log(0, msg);
}
movana.body().destroy_rows(); //ne elimina le righe per poter ricominciare
movana.put(MOVANA_NUMREG, ++numregca); //nuova testata per nuovo movimento
movana.put(MOVANA_NUMREGCG, ++numregcg); //deve incrementare anche il numregcg
} //if (i == righe_movana.last()...
} //if (i > 0 && (rmovana.compare((const.... (cambio categoria)
//al cambio categoria va aggiunta una nuova riga al movana
TRectype& new_rmovana = movana.new_row(); //aggiunge una nuova riga analitica
new_rmovana = rmovana;
new_rmovana.put(RMOVANA_ANNOES, annoes);
new_rmovana.put(RMOVANA_NUMREG, numregca);
new_rmovana.put(RMOVANA_NUMRIG, movana.body().rows());
TImporto importo_riga(new_rmovana.get_char(RMOVANA_SEZIONE), new_rmovana.get_real(RMOVANA_IMPORTO));
totale_movana += importo_riga;
} //for (int i = 0;... (giro delle righe_movana)
}
//metodo che gestisce la creazione dei movimenti CG dovuti ad ammortamenti
long TContabilizza_ce::contabilizza_CG(TAssoc_array& quote_per_codice, TLog_report& cont_cesp_log)
{
TArray saldi_ordinati;
ordina_saldi(quote_per_codice, saldi_ordinati);
const int movdett = _config_ditta_ce->get_int("MOVDETT");
//array con le righe movimento CG
TArray righe_mov;
//riempie l'array delle righe movimento CG
FOR_EACH_ARRAY_ITEM(saldi_ordinati, riga, sldobj)
{
const TSaldo_per_codice& sld = *(const TSaldo_per_codice*)sldobj;
sld.genera_righe_CG(righe_mov, cont_cesp_log, movdett);
}
//controllo sul numero righe dell'array (serve solo per controllo al sagace programmatore...)
const int nrighemov = righe_mov.items();
//a questo punto ha l'array con le righe movimento CG completo (righe_mov); da queste righe deve costruire..
//..uno o piu' movimenti di prima nota
//In base al movdett li creera' con righe per categoria o per cespite ma con fondi per categoria
//E' un metodo semimagico!
const long first_numreg_CG = genera_mov_CG(righe_mov, cont_cesp_log);
return first_numreg_CG;
}
//metodo che gestisce la creazione dei movimenti CA dovuti ad ammortamenti
void TContabilizza_ce::contabilizza_CA(const long first_numreg_CG, TAssoc_array& anal_quote_per_codice, TLog_report& cont_cesp_log)
{
TArray anal_saldi_ordinati;
ordina_saldi(anal_quote_per_codice, anal_saldi_ordinati);
const int movdett = _config_ditta_ce->get_int("MOVDETT");
//array con le righe movimento CA
TArray righe_movana;
//riempie l'array delle righe movimento CA
FOR_EACH_ARRAY_ITEM(anal_saldi_ordinati, riga, sldobj)
{
const TSaldo_per_codice& anal_sld = *(const TSaldo_per_codice*)sldobj;
anal_sld.genera_righe_CA(righe_movana, cont_cesp_log, movdett);
}
//controllo sul numero righe dell'array (serve solo per controllo al sagace programmatore...)
const int nrighmovana = righe_movana.items();
//metodo per la creazione del/dei movana analitici
genera_movana_CA(first_numreg_CG, righe_movana, cont_cesp_log);
}
void TContabilizza_ce::ordina_saldi(TAssoc_array& quote, TArray& saldi_ordinati)
{
//riempie l'array saldi_ordinati con gli elementi dell'assoc quote
FOR_EACH_ASSOC_OBJECT(quote, h, k, obj)
saldi_ordinati.add(h->remove_obj());
//accoppa l'assoc
quote.destroy();
//e ordina l'array per categorie e cespite (questo assurdo giro serve perche' l'assoc non e' ordinabile)
saldi_ordinati.sort();
}
void TContabilizza_ce::fill_salcecms_default(const TString& idcespite, const int codes, TRectype& rec_salcecms) const
{
TString4 anno;
anno << codes;
const TRectype& rec_cce = cache().get("CCE", anno);
const TString& codcdc = rec_cce.get("S2");
const TString& codcms = rec_cce.get("S3");
const TString& codfase = rec_cce.get("S4");
rec_salcecms.put(SALCECMS_IDCESPITE, idcespite);
rec_salcecms.put(SALCECMS_CODES, codes);
rec_salcecms.put(SALCECMS_NRIGA, 1);
rec_salcecms.put(SALCECMS_CODCDC, codcdc);
rec_salcecms.put(SALCECMS_CODCMS, codcms);
rec_salcecms.put(SALCECMS_CODFASE, codfase);
rec_salcecms.put(SALCECMS_PERCUTIL, CENTO);
}
//metodo per gestire la successione degli eventi ad alto livello
void TContabilizza_ce::elabora()
{
// 0) Acquisizione parametri generali, eliminazione movimenti provvisori
//--------------------------------------------------------------------------------
//gettiamo un po' di parametri dalla maschera
const long codes = _mask->get_long(F_ESERCIZIO);
const TDate ini_es = _mask->get_date(F_INIZIO_ES);
const TDate fine_es = _mask->get_date(F_FINE_ES);
//se il trasferimento e' definitivo la data di calcolo e' quella finale dell'esercizio selezionato, senno'...
//...e' quella indicata in F_DATACALC
TDate datacalc;
const bool definitivo = _mask->get_bool(F_PROVDEF);
if (definitivo)
datacalc = _mask->get_date(F_FINE_ES);
else
datacalc = _mask->get_date(F_DATACALC);
const TDate datareg = _mask->get_date(F_DATAREG);
const TDate datacomp = min(fine_es, datareg);
//Legge un po' di parametri dal ditta.ini che servono al tipo di calcolo
//Situazione fiscale (99,99%) o civilistica (1 suora su 1.000.000)?
const int tpamm = _config_ditta_ce->get_int("TPAMM");
//Tipo di calcolo da eseguire in base al dettaglio
const int movdett = _config_ditta_ce->get_int("MOVDETT");
//Genera movimenti plus/minus? Parametro decisivo per poter generare movimenti cg da movimenti ce
const bool mov_plusmin = _config_ditta_ce->get_bool("COPLMN");
//deve accoppare i movimenti provvisori di prima nota da inizio esercizio ad oggi?
if (_mask->get_bool(F_KILLOLD))
{
delete_old_movs(ini_es);
}
//report con log errori
TLog_report cont_cesp_log(TR("Contabilizzazione cespiti"));
cont_cesp_log.kill_duplicates();
// 1) Preparazione contabilizzazione CG/CA: ammortamenti
//----------------------------------------------------------------------
//programma vero e proprio (calcolo ammortamenti, selezione cespiti validi, trasferimento)
TISAM_recordset cespiti("USE CESPI");
const TRecnotype nrec = cespiti.items();
//Assoc_array Categoria-QammTot
TAssoc_array quote_per_codice, anal_quote_per_codice;
TArray ammo_plus_minus;
//giro su tutti i cespiti
TProgind pi(nrec, TR("Ricalcolo ammortamenti in corso..."), true, true);
for (int i = 0; cespiti.move_to(i); i++)
{
if (!pi.addstatus(1))
break;
//id e categoria del cespite corrente
const TString& idcespite = cespiti.get(CESPI_IDCESPITE).as_string();
const int gruppo = cespiti.get(CESPI_CODCGRA).as_int();
const TString4 specie = cespiti.get(CESPI_CODSPA).as_string();
const int codcat = cespiti.get(CESPI_CODCAT).as_int();
//calcola gli ammortamenti di tutti i cespiti; situazione presa dal config_ditta poco prima
//la calc_amm pensa da sola a calcolare gli ammortamenti solo per i cespiti validi
//l'ultimo parametro e' true x' il calcolo viene fatto in memoria!
TCespite cespite(idcespite);
if (cespite.calc_amm(tpamm, datacalc, false, true))
{
//controlla le quote del cespite in questione su AMMCE
const TRectype& rec_ammce = cespite.amm_pro();
//in base al tipo di dettaglio sceglie il codice dell'assoc_array
//movdett = 0 -> codice=codice categoria (assoc_array con record per categorie)
//movdett = 1;2 -> codice=idcespite (assoc_array con record per cespite)
//1.1) preparazione contabilizzazione CG
//----------------------------------------
TToken_string gsc;
//chiave per CG
gsc.add(gruppo); gsc.add(specie); gsc.add(codcat);
if (movdett != 0)
gsc.add(idcespite);
TSaldo_per_codice* sc = (TSaldo_per_codice*)quote_per_codice.objptr(gsc);
//se non trova il codice (categoria o cespite) lo aggiunge...
if (sc == NULL)
{
sc = new TSaldo_per_codice(gruppo, specie, codcat, idcespite);
quote_per_codice.add(gsc, sc);
}
//..e poi somma i valori comunque
sc->add(rec_ammce);
//Parte relativa ad AMMMV (per generazione movimenti cg da movim. cespiti)
if (mov_plusmin)
{
const TArray& ammmv = cespite.ammmv();
const TArray& movam = cespite.movam();
const TArray& movce = cespite.movce();
TPlus_minus* pm = new TPlus_minus(gruppo, specie, codcat, ammmv, movam, movce);
ammo_plus_minus.add(pm);
}
//1.2) preparazione contabilizzazione CA
//----------------------------------------
if (_has_ca)
{
//per prima cosa necessita dei valori da salcecms
TToken_string key;
key.add(idcespite);
key.add(codes);
TRecord_array righe_salcecms(key, LF_SALCECMS);
// calcolo percentuale totale di utilizzo (pu<70> essere < 100)
real percutil_tot;
for (int i = righe_salcecms.last_row(); i > 0; i = righe_salcecms.pred_row(i))
{
const TRectype& curr_salcecms_line = righe_salcecms.row(i);
const real percutil = curr_salcecms_line.get_real(SALCECMS_PERCUTIL);
percutil_tot += percutil;
}
// Aggiunge una eventuale ripartizione sulla commessa di default (GENSPA) per raggiungere 100
if (percutil_tot < CENTO)
{
TRectype rec_salcecms_tappo(LF_SALCECMS);
fill_salcecms_default(idcespite, codes, rec_salcecms_tappo);
rec_salcecms_tappo.put(SALCECMS_NRIGA, righe_salcecms.rows() + 1);
rec_salcecms_tappo.put(SALCECMS_PERCUTIL, CENTO - percutil_tot);
//aggiunge al record_array il record standard con la % per arrivare a 100%
righe_salcecms.add_row(rec_salcecms_tappo);
}
// Inizializza i distrib con le percentuali di utilizzo
TGeneric_distrib d_qnor(rec_ammce.get_real(AMMCE_QNOR), 2);
TGeneric_distrib d_qacc(rec_ammce.get_real(AMMCE_QACC), 2);
TGeneric_distrib d_qant(rec_ammce.get_real(AMMCE_QANT), 2);
for (int i = righe_salcecms.last_row(); i > 0; i = righe_salcecms.pred_row(i))
{
const TRectype& curr_salcecms_line = righe_salcecms.row(i);
const real percutil = curr_salcecms_line.get_real(SALCECMS_PERCUTIL);
d_qnor.add(percutil);
d_qacc.add(percutil);
d_qant.add(percutil);
}
// Ricava le quote di utilizzo in base alle perventuali precedenti
for (int i = righe_salcecms.last_row(); i > 0; i = righe_salcecms.pred_row(i))
{
const TRectype& curr_salcecms_line = righe_salcecms.row(i);
key = gsc;
key.add(curr_salcecms_line.get(SALCECMS_CODCDC));
key.add(curr_salcecms_line.get(SALCECMS_CODCMS));
key.add(curr_salcecms_line.get(SALCECMS_CODFASE));
TSaldo_per_codice* anal_sc = (TSaldo_per_codice*)anal_quote_per_codice.objptr(key);
if (anal_sc == NULL)
{
anal_sc = new TSaldo_per_codice(gruppo, specie, codcat, idcespite);
//ricordiamo la key: gr/sp/cat/(cespite)/cdc/cms/fase
int offset = 0;
if (movdett > 0) //se il dettaglio richiede il cespite -> offset della key
offset++;
anal_sc->_conto.set_costo(key.get(3 + offset));
anal_sc->_conto.set_commessa(key.get(4 + offset));
anal_sc->_conto.set_fase(key.get(5 + offset));
anal_quote_per_codice.add(key, anal_sc);
}
anal_sc->_qnor += d_qnor.get();
anal_sc->_qacc += d_qacc.get();
anal_sc->_qant += d_qant.get();
} //for(int i...
} //if(_has_ca)...
} //if (cespite.calc_amm(tpamm,...
} //for (int i = 0; cespiti.move_to(i); i++)...
// 2) Generazione movimenti CG da ammortamenti cespiti
//----------------------------------------------------------------
//contabilizzazione in CG
const long first_numreg_CG = contabilizza_CG(quote_per_codice, cont_cesp_log);
// 3) Generazione movimenti CG da movimenti cespiti di vendita/eliminazione
//----------------------------------------------------------------------------------
//solo se in configurazione ditta cespiti e' attivo il flag di generazione movimenti plus/minus...
if (mov_plusmin)
{
//controllo sul numero righe dell'array (serve solo per controllo al sagace programmatore...)
const int nrigheammo = ammo_plus_minus.items();
//scandisce l'array con i valori per i movimenti di plus/minus creando un movimento cg per ognuno
FOR_EACH_ARRAY_ITEM(ammo_plus_minus, riga, pmobj)
{
const TPlus_minus& pm = *(const TPlus_minus*)pmobj;
pm.genera_mov_elim_ven(datareg, datacomp, definitivo, cont_cesp_log);
}
}
// 4) Generazione movimenti CA da ammortamenti cespiti
//----------------------------------------------------------
//contabilizzazione in CA
if (_has_ca)
contabilizza_CA(first_numreg_CG, anal_quote_per_codice, cont_cesp_log);
// 5) stampa il log degli errori
//---------------------------------------
TReport_book book;
book.add(cont_cesp_log);
book.preview();
}
bool TContabilizza_ce::create()
{
_mask = new TContabilizza_ce_mask;
//chiede se ha la CA; serve per la contabilizzazione analitica
_has_ca = dongle().active(CAAUT);
//config ditta cespiti
_config_ditta_ce = new TConfig(CONFIG_DITTA, "ce");
return TSkeleton_application::create();
}
bool TContabilizza_ce::destroy()
{
delete _config_ditta_ce;
delete _mask;
return true;
}
void TContabilizza_ce::main_loop()
{
KEY k = K_ENTER;
while (k != K_QUIT)
{
k = _mask->run();
switch (k)
{
case K_ENTER:
elabora();
break;
default:
break;
}
}
}
int ce4400(int argc, char* argv[])
{
TContabilizza_ce a;
a.run(argc,argv,TR("Contabilizzazione cespiti"));
return 0;
}