campo-sirio/lv/lv2400.cpp
luca83 85094049cc Patch level : 10.0 patch 529
Files correlati     : lv2
Ricompilazione Demo : [ ]
Commento            :
Corretto il numero di documenti generati (era sempre 0)


git-svn-id: svn://10.65.10.50/trunk@19673 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-11-27 08:45:41 +00:00

851 lines
29 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <automask.h>
#include <progind.h>
#include <reputils.h>
#include <reprint.h>
#include "lvlib.h"
#include "../mg/anamag.h"
#include "../mg/clifogiac.h"
#include "../ve/velib.h"
#include "../ve/rcondv.h"
#include "doc.h"
#include "lvcondv.h"
#include "lvrcondv.h"
#include "lvrconsplan.h"
#include "rdoc.h"
#include "lv2400a.h"
/////////////////////////////////////
//// TGENERA_DOCUMENTI_MSK ////
/////////////////////////////////////
//classe TGenera_documenti_msk
class TGenera_documenti_msk : public TAutomask
{
public:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
TGenera_documenti_msk (const char* name) : TAutomask(name) {}
};
//ON_FIELD_EVENT: questo metodo gestisce i vari eventi che si verificano sui campi della maschera
bool TGenera_documenti_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
return true;
}
//////////////////////////////////////
//// TGENERA_DOCUMENTI_APP ////
//////////////////////////////////////
//classe TGenera_documenti_app
class TGenera_documenti_app : public TSkeleton_application
{
TGenera_documenti_msk* _msk;
TAssoc_array _quantita;
TAssoc_array _quantita_ritirata;
TConfig* _configlv;
char _buono;
long _ndoc;
private:
//Metodi per la generazione dei documenti
bool crea_documento(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen);
void crea_riga(const TString& codart, const char modpas, const int tplis, const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep);
//Metodi per il recupero di codnum, tpdoc, stato
bool numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const;
bool numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const;
bool numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const;
//Metodi per l'eliminazione dei documenti
void cambia_stato(const char ritoant, const TString_array& docarr);
void elimina_bolle(const long codcli, const long codind, TString_array& docarr);
//Metodi per la scansione dei documenti
int scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen);
void scansione_consegne(const long codcli, const long codind, const TDocumento& docgen);
//Metodo per il calcolo delle quantit<69> in bolla
void calcolo_quantita(const TDocumento& doc, const char ritoant);
//Metodi aggiornare il conguaglio sui contratti
void aggiorna_conguaglio(TRectype& rcondv, const real arr) const;
protected:
virtual bool create();
virtual void on_config_change();
virtual bool destroy();
public:
bool transfer();
virtual void main_loop();
};
////////////////////////////////
//// Metodi Protected ////
////////////////////////////////
//CREATE: metodo costruttore
bool TGenera_documenti_app::create()
{
open_files(LF_DOC, LF_RIGHEDOC, 0);
_msk = new TGenera_documenti_msk("lv2400a");
_ndoc = 0;
_configlv = new TConfig(CONFIG_DITTA,"lv");
_buono = *TApplication::argv(2);
return TSkeleton_application::create();
}
//ON_CONFIG_CHANGE: metodo che aggiorna la variabile TConfig ogni volta
//che faccio un cambiamento al file fisico
void TGenera_documenti_app::on_config_change()
{
if (_configlv != NULL)
delete _configlv;
_configlv = new TConfig(CONFIG_DITTA,"lv");
}
//DESTROY: metodo distruttore
bool TGenera_documenti_app::destroy()
{
delete _configlv;
delete _msk;
return TApplication::destroy();
}
///////////////////////////////////////////////////////
//// Metodi per la generazione dei documenti ////
///////////////////////////////////////////////////////
//CREA_DOCUMENTO: metodo che crea un nuovo documento di trasporto dai dati salvati
bool TGenera_documenti_app::crea_documento(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen)
{
//recupero i dati di interesse dalla maschera
const TDate datagen(TODAY);
//per ogni planning recupero i dati di interesse dal planning
const long codcli = plan.get(LVRCONSPLAN_CODCF).as_int();
const long codcont = plan.get(LVRCONSPLAN_CODCONT).as_int();
const TDate dtcons = plan.get(LVRCONSPLAN_DTCONS).as_date(); //che <20> anche la data documento
const char modpas = plan.get(LVRCONSPLAN_MODPASS).as_string()[0];
const int coditi = plan.get(LVRCONSPLAN_CODITI).as_int();
const int anno = dtcons.year();
//preparo la chiave per la tabella contratti
TToken_string keycont;
keycont.add(codcli);
keycont.add(codcont);
//instanzio una cache sulla tabella dei contratti
const TRectype& tcont = cache().get(LF_LVCONDV,keycont);
//estraggo i dati di interesse dalla cache
const long codind = tcont.get_long(LVCONDV_CODINDSP); //codice dell'indirizzo di spedizione
const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino
//const bool prinbo = tcont.get_bool(LVCONDV_STPRZBOL); //prezzo in bolla
const bool prinbo = true; //sempre a true; verr<72> gestita a video in futuro (27/10/2009)
//variabili che conterranno i parametri dei documenti che devo generare...
//...settati dalla funzione numerazione_ddt()
TString4 codnum;
TString4 tpdoc;
TString4 statoi;
TString4 statof;
//Cerco il tipo documento da generaresul contratto; se non lo trovo lo cerco in configurazione.
//Se non trovo quale documento generare, evito il resto dell'elaborazione
if(tcont.get(LVCONDV_CODNUM).full() && _buono == 'C')
{
codnum = tcont.get(LVCONDV_CODNUM);
tpdoc = tcont.get(LVCONDV_TPDOC);
//instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale)
const TString& s2 = cache().get("%TIP",tpdoc,"S2");
statoi = s2.left(1);
statof = s2.mid(1,1);
}
else if (!numerazione_ddt(codnum, tpdoc, statoi, statof))
return NOERR;
if(_ndoc == 0)
{
TString query2;
query2 << "USE DOC\n"
<< "FROM PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\"\n"
<< "TO PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\"";
TISAM_recordset bolle(query2);
if (bolle.move_last())
_ndoc = bolle.get(DOC_NDOC).as_int();
}
//recupero il codpag
TToken_string key;
key.add('C');
key.add(codcli);
const TString4 codpag = cache().get(LF_CLIFO, key, CLI_CODPAG);
//reupero la cuasale di magazzino di testata
const TString16 causmag = cache().get("%TIP", tpdoc, "S9");
//creo il documento corretto riempiendo i campi che gi<67> conosco
TDocumento doc('D', anno, codnum, ++_ndoc);
doc.put(DOC_TIPODOC, tpdoc);
doc.put(DOC_DATADOC, dtcons);
doc.put(DOC_TIPOCF, 'C');
doc.put(DOC_CODCF, codcli);
doc.put(DOC_CODCONT, codcont);
doc.put(DOC_CODPAG, codpag);
doc.put(DOC_CAUSMAG, causmag);
doc.put("DATAGEN", datagen); //data generazione del documento
doc.put("DATAPRCO", dtcons); //data prevista consegna
doc.put("CODITI", coditi); //codice itinerario
//calcola tutte le quantit<69> riportate sui documenti di ritiro, sui documenti di anticipo
int numerodoc = scansione_ritiri_anticipi(codcli, dtcons, 'R', doc);
scansione_ritiri_anticipi(codcli, dtcons, 'A', doc);
int err = 1;
if(numerodoc > 0)
{
FOR_EACH_ASSOC_OBJECT(_quantita,h,codart,obj)
{
//preparo la chiave per la tabella righe contratti
TToken_string keyrcont;
keyrcont.add(codcli);
keyrcont.add(codcont);
keyrcont.add(codart);
const TRectype& rcont = cache().get(LF_LVRCONDV, keyrcont);
const TDate dadata = (TDate)rcont.get(LVRCONDV_INDTTMP);
const TDate adata = (TDate)rcont.get(LVRCONDV_FIDTTMP);
if (dadata.ok() && dtcons >= adata)
crea_riga(codart, modpas, tplis, true, prinbo, doc, rep);
else
crea_riga(codart, modpas, tplis, false, prinbo, doc, rep);
}
if (doc.rows() > 0)
{
err = doc.rewrite();
++numdocgen;
}
else
doc.remove();
//scrivo sul planning il riferimento alla bolla che lo accompagna
if (err == NOERR)
{
TLocalisamfile& f = plan.cursor()->file();
f.put(LVRCONSPLAN_ANNO, anno);
f.put(LVRCONSPLAN_CODNUM, codnum);
f.put(LVRCONSPLAN_NDOC, _ndoc);
f.rewrite();
}
}
return err == NOERR;
}
//CREA_RIGA: questa funzione crea una riga merce per una bolla di consegna
void TGenera_documenti_app::crea_riga(const TString& codart, const char modpas, const int tplis, const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep)
{
const int perarr = ini_get_int(CONFIG_DITTA, "lv", "Perarr");
//creo la nuova riga
TString4 tiporiga;
switch (_buono)
{
case 'P': tiporiga = "24"; break;
case 'C': tiporiga = "21"; break;
default: break;
}
const long codcli = doc.get_long(DOC_CODCF);
const long codcont = doc.get_long(DOC_CODCONT);
//calcolo della quantit<69> che va sulla bolla
//preparo la chiave per la tabella righe contratti
TLaundry_contract cont(codcli, codcont);
const TRectype& rcont = cont.row(codart);
//recupero i dati di interesse dalla riga del contratto
bool arrot;
if (rcont.get_int(LVRCONDV_CALCCONS) == 1)
arrot = true;
else
arrot = false;
const real conguaglio = rcont.get_real(LVRCONDV_QTACONG);
real& qta = *(real*)_quantita.objptr(codart);
const real& qta1 = *(real*)_quantita_ritirata.objptr(codart);
const real przdttmp = rcont.get_real(LVRCONDV_PRZDTTMP);
//instanzio una cache sulla tabella del magazzino
const TRectype& anamag = cache().get(LF_ANAMAG,codart);
//recupero i dati di interesse dall'anagrafica di magazzino, ma devo evitare divisioni per 0
const real ppconf = anamag.get_real(ANAMAG_PPCONF) != 0 ? anamag.get_real(ANAMAG_PPCONF) : 1;
const TString80 descrart = anamag.get(ANAMAG_DESCR);
//recupero i valori delle dotazione temporanea dal magazzino del cliente
TLocalisamfile magcli(LF_CLIFOGIAC);
magcli.put(CLIFOGIAC_ANNOES, doc.get_date(DOC_DATADOC).year());
magcli.put(CLIFOGIAC_TIPOCF, 'C');
magcli.put(CLIFOGIAC_CODCF, codcli);
magcli.put(CLIFOGIAC_INDSPED, 0); //in realt<6C> <20> da leggere dal contratto
magcli.put(CLIFOGIAC_CODART, codart);
magcli.put(CLIFOGIAC_NRIGA, 1);
//leggo il record corrispondente
magcli.read();
long dottmp = magcli.get_long(CLIFOGIAC_DOTTM);
long dotod = magcli.get_long(CLIFOGIAC_DOTOD);
//GESTIONE DOTAZIONE TEMPOARANEA
if (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && dottmp > 0)
{
TRiga_documento& rdoc = doc.new_row(tiporiga);
rdoc.put(RDOC_CODART,codart);
if (descrart.len() > 50)
{
rdoc.put(RDOC_DESCR, descrart.left(50));
rdoc.put(RDOC_DESCLUNGA, true);
rdoc.put(RDOC_DESCEST, descrart.sub(50));
}
else
rdoc.put(RDOC_DESCR, descrart);
rdoc.put(RDOC_CODARTMAG,codart);
rdoc.put(RDOC_CHECKED,'X');
if (prinbo)
rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); //prezzo
rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva
//se ho ritirato un quantitativo di roba maggiore o uguale alla dotazione temporanea
//allora creo la nuova riga documento e azzero la dottmp; altrimenti preparo la riga
//per la quantit<69> che ho ritirato e tengo traccia della cosa
if (qta >= dottmp)
{
qta -= dottmp;
rdoc.put(RDOC_QTAGG1, dottmp); //quantit<69> ritirata
rdoc.put(RDOC_GENERATA, true);
rdoc.put(RDOC_CODAGG1, ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT"));
dottmp = 0;
dotod -= dottmp;
TString str;
str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC)
<< " numero " << doc.get(DOC_NDOC) << " in dotazione <20> stato ritirato completamente.";
rep.log(1, str);
}
else
{
dottmp -= qta.integer();
dotod -= qta.integer();
rdoc.put(RDOC_QTAGG1, qta); //quantit<69> ritirata
rdoc.put(RDOC_GENERATA, true);
rdoc.put(RDOC_CODAGG1, ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT"));
TString str;
str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC)
<< " numero " << doc.get(DOC_NDOC) << " in dotazione temporanea non <20> stato ritirato completamente."
<< " Mancano " << dottmp << "unit<EFBFBD>";
rep.log(1, str);
qta = ZERO;
}
//scrivo il magazzino
TString8 magazzino;
TString8 magazzinoc;
magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN");
magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC");
rdoc.put(RDOC_CODMAG, magazzino);
rdoc.put(RDOC_CODMAGC, magazzinoc);
//recupero l'unit<69> di misura principale di quest'articolo
TToken_string key;
key.add(codart);
key.add(1);
const TRectype& umart = cache().get(LF_UMART, key);
TString4 um = umart.get(UMART_UM);
rdoc.put(RDOC_UMQTA, um);
}
if (qta > ZERO)
{
TRiga_documento& rdoc = doc.new_row(tiporiga);
const real quantita_noarr = qta - conguaglio;
real quantita_arr = quantita_noarr > ZERO ? quantita_noarr : ZERO;
//se devo arrotondare
if (quantita_arr > ZERO && arrot)
{
//calcolo di quanti pezzi sforo
long arr = quantita_arr.integer() % ppconf.integer();
//se sforo (arr > 0) allora calcolo quanti pezzi in pi<70> gli devo dare e aggiorno la quantit<69>
if (arr > 0)
if (arr > ppconf.integer() * perarr / 100) //arr <= ppconf*perarr/100 -> formula calcolo congualgio di Tassan
{
arr = ppconf.integer() - arr;
quantita_arr += arr;
}
else
quantita_arr -= arr;
}
//scrivo le quantit<69>
rdoc.put(RDOC_QTA, quantita_arr); //quantit<69> consegnata eventualmente arrotondata
//se no scrivo le quantit<69> sbalgiate
if (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP))
rdoc.put(RDOC_QTAGG1, qta); //quantit<69> ritirata
else
rdoc.put(RDOC_QTAGG1, qta1); //quantit<69> ritirata
rdoc.put(RDOC_QTAGG2, conguaglio); //conguaglio
rdoc.put(RDOC_QTAGG3, quantita_arr); //copia della quantit<69> consegnata
rdoc.put(RDOC_QTAGG4, quantita_noarr); //quantit<69> che avrei consegnato se non arrotondavo (qta ritirata)
rdoc.put(RDOC_GENERATA, true);
rdoc.put(RDOC_CODAGG1, ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV")); //causale presa dalla configurazione
//aggiorno il conguaglio sulla riga del contratto
if (!rcont.empty())
aggiorna_conguaglio((TRectype&)rcont, quantita_arr - quantita_noarr);
//elaborazione sul prezzo da utilizzare
real prezzo;
if (rcont.empty())
{
//PROPONI PREZZO
TToken_string key;
key.add('C');
key.add(codcli);
const TRectype& cfven = cache().get(LF_CFVEN, key);
bool trvlst = false;
if (!cfven.empty())
{
//se <20> settata la categoria merceologica, leggo sia il listino che la cat merc, altrimenti solo il listino
TString8 codlis = cfven.get(CFV_CODLIST);
TString8 catven;
TConfig* configve = new TConfig(CONFIG_DITTA,"ve");
const char gesliscv = configve->get_char("GESLISCV");
if (gesliscv != 'X')
catven = "";
else
catven = cfven.get(CFV_CATVEN);
//cerco il prezzo sul listino
key.cut(0);
key.add('L'); //tipo
key.add(catven); //catven
key.add(""); //tipocf
key.add(""); //codcf
key.add(codlis); //codlis
key.add('A'); //tiporiga
key.add(codart); //codriga
key.add(""); //um
key.add(""); //nscagl
const TRectype& rcondv = cache().get(LF_RCONDV, key);
if (!rcondv.empty())
{
prezzo = rcondv.get_real(RCONDV_PREZZO);
trvlst = true;
}
}
//se non ho trovato un listino, o se non c'<27> un listino impostato
//propongo come prezzo il valore convenzionale
if (!trvlst)
{
key.cut(0);
key.add(codart);
key.add(1);
const TRectype& umart = cache().get(LF_UMART, key);
prezzo = umart.get_real(UMART_PREZZO);
if (umart.get(UMART_PREZZO).full())
trvlst = true;
}
}
else
{
//elaborazione per il prezzo: o lo prendo dalle righe contratto, o dall'anagrafica magazzino
if (tplis == 0)
prezzo = rcont.get_real(LVRCONDV_PREZZO);
else
prezzo = anamag.get_real(ANAMAG_COSTSTD);
}
rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva
rdoc.put(RDOC_CODART,codart);
if (descrart.len() > 50)
{
rdoc.put(RDOC_DESCR, descrart.left(50));
rdoc.put(RDOC_DESCLUNGA, true);
rdoc.put(RDOC_DESCEST, descrart.sub(50));
}
else
rdoc.put(RDOC_DESCR, descrart);
rdoc.put(RDOC_CODARTMAG,codart);
rdoc.put(RDOC_CHECKED,'X');
if (prinbo)
{
if (!tmp)
rdoc.put(RDOC_PREZZO, prezzo);
else
rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP));
rdoc.put(RDOC_SCONTO,rcont.get(LVRCONDV_SCONTPERC)); //sconto
}
//recupero l'unit<69> di misura principale di quest'articolo
TToken_string key;
key.add(codart);
key.add(1);
const TRectype& umart = cache().get(LF_UMART, key);
TString4 um = umart.get(UMART_UM);
rdoc.put(RDOC_UMQTA, um);
//scrivo il magazzino
TString8 magazzino;
TString8 magazzinoc;
magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN");
magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC");
rdoc.put(RDOC_CODMAG, magazzino);
rdoc.put(RDOC_CODMAGC, magazzinoc);
//se il record di riga contratto <20> vuoto aggiorno il log
if (rcont.empty())
{
TString str;
str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC)
<< " numero " << doc.get(DOC_NDOC) << " per la quantit<69> di " << quantita_arr << " unit<69>"
<< " non <20> prsente sul contratto del cliente " << codcli;
rep.log(1, str);
}
}
if (dottmp == 0)
{
cont.update_row(codart, LVRCONDV_INDTTMP, NULLDATE);
cont.update_row(codart, LVRCONDV_FIDTTMP, NULLDATE);
}
}
//////////////////////////////////////////////////////////////
//// Metodi per il recupero di codnum, tpdoc, stato ////
//////////////////////////////////////////////////////////////
//NUMERAZIONE_DDT: questa funzione cerca quali sono i codnum e i tpdoc che devo generare
bool TGenera_documenti_app::numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const
{
//questo switc mi permette di generare con lo stesso programma sia i buoni di prelievo (P)
//che i buoni di consegna (C); la variabile globale _buono viene inizializzata con il valore
//passato come parametro al programma al momento della chiamata da men<65>
switch (_buono)
{
case 'P':
{
codnum = _configlv->get("NUM_PRE(0)");
tpdoc = _configlv->get("TIPODOC_PRE(0)");
}
break;
case 'C':
{
codnum = _configlv->get("NUM_GEN");
tpdoc = _configlv->get("TIPODOC_GEN");
}
break;
default: break;
}
//instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale)
const TString& s2 = cache().get("%TIP",tpdoc,"S2");
statoi = s2.left(1);
statof = s2.mid(1,1);
return codnum.full() && tpdoc.full();
}
//NUMERAZIONE_DRIT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di ritiro
bool TGenera_documenti_app::numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const
{
codnum = _configlv->get("NUM_RIT", NULL, cod);
tpdoc = _configlv->get("TIPODOC_RIT", NULL, cod);
codnum = _configlv->get("NUM_RIT", NULL, cod);
tpdoc = _configlv->get("TIPODOC_RIT", NULL, cod);
//instanzio una cache sulla tabella tipi documento (cerco lo stato iniziale)
const TString& s2 = cache().get("%TIP",tpdoc,"S2");
statoi = s2.left(1);
statof = s2.mid(1,1);
return codnum.full() && tpdoc.full();
}
//NUMERAZIONE_DANT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di anticipo
bool TGenera_documenti_app::numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const
{
codnum = _configlv->get("NUM_ANT", NULL, cod);
tpdoc = _configlv->get("TIPODOC_ANT", NULL, cod);
//instanzio una cache sulla tabella delle righe contratti (cerco lo stato iniziale)
const TString& s2 = cache().get("%TIP",tpdoc,"S2");
statoi = s2.left(1);
statof = s2.mid(1,1);
return codnum.full() && tpdoc.full();
}
//////////////////////////////////////////////////////////////
//// Metodi per la scansione dei documenti ////
//////////////////////////////////////////////////////////////
//SCANSIONE_RITIRI_ANTICIPI: questa funzione cerca tutte le bolle di ritiro relative a un certo cliente non ancora evase...
//e, dopo l'elaborazione, gli cambia stato
int TGenera_documenti_app::scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen)
{
const long aanno = data.year();
TDate dadata = data; dadata.addmonth(-1);
const long daanno = dadata.year();
TString4 codnum;
TString4 tpdoc;
TString4 statoi;
TString4 statof;
bool err = NOERR;
//distinguo se sto scandendo i documenti di ritiro o i documenti di anticipo
switch (ritoant)
{
case 'R':
err = numerazione_drit(0, codnum, tpdoc, statoi, statof);
break;
case 'A':
err = numerazione_dant(0, codnum, tpdoc, statoi, statof);
break;
default:
break;
}
if (!err)
return err;
//instanzio un recordset che contiene tutti i documenti di interesse
TString query;
query << "USE DOC "
<< "SELECT (TIPOCF=\"C\")&&(CODCF=" << codcli << ")&&"
<< "(ANSI(G1:DATAPRCO)<=#ADATA)&&"
<< "(STATO=\"" << statoi <<"\")\n"
<< "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n"
<< "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n";
//instanzio un recordset che contiene tutti i documenti di interesse
TISAM_recordset docritiri(query);
docritiri.set_var("#ADATA", data);
//per ogni documento che trovo, aggiorno la quantit<69>, e poi cambio stato al documento
for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next())
{
TDocumento doc(docritiri.cursor()->curr()); //instanzio il documento
calcolo_quantita(doc, ritoant);
doc.put(DOC_STATO,statof); //stato di elaborato
//salvo i riferimenti del documento che sto andando a generare
doc.put("PROVVDG", docgen.get(DOC_PROVV));
doc.put("ANNODG", docgen.get(DOC_ANNO));
doc.put("CODNUMDG", docgen.get(DOC_CODNUM));
doc.put("NDCODG", docgen.get(DOC_NDOC));
doc.rewrite();
}
return docritiri.items();
}
//////////////////////////////////////////////////////////////
//// Metodo per il calcolo delle quantit<69> in bolla ////
//////////////////////////////////////////////////////////////
//CALCOLO_QUANTITA: questa funzione scorre tutte le righe documento di una bolla di ritiro, riempiendo un...
//TAssoc_array con le quantit<69> ritirate per ogni articolo, sommando le diverse righe con lo stesso articolo...
//Questa funzione viene richiamata per ogni documento valido individuato dalla SCANSIONE_RITIRI
void TGenera_documenti_app::calcolo_quantita(const TDocumento& doc, const char ritoant)
{
//scorro le righe documento
for (long i = 1; i <= doc.rows(); i++)
{
//instanzio la riga corrente
const TRiga_documento& rdoc = doc[i];
//estraggo i dati di interesse
const TString80 codart = rdoc.get(RDOC_CODARTMAG);
const real qtardoc = rdoc.get_real(RDOC_QTAGG1);
//se <20> una riga che riguarda un articolo e se la quantit<69> su questa riga non <20> nulla, allora la elaboro
if (codart.full() && !qtardoc.is_zero())
{
TArticolo& art = rdoc.articolo();
//leggo se esiste gi<67> nel TAssoc_array
real *qta = (real*)_quantita.objptr(codart);
real *qta1 = (real*)_quantita_ritirata.objptr(codart);
//se non esiste
if (qta == NULL)
{
//per ora memorizzo zero
qta = new real;
_quantita.add(codart,qta);
}
if (qta1 == NULL)
{
//per ora memorizzo zero
qta1 = new real;
_quantita_ritirata.add(codart,qta1);
}
//aggiorno la quantit<69> convertendola all'unit<69> di misura di base, aggiungendola o sottraendola
//...se si tratta di un ritiro o di un anticipo rispettivamente; nel caso della scansione delle
//...bolle di consegna modificate a mano (caso 'B'), devo modificare la quantit<69> da consegnare
//...tenendo conto delle modifiche manuali
switch (ritoant)
{
case 'R':
*qta += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA));
*qta1 += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA));
break;
case 'A':
*qta -= art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA));
break;
default:
break;
}
}
}
return;
}
//////////////////////////////////////////////////////////////
//// Metodi aggiornare il conguaglio sui contratti ////
//////////////////////////////////////////////////////////////
//AGGIORNA_CONGUAGLIO: questa funzione aggiorna il parametro conguaglio sulla riga del contratto
void TGenera_documenti_app::aggiorna_conguaglio(TRectype& rcondv, const real arr) const
{
TLocalisamfile rcont(LF_LVRCONDV);
rcondv.put(LVRCONDV_QTACONG,arr);
rcondv.rewrite(rcont);
}
////////////////////////////////
//// Metodi Pubblic ////
////////////////////////////////
bool TGenera_documenti_app::transfer()
{
//leggo i dati dalla maschera
const TDate adata = _msk->get_date(F_DTCONS);
TDate dadata(TODAY);
if (_msk->get_int(F_TPGEN) == 1)
dadata = adata;
else
++dadata;
const int daanno = dadata.year();
const int aanno = adata.year();
const long coditi = _msk->get_long(F_CODITI);
const long codaut = _msk->get_long(F_CODAUT);
long codcli = _msk->get_long(F_CODCF);
TLog_report rep("Riepilogo associazioni");
rep.kill_duplicates(true);
//preparo un recordset che contiene tutti planning per cui voglio creare i documenti relativi
TString4 codnum;
TString4 tpdoc;
TString4 statoi;
TString4 statof;
numerazione_drit(0, codnum, tpdoc, statoi, statof);
int numdocgen = 0;
for (dadata; dadata <= adata; ++dadata)
{
//per ogni data cerco i documenti e per ogni documento cerco i dati del passaggio
TString query;
query << "USE DOC "
<< "SELECT (ANSI(G1:DATAPRCO)<=#ADATA)&&"
<< "(STATO=\"" << statoi <<"\")\n"
<< "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n"
<< "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n";
TISAM_recordset docritiri(query);
docritiri.set_var("#ADATA", adata);
TProgind pi(docritiri.items(), TR("Generazione documenti in corso..."), true, true);
for(bool ok = docritiri.move_first(); ok; ok = docritiri.move_next())
{
if (!pi.addstatus(1))
break;
if (_msk->field(F_CODCF).empty())
codcli = docritiri.get(DOC_CODCF).as_int();
//instanzio un recordset che contiene tutti i documenti di interesse
TString query = "USE LVRCONSPLAN KEY 2";
query << " SELECT (CODCF=" << codcli << ")";
if (coditi || codaut)
{
if (coditi > 0)
query << "&&(CODITI=" << coditi << ")";
if (codaut > 0)
query << "&&(CODAUT=" << codaut << ")";
}
query << "\nFROM DTCONS=#DADATA\n";
query << "TO DTCONS=#ADATA";
TISAM_recordset plan(query);
plan.set_var("#DADATA", dadata);
plan.set_var("#ADATA", dadata);
if (plan.move_first())
{
_quantita.destroy();
_quantita_ritirata.destroy();
crea_documento(plan, rep, numdocgen);
}
}
}
if (adata < TODAY && _msk->get_int(F_TPGEN) == 0)
warning_box(TR("Non <20> stato possibile generare documenti con data prevista consegna nel passato"));
else
{
TReport_book buc;
buc.add(rep);
if (buc.pages() > 0)
buc.preview();
else
{
TString str;
if (numdocgen > 1)
str << "Sono stati generati " << numdocgen << " buoni.";
else
str << "E' stato generato " << numdocgen << " buono.";
message_box(str);
message_box(TR("Generazione terminata"));
}
}
return true;
}
void TGenera_documenti_app::main_loop()
{
while (_msk->run() == K_ENTER)
transfer();
}
int lv2400(int argc, char* argv[])
{
TGenera_documenti_app app;
app.run(argc, argv, TR("Generazione documenti"));
return 0;
}