#include #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) { TString16 key; key << codcf; return *(TDocumento*)objptr(codcf); } //metodo costruttore di una cache di 20 elementi TOrdf_cache::TOrdf_cache(const char* from_tipodoc, const TDate& datadoc) : TCache() { TToken_string key; key.add("TIP"); key.add(from_tipodoc); TString80 cod_elab = cache().get(LF_TABCOM, key, "S3"); cod_elab.mid(4,8); cod_elab.strip(" "); key.cut(0); key.add("ELD"); key.add(cod_elab); const TRectype& eld = cache().get(LF_TABCOM, key); _codnum = eld.get("S6"); _tipodoc = eld.get("S8"); _stato = eld.get("S9"); _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 "cg";} virtual void main_loop(); const real cerca_prezzo(const char* codart, const TDocumento & ordf); const bool cerca_orf(TDoc_key& dadoc, const long daidriga, const long codfor, TDoc_key& ordf); void aggiorna_righe(TDocumento& ordf, const TDocumento& ordc, const TRiga_documento& rordc, TRiga_documento& rordf, int idrigac); 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); TDoc_key * 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_cliente(); 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) { TToken_string key; //gestione RCONDV - Contratti key.add('C'); //tipo key.add(""); //categoria di vendita key.add('F'); //tipocf key.add(ordf.get(DOC_CODCF)); //codcf key.add("001"); //codice contratto key.add('A'); //rticolo key.add(codart); //codice articolo real prezzo(cache().get(LF_RCONDV, key, RCONDV_PREZZO)); if(prezzo == 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'); //rticolo key.add(codart); //codice articolo const TRectype& rcondv = cache().get(LF_RCONDV, key); prezzo = rcondv.get_real(RCONDV_PREZZO); if(prezzo == 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(TDocumento& ordf, const TDocumento& ordc, const TRiga_documento& rordc, TRiga_documento& rordf, int idrigac) { ordf.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.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); rordf.dirty_fields(); const real r = 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(int i = 1; i <= ordf.rows(); i++) { TRiga_documento& rordf = ordf[i]; if(idrigac == rordf.get_int(RDOC_DAIDRIGA)) { trovato = true; aggiorna_righe(ordf, ordc, rordc, rordf, idrigac); } } if(! trovato) { TRiga_documento& rordf = ordf.new_row(); aggiorna_righe(ordf, ordc, rordc, rordf, idrigac); } } //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_CODCONT, codlist); } //gestione CONDV - Contratti TString8 codcont = orfrow.get(first ? "CF1" : "CF2"); if (codcont.full()) { keyc.cut(0); keyc.add('C'); //tipo keyc.add(""); //categoria di vendita keyc.add('F'); //tipocf keyc.add(codcf); //codcf keyc.add(orfrow.get(first ? "CF1" : "CF2")); const TRectype & contr = cache().get(LF_CONDV, keyc); if (!contr.empty()) ordf.put(DOC_CODCONT, codcont); else codcont.cut(0); } if (codcont.full()) { keyc.cut(0); keyc.add('C'); //tipo keyc.add(""); //categoria di vendita keyc.add('F'); //tipocf keyc.add(codcf); //codcf keyc.add("001"); //codice contratto const TRectype & contr1 = cache().get(LF_CONDV, keyc); if (!contr1.empty()) ordf.put(DOC_CODCONT, "001"); } ordini_fornitore(ordc, nriga, ordf); } //CREA_ORDF: creo un nuovo ordine cliente TDoc_key * 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 * wrk = cerca_orf(kdadoc, 0, codfor, kordf) ? &ca.doc(kordf) : &ca.doc(codfor); TDocumento& ordf = *wrk; 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)); 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_CODCONT, codlist); } //gestione CONDV - Contratti TString8 codcont = orfrow.get(first ? "CF1" : "CF2"); if (codcont.full()) { keyc.cut(0); keyc.add('C'); //tipo keyc.add(""); //categoria di vendita keyc.add('F'); //tipocf keyc.add(codcf); //codcf keyc.add(orfrow.get(first ? "CF1" : "CF2")); const TRectype & contr = cache().get(LF_CONDV, keyc); if (!contr.empty()) ordf.put(DOC_CODCONT, codcont); else codcont.cut(0); } if (codcont.full()) { keyc.cut(0); keyc.add('C'); //tipo keyc.add(""); //categoria di vendita keyc.add('F'); //tipocf keyc.add(codcf); //codcf keyc.add("001"); //codice contratto const TRectype & contr1 = cache().get(LF_CONDV, keyc); if (!contr1.empty()) ordf.put(DOC_CODCONT, "001"); } 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); } ordini_fornitore(ordc, nriga, ordf); return new TDoc_key(ordf.get_int(DOC_ANNO), ordf.get(DOC_CODNUM), ordf.get_long(DOC_NDOC), ordf.get_char(DOC_PROVV)); } //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_first(); ok; ok = rdoc.move_next()) { const int daidriga = rdoc.get(RDOC_DAIDRIGA).as_int(); const int nriga = rdoc.get(RDOC_NRIGA).as_int(); 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 ndoc = ordf.get_long(DOC_NDOC); const long codfor = ordf.get_long(DOC_CODCF); // bool trovato = false; TRiga_documento & r = ordf[nriga]; const TRectype * rordc = r.find_original_rdoc(); if (rordc != NULL) { if (rordc->get(RDOC_PROVV) == rordc->get(DOC_PROVV) && rordc->get(RDOC_CODNUM) == rordc->get(DOC_CODNUM) && rordc->get(RDOC_ANNO) == rordc->get(DOC_ANNO) && rordc->get(RDOC_NDOC) == rordc->get(DOC_NDOC)) { if ((rordc->get_long(RDOC_CODAGG1) != codfor) && (rordc->get_long(RDOC_CODAGG2) != codfor)) r.put("D", "X"); } } } for(bool ok = rdoc.move_first(); ok; ok = rdoc.move_next()) { 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); for(int i = ordf.physical_rows(); i >= 1 ; i--) { if (ordf[i].get("D") == "X") ordf.destroy_row(i, true); } for (int i = 1; i <= ordf.physical_rows(); i++) ordf[i].put(RDOC_NRIGA, i); } } //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); const bool delete_docs = ini.get(DOC_NOTE, para) == "DELETING"; TDoc_key dadoc(anno, codnum, ndoc, provv); TDoc_key ordf; TDocumento ordc(provv, anno, codnum, ndoc); TOrdf_cache ca(ordc.get(DOC_TIPODOC), 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 // message_box("start"); 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 (codfor1 > 0) { if(cerca_orf(dadoc, idrigac, codfor1, ordf)) { if (delete_docs) elimina_ordf(ordf, ca); else aggiorna_ordf(ordc, i, ordf, ca, true); } else TDoc_key * ordf = crea_ordf(ordc, i, codfor1, ca, true); } if (codfor2 > 0) { if(cerca_orf(dadoc, idrigac, codfor2, ordf)) { if (delete_docs) elimina_ordf(ordf, ca); else aggiorna_ordf(ordc, i, ordf, ca, false); } else TDoc_key * ordf = 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 { 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 //é 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; }