diff --git a/mg/mg0.cpp b/mg/mg0.cpp index f44c26d96..0ee61bc3e 100755 --- a/mg/mg0.cpp +++ b/mg/mg0.cpp @@ -12,6 +12,5 @@ int main(int argc, char** argv) case 3: mg0400(argc,argv); break; // giacenze per cliente/fornitore default: mg0100(argc,argv); break; // gestione tabelle } - exit(0); return 0; } diff --git a/mg/mg2.cpp b/mg/mg2.cpp index 31e8fafd2..27950e3a6 100755 --- a/mg/mg2.cpp +++ b/mg/mg2.cpp @@ -1,10 +1,8 @@ #include -#include -// + // Modulo di Gestione ??? #include "mg0.h" - int main(int argc, char** argv) { int rt = -1; @@ -14,7 +12,7 @@ int main(int argc, char** argv) { case 0: // gestione default: - error_box(FR("Error - usage : %s -{0|1|2|3|4|5|6|7|8|9}"), argv[0]) ; break; + break; } return rt ; diff --git a/mg/mg4400.cpp b/mg/mg4400.cpp index 1085abc32..ad92c6df9 100755 --- a/mg/mg4400.cpp +++ b/mg/mg4400.cpp @@ -1,249 +1,251 @@ #include -#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 +class TCheckdoc_mask: public TMask { public: - bool on_field_event(TOperable_field& o, TField_event e, long jolly); - TControllo_movdadoc_msk (const char* name) : TAutomask(name) {} + TCheckdoc_mask() : TMask("mg4400") {} }; -//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 +class TCheckdoc_app : public TSkeleton_application { - TControllo_movdadoc_msk* _msk; - protected: - virtual bool create(); - virtual bool destroy(); - virtual void main_loop(); + void segnala_documento(TRecordset& doc, TLog_report& rep, const char* msg) const; + bool cerca_articolo(const TMov_mag& mov, const TString& codart) const; + void elabora_mov(int anno, TAssoc_array& duplicati, TLog_report& log) const; + void elabora_doc(int anno, TAssoc_array& duplicati, TLog_report& log) const; - bool check(); - bool scorri_documenti(const TString4& codnum, const TAssoc_array& tpdoc, TLog_report& log); +public: + virtual void main_loop(); }; -//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() +void TCheckdoc_app::segnala_documento(TRecordset& doc, TLog_report& rep, const char* msg) const { - 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; + TString s; + s << TR("Il doc. ") << doc.get(DOC_CODNUM) << ' ' << doc.get(DOC_ANNO) << '/' << doc.get(DOC_NDOC) + << TR(" del ") << doc.get(DOC_DATADOC) << ' ' << msg; + rep.log(0, ""); + rep.log(2, s); } -//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) +bool TCheckdoc_app::cerca_articolo(const TMov_mag& mov, const TString& codart) const { - 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()) + const TRecord_array& rmov = mov.body(); + int i = 0; + for (i = rmov.last_row(); i > 0; i = rmov.pred_row(i)) { - 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)); + const TRectype& rowi = rmov.row(i); + const TString& art = rowi.get(RMOVMAG_CODART); + if (codart == art) + break; + } + return i > 0; +} - if (doc.get_int(DOC_STATO) < dastato->integer()) +void TCheckdoc_app::elabora_mov(int anno, TAssoc_array& duplicati, TLog_report& log) const +{ + TISAM_recordset mov("USE MOVMAG KEY 2\nFROM ANNOES=#ANNO\nTO ANNOES=#ANNO"); + mov.set_var("#ANNO", long(anno)); + + TString msg; + msg << TR("Controllo duplicati su ") << mov.items() << TR(" movimenti di magazzino del ") << anno; + + log.log(0, ""); + log.log(0, msg); + log.log(0, ""); + + TProgind pi(mov.items(), msg); + const TRectype& curr = mov.cursor()->curr(); + TAssoc_array ass; + for (bool ok = mov.move_first(); ok; ok = mov.move_next()) + { + if (!pi.addstatus(1)) + break; + const TDoc_key k(curr); + if (k.ndoc() > 0) + { + TToken_string* d = (TToken_string*)ass.objptr(k); + if (d != NULL) + { + const TRectype& doc = cache().get(LF_DOC, k); + const TString& tipodoc = doc.get(DOC_TIPODOC); + const TTipo_documento& td = cached_tipodoc(tipodoc); + if (!td.is_ordine() && !td.scarica_residuo()) + { + const long numreg = curr.get_long(MOVMAG_NUMREG); + d->add(numreg); + msg.cut(0) << TR("Il mov. ") << numreg << TR(" ed il mov. ") << d->get(0) + << TR(" si riferiscono allo stesso doc. ") + << k.codnum() << ' ' << k.anno() << '/' << k.ndoc(); + log.log(d->items() == 2 ? 1 : 2, msg); + duplicati.add(k, *d, true); + } + } + else + { + d = new TToken_string(curr.get(MOVMAG_NUMREG)); + ass.add(k, d); + } + } + } +} + +void TCheckdoc_app::elabora_doc(int anno, TAssoc_array& duplicati, TLog_report& log) const +{ + TISAM_recordset doc("USE DOC SELECT CAUSMAG!=\"\"\nFROM PROVV=D ANNO=#ANNO\nTO PROVV=D ANNO=#ANNO"); + doc.set_var("#ANNO", long(anno)); + + TString msg; + msg << TR("Controllo di ") << doc.items() << TR(" documenti che movimentano il magazzino del ") << anno; + + log.log(0, ""); + log.log(0, msg); + + TProgind pi(doc.items(), msg); + + for (bool ok = doc.move_first(); ok; ok = doc.move_next()) + { + if (!pi.addstatus(1)) + break; + + bool good = false; + const TString& tipodoc = doc.get(DOC_TIPODOC).as_string(); + const TTipo_documento& td = cached_tipodoc(tipodoc); + if (td.mov_mag() && !td.is_ordine() && !td.scarica_residuo()) + { + const char stato = doc.get(DOC_STATO).as_string()[0]; + good = stato >= td.stato_mov_iniziale(); + } + if (!good) // Inutile controllare documenti nello stato che NON abbia ancora generato movimenti continue; - //controllo se effettivamente esiste il movimento di magazzino - const TRectype& movmag = cache().get(LF_MOVMAG, doc.get_long(DOC_MOVMAG)); - if (movmag.empty()) + const long numreg = doc.get(DOC_MOVMAG).as_int(); + if (numreg <= 0) { - 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); + segnala_documento(doc, log, "Nessun movimento associato"); continue; } - //scorro tutte le righe documento - for (long i = 1; i <= doc.rows(); i++) + TMov_mag mov(numreg); + if (mov.get_int(MOVMAG_ANNOES) <= 0) { - const TRiga_documento& rdoc = doc[i]; - const TString80 codart = rdoc.get(RDOC_CODARTMAG); + msg.cut(0) << TR("Non esiste il movimento associato ") << numreg; + segnala_documento(doc, log, msg); + continue; + } - if (codart.full()) - { - TArticolo& art = rdoc.articolo(); + TToken_string key; + key.add(doc.get(DOC_CODNUM).as_string()); + key.add(doc.get(DOC_ANNO).as_int()); + key.add(doc.get(DOC_PROVV).as_string()); + key.add(doc.get(DOC_NDOC).as_int()); + TRecord_array rdoc(key, LF_RIGHEDOC); - //leggo se esiste già nel TAssoc_array - real *qta = (real*)qtardoc.objptr(codart); + TAssoc_array qtardoc; + for (int r = rdoc.last_row(); r > 0; r = rdoc.pred_row(r)) + { + const TRectype& row = rdoc.row(r); + const TString80 codart = row.get(RDOC_CODARTMAG); + const real qta = row.get(td.field_qta()); + if (codart.full() && !qta.is_zero()) + { + TArticolo art(codart); + real* q = (real*)qtardoc.objptr(codart); //se non esiste - if (qta == NULL) + if (q == NULL) { //per ora memorizzo zero - qta = new real; - qtardoc.add(codart,qta); + q = new real; + qtardoc.add(codart,q); } //aggiorno la quantità convertendola all'unità di misura di base - *qta += art.convert_to_um(rdoc.quantita(), NULL, rdoc.get(RDOC_UMQTA)); + *q += art.convert_to_um(qta, EMPTY_STRING, row.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()) + if (!qtardoc.empty()) { - 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) + TAssoc_array qtarmov; + const TRecord_array& rmov = mov.body(); + int i = 0; + for (i = rmov.last_row(); i > 0; i = rmov.pred_row(i)) { - 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; + const TRectype& rowi = rmov.row(i); + const TString& codart = rowi.get(RMOVMAG_CODART); + const real qta = rowi.get(RMOVMAG_QUANT); + if (codart.full() && !qta.is_zero()) + { + real* q = (real*)qtarmov.objptr(codart); + if (q == NULL) + qtarmov.add(codart, qta); + else + *q += qta; + } } - } - } //ciclo for che scorre i documenti - return corretto; + bool signalled = false; + FOR_EACH_ASSOC_OBJECT(qtardoc, h, codart, q) + { + const real& qd = *(const real*)q; + const real* qm = (const real*)qtarmov.objptr(codart); + if (qm == NULL || qd != *qm) + { + if (!signalled) + { + msg.cut(0) << TR("non corrisponde al mov. ") << numreg; + segnala_documento(doc, log, msg); + signalled = true; + } + msg.cut(0) << TR("Articolo ") << codart << TR(" quantità ") << qd << " <> " << (qm ? *qm : ZERO); + + if (qm == NULL) + { + const TDoc_key dk(mov); + TToken_string* movs = (TToken_string*)duplicati.objptr(dk); + if (movs != NULL) + { + FOR_EACH_TOKEN(*movs, tok) if (mov.get(MOVMAG_NUMREG) != tok) + { + const long nreg = atol(tok); + TMov_mag mov_doppio(nreg); + if (cerca_articolo(mov_doppio, codart)) + { + msg << TR(" ritrovato nel movimento ") << nreg; + break; + } + } + } + } + log.log(0, msg); + } + } + } + } } -//CREATE: metodo costruttore -bool TControllo_movdadoc_app::create() +void TCheckdoc_app::main_loop() { - _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(); + TCheckdoc_mask m; + while (m.run()==K_ENTER) + { + const int anno = m.get_int(F_ANNO); + TLog_report log; + TAssoc_array duplicati; + elabora_mov(anno, duplicati, log); + elabora_doc(anno, duplicati, log); + log.preview(); + } } int mg4400(int argc, char* argv[]) { - TControllo_movdadoc_app a; - a.run(argc,argv,TR("Controllo lista movimenti")); + TCheckdoc_app a; + a.run(argc, argv, TR("Controllo documenti/movimenti")); return 0; } diff --git a/mg/mg4400.h b/mg/mg4400.h index 1e037959c..cb0f870b6 100755 --- a/mg/mg4400.h +++ b/mg/mg4400.h @@ -1 +1 @@ -#define F_ANNOES 101 \ No newline at end of file +#define F_ANNO 201 \ No newline at end of file diff --git a/mg/mg4400.uml b/mg/mg4400.uml index f4a05ab29..066160934 100755 --- a/mg/mg4400.uml +++ b/mg/mg4400.uml @@ -1,27 +1,20 @@ -#include "mg4400.h" +#include "mg1300.h" -PAGE "Controllo lista movimenti" -1 -1 30 2 +PAGE "Controllo Documenti/Movimenti" -1 -1 40 3 -NUMBER F_ANNOES 4 +NUMBER F_ANNO 4 BEGIN - FLAGS "AZ" - PROMPT 2 1 "Codice esercizio " - USE ESC - INPUT CODTAB F_ANNOES - DISPLAY "Esercizio" CODTAB - DISPLAY "Dal@12" D0 - DISPLAY "Al@12" D1 - OUTPUT F_ANNOES CODTAB - ADD NONE + PROMPT 1 1 "Anno " CHECKTYPE REQUIRED + FLAGS "A" END ENDPAGE -TOOLBAR "" 0 0 0 2 - +TOOLBAR "topbar" 0 0 0 2 #include - ENDPAGE + ENDMASK +