Patch level : 10.0
Files correlati : mg4.exe Ricompilazione Demo : [ ] Commento : Corretto ed ottimizzato programma controllo coerenza tra documenti e movimenti git-svn-id: svn://10.65.10.50/branches/R_10_00@22495 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
62fcca5419
commit
4a583a7566
@ -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;
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include <xvt.h>
|
||||
#include <strings.h>
|
||||
//
|
||||
|
||||
// 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 ;
|
||||
|
396
mg/mg4400.cpp
396
mg/mg4400.cpp
@ -1,249 +1,251 @@
|
||||
#include <applicat.h>
|
||||
#include <automask.h>
|
||||
#include <mask.h>
|
||||
#include <progind.h>
|
||||
#include <recset.h>
|
||||
#include <reprint.h>
|
||||
#include <reputils.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
#define F_ANNOES 101
|
||||
#define F_ANNO 201
|
@ -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 <elabar.h>
|
||||
|
||||
ENDPAGE
|
||||
|
||||
|
||||
ENDMASK
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user