e85d90e7f7
Files correlati : lv2 Ricompilazione Demo : [ ] Commento : Ottimizzazioni minori ma eleganti git-svn-id: svn://10.65.10.50/trunk@19234 c028cbd2-c16b-5b4b-a496-9718f37d4682
944 lines
33 KiB
C++
Executable File
944 lines
33 KiB
C++
Executable File
#include <automask.h>
|
||
#include <progind.h>
|
||
#include <reputils.h>
|
||
#include <reprint.h>
|
||
|
||
#include "lvlib.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_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;
|
||
long _ndoc;
|
||
|
||
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(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_mask("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)
|
||
{
|
||
//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;
|
||
|
||
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);
|
||
bolle.move_last();
|
||
_ndoc = bolle.get(DOC_NDOC).as_int();
|
||
}
|
||
|
||
//creo il documento corretto riempiendo i campi che gi<67> conosco
|
||
TDocumento doc('D', anno, codnum, ++_ndoc);
|
||
doc.put(DOC_TIPODOC, tpdoc);
|
||
|
||
//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);
|
||
|
||
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();
|
||
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 = "21"; 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
|
||
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);
|
||
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);
|
||
|
||
//GESTIONE DOTAZIONE TEMPOARANEA
|
||
if (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP))
|
||
{
|
||
TRiga_documento& rdoc = doc.new_row(tiporiga);
|
||
rdoc.put(RDOC_CODART,codart);
|
||
rdoc.put(RDOC_CODARTMAG,codart);
|
||
rdoc.put(RDOC_CHECKED,'X');
|
||
|
||
if (prinbo)
|
||
rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); //prezzo
|
||
|
||
//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);
|
||
|
||
//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;
|
||
}
|
||
else
|
||
{
|
||
dottmp -= 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;
|
||
}
|
||
|
||
//riscrivo la dotazione temporanea aggiornata
|
||
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);
|
||
magcli.put(CLIFOGIAC_DOTTM, dottmp);
|
||
magcli.rewrite();
|
||
}
|
||
|
||
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
|
||
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_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) << " per la quantit<69> di " << quantita_arr << " unit<69>"
|
||
<< " 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)
|
||
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);
|
||
//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 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.addmonth(-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 << ")&&"
|
||
<< "(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", adatabolla);
|
||
|
||
//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(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 campi dalla maschera
|
||
const TDate adatacons = _msk->get_date(F_DTCONS);
|
||
TDate dadatacons = adatacons;
|
||
dadatacons.addmonth(-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(true);
|
||
|
||
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 << ")&&";
|
||
|
||
if(_msk->get_int(F_TPGEN) == 1)
|
||
query_bolle << "(ANSI(G1:DATAPRCO)=#ADATA)&&";
|
||
else
|
||
query_bolle << "(ANSI(G1:DATAPRCO)<=#ADATA)&&";
|
||
|
||
query_bolle << "(STATO=\"" << statoi << "\")\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("#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();
|
||
const TDate data = docritiri.get("G1:DATAPRCO").as_date();
|
||
|
||
//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";
|
||
|
||
query << "FROM DTCONS=#DATA\n";
|
||
query << "TO DTCONS=#DATA";
|
||
|
||
TISAM_recordset plan(query);
|
||
plan.set_var("#DATA", data);
|
||
|
||
if (plan.move_first())
|
||
{
|
||
_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;
|
||
}
|