campo-sirio/lv/lv2400.cpp
luca83 879ef7ba98 Patch level : 10.0 patch 413
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
2009-08-11 14:29:29 +00:00

873 lines
30 KiB
C++
Executable File
Raw Blame History

#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;
}