#include #include #include #include #include #include #include "mglib.h" #include "mg4400.h" #include "movmag.h" #include "rmovmag.h" #include "../ve/velib.h" /////////////////////////////////////// //// TControllo_movdadoc_msk //// /////////////////////////////////////// //classe TControllo_movdadoc_msk class TControllo_movdadoc_msk : public TAutomask { public: bool on_field_event(TOperable_field& o, TField_event e, long jolly); TControllo_movdadoc_msk (const char* name) : TAutomask(name) {} }; //ON_FIELD_EVENT: metodo che gestisce gli eventi sui campi della maschera bool TControllo_movdadoc_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { return true; } /////////////////////////////////////// //// TControllo_movdadoc_app //// /////////////////////////////////////// //classe TControllo_movdadoc_app class TControllo_movdadoc_app : public TSkeleton_application { TControllo_movdadoc_msk* _msk; protected: virtual bool create(); virtual bool destroy(); virtual void main_loop(); bool check(); bool scorri_documenti(const TString4& codnum, const TAssoc_array& tpdoc, TLog_report& log); }; //CHECK: metodo che ricerca le numerazioni che effettivamente generano movimenti di magazzino //e richiama il metodo scorri_documenti() che effettivamente si occupa di fare tutti i controlli bool TControllo_movdadoc_app::check() { TAssoc_array tpdoc; TString_array numerazioni; TLog_report log("Controllo movimenti magazzino"); { //cerco quali sono i tipi documento che generano movimenti di magazzino TISAM_recordset tipi("USE %TIP SELECT (B1=\"X\")&& (S7 != \"\")"); for (bool ok = tipi.move_first(); ok; ok = tipi.move_next()) tpdoc.add(tipi.get("CODTAB").as_string(), tipi.get("S7").as_real()); } if (tpdoc.items() > 0) { //cerco i codnum che mi servono effettivamente TISAM_recordset num("USE %NUM"); for (bool ok = num.move_first(); ok; ok = num.move_next()) { const TCodice_numerazione& cn = cached_numerazione(num.get("CODTAB").as_string()); bool found = false; for (int t = cn.ntipi_doc()-1; t >= 0 && !found; t--) found = tpdoc.is_key(cn.tipo_doc(t)); if (found) numerazioni.add(cn.codice()); } } bool corretto = true; //scorro tutti i documenti numerazione per numerazione FOR_EACH_ARRAY_ROW(numerazioni, n, codnum) { if (!corretto) { corretto = scorri_documenti(*codnum, tpdoc, log); corretto = false; } else corretto = scorri_documenti(*codnum, tpdoc, log); } if (corretto) log.log(1, "Non sono stati rilevati errori"); //Mostro il log degli errori TReport_book buc; buc.add(log); buc.preview(); return true; } //SCORRI_DOCUMENTI: metodo che effettivamente si occupa di scorrere tutti i documenti di tutte le numerazioni //e controlla la corrispondenza con i movimenti di magazzino associati ai documenti bool TControllo_movdadoc_app::scorri_documenti(const TString4& codnum, const TAssoc_array& tpdoc, TLog_report& log) { const TString4 anno = _msk->get(F_ANNOES); //preparo la query che limita i movimenti TString query; query << "USE DOC\nFROM PROVV=D ANNO=" << anno << " CODNUM=" << codnum << "\nTO PROVV=D ANNO=" << anno << " CODNUM=" << codnum; TISAM_recordset documenti(query); bool corretto = true; for (bool ok = documenti.move_first(); ok; ok = documenti.move_next()) { TAssoc_array qtardoc; TAssoc_array qtarmov; TDocumento doc(documenti.cursor()->curr()); const long ndoc = doc.get_long(DOC_NDOC); real *dastato = (real*)tpdoc.objptr(doc.get(DOC_TIPODOC)); if (doc.get_int(DOC_STATO) < dastato->integer()) continue; //controllo se effettivamente esiste il movimento di magazzino const TRectype& movmag = cache().get(LF_MOVMAG, doc.get_long(DOC_MOVMAG)); if (movmag.empty()) { corretto = false; TString str; str << "Non esiste il movimento di magazzino associato al documento " << codnum << " numero " << ndoc << " del " << doc.get_date(DOC_DATADOC); log.log(2, str); continue; } //scorro tutte le righe documento for (long i = 1; i <= doc.rows(); i++) { const TRiga_documento& rdoc = doc[i]; const TString80 codart = rdoc.get(RDOC_CODARTMAG); if (codart.full()) { TArticolo& art = rdoc.articolo(); //leggo se esiste già nel TAssoc_array real *qta = (real*)qtardoc.objptr(codart); //se non esiste if (qta == NULL) { //per ora memorizzo zero qta = new real; qtardoc.add(codart,qta); } //aggiorno la quantità convertendola all'unità di misura di base *qta += art.convert_to_um(rdoc.quantita(), NULL, rdoc.get(RDOC_UMQTA)); } } //instanzio il movimento TMov_mag mov(doc.get_long(DOC_MOVMAG)); //scorro tutte le righe dei movimenti di magazzino for (long i = 1; i<= mov.rows(); i++) { TString80 codart = mov.body().row(i).get(RMOVMAG_CODART); //leggo se esiste già nel TAssoc_array real *qta = (real*)qtarmov.objptr(codart); //se non esiste if (qta == NULL) { //per ora memorizzo zero qta = new real; qtarmov.add(codart,qta); } //aggiorno la quantità convertendola all'unità di misura di base *qta += mov.body().row(i).get_real(RMOVMAG_QUANT); } //se non corrisoinde il numero di items, segnalo errore if (qtardoc.items() != qtarmov.items()) { corretto = false; TString str; str << "Non sono state create tutte le righe del movimento associate al documento " << codnum << " numero " << ndoc << " del " << doc.get_date(DOC_DATADOC); log.log(2, str); continue; } //controllo la corriposndenza tra i due array FOR_EACH_ASSOC_OBJECT(qtardoc, obj, key, itm) { real *dqta = (real*)itm; real *mqta = (real*)qtarmov.objptr(key); if (mqta == NULL || *dqta != *mqta) { corretto = false; TString str; str << "Non c'è corrispondenza tra le righe documento e le righe movimento per il documento " << codnum << " numero " << ndoc << " del " << doc.get_date(DOC_DATADOC); log.log(2, str); break; } } } //ciclo for che scorre i documenti return corretto; } //CREATE: metodo costruttore bool TControllo_movdadoc_app::create() { _msk = new TControllo_movdadoc_msk("mg4400"); return TSkeleton_application::create(); } //DESTROY: metodo distruttore bool TControllo_movdadoc_app::destroy() { delete _msk; return TSkeleton_application::destroy(); } void TControllo_movdadoc_app::main_loop() { while (_msk->run() == K_ENTER) check(); } int mg4400(int argc, char* argv[]) { TControllo_movdadoc_app a; a.run(argc,argv,TR("Controllo lista movimenti")); return 0; }