campo-sirio/ps/pg0388200.cpp

604 lines
15 KiB
C++
Raw Normal View History

#include <applicat.h>
#include <automask.h>
#include <clifo.h>
#include <config.h>
#include <execp.h>
#include <filetext.h>
#include <log.h>
#include <progind.h>
#include <reprint.h>
#include <sheet.h>
#include <tabutil.h>
#include <utility.h>
#include "pg0388200a.h"
#include "../ve/velib.h"
#include "../sv/svlib09.h"
#include "../mg/mag.h"
//---------------------------------
// TAutomask
//---------------------------------
class TImpBol0388_mask : public TAutomask
{
protected:
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
bool select_file_ext(const char* ext, TFilename& filename);
public:
TImpBol0388_mask();
virtual ~TImpBol0388_mask(){};
};
TImpBol0388_mask::TImpBol0388_mask() :TAutomask ("pg0388200a")
{
}
bool TImpBol0388_mask::select_file_ext(const char* ext, TFilename& filename)
{
TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"),
"File@48");
TFilename path = get(F_PATH);
path.add("*");
path.ext(ext);
list_files(path, as.rows_array());
TFilename name;
FOR_EACH_ARRAY_ROW(as.rows_array(), i, row)
{
name = *row;
*row = name.name();
}
bool ok = as.run() == K_ENTER;
if (ok)
{
filename = as.row(as.selected());
}
return ok;
}
bool TImpBol0388_mask::on_field_event(TOperable_field& f, TField_event e, long jolly)
{
switch (f.dlg())
{
//giochetto per avere la lista dei files validi nella directory di trasferimento!
case F_NAMEBOL:
if (e == fe_button)
{
TFilename name;
if (select_file_ext("txt", name))
f.set(name);
}
break;
case F_NAMEINV:
if (e == fe_button)
{
TFilename name;
if (select_file_ext("csv", name))
f.set(name);
}
break;
default:
break;
}
return true;
}
//--------------------------------
// TFile_text
//--------------------------------
class TImpBol0388_file: public TFile_text
{
protected:
virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str);
public:
TImpBol0388_file(const TString& file_name, char tipo);
virtual ~TImpBol0388_file() { }
};
TImpBol0388_file::TImpBol0388_file(const TString& file_name, char tipo)
: TFile_text(file_name, tipo == 'B' ? "pg0388200a.ini" : "pg0388200b.ini"){}
void TImpBol0388_file::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str)
{
const TString code(s.get(0));
TString valore = str;
if (code == "_UPPERCASE")
{
valore.upper();
}
else NFCHECK("Macro non definita: %s", (const char *)code);
str = valore;
}
//----------------------------------
// TDocumento_cache
//----------------------------------
//classe necessaria per avere una lista di documenti in RAM di dimensione limitata
class TDocumento_cache : public TArray
{
public:
void flush();
TDocumento& doc(const int anno, const char* codnum, const long ndoc);
};
TDocumento& TDocumento_cache::doc(const int anno, const char* codnum, const long ndoc)
{
TDocumento* doc = NULL;
for (int i = 0; i < items(); i++)
{
TDocumento& d = (TDocumento&)operator[](i);
if (d.get(DOC_CODNUM) == codnum)
{
if (d.get_int(DOC_ANNO) != anno || d.get_long(DOC_NDOC) != ndoc)
{
const TString& tipodoc = d.get(DOC_TIPODOC);
if (tipodoc.full())
d.write();
destroy(i, true);
}
else
doc = &d;
break;
}
}
if (doc == NULL)
{
doc = new TDocumento('D', anno, codnum, ndoc);
add(doc);
}
return *doc;
}
void TDocumento_cache::flush()
{
for (int i = 0; i < items(); i++)
{
const TDocumento& d = (const TDocumento&)operator[](i);
const TString& tipodoc = d.get(DOC_TIPODOC);
if (tipodoc.full())
d.write();
}
destroy();
}
//----------------------------------
// TSkeleton_application
//----------------------------------
class TImpBol0388 : public TSkeleton_application
{
TImpBol0388_mask* _msk;
TImpBol0388_file* _trasfile;
TConfig* _configfile;
TDocumento_cache _doc;
TRelation* _rel;
TCursor* _cur;
TProgind* _prog;
TString4 _numbol, _tipobol, _numord;
int _statobol;
long _forbidden_ndoc, _lastbol;
virtual const char * extra_modules() const {return "ba";}
protected:
void mask2ini();
void ini2mask();
bool transfer();
void transfer_testata(const TRecord_text& curr, TError_log& log);
void transfer_righe(const TRecord_text& curr);
void evasione(TRiga_documento& riga_doc, const real& qta) const;
int crea_riga_bolla(const TRecord_text& curr, TDocumento& bol, bool is_omaggio);
bool transfer_inventario();
public:
virtual bool create();
virtual bool destroy();
virtual void main_loop();
TImpBol0388() {}
};
TImpBol0388& app() { return (TImpBol0388&) main_app(); }
/////////////////////////////////////////////////
// Trasferimento bolle e aggiornamento ordini
/////////////////////////////////////////////////
bool TImpBol0388::transfer()
{
_forbidden_ndoc = 0L;
//file da trasferire
//costruire il nome del file con path
TFilename file = _msk->get(F_PATH);
file.add(_msk->get(F_NAMEBOL));
file.ext("txt");
_trasfile = new TImpBol0388_file(file, 'B');
_trasfile->open(file,'r');
//preparazione del log
TError_log log;
log.set_header(TR("Trasferimento bolle"));
const long dimension = fsize(file);
TProgind pi(dimension,TR("Importazione bolle in corso..."));
int err = NOERR;
TRecord_text curr;
//parametri dei documenti da creare ed aggiornare
_numbol = _msk->get(F_NUMBOL);
_tipobol = _msk->get(F_TIPOBOL);
_numord = _msk->get(F_NUMORD);
_statobol = _msk->get_int(F_STATOBOL);
while (_trasfile->read(curr) == NOERR && !pi.iscancelled() && err == NOERR)
{
pi.setstatus(_trasfile->read_file()->tellg());
//in base al tipo record scandisce tetate o righe con il relativo tracciato sul .ini
const TString& tipo_rec = curr.type();
if (tipo_rec == "TB01")
{
transfer_testata(curr, log);
}
if (tipo_rec == "RB01")
{
transfer_righe(curr);
}
}
_trasfile->close();
delete _trasfile;
_doc.flush(); //accoppa la TDocumento_cache
log.show();
return true;
}
void TImpBol0388::transfer_testata(const TRecord_text& curr, TError_log& log)
{
const long num_bol = atol(curr.get(1));
const TDate datadoc = curr.get(2);
const int anno_ord = atoi(curr.get(4));
const long num_ord = atol(curr.get(5));
// creo il documento, se esiste cancello le righe perche' le ricreo successivamente
TDocumento& bol = _doc.doc(datadoc.year(), _numbol, num_bol);
const bool isnew = bol.rows() == 0;
if (isnew)
{
_forbidden_ndoc = 0L;
bol.put(DOC_TIPODOC, _tipobol);
bol.put(DOC_DATADOC, datadoc);
bol.put(DOC_STATO, _statobol);
bol.put("DAANNO", anno_ord);
bol.put("DANDOC", num_ord);
//legge la testata dell'ordine per avere il clifo
TDocumento& ordine = _doc.doc(anno_ord, _numord, num_ord);
const char tipocf = ordine.get_char(DOC_TIPOCF);
const long codcf = ordine.get_int(DOC_CODCF);
bol.put(DOC_TIPOCF, tipocf);
bol.put(DOC_CODCF, codcf);
//codice pagamento e coordinate bancarie
TToken_string key;
key.add(tipocf);
key.add(codcf);
const TRectype& rec_clifo = cache().get(LF_CLIFO, key);
bol.put(DOC_CODPAG, rec_clifo.get(CLI_CODPAG));
bol.put(DOC_CODABIA, rec_clifo.get_long(CLI_CODABI));
bol.put(DOC_CODCABA, rec_clifo.get_long(CLI_CODCAB));
_lastbol = num_bol; //aggiorna l'indicatore dell'ultima bolla trasferita
}
else
{
_forbidden_ndoc = num_bol;
TString msg;
msg.format(FR("La bolla %ld e' gia' stata trasferita"), num_bol);
log.log(1, msg);
}
}
void TImpBol0388::evasione(TRiga_documento& riga_doc, const real& qta) const
{
const real quantita = riga_doc.quantita();
const real qtaevasa = riga_doc.qtaevasa() + qta;
riga_doc.put(riga_doc.field_qtaevasa(), qta);
const bool evasa = qtaevasa >= quantita;
if (evasa)
riga_doc.put(RDOC_RIGAEVASA, evasa);
}
int TImpBol0388::crea_riga_bolla(const TRecord_text& curr, TDocumento& bol, bool is_omaggio)
{
//carica i valori dal file di testo...
//intanto la quantita', sia fatturata che omaggio
const real qta = curr.get(is_omaggio ? 8 : 7);
//se la quantita' e' vuota e' inutile proseguire (sara' una riga descrizione trattata a parte)
if (qta <= ZERO)
return 0;
//il numero riga dell'ordine e' aumentato di 1 se omaggio
const int nriga_ord = atoi(curr.get(4)) + (is_omaggio ? 1 : 0);
TString16 codart = curr.get(5); codart.trim();
TString16 strdata_scad = curr.get(10);
strdata_scad.trim();
const TDate data_scad(strdata_scad);
const long lotto = atol(curr.get(11));
//TRiga_documento& rdoc = bol.new_row(is_omaggio ? "09" : "01");
TRiga_documento& rdoc = bol.new_row("01");
//legge l'ordine originario della bolla sfruttando i dati noti
const int ord_anno = bol.get_int("DAANNO");
const long ord_ndoc = bol.get_long("DANDOC");
TDocumento& ordine = _doc.doc(ord_anno, _numord, ord_ndoc);
const int righe_ordine = ordine.physical_rows();
bool da_ordine = nriga_ord > 0 && nriga_ord <= righe_ordine;
if (da_ordine)
{
const TRiga_documento& rdocord = ordine[nriga_ord];
da_ordine = rdocord.get(RDOC_CODART) == codart &&
rdocord.get(RDOC_TIPORIGA) == rdoc.get(RDOC_TIPORIGA);
}
//righe merce da ordine
if (da_ordine)
{
TRiga_documento& rdocord = ordine[nriga_ord];
//copia la riga dell'ordine originale nella riga della bolla, in modo da avere gia'..
//..una parte dei campi completata, e dover solo aggiornare le quantita
TDocumento::copy_data(rdoc, rdocord);
//Evasione della riga ordine originaria
evasione(rdocord, qta);
}
else //righe merce non da ordine
{
const TString& codiva = cache().get(LF_ANAMAG, codart, ANAMAG_CODIVA);
rdoc.put(RDOC_CODIVA, codiva);
TToken_string key;
key.format("%s|1", (const char*) codart);
const TRectype& rec_umart = cache().get(LF_UMART, key);
const TString& um = rec_umart.get(UMART_UM);
rdoc.put(RDOC_UMQTA, um);
const real prezzo = rec_umart.get(UMART_PREZZO);
rdoc.put(RDOC_PREZZO, prezzo);
rdoc.put(RDOC_CODART, codart);
}
rdoc.put(RDOC_DESCR, curr.get(6));
rdoc.put(RDOC_QTA, qta);
rdoc.put(RDOC_CODAGG1, data_scad);
rdoc.put(RDOC_CODAGG2, lotto);
if (is_omaggio)
{
rdoc.put(RDOC_GENERATA, "X");
rdoc.put(RDOC_SCONTO, "100");
}
return rdoc.get_int(RDOC_NRIGA);
}
void TImpBol0388::transfer_righe(const TRecord_text& curr)
{
const long numbol = atol(curr.get(1));
const TDate datadoc = curr.get(2);
const int nriga = atoi(curr.get(3));
if (numbol != _forbidden_ndoc) //non puo' riscrivere righe di una bolla esistente!
{
// crea la bolla della testata
TDocumento& bol = _doc.doc(datadoc.year(), _numbol, numbol);
/***prima versione dei file da importare con sottorighe descrizione
//deve distinguere le righe speciali di descrizione
TString8 str_numriga = curr.get(4);
const int riga_descr = atoi(str_numriga.left(3));
const int riga_ord = atoi(str_numriga.mid(3));
if (riga_descr > 0 || codart == "**") //il codart e' comunque lungo 10
{
switch (riga_descr)
{
case 0:
break;
case 1:
{
TRiga_documento& rdoc = bol.new_row("05");
rdoc.put(RDOC_DESCR, curr.get(6));
}
break;
default:
{
TRiga_documento& rdoc = bol[bol.rows()];
TString descest = rdoc.get(RDOC_DESCEST);
descest << "\n" << curr.get(6);
rdoc.put(RDOC_DESCEST, descest);
rdoc.put(RDOC_DESCLUNGA, 'X');
}
break;
}
} //if (riga_descr > 0...*/
//versione attuale
TString16 codart = curr.get(5); codart.trim();
//riga descrizione
if (codart.blank())
{
TRiga_documento& rdoc = bol.new_row("05");
rdoc.put(RDOC_DESCR, curr.get(6));
}
else //e' riga merce o omaggio...
{
crea_riga_bolla(curr, bol, false); // Crea eventuale riga merce
crea_riga_bolla(curr, bol, true); // Crea eventuale riga omaggio
}
} //if (numbol != _forbidden_ndoc...
}
//////////////////////////////////////
// Trasferimento inventario
//////////////////////////////////////
bool TImpBol0388::transfer_inventario()
{
//file da trasferire
//costruire il nome del file con path
TFilename file = _msk->get(F_PATH);
file.add(_msk->get(F_NAMEINV));
file.ext("csv");
_trasfile = new TImpBol0388_file(file, 'I');
_trasfile->open(file,'r');
//preparazione del log
TError_log log;
log.set_header(TR("Trasferimento inventario"));
const long dimension = fsize(file);
TProgind pi(dimension,TR("Importazione inventario in corso..."));
int err = NOERR;
TRecord_text curr;
TLocalisamfile mag_file(LF_MAG);
TString80 last_codart;
TAssoc_array last_codmag;
while (_trasfile->read(curr) == NOERR && !pi.iscancelled() && err == NOERR)
{
pi.setstatus(_trasfile->read_file()->tellg());
//acquisizione dati dal record del file csv
TString80 codart = curr.get(0);
codart.strip("\"");
//campi senza destinazione, per ora
/* TString80 lotto = curr.get(1);
lotto.strip("\"");
TString16 str_data = curr.get(2);
str_data.strip("\"");
TDate data(str_data);*/
TString16 str_giac = curr.get(3);
str_giac.strip("\"");
real giac(str_giac);
TString8 codmag = curr.get(4);
codmag.strip("\"");
//scrittura dei record
if (codart == last_codart && last_codmag.objptr(codmag) != NULL)
{
real& tot_giac = *(real*)last_codmag.objptr(codmag);
tot_giac += giac;
mag_file.put(MAG_RIM, tot_giac);
mag_file.put(MAG_GIAC, tot_giac);
mag_file.rewrite();
}
else
{
mag_file.put(MAG_CODMAG, codmag);
mag_file.put(MAG_CODART, codart);
mag_file.put(MAG_NRIGA, 1);
mag_file.put(MAG_RIM, giac);
mag_file.put(MAG_GIAC, giac);
last_codart = codart;
last_codmag.destroy();
last_codmag.add(codmag, giac);
//precauzione nel caso venga reimportato un record simile
if (mag_file.write() != NOERR)
mag_file.rewrite();
}
}
_trasfile->close();
delete _trasfile;
log.show();
return true;
}
////////////////////////////
// Parte comune
////////////////////////////
void TImpBol0388::mask2ini()
{
//aggiorna il numero dell'ultima bolla trasferita
_msk->set(F_LASTBOL, _lastbol);
//carica i parametri del file di configurazione
_configfile->set_paragraph("RICEZIONE");
for (int i = 0; i < _msk->fields() ; i++)
{
TMask_field& f = _msk->fld(i);
const TFieldref* fr = f.field();
if (fr != NULL)
_configfile->set(fr->name(), f.get());
}
}
void TImpBol0388::ini2mask()
{
//carica i parametri del file di configurazione
_configfile->set_paragraph("RICEZIONE");
_lastbol = atol(_configfile->get("LASTBOL"));
for (int i = 0; i < _msk->fields() ; i++)
{
TMask_field& f = _msk->fld(i);
const TFieldref* fr = f.field();
if (fr != NULL)
{
const TString& val = _configfile->get(fr->name());
f.set(val);
}
}
}
bool TImpBol0388::create()
{
_configfile = new TConfig("pg0388conf.ini");
_msk = new TImpBol0388_mask();
open_files(LF_DOC, LF_RIGHEDOC, 0);
return TSkeleton_application::create();
}
bool TImpBol0388::destroy()
{
delete _msk;
delete _configfile;
return TApplication::destroy();
}
void TImpBol0388::main_loop()
{
KEY tasto;
ini2mask();
tasto = _msk->run();
if (tasto == K_ENTER)
{
if (_msk->get_bool(F_IMPBOL))
{
if (transfer())
message_box(TR("Importazione bolle completata"));
}
if (_msk->get_bool(F_IMPINV))
{
if (transfer_inventario())
message_box(TR("Importazione inventario completata"));
}
mask2ini();
}
}
int pg0388200 (int argc, char* argv[])
{
TImpBol0388 main_app;
main_app.run(argc, argv, TR("Importazione Bolle"));
return TRUE;
}