campo-sirio/lv/lv2400.cpp
luca83 0b70cb0150 Patch level : 10.0 patch 64?
Files correlati     : lv2 lv3
Ricompilazione Demo : [ ]
Commento            :
1)  Quella di ritiro dotazione temporanea pero con la causale lavanderia 107 (la corrispettiva del 007 da generazione automatica). Avrebbe dovuto prendere la 88 dai dati societari

2) La quantità del reso è un di cui quindi mi aspetto:
    ritirato         35                                    causale 88
    ritirato         44        consegnato 10    causale 107

3) Ho fatto poi un buono di prelievo sempre per quel cliente e n0235 come articolo.
    100 di dotazione temporanea causale 66 data consegna 23-2
    il planning di marzo non c’è -> non mi propone la data di fine dotazione          temporanea ma solo quella di inizio (certo non c’è il planning)
    scrivo il il 10/3/2010 -> sul buono di prelievo si salva / sul contratto no
    creo il buono di consegna -> non c’è la data di fine dot.temp. ne sul buono di consegna ne sul contratto


git-svn-id: svn://10.65.10.50/trunk@20139 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-02-18 07:51:39 +00:00

1038 lines
36 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <automask.h>
#include <execp.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) {set(F_STAMPA, 'X');}
};
//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, TAssoc_array& documenti);
void crea_riga(TToken_string& chiave, 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, TAssoc_array& documenti)
{
//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 TString8 codaut = plan.get(LVRCONSPLAN_CODAUT).as_string().right(5);
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 generare sul 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 i dati di interesse dal cliente
TToken_string key;
key.add('C');
key.add(codcli);
const TRectype& clifo = cache().get(LF_CLIFO, key);
const TString4 codpag = clifo.get(CLI_CODPAG);
const long codabi = clifo.get_long(CLI_CODABI);
const long codcab = clifo.get_long(CLI_CODCAB);
const TString80 iban = clifo.get(CLI_IBAN);
//reupero la cuasale di magazzino di testata
const TString16 causmag = cache().get("%TIP", tpdoc, "S9");
//recupero i dati di interesse dal file CFVEN
const TRectype& cfven = cache().get(LF_CFVEN, key);
const long codabipr = cfven.get_long(CFV_CODABIPR);
const long codcabpr = cfven.get_long(CFV_CODCABPR);
const bool ragdoc = cfven.get_bool(CFV_RAGGDOC);
const int codindsp = cfven.get_int(CFV_CODINDSP);
const TString8 codag1 = cfven.get(CFV_CODAG1);
const TString4 codmez = cfven.get(CFV_CODSPMEZZO);
const TString4 codporto = cfven.get(CFV_CODPORTO);
const TString4 codnote1 = cfven.get(CFV_CODNOTESP1);
const TString4 codnote2 = cfven.get(CFV_CODNOTESP2);
const TString4 codnote = cfven.get(CFV_CODNOTE);
const TString8 codvet1 = cfven.get(CFV_CODVETT1);
const TString8 codvet2 = cfven.get(CFV_CODVETT2);
const TString8 codvet3 = cfven.get(CFV_CODVETT3);
const real speseinc = cfven.get_real(CFV_PERCSPINC);
const TString4 catven = cfven.get(CFV_CATVEN);
const bool addbolli = cfven.get_bool(CFV_ADDBOLLI);
const TString8 codlist = cfven.get(CFV_CODLIST);
const TString4 codzona = cfven.get(CFV_CODZONA);
//gestione sconto
TString sconto;
const char tpgest = ini_get_string(CONFIG_DITTA, "ve", "GESSCO")[0];
switch(tpgest)
{
case 'P': sconto = cfven.get(CFV_SCONTO); break; //Percentuale su anagrafica cliente
case 'T': sconto = cache().get("%SCC", cfven.get(CFV_CODSCC), "S1"); break; //Gestione tabella sconti
case 'A': //Gestione archivio sconti
{
TConfig ditta(CONFIG_DITTA, "ve");
TLocalisamfile sconti(LF_SCONTI);
sconti.put("TIPO", "I");
if(ditta.get_bool("SCOKEY", "ve", 1))
sconti.put("CODCAT", cfven.get(CFV_CATVEN));
TString16 cod;
if(ditta.get_bool("SCOKEY", "ve", 2))
cod.format("%-2s", (const char*)cfven.get(CFV_CODSCC));
else
cod = " ";
if(ditta.get_bool("SCOKEY", "ve", 3))
{
TString8 tmp;
tmp.format("%-2s", (const char*)cfven.get(CFV_CODZONA));
cod << tmp;
}
else
cod << " ";
if(ditta.get_bool("SCOKEY", "ve", 4))
cod << clifo.get(CLI_CODPAG);
sconti.put("CODART", cod);
if (sconti.read() == NOERR)
sconto = sconti.get("SCONTO");
}
case 'N': //sconto non gestito
default: break;
}
//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);
if(codindsp > 0)
doc.put(DOC_CODINDSP, codindsp);
doc.put(DOC_RAGGR, ragdoc);
doc.put(DOC_CODPAG, codpag);
doc.put(DOC_CODABIA, codabi);
doc.put(DOC_CODCABA, codcab);
doc.put(DOC_IBAN, iban);
doc.put(DOC_CODABIP, codabipr);
doc.put(DOC_CODCABP, codcabpr);
doc.put(DOC_CODAG, codaut);
doc.put(DOC_CODAGVIS, codag1);
doc.put(DOC_CODSPMEZZO, codmez);
doc.put(DOC_ZONA, codzona);
doc.put(DOC_CODPORTO, codporto);
doc.put(DOC_CODNOTESP1, codnote1);
doc.put(DOC_CODNOTESP2, codnote2);
doc.put(DOC_CODNOTE, codnote);
doc.put(DOC_CODVETT1, codvet1);
doc.put(DOC_CODVETT2, codvet2);
doc.put(DOC_CODVETT3, codvet3);
doc.put(DOC_CATVEN, catven);
doc.put(DOC_CODLIST, codlist);
doc.put(DOC_CAUSMAG, causmag);
doc.put(DOC_PERCSPINC, speseinc);
doc.put(DOC_ADDBOLLI, addbolli);
doc.put(DOC_SCONTOPERC, sconto);
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,key,obj)
{
TToken_string chiave(key);
const TString80 codart = chiave.get(0);
//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 = rcont.get_date(LVRCONDV_INDTTMP);
const TDate adata = rcont.get_date(LVRCONDV_FIDTTMP);
if (dadata.ok() && dtcons >= adata)
crea_riga(chiave, modpas, tplis, true, prinbo, doc, rep);
else
crea_riga(chiave, modpas, tplis, false, prinbo, doc, rep);
}
if (doc.rows() > 0)
{
TToken_string orderkey;
orderkey.add(RDOC_CODART);
doc.sort_rows(orderkey);
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();
//tengo traccia dei documenti che sto generando, per poterli stampare dopo
TDoc_key kdoc(doc.get_int(DOC_ANNO), doc.get(DOC_CODNUM), doc.get_int(DOC_NDOC));
if (!documenti.is_key(kdoc))
documenti.add(kdoc, kdoc);
}
}
return err == NOERR;
}
//CREA_RIGA: questa funzione crea una riga merce per una bolla di consegna
void TGenera_documenti_app::crea_riga(TToken_string& chiave, 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);
const TString80 codart = chiave.get(0);
const TString4 causale = chiave.get(1);
//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(chiave);
const real& qta1 = *(real*)_quantita_ritirata.objptr(chiave);
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();
real dottmp = magcli.get_real(CLIFOGIAC_DOTTM);
real dotod = magcli.get_real(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
const TCausale_lavanderie caudt(ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT"));
//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, caudt.caucol().empty() ? caudt.codice() : caudt.caucol());
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;
dotod -= qta;
rdoc.put(RDOC_QTAGG1, qta); //quantit<69> ritirata
rdoc.put(RDOC_GENERATA, true);
rdoc.put(RDOC_CODAGG1, caudt.caucol().empty() ? caudt.codice() : caudt.caucol());
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
TCausale_magazzino rit(caudt.causale_ritiro());
TCausale_magazzino con(caudt.causale_consegna());
TString8 magazzino;
TString8 magazzinoc;
if(rit.get("S10").full())
magazzino = con.get("S10").mid(0,5);
else
magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN");
if(con.get("S10").full())
magazzinoc = rit.get("S10").mid(0,5);
else
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);
//scrivo gli estremi della dotazione temporanea
rdoc.put("DADATATMP", rcont.get_date(LVRCONDV_INDTTMP));
rdoc.put("ADATATMP", rcont.get_date(LVRCONDV_FIDTTMP));
}
if (qta > ZERO)
{
TRiga_documento& rdoc = doc.new_row(tiporiga);
//causale da mettere sulle righe documento
const TCausale_lavanderie cau(causale);
const TString4 codcau = cau.caucol().empty() ? cau.codice() : cau.caucol();
rdoc.put(RDOC_CODAGG1, codcau);
if(cau.is_consegna())
{
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_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);
//aggiorno il conguaglio sulla riga del contratto
//altrimenti se il record di riga contratto <20> vuoto aggiorno il log
if (!rcont.empty())
aggiorna_conguaglio((TRectype&)rcont, quantita_arr - quantita_noarr);
else
{
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);
}
}
//essendo la dot tmp un di cui la quantit<69> ritirata <20> sempre quella
if(cau.is_ritiro())
rdoc.put(RDOC_QTAGG1, qta1); //quantit<69> ritirata
//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
TCausale_magazzino rit(cau.causale_ritiro());
TCausale_magazzino con(cau.causale_consegna());
TString8 magazzino;
TString8 magazzinoc;
if(rit.get("S10").full())
magazzino = rit.get("S10").mid(0,5);
else
magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN");
if(con.get("S10").full())
magazzinoc = con.get("S10").mid(0,5);
else
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);
}
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 TString4 codcau = rdoc.get(RDOC_CODAGG1);
TToken_string key; key.add(codart); key.add(codcau);
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(key);
real *qta1 = (real*)_quantita_ritirata.objptr(key);
//se non esiste
if (qta == NULL)
{
//per ora memorizzo zero
qta = new real;
_quantita.add(key,qta);
}
if (qta1 == NULL)
{
//per ora memorizzo zero
qta1 = new real;
_quantita_ritirata.add(key,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;
TAssoc_array documenti;
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, documenti);
}
}
}
if (_msk->get_bool(F_STAMPA) && documenti.items() > 0)
{
TFilename tmp;
tmp.temp("", "ini");
// Ensure that the ofstream is well closed before ve1 call
if (tmp.full()) // dummy test
{
TDoc_key kd(documenti.get_hashobj()->key());
TString16 chiavedoc; // Parte della chiave comune a tutti i documenti
chiavedoc << kd.provv() << '|' << kd.anno() << '|' << kd.codnum() << '|';
ofstream outf(tmp);
outf << "[Transaction]" << endl; // Transaction header
outf << "Action=S" << endl; // 'S'tampa o 'A'nteprima
outf << "Mode=D" << endl; // Definitive (always?)
outf << "NoPrintDlg=X" << endl; // Dont' prompt the user with the print dialog
outf << endl;
outf << "[33]" << endl; // Transaction body
long nx = 0; // Document counter
FOR_EACH_ASSOC_OBJECT(documenti, obj, r, riga)
{
TDoc_key& kdoc = *(TDoc_key*)riga;
outf << "Doc(" << (nx++) << ")=";
outf << chiavedoc << kdoc.ndoc() << endl;
}
}
if (tmp.exist())
{
TString cmdline; cmdline << "ve1 -2 -i" << tmp;
TExternal_app app(cmdline);
app.run();
tmp.fremove();
}
}
if (documenti.items() == 0)
warning_box(TR("Non <20> stato possibile generare nessun documento; probabilmente i documenti richiesti esistono gi<67>"));
else
{
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;
}