campo-sirio/ce/ce4400.cpp
luca a3e5930e37 Patch level :10.0
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :continua la contabilizzazione cespiti


git-svn-id: svn://10.65.10.50/trunk@15962 c028cbd2-c16b-5b4b-a496-9718f37d4682
2008-01-08 17:08:23 +00:00

598 lines
18 KiB
C++
Executable File

#include <applicat.h>
#include <automask.h>
#include <progind.h>
#include <reprint.h>
#include <reputils.h>
#include "../cg/cg2101.h"
#include "celib.h"
#include "ce2101.h"
#include "ce4400a.h"
#include "ammce.h"
#include "cespi.h"
//===============================================================================================
//maschera
class TTrasf_mov_ce_cg_mask: public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TTrasf_mov_ce_cg_mask():TAutomask("ce4400a") { ditta_cespiti().init_mask(*this); }
};
bool TTrasf_mov_ce_cg_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
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("La data di calcolo deve appartenere all'esercizio selezionato!");
}
break;
default: break;
}
return true;
}
//===============================================================================================
//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;
TRigamov(const int grp, const TString& spc, const int cat) : TRectype(LF_RMOV) { _grp = grp; _spc = spc; _cat = cat;}
};
const TRectype& TRigamov::categoria() const
{
return ditta_cespiti().categoria(_grp, _spc, _cat, true);
}
//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;
TString80 _idcespite;
real _qnor, _qant, _qacc;//, _qperse;
void add(const TRectype& rec_ammce);
virtual int compare(const TSortable& s) const;
const TRectype& categoria() const;
int compila_rmov(const int tipo, const int riga_nor, TArray& righe_mov, TLog_report& log, const int movdett) const;
int genera_righe(TArray& righe_mov, 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) {}
};
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;
}
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::compila_rmov(const int tipo, const int riga_nor, TArray& righe_mov, TLog_report& log,
const int movdett) const
{
int pos = 0;
const char* field = "S1";
real quota;
switch (tipo)
{
case 1: quota = _qnor; pos = 24; break;
case 2: quota = _qant; pos = 36; break;
case 3: quota = _qacc; pos = 48; break;
// case 4: quota = _qperse; pos = 0; field = "S2"; break;
default: break;
}
if (quota <= ZERO)
return -1;
const TRectype& rec_cac = categoria();
const TString& stringona = rec_cac.get(field);
TBill zio;
if (!str2bill(stringona, pos, zio))
{
//if (tipo < 4)
//{
pos = 24;
if (tipo == 1 || !str2bill(stringona, pos, zio))
{
TString msg;
msg << TR("Manca il conto per le quote ammortamento normali della categoria ") << rec_cac.get("CODTAB");
log.log(2, msg);
return -1;
}
//}
/* else
{
TString msg;
msg << TR("Manca il conto per le quote perse della categoria ") << rec_cac.get("CODTAB");
log.log(2, msg);
return -1;
}*/
}
if (pos == 24 && 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, rec_cac.get("S0"));
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);
}
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(TArray& righe_mov, TLog_report& log, const int movdett) const
{
const int righe_prima = righe_mov.items();
const int riga_nor = compila_rmov(1, -1, righe_mov, log, movdett);
const int riga_ant = compila_rmov(2, riga_nor, righe_mov, log, movdett);
const int riga_acc = compila_rmov(3, riga_nor, righe_mov, log, movdett);
// const int riga_persa = compila_rmov(4, -1, righe_mov, log, movdett);
const int righe_dopo = righe_mov.items();
return righe_dopo - righe_prima; //messo qui tanto per poter compilare
}
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);
}
//===============================================================================================
//TMovimentoPN_CE
class TMovimentoPN_CE : public TMovimentoPN
{
public:
TRectype& nuova_riga();
TRectype& nuova_riga(const TRectype& row);
};
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;
}
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));
return riga;
}
//===============================================================================================
//Applicazione
class TTrasf_mov_ce_cg : public TSkeleton_application
{
TTrasf_mov_ce_cg_mask* _mask;
protected:
virtual void main_loop();
virtual bool create();
virtual bool destroy();
void elabora();
void genera_mov_per_cat(TArray& righe_mov, const TDate& datareg, const TDate& datacomp,
const TString& codcaus, const bool definitivo);
void genera_mov_per_ces(TArray& righe_mov, const TDate& datareg, const TDate& datacomp,
const TString& codcaus, const bool definitivo);
void delete_old_movs(const TDate& ini_es);
long get_new_numreg() const;
public:
};
void TTrasf_mov_ce_cg::delete_old_movs(const TDate& ini_es)
{
TMovimentoPN 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 vecchi movimenti provvisori cespiti in corso...", false, true);
for (cur_mov = 0; cur_mov.pos() < items; ++cur_mov)
{
progind.addstatus(1);
pn.read();
pn.remove();
}
}
long TTrasf_mov_ce_cg::get_new_numreg() const
{
TLocalisamfile mov(LF_MOV);
mov.last();
//primo numero libero da usare come numreg
return mov.curr().get_long(MOV_NUMREG) + 1;
}
//metodo per la generazione di movimenti con righe per categoria (chiamata se movdett=0)
void TTrasf_mov_ce_cg::genera_mov_per_cat(TArray& righe_mov, const TDate& datareg, const TDate& datacomp,
const TString& codcaus, const bool definitivo)
{
//riempie i campi della testata movimento
long numreg = get_new_numreg();
TMovimentoPN_CE pn;
TRectype& head = pn.curr();
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);
if (!definitivo)
head.put(MOV_PROVVIS, 'C');
head.put(MOV_DESCR, TR("Rilevazione quote ammortamento cespiti"));
int first_row = 0;
righe_mov.add(new TRigamov(0, EMPTY_STRING, 0));
for (int i = 0; i < righe_mov.items(); i++)
{
const TRigamov& rigamov = (const TRigamov&)righe_mov[i];
// Se cambio categoria
if (i > 0 && rigamov.compare((const TRigamov&)righe_mov[i-1]) != 0)
{
TRectype& riga_fondo = pn.nuova_riga();
TImporto fondo;
for (int j = first_row; j < i; j++)
{
TImporto imp_riga(pn.cg(j).get_char(RMV_SEZIONE), pn.cg(j).get_real(RMV_IMPORTO));
fondo += imp_riga;
}
fondo.swap_section();
fondo.normalize();
riga_fondo.put(RMV_SEZIONE, fondo.sezione());
riga_fondo.put(RMV_IMPORTO, fondo.valore());
//ci vogliono 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(13,3));
riga_fondo.put(RMV_CONTO, stringone.mid(16,3));
riga_fondo.put(RMV_SOTTOCONTO, stringone.mid(19,6));
//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())
{
pn.write();
pn.destroy_rows(++numreg);
}
first_row = pn.cg_items();
}
pn.nuova_riga(rigamov);
}
}
//metodo per la generazione di movimenti con righe per cespite raggruppate e pareggiate per categoria (chiamata se movdett>0)
void TTrasf_mov_ce_cg::genera_mov_per_ces(TArray& righe_mov, const TDate& datareg, const TDate& datacomp,
const TString& codcaus, const bool definitivo)
{
}
//metodo per gestire la successione degli eventi ad alto livello
void TTrasf_mov_ce_cg::elabora()
{
//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);
//deve accoppare i movimenti provvisori di prima nota da inizio esercizio ad oggi?
if (_mask->get_bool(F_KILLOLD))
delete_old_movs(ini_es);
//ragionamenti sulle date
const TDate datareg = _mask->get_date(F_DATAREG);
const TDate datacomp = min(fine_es, datareg);
//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);
//programma vero e proprio (calcolo ammortamenti, selezione cespiti validi, trasferimento)
TISAM_recordset cespiti("USE CESPI");
const TRecnotype nrec = cespiti.items();
//report con log errori
TLog_report cont_cesp_log(TR("Contabilizzazione cespiti"));
//Legge un po' di parametri dal ditta.ini che servono al tipo di calcolo
TConfig config_ditta_ce(CONFIG_DITTA, "ce");
//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");
//Codice causale da mettere nei movimenti generati
const TString4 codcaus = config_ditta_ce.get("COAUQU");
//Assoc_array Categoria-QammTot-QperseTot
TAssoc_array quote_per_codice;
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)
TToken_string gsc;
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);
}
} //for(int i...
TArray saldi_ordinati;
//riempie l'array saldi_ordinati con gli elementi dell'assoc quote_per_codice
FOR_EACH_ASSOC_OBJECT(quote_per_codice, h, k, obj)
saldi_ordinati.add(h->remove_obj());
//accoppa l'assoc
quote_per_codice.destroy();
//e ordina l'array (questo assurdo giro serve perche' l'assoc non e' ordinabile)
saldi_ordinati.sort();
//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(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
if (movdett == 0)
{
genera_mov_per_cat(righe_mov, datareg, datacomp, codcaus, definitivo);
}
else
{
genera_mov_per_ces(righe_mov, datareg, datacomp, codcaus, definitivo);
}
//stampa il log degli errori
TReport_book book;
book.add(cont_cesp_log);
book.preview();
//calcolati,se richiesti,gli ammortamenti, passa in rassegna AMMCE e AMMMV alla ricerca dei cespiti..
//..da considerare per il trasferimento vero e proprio (sono quelli
}
bool TTrasf_mov_ce_cg::create()
{
_mask = new TTrasf_mov_ce_cg_mask;
return TSkeleton_application::create();
}
bool TTrasf_mov_ce_cg::destroy()
{
delete _mask;
return true;
}
void TTrasf_mov_ce_cg::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[])
{
TTrasf_mov_ce_cg a;
a.run(argc,argv,TR("Trasferimento cespiti in contabilita'"));
return 0;
}