campo-sirio/ps/pd0610200.cpp

440 lines
13 KiB
C++
Raw Normal View History

#include <applicat.h>
#include "../ve/velib.h"
#include "doc.h"
#include "rdoc.h"
////////////////////////
//// TDOC_KEY ////
////////////////////////
//classe TDoc_key
class TDoc_key: public TToken_string
{
public:
const char provv();
const int anno();
const char* codnum();
const long ndoc();
void set_provv(const char = 'D');
void set_anno(const int anno);
void set_codnum(const char* codnum);
void set_ndoc(const long ndoc);
TDoc_key& operator= (const char* key){set(key);}
TDoc_key(const int anno, const TString& codnum, const long ndoc, const char provv = 'D');
TDoc_key(const char* key):TToken_string(key){}
TDoc_key(const TToken_string& key):TToken_string(key){}
TDoc_key(const TDoc_key& key):TToken_string(key){}
TDoc_key():TToken_string(){}
};
//CODNUM: metodo che restituisce il codnum dalla TToken_string chiave dei documenti
const char TDoc_key::provv()
{
return get(0)[0];
}
//ANNO: metodo che restituisce l'anno dalla TToken_string chiave dei documenti
const int TDoc_key::anno()
{
return get_int(1);
}
//CODNUM: metodo che restituisce il codnum dalla TToken_string chiave dei documenti
const char* TDoc_key::codnum()
{
return get(2);
}
//NDOC: metodo che restituisce il numero documento dalla TToken_string chiave dei documenti
const long TDoc_key::ndoc()
{
return get_int(3);
}
//SET_PROVV: metodo che setta il campo provv
void TDoc_key::set_provv(const char provv)
{
add(provv, 0);
}
//SET_ANNO: metodo che setta il campo anno
void TDoc_key::set_anno(const int anno)
{
add(anno, 1);
}
//SET_CODNUM: metodo che setta il campo codnum
void TDoc_key::set_codnum(const char* codnum)
{
add(codnum, 2);
}
//SET_NDOC: metodo che setta il campo ndoc
void TDoc_key::set_ndoc(const long ndoc)
{
add(ndoc, 3);
}
//metodi costruttori
TDoc_key::TDoc_key(const int anno, const TString& codnum, const long ndoc, const char provv)
{
add(provv);
add(anno);
add(codnum);
add(ndoc);
}
///////////////////////////
//// TORDF_CACHE ////
///////////////////////////
//classe TOrdf_cache
class TOrdf_cache : public TCache
{
TString4 _codnum, _tipodoc;
int _anno;
protected:
virtual void discarding(const THash_object* obj);
virtual TObject* key2obj(const char* key);
public:
TDocumento& doc(const TDoc_key& kdoc);
TDocumento& doc(const long codcf);
TOrdf_cache();
};
//DISCARDING: salva un documento sul disco prima di eliminarlo dalla cache
void TOrdf_cache::discarding(const THash_object* obj)
{
TDocumento& doc = (TDocumento&)obj->obj();
int err = doc.rewrite();
}
//KEY2OBJ:sceglie il documento giusto da disco in modo da poterlo continuare, o lo crea se non c'<27>
TObject* TOrdf_cache::key2obj(const char* key)
{
TDocumento* doc = NULL;
TToken_string tmp(key);
if(tmp.items() == 1)
{
const long codcf = tmp.get_long(0);
doc = new TDocumento('D', _anno, _codnum, 0);
doc->put(DOC_TIPODOC, _tipodoc);
doc->put(DOC_TIPOCF, 'F');
doc->put(DOC_CODCF, codcf);
}
else
{
TDoc_key chiave(key);
const char provv = chiave.provv();
const int anno = chiave.anno();
const TString& codnum = chiave.codnum();
const int ndoc = chiave.ndoc();
doc = new TDocumento(provv, anno, codnum, ndoc);
}
return doc;
}
//DOC: restituisce un puntatore ad un documento identificato dalla chiave documento completa
TDocumento& TOrdf_cache::doc(const TDoc_key& kdoc)
{
return *(TDocumento*)objptr(kdoc);
}
//DOC: restituisce un puntatore ad un documento identificato dal codcf
TDocumento& TOrdf_cache::doc(const long codcf)
{
TString16 key;
key << codcf;
return *(TDocumento*)objptr(codcf);
}
//metodo costruttore di una cache di 20 elementi
TOrdf_cache::TOrdf_cache() : TCache(20)
{
_codnum = "ORDF";
_tipodoc = "ORDF";
const TDate oggi(TODAY);
_anno = oggi.year();
}
////////////////////////////////////
//// TCREA_ORDINI_SRM_APP ////
////////////////////////////////////
//Classe TCrea_ordini_srm_app
class TCrea_ordini_srm_app : public TSkeleton_application
{
private:
TFilename _ini_name;
protected:
virtual bool check_autorization() const {return false;}
virtual const char * extra_modules() const {return "cg";}
virtual void main_loop();
const bool cerca_orf(TDoc_key& dadoc, const long daidriga, const long for1, const long for2, TDoc_key& ordf1, TDoc_key& ordf2);
void ordini_fornitore(const TDocumento& ordc, const int nriga, TDocumento& ordf);
void aggiorna_ordf(const TDocumento& ordc, const int nriga, const TDoc_key& adoc, TOrdf_cache& ca);
void crea_ordf(const TDocumento& ordc, const long nriga, const long codfor, TOrdf_cache& ca);
void elimina_righe(const TDocumento& ordc, TOrdf_cache& ca);
void elabora_ordini_cliente();
public:
bool load_ini(bool check);
};
//CERCA_ORF: cerco se esistono degli ordini fornitori che arrivano dall'ordine cliente in esame
const bool TCrea_ordini_srm_app::cerca_orf(TDoc_key& dadoc, const long daidriga, const long for1, const long for2, TDoc_key& ordf1, TDoc_key& ordf2)
{
bool trovato = false;
TString query;
query << "USE RDOC KEY 4\n"
<< "FROM DAPROVV=\"" << dadoc.provv() << "\" DAANNO=" << dadoc.anno() << " DACODNUM=\"" << dadoc.codnum() << "\" DANDOC=" << dadoc.ndoc() << " DAIDRIGA=" << daidriga << "\n"
<< "TO DAPROVV=\"" << dadoc.provv() << "\" DAANNO=" << dadoc.anno() << " DACODNUM=\"" << dadoc.codnum() << "\" DANDOC=" << dadoc.ndoc() << " DAIDRIGA=" << daidriga;
TISAM_recordset rdoc(query);
for(bool ok = rdoc.move_first(); ok; ok = rdoc.move_next())
{
const char provv = rdoc.get(RDOC_PROVV).as_string()[0];
const int anno = rdoc.get(RDOC_ANNO).as_int();
const TString8 codnum = rdoc.get(RDOC_CODNUM).as_string();
const int ndoc = rdoc.get(RDOC_NDOC).as_int();
TDoc_key key(anno, codnum, ndoc, provv);
const long codcf = atol(cache().get(LF_DOC, key, DOC_CODCF));
if(for1 > 0 && codcf == for1 && ordf1.empty())
ordf1 = key;
if(for2 > 0 && codcf == for2 && ordf2.empty())
ordf2 = key;
trovato = true;
}
return trovato;
}
//ORDINI_FORNITORE: metodo che genera effettivamente gli ordini fornitore
void TCrea_ordini_srm_app::ordini_fornitore(const TDocumento& ordc, const int nriga, TDocumento& ordf)
{
const TRiga_documento rordc = ordc[nriga];
const int idrigac = rordc.get_int(RDOC_IDRIGA);
bool trovato = false;
//ciclo di aggiornamento delle righe che ancora esistono
for(int i = 1; i <= ordf.rows(); i++)
{
TRiga_documento& rordf = ordf[i];
if(idrigac == rordf.get_int(RDOC_DAIDRIGA))
{
trovato = true;
ordf.copy_data(rordf, rordc);
rordf.put(RDOC_CODAGG1, 0);
rordf.put(RDOC_CODAGG2, 0);
rordf.put(RDOC_DAPROVV, ordc.get_char(DOC_PROVV));
rordf.put(RDOC_DAANNO, ordc.get_int(DOC_ANNO));
rordf.put(RDOC_DACODNUM, ordc.get(DOC_CODNUM));
rordf.put(RDOC_DANDOC, ordc.get(DOC_NDOC));
rordf.put(RDOC_DAIDRIGA, idrigac);
}
}
if(! trovato)
{
TRiga_documento& rordf = ordf.new_row();
ordf.copy_data(rordf, rordc);
rordf.put(RDOC_CODAGG1, 0);
rordf.put(RDOC_CODAGG2, 0);
rordf.put(RDOC_DAPROVV, ordc.get_char(DOC_PROVV));
rordf.put(RDOC_DAANNO, ordc.get_int(DOC_ANNO));
rordf.put(RDOC_DACODNUM, ordc.get(DOC_CODNUM));
rordf.put(RDOC_DANDOC, ordc.get(DOC_NDOC));
rordf.put(RDOC_DAIDRIGA, idrigac);
}
}
//AGGIORNA_ORDF: aggiorno l'ordine fornitore che esiste gi<67> in base alle modifiche fatte sull'ordine cliente attuale
void TCrea_ordini_srm_app::aggiorna_ordf(const TDocumento& ordc, const int nriga, const TDoc_key& adoc, TOrdf_cache& ca)
{
TDocumento& ordf = ca.doc(adoc);
ordini_fornitore(ordc, nriga, ordf);
}
//CREA_ORDF: creo un nuovo ordine cliente
void TCrea_ordini_srm_app::crea_ordf(const TDocumento& ordc, const long nriga, const long codfor, TOrdf_cache& ca)
{
TDocumento& ordf = ca.doc(codfor);
ordini_fornitore(ordc, nriga, ordf);
}
//ELIMINA_RIGHE: elimino le righe dagli ordini fornitore che non compaiono pi<70> nell'ordine cliente in esame
void TCrea_ordini_srm_app::elimina_righe(const TDocumento& ordc, TOrdf_cache& ca)
{
const char provv = ordc.get_char(DOC_PROVV);
const int anno = ordc.get_int(DOC_ANNO);
const TString4 codnum = ordc.get(DOC_CODNUM);
const long ndoc = ordc.get_long(DOC_NDOC);
TString query;
query << "USE RDOC KEY 4\n"
<< "FROM DAPROVV=\"" << provv << "\" DAANNO=" << anno << " DACODNUM=\"" << codnum << "\" DANDOC=" << ndoc << "\n"
<< "TO DAPROVV=\"" << provv << "\" DAANNO=" << anno << " DACODNUM=\"" << codnum << "\" DANDOC=" << ndoc;
TISAM_recordset rdoc(query);
//scorro tutte le righe degli ordini fornitori; per ogni riga controllo se esiste ancora sull'ordine cliente;
//se non esiste pi<70> la elimino dall'ordine fornitore, sfruttando la cache dei documenti
for(bool ok = rdoc.move_first(); ok; ok = rdoc.move_next())
{
const int daidriga = rdoc.get(RDOC_DAIDRIGA).as_int();
const int nriga = rdoc.get(RDOC_NRIGA).as_int();
bool trovato = false;
for(int i = 1; i <= ordc.rows(); i++)
{
TRiga_documento rdoc = ordc[i];
if(daidriga == rdoc.get_long(RDOC_IDRIGA))
trovato = true;
}
if(!trovato)
{
TDoc_key kordf(rdoc.get(RDOC_ANNO).as_int(), rdoc.get(RDOC_CODNUM).as_string(), rdoc.get(RDOC_NDOC).as_int(), rdoc.get(RDOC_PROVV).as_string()[0]);
TDocumento& ordf = ca.doc(kordf);
ordf.destroy_row(nriga, true);
}
}
}
//ELABORA_ORDINI_CLIENTE: scorro il file ini e aggiungo alla tabella dei listini le righe mancanti
void TCrea_ordini_srm_app::elabora_ordini_cliente()
{
TConfig ini(_ini_name, "33");
TString4 para; para.format("%d", LF_DOC);
const char provv = ini.get_char(DOC_PROVV, para);
const int anno = ini.get_int(DOC_ANNO, para);
const TString& codnum = ini.get(DOC_CODNUM, para);
const long ndoc = ini.get_long(DOC_NDOC, para);
TDoc_key dadoc(anno, codnum, ndoc, provv);
TDoc_key ordf1;
TDoc_key ordf2;
TOrdf_cache ca;
TDocumento ordc(provv, anno, codnum, ndoc);
//scorro le righe documento, fermandomi quando la set_paragraph fallisce
//dal momento che non so a priori quante sono le righe del documento
for(int i = 1; i <= ordc.rows(); i++)
{
TRiga_documento& rordc = ordc[i];
const long codfor1 = rordc.get_long(RDOC_CODAGG1); //da prendere dalla riga
const long codfor2 = rordc.get_long(RDOC_CODAGG2); //da prendere dalla riga
const int idrigac = rordc.get_int(RDOC_IDRIGA);
if(cerca_orf(dadoc, idrigac, codfor1, codfor2, ordf1, ordf2))
{
if(codfor1 > 0)
aggiorna_ordf(ordc, i, ordf1, ca);
if(codfor2 > 0)
aggiorna_ordf(ordc, i, ordf2, ca);
}
else
{
if(codfor1 > 0)
crea_ordf(ordc, i, codfor1, ca);
if(codfor2 > 0)
crea_ordf(ordc, i, codfor2, ca);
}
}
elimina_righe(ordc, ca);
ca.destroy();
}
//LOAD_INI: carica il file ini che contiene il documento
bool TCrea_ordini_srm_app::load_ini(bool check)
{
//argc <20> un intero che specifica quanti parametri vengono passati al programma dalla linea di comando
const int args = argc();
const int narg = check ? 3 : 2;
//argv <20> un array di null-terminated strings
if (args <= narg)
return false;
const TFixed_string arg = argv(narg);
if ((arg[0] != '-' && arg[0] != '/') || (arg[1] != 'i' && arg[1] != 'I'))
return false;
_ini_name = arg.mid(2);
if (_ini_name.blank() && args > 3)
_ini_name = argv(3);
//controlla che il file su cui deve scrivere ci sia; se non c'<27> d<> una segnalazione di errore
if (!_ini_name.exist())
return false;
return true;
}
void TCrea_ordini_srm_app::main_loop() //definizione della member function main_loop, della classe TCrea_ordini_srm_app
{
TString sw(argv(2)); sw.upper();
const bool chk_doc = sw == "-V";
open_files(LF_TAB, LF_DOC, LF_RIGHEDOC, 0);
//mostra un messaggio di errore se non riesce ad aprire il file richiesto; nota la conversione dei tipi che
//<2F> da eseguire quando devo passare una TString ad un %s
if(!load_ini(chk_doc))
{
error_box(TR("Impossibile aprire il file '%s'"), (const char*)_ini_name);
return;
}
else
{
elabora_ordini_cliente();
message_box(TR("Creazione ordini fornitore completata"));
}
}
////// Esecuzione del programma ///////////
int pd0610200(int argc, char* argv[])
{
TCrea_ordini_srm_app app;
app.run(argc,argv,"Ordini Fornitori");
return 0;
}