campo-sirio/ps/pd0610200.cpp

545 lines
16 KiB
C++
Executable File

#include <applicat.h>
#include "../ve/velib.h"
#include "../mg/anamag.h"
#include "../ve/rcondv.h"
#include "cfven.h"
#include "doc.h"
#include "rdoc.h"
///////////////////////////
//// TORDF_CACHE ////
///////////////////////////
//classe TOrdf_cache
class TOrdf_cache : public TCache
{
TString4 _codnum, _tipodoc, _stato;
int _anno;
TDate _data;
protected:
virtual void discarding(const THash_object* obj);
virtual TObject* key2obj(const char* key);
public:
const TString& codnum() { return _codnum;}
const TString& tipodoc() { return _tipodoc;}
TDocumento& doc(const TDoc_key& kdoc);
TDocumento& doc(const long codcf);
TOrdf_cache(const char* from_tipodoc, const TDate& datatdoc);
};
//DISCARDING: salva un documento sul disco prima di eliminarlo dalla cache
void TOrdf_cache::discarding(const THash_object* obj)
{
TDocumento& doc = (TDocumento&)obj->obj();
if (doc.physical_rows() == 0 || (doc.physical_rows() == 1 && doc[1].get(RDOC_TIPORIGA) == "05"))
doc.remove();
else
doc.rewrite();
}
//KEY2OBJ:sceglie il documento giusto da disco in modo da poterlo continuare, o lo crea se non c'è
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_STATO, _stato);
doc->put(DOC_TIPOCF, 'F');
doc->put(DOC_CODCF, codcf);
doc->put(DOC_DATADOC, _data);
doc->put(DOC_DATACONS, _data);
}
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)
{
TString8 key; key << codcf;
return *(TDocumento*)objptr(codcf);
}
//metodo costruttore di una cache di 20 elementi
TOrdf_cache::TOrdf_cache(const char* cod_elab, const TDate& datadoc) : TCache()
{
const TRectype& eld = cache().get("%ELD", cod_elab);
_codnum = eld.get("S6");
_tipodoc = eld.get("S8");
_stato = eld.get("S9");
if (_codnum.blank())
error_box(FR("Manca il codice numerazione sull'elaborazione '%s'"), cod_elab);
_anno = datadoc.year();
_data = datadoc;
}
////////////////////////////////////
//// 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 "ve"; }
virtual void main_loop();
const real cerca_prezzo(const char* codart, const TDocumento & ordf) const;
const bool cerca_orf(TDoc_key& dadoc, const long daidriga, const long codfor, TDoc_key& ordf);
void aggiorna_righe(const TRiga_documento& rordc, TRiga_documento& rordf) const;
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, bool first);
void crea_ordf(const TDocumento& ordc, const long nriga, const long codfor, TOrdf_cache& ca, bool first);
void elimina_ordf(const TDoc_key& adoc, TOrdf_cache& ca);
void elimina_righe(const TDocumento& ordc, TOrdf_cache& ca);
void elabora_ordini();
public:
bool load_ini(bool check);
};
//CERCA_PREZZO: cerco il prezzo di un articolo per un dato fornitore
const real TCrea_ordini_srm_app::cerca_prezzo(const char* codart, const TDocumento & ordf) const
{
TToken_string key;
//gestione RCONDV - Contratti
key.add('C'); //tipo
key.add(""); //categoria di vendita nulla sui contratti
key.add('F'); //tipocf
key.add(ordf.get(DOC_CODCF)); //codcf
key.add(ordf.get(DOC_CODCONT)); //codice contratto
key.add('A'); //<A>rticolo
key.add(codart); //codice articolo
real prezzo = cache().get(LF_RCONDV, key, RCONDV_PREZZO);
if (prezzo.is_zero())
{
key.cut(0);
//gestione RCONDV - Listini
key.add('L'); //tipo
key.add(ordf.get(DOC_CATVEN)); //categoria di vendita
key.add(""); //tipocf
key.add(""); //codcf
key.add(ordf.get(DOC_CODLIST)); //codice listino
key.add('A'); //<A>rticolo
key.add(codart); //codice articolo
const TRectype& rcondv = cache().get(LF_RCONDV, key);
prezzo = rcondv.get_real(RCONDV_PREZZO);
if (prezzo.is_zero())
{
const TRectype& anamag = cache().get(LF_ANAMAG, codart);
prezzo = anamag.get_real(ANAMAG_ULTCOS1);
}
}
return prezzo;
}
//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 codfor, TDoc_key& ordf)
{
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();
if (daidriga > 0)
query << " DAIDRIGA=" << daidriga << "\n";
else
query << " DAIDRIGA=999999\n";
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(codcf == codfor)
{
ordf = key;
return true;
}
}
return false;
}
//AGGIORNA_RIGHE: riempie le righe dell'ordine fornitore con i dati corretti
void TCrea_ordini_srm_app::aggiorna_righe(const TRiga_documento& rordc, TRiga_documento& rordf) const
{
const TDocumento& ordf = rordf.doc();
TDocumento::copy_data(rordf, rordc);
rordf.put(RDOC_PREZZO, cerca_prezzo(rordf.get(RDOC_CODART), ordf));
rordf.zero(RDOC_CODAGG1);
rordf.zero(RDOC_CODAGG2);
rordf.zero(RDOC_PERCPROV);
rordf.zero(RDOC_PERCPROV1);
rordf.set_original_rdoc_key(rordc);
rordf.dirty_fields();
rordf.get("IMPNS"); // serve per aggiornare i valori della riga
}
//ORDINI_FORNITORE: 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_EACH_PHYSICAL_RDOC(ordf, i, rordf)
{
if (idrigac == rordf->get_int(RDOC_DAIDRIGA))
{
trovato = true;
aggiorna_righe(rordc, *rordf);
break; // Aggiunto 21/7/2014
}
}
if (!trovato)
{
TRiga_documento& rordf = ordf.new_row();
aggiorna_righe(rordc, rordf);
}
}
//AGGIORNA_ORDF: aggiorno l'ordine fornitore che esiste già 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, bool first)
{
TDocumento& ordf = ca.doc(adoc);
const TRiga_documento & orfrow = ordc[nriga];
const long codcf = ordf.get_long(DOC_CODCF);
TToken_string keyc;
const TString8 codlist = orfrow.get(first ? "LF1" : "LF2");
//gestione CONDV - Listini
if (codlist.full())
{
keyc.add('L'); //tipo
keyc.add(ordf.get(DOC_CATVEN)); //categoria di vendita
keyc.add(""); //tipocf
keyc.add(""); //codcf
keyc.add(codlist);
const TRectype& list = cache().get(LF_CONDV, keyc);
if (!list.empty())
ordf.put(DOC_CODLIST, codlist);
}
//gestione CONDV - Contratti
const TString8 codcont = orfrow.get(first ? "CF1" : "CF2");
if (codcont.full())
{
keyc = "C"; //tipo
keyc.add(""); //categoria di vendita nulla sui contratti
keyc.add('F'); //tipocf
keyc.add(codcf); //codcf
keyc.add(codcont);
const TRectype& contr = cache().get(LF_CONDV, keyc);
if (contr.empty())
{
warning_box("Non trovando il contratto %s si utilizza lo 001.", (const char*)keyc);
keyc.add("001", 4); // codice contratto default
if (!cache().get(LF_CONDV, keyc).empty())
ordf.put(DOC_CODCONT, "001");
}
else
ordf.put(DOC_CODCONT, codcont);
}
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, bool first)
{
TDoc_key kordf;
TDoc_key kdadoc(ordc.get_int(DOC_ANNO), ordc.get(DOC_CODNUM), ordc.get_long(DOC_NDOC), ordc.get_char(DOC_PROVV));
TDocumento& ordf = cerca_orf(kdadoc, 0, codfor, kordf) ? ca.doc(kordf) : ca.doc(codfor);
if (ordf.physical_rows() == 0)
{
ordf.cli2doc();
ordf.put(DOC_CODCMS, ordc.get(DOC_CODCMS));
ordf.put(DOC_CODCOSTO, ordc.get(DOC_CODCOSTO));
ordf.put(DOC_FASCMS, ordc.get(RDOC_FASCMS));
ordf.put(DOC_NUMDOCRIF, ordc.numero());
ordf.put(DOC_DATADOCRIF, ordc.get(DOC_DATADOC));
TRiga_documento & row = ordf.new_row("05");
TString rif;
ordc.riferimento(rif);
if (rif.empty())
rif = ordc.tipo().descrizione();
if (rif.full())
rif << ' ';
rif << "n. " << ordc.numero();
rif << " del " << ordc.get(DOC_DATADOC);
row.put(RDOC_DESCR, rif);
}
const TRiga_documento & orfrow = ordc[nriga];
const long codcf = ordf.get_long(DOC_CODCF);
TToken_string keyc;
const TString8 codlist = orfrow.get(first ? "LF1" : "LF2");
//gestione CONDV - Listini
if (codlist.full())
{
keyc = "L"; // 'L'istino
keyc.add(ordf.get(DOC_CATVEN)); //categoria di vendita
keyc.add(""); //tipocf
keyc.add(""); //codcf
keyc.add(codlist);
const TRectype& list = cache().get(LF_CONDV, keyc);
if (!list.empty())
ordf.put(DOC_CODLIST, codlist);
}
//gestione CONDV - Contratti
const TString8 codcont = orfrow.get(first ? "CF1" : "CF2");
if (codcont.full())
{
keyc = "C"; // 'C'ontratti
keyc.add(""); // categoria di vendita nulla sui contratti
keyc.add('F'); // tipocf
keyc.add(codcf); // codcf
keyc.add(codcont); // codice contratto
const TRectype& contr = cache().get(LF_CONDV, keyc);
if (contr.empty())
{
warning_box("Non trovando il contratto %s si utilizza lo 001.", (const char*)keyc);
keyc.add("001", 4); // codice contratto di default
if (!cache().get(LF_CONDV, keyc).empty())
ordf.put(DOC_CODCONT, "001");
}
else
ordf.put(DOC_CODCONT, codcont);
}
ordini_fornitore(ordc, nriga, ordf);
}
//ELIMINA_ORDF: aggiorno l'ordine fornitore che esiste già in base alle modifiche fatte sull'ordine cliente attuale
void TCrea_ordini_srm_app::elimina_ordf(const TDoc_key& adoc, TOrdf_cache& ca)
{
TDocumento& ordf = ca.doc(adoc);
ordf.destroy_rows();
}
//ELIMINA_RIGHE: elimino le righe dagli ordini fornitore che non compaiono più 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 SELECT CODNUM==\"" << ca.codnum() << "\"\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ù la elimino dall'ordine fornitore, sfruttando la cache dei documenti
for (bool ok = rdoc.move_last(); ok; ok = rdoc.move_prev())
{
const 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);
const long codfor = ordf.get_long(DOC_CODCF);
const int daidriga = rdoc.get(RDOC_DAIDRIGA).as_int();
const int nriga = rdoc.get(RDOC_NRIGA).as_int();
TRiga_documento& r = ordf[nriga];
bool kill = false;
int ordc_row = 0;
for (ordc_row = ordc.physical_rows(); ordc_row > 0; ordc_row = ordc_row--)
{
const TRiga_documento& rc = ordc[ordc_row];
if (rc.get_int(RDOC_IDRIGA) == daidriga)
{
if ((rc.get_long(RDOC_CODAGG1) != codfor) && (rc.get_long(RDOC_CODAGG2) != codfor))
kill = true;
break;
}
}
if (ordc_row <= 0)
kill = true;
if (kill)
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()
{
TString4 para; para.format("%d", LF_DOC);
TConfig ini(_ini_name, para);
const char provv = ini.get_char(DOC_PROVV, para);
const int anno = ini.get_int(DOC_ANNO, para);
const TString4 codnum = ini.get(DOC_CODNUM, para);
const long ndoc = ini.get_long(DOC_NDOC, para);
const bool delete_docs = ini.get(DOC_NOTE, para) == "DELETING";
const TString8 cod_elab = ini.get("Action", "Transaction");
TDoc_key dadoc(anno, codnum, ndoc, provv);
TDocumento ordc(provv, anno, codnum, ndoc);
TOrdf_cache ca(cod_elab, ordc.get_date(DOC_DATADOC));
//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++)
{
const TRiga_documento& rordc = ordc[i];
const long codfor1 = rordc.get_long(RDOC_CODAGG1); //da prendere dalla riga
if (codfor1 > 0)
{
TDoc_key ordf;
if (cerca_orf(dadoc, 0, codfor1, ordf))
{
if (delete_docs)
elimina_ordf(ordf, ca);
else
aggiorna_ordf(ordc, i, ordf, ca, true);
}
else
crea_ordf(ordc, i, codfor1, ca, true);
}
const long codfor2 = rordc.get_long(RDOC_CODAGG2); //da prendere dalla riga
if (codfor2 > 0)
{
TDoc_key ordf;
if (cerca_orf(dadoc, 0, codfor2, ordf))
{
if (delete_docs)
elimina_ordf(ordf, ca);
else
aggiorna_ordf(ordc, i, ordf, ca, false);
}
else
crea_ordf(ordc, i, codfor2, ca, false);
}
}
if (!delete_docs)
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 é 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 é 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'é 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
{
open_files(LF_TAB, LF_TABCOM, LF_DOC, LF_RIGHEDOC, 0);
const TFixed_string sw = argv(2);
const bool chk_doc = sw.starts_with("-V", true);
// mostra un messaggio di errore se non riesce ad aprire il file richiesto
if (load_ini(chk_doc))
{
elabora_ordini();
xvt_dm_popup_message(TR("Creazione ordini fornitore completata"));
}
else
cantread_box(_ini_name);
}
////// Esecuzione del programma ///////////
int pd0610200(int argc, char* argv[])
{
TCrea_ordini_srm_app app;
app.run(argc,argv, TR("Ordini Fornitori"));
return 0;
}