Files correlati : lv2 Ricompilazione Demo : [ ] Commento : 2) Quando inserisco un buono di ritiro a mano, solo il buono di ritiro e non il buono di consegna data di consegna prevista me la deve proporre in automatico, la prima con data superiore alla data del buono di ritiro. Se ne inserisco una a mano di un giorno che non è in consegna (inserisco un martedi e il cliente passa il lunedi e il giovedi (file lvpasplan) quel giorno non è previsto nel giri cioè non ho inserito una consegna per quella data (file lvrconsplan)) mi dovrebbe dare una segnalazione di conferma tipo giorno di prevista consegna non corrispondente al cliente, confermi? Mi propone anche la data del buono di ritiro, ma deve propormi almeno il giorno dopo, difficile che conto lo sporco oggi per oggi 6) Come di avevo anticipato al telefono occorre un tabulato durante la generazione delle bolle di consegna Per elencare gli articoli SULLA BOLLA DI SPORCO e messi in bolla di consegna che non sono presenti in contratto Il tabulato dovrebbe fornire i seguenti dati Cliente,articolo quantità , numero e data bolla (Corretto il mesaggio del log) git-svn-id: svn://10.65.10.50/trunk@19202 c028cbd2-c16b-5b4b-a496-9718f37d4682
873 lines
30 KiB
C++
Executable File
873 lines
30 KiB
C++
Executable File
#include <automask.h>
|
||
#include <progind.h>
|
||
#include <reputils.h>
|
||
#include <reprint.h>
|
||
|
||
#include "lvlib.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_MASK ////
|
||
//////////////////////////////////////
|
||
|
||
//classe TGenera_documenti_mask
|
||
class TGenera_documenti_mask : public TAutomask
|
||
{
|
||
public:
|
||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
TGenera_documenti_mask (const char* name) : TAutomask(name) {}
|
||
};
|
||
|
||
//ON_FIELD_EVENT: questo metodo gestisce i vari eventi che si verificano sui campi della maschera
|
||
bool TGenera_documenti_mask::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_mask* _msk;
|
||
TAssoc_array _quantita;
|
||
TAssoc_array _quantita_ritirata;
|
||
TConfig* _configlv;
|
||
char _buono;
|
||
|
||
private:
|
||
//Metodi per la generazione dei documenti
|
||
bool crea_documento(const TISAM_recordset& plan, TLog_report& rep);
|
||
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 long codind, 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(const long codcli, const long codcont, const TString& codart, 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, 34, 0);
|
||
_msk = new TGenera_documenti_mask("lv2400a");
|
||
_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)
|
||
{
|
||
//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 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
|
||
|
||
//elimina eventuali documenti di consegna che sono ancora in stato iniziale
|
||
//...e riporta in stato iniziale i documenti di ritiro e di anticipo che concorrono
|
||
//...a calcolare le quantit<69> da riportare sulla bolla
|
||
|
||
/*TString_array docarr; //array che conterr<72> i riferimenti ai documenti da cancellare
|
||
elimina_bolle(codcli, codind, docarr);
|
||
cambia_stato('R', docarr);
|
||
cambia_stato('A', docarr);*/
|
||
|
||
//variabili che conterranno i parametri dei documenti che devo generare...
|
||
//...settati dalla funzione numerazione_ddt()
|
||
TString4 codnum;
|
||
TString4 tpdoc;
|
||
TString4 statoi;
|
||
TString4 statof;
|
||
|
||
//se non trovo quale documento generare, evito il resto dell'elaborazione
|
||
if (!numerazione_ddt(codnum, tpdoc, statoi, statof))
|
||
return NOERR;
|
||
|
||
|
||
//creo il documento corretto riempiendo i campi che gi<67> conosco
|
||
TDocumento doc('D',anno,codnum,0);
|
||
doc.put(DOC_TIPODOC, tpdoc);
|
||
doc.write();
|
||
|
||
//calcola tutte le quantit<69> riportate sui documenti di ritiro, sui documenti di anticipo e sulle bolle di consegna
|
||
//...eventualmente modificate a mano
|
||
int numerodoc = scansione_ritiri_anticipi(codcli, codind, 'R', doc);
|
||
//scansione_ritiri_anticipi(codcli, codind,'A', doc);
|
||
//scansione_consegne(codcli, codind, doc);
|
||
|
||
int err = 1;
|
||
if(numerodoc > 0)
|
||
{
|
||
//se non trovo quale documento generare, evito il resto dell'elaborazione
|
||
if (!numerazione_ddt(codnum, tpdoc, statoi, statof))
|
||
return NOERR;
|
||
|
||
doc.put(DOC_STATO, statoi);
|
||
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);
|
||
|
||
//per evitare che ci metta uno zero
|
||
if (codind > 0)
|
||
doc.put(DOC_CODINDSP, codind);
|
||
|
||
doc.put("DATAGEN", datagen);
|
||
doc.put("DATAPRCO", dtcons);
|
||
|
||
const long ndoc = doc.get_long(DOC_NDOC);
|
||
|
||
//preparo la chiave per la tabella righe contratti
|
||
TToken_string keyrcont;
|
||
keycont.add(codcli);
|
||
keycont.add(codcont);
|
||
|
||
FOR_EACH_ASSOC_OBJECT(_quantita,h,codart,obj)
|
||
{
|
||
crea_riga(codart, modpas, tplis, false, prinbo ,doc, rep);
|
||
|
||
/*const TDate dadata = rcont.get(LVRCONDV_INDTTMP).as_date();
|
||
const TDate adata = rcont.get(LVRCONDV_FIDTTMP).as_date();
|
||
if (dadata.ok() && dtcons >= dadata && dtcons <= adata)
|
||
crea_riga(rcont, modpas, true, doc);*/
|
||
}
|
||
|
||
if (doc.rows() > 0)
|
||
err = doc.rewrite();
|
||
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 = _configlv->get_int("Perarr");
|
||
|
||
//creo la nuova riga
|
||
TString4 tiporiga;
|
||
switch (_buono)
|
||
{
|
||
case 'P': tiporiga = "21"; break;
|
||
case 'C': tiporiga = "21"; break;
|
||
default: break;
|
||
}
|
||
|
||
TRiga_documento& rdoc = doc.new_row(tiporiga);
|
||
|
||
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
|
||
TToken_string keyrcont;
|
||
keyrcont.add(codcli);
|
||
keyrcont.add(codcont);
|
||
keyrcont.add(codart);
|
||
//instanzio una cache sulla tabella delle righe contratti
|
||
const TRectype& rcont = cache().get(LF_LVRCONDV,keyrcont);
|
||
|
||
//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);
|
||
const real& qta = *(real*)_quantita.objptr(codart);
|
||
const real& qta1 = *(real*)_quantita_ritirata.objptr(codart);
|
||
|
||
//instanzio una cache sulla tabella del magazzino
|
||
const TRectype& anamag = cache().get(LF_ANAMAG,codart);
|
||
//recupero i dati di interesse dall'anagrafica di magazzino
|
||
const real ppconf = anamag.get_real(ANAMAG_PPCONF);
|
||
|
||
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
|
||
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);
|
||
|
||
const TString4 causale = ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV");
|
||
rdoc.put(RDOC_CODAGG1, causale); //causale presa dalla configurazione
|
||
|
||
//aggiorno il conguaglio sulla riga del contratto
|
||
aggiorna_conguaglio(codcli, codcont, codart, 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_CODART,codart);
|
||
rdoc.put(RDOC_CODARTMAG,codart);
|
||
rdoc.put(RDOC_CHECKED,'X');
|
||
if (prinbo)
|
||
{
|
||
if (!tmp)
|
||
rdoc.put(RDOC_PREZZO, prezzo);
|
||
else //per adesso per questo ramo non ci passa mai, perch<63> non sappiamo come gestire le dotazioni temporanee
|
||
rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP));
|
||
rdoc.put(RDOC_SCONTO,rcont.get(LVRCONDV_SCONTPERC)); //sconto
|
||
}
|
||
|
||
//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) << " in quantit<69> " << quantita_arr
|
||
<< "non <20> prsente sul contratto del cliente " << codcli;
|
||
rep.log(1, str);
|
||
}
|
||
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
//// 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)
|
||
statoi = cache().get("%TIP",tpdoc,"S2").left(1);
|
||
statof = cache().get("%TIP",tpdoc,"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
|
||
{
|
||
TString16 tmp;
|
||
tmp << "NUM_RIT(" << cod << ")";
|
||
codnum = _configlv->get(tmp);
|
||
|
||
tmp.cut(0);
|
||
tmp << "TIPODOC_RIT(" << cod << ")";
|
||
tpdoc = _configlv->get(tmp);
|
||
//instanzio una cache sulla tabella tipi documento (cerco lo stato iniziale)
|
||
statoi = cache().get("%TIP",tpdoc,"S2").left(1);
|
||
statof = cache().get("%TIP",tpdoc,"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)
|
||
statoi = cache().get("%TIP",tpdoc,"S2").left(1);
|
||
statof = cache().get("%TIP",tpdoc,"S2").mid(1,1);
|
||
|
||
return codnum.full() && tpdoc.full();
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
//// Metodi per l'eliminazione dei documenti ////
|
||
//////////////////////////////////////////////////////////////
|
||
|
||
//CAMBIA_STATO: questa funzione cerca tutte le bolle di ritiro e anticipo relative a un certo cliente...
|
||
//in un certo intervallo di date, e gli cambia stato
|
||
void TGenera_documenti_app::cambia_stato(const char ritoant, const TString_array& docarr)
|
||
{
|
||
//per ogni paragrafo scritto in ditta.ini...
|
||
//recupero numerazione, tipo documento e stato tramite la funzione apposita
|
||
for (int i = 0; ; i++)
|
||
{
|
||
TString4 codnum;
|
||
TString4 tpdoc;
|
||
TString4 statoi;
|
||
TString4 statof;
|
||
bool err;
|
||
|
||
//distinguo se sto scandendo i documenti di ritiro o i documenti di anticipo
|
||
switch (ritoant)
|
||
{
|
||
case 'R':
|
||
err = numerazione_drit(i, codnum, tpdoc, statoi, statof);
|
||
break;
|
||
case 'A':
|
||
err = numerazione_dant(i, codnum, tpdoc, statoi, statof);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
//se non trovo la numerazione richiesta, interrompo il ciclo
|
||
if (!err)
|
||
break;
|
||
|
||
FOR_EACH_ARRAY_ROW(docarr, r, row);
|
||
{
|
||
TToken_string(row);
|
||
|
||
TString str;
|
||
str << "USE DOC\n"
|
||
<< "FROM PROVV=" << row.get(0) << " ANNO=" << row.get(1) << " CODNUM=" << row.get(2) << " NDOC=" << row.get(3) << "\n"
|
||
<< "TO PROVV=" << row.get(0) << " ANNO=" << row.get(1) << " CODNUM=" << row.get(2) << " NDOC=" << row.get(3);
|
||
TISAM_recordset docritiro (str);
|
||
|
||
if (!docritiro.empty())
|
||
{
|
||
TDocumento doc(docritiro.cursor()->curr()); //instanzio il documento
|
||
doc.put(DOC_STATO, statoi);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//ELIMINA_BOLLE: questa funzione cerca tutte le bolle di consegna relative a un certo cliente ancora...
|
||
//nello stato iniziale in un certo intervallo di date e le elimina
|
||
void TGenera_documenti_app::elimina_bolle(const long codcli, const long codind, TString_array& docarr)
|
||
{
|
||
//recupero dalla maschera i campi di interesse
|
||
const TDate adatabolla = _msk->get_date(F_DTCONS);
|
||
const long aanno = adatabolla.year();
|
||
|
||
TDate dadatabolla = adatabolla; dadatabolla.set_month(adatabolla.month() - 2);
|
||
const long daanno = dadatabolla.year();
|
||
|
||
|
||
//recupero numerazione, tipo documento e stato tramite la funzione apposita
|
||
TString4 codnum;
|
||
TString4 tpdoc;
|
||
TString4 statoi;
|
||
TString4 statof;
|
||
|
||
//se non trovo la numerazione richiesta, interrompo la funzione
|
||
if (!numerazione_ddt(codnum, tpdoc, statoi, statof))
|
||
return;
|
||
|
||
//instanzio un recordset che contiene tutti i documenti di interesse
|
||
TString query;
|
||
query << "USE DOC "
|
||
<< "SELECT (TIPOCF=\"C\")&&(CODCF=" << codcli
|
||
<< ")&&(TIPODOC=\"" << tpdoc << "\")&&(STATO=\"" << statoi <<"\")&&(DATADOC>=" << dadatabolla << ")\n"
|
||
<< "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n"
|
||
<< "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n";
|
||
|
||
TISAM_recordset bolle(query);
|
||
|
||
//per ogni documento che trovo, aggiorno la quantit<69> e gli cambio stato
|
||
for (bool ok = bolle.move_first(); ok; ok = bolle.move_next())
|
||
{
|
||
TDocumento doc(bolle.cursor()->curr()); //instanzio il documento
|
||
|
||
//salvo la chiave del documento che sto cancellando
|
||
TToken_string key;
|
||
key.add(doc.get(DOC_PROVV));
|
||
key.add(doc.get(DOC_ANNO));
|
||
key.add(doc.get(DOC_CODNUM));
|
||
key.add(doc.get(DOC_NDOC));
|
||
docarr.add(key);
|
||
|
||
doc.remove(); //stato di bloccato
|
||
}
|
||
return;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
//// 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 long codind, const char ritoant, const TDocumento& docgen)
|
||
{
|
||
//recupero dalla maschera i campi di interesse
|
||
const TDate adatabolla = _msk->get_date(F_DTCONS);
|
||
const long aanno = adatabolla.year();
|
||
|
||
TDate dadatabolla = adatabolla; dadatabolla.set_month(adatabolla.month() - 2);
|
||
const long daanno = dadatabolla.year();
|
||
|
||
TString4 codnum;
|
||
TString4 tpdoc;
|
||
TString4 statoi;
|
||
TString4 statof;
|
||
bool err;
|
||
//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;
|
||
}
|
||
|
||
//instanzio un recordset che contiene tutti i documenti di interesse
|
||
TString query;
|
||
query << "USE DOC "
|
||
<< "SELECT (TIPOCF=\"C\")&&(CODCF=" << codcli
|
||
<< ")&&(TIPODOC=\"" << tpdoc << "\")&&(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);
|
||
|
||
//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, preso dallo sheet
|
||
//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();
|
||
}
|
||
|
||
//SCANSIONE_CONSEGNE: questa funzione cerca tutte le bolle di consegna relative a un certo cliente ancora...
|
||
//nello stato iniziale in un certo intervallo di date
|
||
void TGenera_documenti_app::scansione_consegne(const long codcli, const long codind, const TDocumento& docgen)
|
||
{
|
||
//recupero dalla maschera i campi di interesse
|
||
const TDate adatabolla = _msk->get_date(F_DTCONS);
|
||
const long aanno = adatabolla.year();
|
||
|
||
TDate dadatabolla = adatabolla; dadatabolla.set_month(adatabolla.month() - 2);
|
||
const long daanno = dadatabolla.year();
|
||
|
||
//recupero numerazione, tipo documento e stato tramite la funzione apposita
|
||
TString4 codnum;
|
||
TString4 tpdoc;
|
||
TString4 statoi;
|
||
TString4 statof;
|
||
|
||
//se non trovo la numerazione richiesta, interrompo la funzione
|
||
if (!numerazione_ddt(codnum, tpdoc, statoi, statof))
|
||
return;
|
||
|
||
//instanzio un recordset che contiene tutti i documenti di interesse
|
||
TString query;
|
||
query << "USE DOC "
|
||
<< "SELECT (TIPOCF=\"C\")&&(CODCF=" << codcli
|
||
<< ")&&(TIPODOC=\"" << tpdoc << "\")&&(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);
|
||
|
||
//per ogni documento che trovo, aggiorno la quantit<69> e gli cambio stato
|
||
for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next())
|
||
{
|
||
TDocumento doc(docritiri.cursor()->curr()); //instanzio il documento
|
||
calcolo_quantita(doc,'B');
|
||
doc.put(DOC_STATO,statof); //stato di bloccato
|
||
//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));
|
||
}
|
||
return;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
//// 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;
|
||
case 'B':
|
||
{
|
||
const real qtagg3 = rdoc.get_real(RDOC_QTAGG3);
|
||
real modifica = qtardoc - qtagg3;
|
||
*qta -= art.convert_to_um(modifica, 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(const long codcli, const long codcont, const TString& codart, const real arr) const
|
||
{
|
||
TLocalisamfile rcondv(LF_LVRCONDV);
|
||
rcondv.put(LVRCONDV_CODCF,codcli);
|
||
rcondv.put(LVRCONDV_CODCONT,codcont);
|
||
rcondv.put(LVRCONDV_CODART,codart);
|
||
if (rcondv.read() == NOERR)
|
||
{
|
||
rcondv.put(LVRCONDV_QTACONG,arr);
|
||
rcondv.rewrite();
|
||
}
|
||
}
|
||
|
||
////////////////////////////////
|
||
//// Metodi Pubblic ////
|
||
////////////////////////////////
|
||
|
||
bool TGenera_documenti_app::transfer()
|
||
{
|
||
//leggo i campi dalla maschera
|
||
const TDate adatacons = _msk->get_date(F_DTCONS);
|
||
TDate dadatacons = adatacons;
|
||
dadatacons.set_month(adatacons.month() - 2);
|
||
const long coditi = _msk->get_long(F_CODITI);
|
||
long codcli = _msk->get_long(F_CODCF);
|
||
long codaut = _msk->get_long(F_CODAUT);
|
||
|
||
int daanno = dadatacons.year();
|
||
int aanno = adatacons.year();
|
||
|
||
TString4 codnum;
|
||
TString4 tpdoc;
|
||
TString4 statoi;
|
||
TString4 statof;
|
||
// bool err;
|
||
|
||
TLog_report rep("Articoli non in contratto");
|
||
rep.kill_duplicates();
|
||
|
||
numerazione_drit(0, codnum, tpdoc, statoi, statof);
|
||
|
||
//instanzio un recordset che contiene tutti i documenti di interesse
|
||
TString query_bolle = "USE DOC\nSELECT ";
|
||
|
||
if(codcli > 0)
|
||
query_bolle << "(TIPOCF=\"C\")&&(CODCF=" << codcli << ")&&";
|
||
|
||
query_bolle << "(TIPODOC=\"" << tpdoc << "\")&&(STATO=\"" << statoi << "\")&&";
|
||
query_bolle << "(BETWEEN(G1:DATAPRCO,#DADATA,#ADATA))\n";
|
||
query_bolle << "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n";
|
||
query_bolle << "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n";
|
||
|
||
TISAM_recordset docritiri(query_bolle);
|
||
docritiri.set_var("#DADATA", dadatacons);
|
||
docritiri.set_var("#ADATA", adatacons);
|
||
|
||
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;
|
||
|
||
codcli = docritiri.get(DOC_CODCF).as_int();
|
||
|
||
//preparo un recordset che contiene tutti planning per cui voglio creare i documenti relativi
|
||
TString query = "USE LVRCONSPLAN KEY 2";
|
||
|
||
if (coditi || codcli || codaut)
|
||
{
|
||
query << " SELECT ";
|
||
if (codcli > 0)
|
||
query << "(CODCF=" << codcli << ')';
|
||
if (coditi > 0)
|
||
{
|
||
if (codcli > 0)
|
||
query << "&&";
|
||
query << "(CODITI=" << coditi << ')';
|
||
}
|
||
if (codaut > 0)
|
||
{
|
||
if (codcli > 0 || coditi > 0)
|
||
query << "&&";
|
||
query << "(CODAUT=" << codaut << ')';
|
||
}
|
||
}
|
||
query << "\n";
|
||
if(_msk->get_int(F_TPGEN) == 1)
|
||
query << "FROM DTCONS=" << adatacons << "\n";
|
||
else
|
||
query << "FROM DTCONS=" << dadatacons << "\n";
|
||
query << "TO DTCONS=" << adatacons << "\n";
|
||
|
||
TISAM_recordset plan(query);
|
||
|
||
if (plan.move_to(1))
|
||
{
|
||
_quantita.destroy();
|
||
_quantita_ritirata.destroy();
|
||
crea_documento(plan, rep);
|
||
}
|
||
}
|
||
|
||
TReport_book buc;
|
||
buc.add(rep);
|
||
if (buc.pages() > 0)
|
||
buc.preview();
|
||
else
|
||
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;
|
||
}
|