campo-sirio/ps/ps1001100.cpp
luca 2184df7b0a Patch level :
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :


git-svn-id: svn://10.65.10.50/branches/R_10_00@20884 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-09-21 10:56:12 +00:00

459 lines
13 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <automask.h>
#include <progind.h>
#include <reputils.h>
#include <relation.h>
#include <textset.h>
#include <utility.h>
#include "../ca/calib01.h"
#include "../ca/movana.h"
#include "../ca/rmovana.h"
#include "../cg/cglib01.h"
#include "ps1001.h"
#include "ps1001100a.h"
///////////////////////////////////////////////////////////
// TAutomask
///////////////////////////////////////////////////////////
class TImporta_movana_mask : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TImporta_movana_mask();
};
TImporta_movana_mask::TImporta_movana_mask() :TAutomask ("ps1001100a")
{
}
bool TImporta_movana_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
//giochetto per avere la lista dei files validi nella directory di trasferimento!
case F_NAME:
if (e == fe_button)
{
TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"), "File@32");
TFilename path = get(F_PATH);
path.add("*.csv"); //files delle testate
list_files(path, as.rows_array());
TFilename name;
FOR_EACH_ARRAY_ROW(as.rows_array(), i, row)
{
name = *row;
*row = name.name();
}
if (as.run() == K_ENTER)
{
o.set(as.row(as.selected()));
}
}
break;
//controlli sui campi della testata documento
case F_DATAREG:
if ((e == fe_modify || e == fe_close) && !query_mode())
{
const TDate datareg = o.get();
const TEsercizi_contabili ec;
if (ec.date2esc(datareg) <= 0)
return error_box(((TEdit_field&)o).get_warning());
if (e == fe_close && field(F_DATACOMP).empty())
set(F_DATACOMP, datareg);
}
break;
case F_DATACOMP:
if ((e == fe_modify || e == fe_close) && !query_mode())
{
const TDate datareg = get(F_DATAREG);
TDate datacomp = o.get();
if (!datacomp.ok())
datacomp = datareg;
const bool preventivo = get(F_TIPO).full();
//i movimenti normali devono avere data competenza nel presente o passato!!
if (!preventivo && datacomp > datareg)
return error_box(TR("La data di competenza non puo' superare la data di registrazione"));
const TEsercizi_contabili ec;
int ae = ec.date2esc(datacomp);
//movimenti preventivi in esercizi futuri
if (ae <= 0 && preventivo && datacomp > datareg)
ae = ec.date2esc(datareg) + datacomp.year() - datareg.year();
if (ae > 0)
set(F_ANNOES, ae, 0x1);
else
return error_box(((TEdit_field&)o).get_warning());
const int ar = ec.date2esc(datareg);
const int ap = ec.pred(ar);
//preventivi un anno indietro, nel presente o nel futuro
if (preventivo)
{
if (ae < ap)
return error_box(FR("La data di competenza non pu<70> precedere l'esercizio %d"), ap);
}
else //normali solo un anno indietro o nel presente
{
if (ae != ar && ae != ap)
return error_box(FR("La data di competenza deve appartenere all'esercizio in corso o al precedente"));
}
}
break;
case F_DATAFCOMP:
if (e == fe_modify || e == fe_close)
{
const TDate datacomp = get(F_DATACOMP);
const TDate datafcomp = o.get();
if (datafcomp.ok())
{
if (datafcomp < datacomp)
return error_box(((TEdit_field&)o).get_warning());
}
else
o.set(datacomp.string()); //se la data fine competenza viene lasciata vuota -> e' uguale alla datacomp
}
break;
default:
break;
}
return true;
}
/////////////////////////////////////////////////////////////
// Recordset specifici per i dati da trasferire
/////////////////////////////////////////////////////////////
class TImporta_movana_recordset : public TCSV_recordset
{
char _sep_field;
protected:
virtual TRecnotype new_rec(const char* buf = NULL);
public:
TImporta_movana_recordset(const char * fileName, char sep);
};
TRecnotype TImporta_movana_recordset::new_rec(const char* buf)
{
TToken_string str(256,'\t'); //nuovo record tab separator
if(buf && *buf)
{
bool apici = false;
for (const char* c = buf; *c ; c++)
{
if (*c == '"')
{
apici = !apici;
}
else
{
if (*c == _sep_field) //tipo di separatore dei campi che si trova nel record di origine
{
if (!apici)
str << str.separator();
else
str << *c;
}
else
str << *c;
}
}
}
const TRecnotype n = TText_recordset::new_rec(str);
if (n >= 0)
row(n).separator(str.separator());
return n;
}
TImporta_movana_recordset::TImporta_movana_recordset(const char * filename, char sep_field)
: TCSV_recordset("CSV(;)"), _sep_field(sep_field) //separatore campi
{
load_file(filename);
}
///////////////////////////////////////
// TSkeleton_application
///////////////////////////////////////
class TImporta_movana : public TSkeleton_application
{
virtual bool check_autorization() const { return false; }
virtual const char * extra_modules() const { return "ca"; }
TImporta_movana_mask* _msk;
protected:
public:
virtual bool create();
virtual bool destroy();
virtual void main_loop();
bool transfer(const TFilename& file);
TImporta_movana() {};
};
bool TImporta_movana::transfer(const TFilename& file)
{
//roba dalla maschera
//parametri di importazione
const char sep_field = _msk->get(F_SEP_FIELD)[0]; //separatore dei campi
const char sep_dec = _msk->get(F_SEP_DEC)[0]; //separatore decimali
//parametri del movana
const long numreg = _msk->get_long(F_NUMREGCA);
const int annoes = _msk->get_int(F_ANNOES);
const TDate datareg = _msk->get_date(F_DATAREG);
const TDate datacomp = _msk->get_date(F_DATACOMP);
const TDate datafcomp = _msk->get_date(F_DATAFCOMP);
const bool autofcomp = _msk->get_bool(F_AUTOFCOMP);
const TString descrizione = _msk->get(F_DESCR);
const char tipomov = _msk->get(F_TIPO)[0];
const TString4 codcaus = _msk->get(F_CODCAUS);
const real ori_totimp = _msk->get_real(F_TOTMOV);
const char ori_totsez = _msk->get(F_TOTMOV_SEZ)[0];
//crea il recordset sul file di input utilizzando il separatore
TImporta_movana_recordset s(file, sep_field);
const long recset_items = s.items();
//un po' di roba iniziale
TProgind pi(s.items(),"Importazione movimento in corso ...",true,true);
TLog_report log("ERRORI DI TRASFERIMENTO");
int curr_line = 0;
//testata
//-------
//movimento analitico che sar<61> generato
TAnal_mov movana;
//il movana esisteva gi<67> o <20> nuovo?
const int err = movana.read(numreg);
//se esisteva gi<67> deve accoppare tutte le righe visto che le sostituir<69>
if (err == NOERR)
movana.destroy_rows(LF_RMOVANA);
else
movana.put(MOVANA_NUMREG, numreg);
movana.put(MOVANA_DATAREG, datareg);
movana.put(MOVANA_DATACOMP, datacomp);
movana.put(MOVANA_DATAFCOMP, datafcomp);
movana.put(MOVANA_ANNOES, annoes);
movana.put(MOVANA_DESCR, descrizione);
movana.put(MOVANA_TIPOMOV, tipomov);
movana.put(MOVANA_CODCAUS, codcaus);
movana.put(MOVANA_AUTOFCOMP, autofcomp);
TImporto totale;
//giro su tutti i record del recordset per importarli; ogni record <20> una riga
//TRACCIATO RECORD all'ultima moda (21/09/2010): codcms/cdc/importo/sezione/gr/co/sott/fase (valido per crpa e dinamica)
//righe analitiche
//----------------
for (bool ok = s.move_first(); ok; ok = s.move_next())
{
if (!pi.addstatus(1))
break;
curr_line ++;
//prende i dati dal record di input del file csv
//----------------------------------------------
//CODCMS ci deve essere e va maiuscolizzato; se non c'<27> va segnalato sul log..
//..ed impedir<69> la write del movana
TString80 codcms = s.get(0).as_string();
if (codcms.blank())
{
//controllo necessario e decisivo per evitare l'errore dovuto all'ultimo 'a capo' che pretendeva una riga ulteriore
if (curr_line < recset_items)
{
TString msg;
msg.format("Manca la commessa nella riga %ld", curr_line);
log.log(2, msg);
}
continue;
}
codcms.upper();
//altra modifica all'ultima moda: se c'<27> un '_' in realt<6C> vorrebbe un '/' (21/09/2010)
codcms.replace('_', '/');
//CDC ci deve essere e va maiuscolizzato; se non c'<27> va segnalato sul log..
//..ed impedir<69> la write del movana
TString80 cdc = s.get(1).as_string();
if (cdc.blank())
{
TString msg;
msg.format("Manca la sede nella riga %ld", curr_line);
log.log(2, msg);
continue;
}
cdc.upper();
//IMPORTO (inizialmente come stringa x poter fare le replace); se nullo va segnalato..
//..ma niente bloccaggio della write
TString80 str_importo = s.get(2).as_string();
if (sep_dec == ',')
{
str_importo.strip("."); //togle il separatore delle migliaia
str_importo.replace(',','.'); //sostituisce il separatore decimale
}
else
str_importo.strip(",");
const real importo = str_importo;
/*if (importo == ZERO)
{
TString msg;
msg.format("Importo nullo nella riga %ld", curr_line);
log.log(0, msg);
}*/
//SEZIONE
TString8 str_sezione = s.get(3).as_string();
if (str_sezione.blank())
{
TString msg;
msg.format("Manca la sezione nella riga %ld", curr_line);
log.log(2, msg);
continue;
}
str_sezione.upper();
const char sezione = str_sezione[0];
//CONTO
const int gr = s.get(4).as_int();
const int co = s.get(5).as_int();
const long so = s.get(6).as_int();
TString80 conto;
conto.format("%03d%03d%06ld", gr, co, so);
if (conto.blank())
{
TString msg;
msg.format("Manca il conto nella riga %ld", curr_line);
log.log(2, msg);
continue;
}
//FASE ci pu<70> essere e va maiuscolizzata;
TString80 fase = s.get(7).as_string();
/*if (fase.blank())
{
TString msg;
msg.format("Manca la fase nella riga %ld", curr_line);
log.log(2, msg);
continue;
}*/
fase.upper();
//riempie la riga analitica
//-------------------------
//nuova riga del movana (sfrutta il fatto che <20> un multiple rectype)
TRectype& rmovana = movana.new_row();
rmovana.put(RMOVANA_DESCR, "Riga importata");
rmovana.put(RMOVANA_CODCONTO, conto);
rmovana.put(RMOVANA_CODCMS, codcms);
rmovana.put(RMOVANA_CODCCOSTO, cdc);
rmovana.put(RMOVANA_CODFASE, fase);
rmovana.put(RMOVANA_SEZIONE, sezione);
rmovana.put(RMOVANA_IMPORTO, importo);
//aggiorna anche il totale documento..
TImporto importo_riga(sezione, importo);
totale += importo_riga;
}
//completa la testata
//-------------------
totale.normalize();
const char totsez = totale.sezione();
const real totimp = totale.valore();
//controllo sul totmov in caso di riscrittura
if (ori_totimp != totimp || (ori_totimp == ZERO && ori_totsez != totsez))
{
TString str_totimp;
str_totimp << totimp;
TString str_ori_totimp;
str_ori_totimp << ori_totimp;
TString msg;
msg.format("Il totale movimento originale e' %s %c, quello importato e' %s %c.\n"
"Registrare il movimento con il totale delle righe importate?",
(const char*)str_totimp, totsez, (const char*)str_ori_totimp, ori_totsez);
if (!yesno_box(msg))
log.log(2, "Totale movimento originale NON coincidente con quello importato !");
}
movana.put(MOVANA_SEZIONE, totale.sezione());
movana.put(MOVANA_TOTDOC, totale.valore());
//solo se non ci sono errori procede alla registrazione del movimento
const int items = log.recordset()->items();
if (items > 0)
log.preview();
else
{
TLocalisamfile fmovana(LF_MOVANA);
int err = movana.rewrite_write(fmovana);
if (err != NOERR)
error_box("Impossibile registrare il movimento analitico !");
}
return true;
}
bool TImporta_movana::create()
{
_msk = new TImporta_movana_mask();
return TSkeleton_application::create();
}
bool TImporta_movana::destroy()
{
delete _msk;
return TApplication::destroy();
}
void TImporta_movana::main_loop()
{
KEY tasto;
tasto = _msk->run();
TConfig& cfg = ca_config();
const bool use_pdcc = cfg.get_bool("UsePdcc");
if (use_pdcc)
{
if (tasto == K_ENTER)
{
//genero il nome del file da caricare
TFilename name = _msk->get(F_PATH);
name.add(_msk->get(F_NAME));
if (transfer(name))
{
message_box(TR("Elaborazione completata"));
}
}
}
else
error_box("Il programma richiede che sia impostato l'uso del piano dei conti contabile in analitica!");
}
TImporta_movana& app() { return (TImporta_movana&) main_app(); }
int ps1001100 (int argc, char* argv[])
{
TImporta_movana main_app;
main_app.run(argc, argv, TR("Importazione movimento analitico da CSV"));
return true;
}