#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) { 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'); //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'); //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; }