1351 lines
47 KiB
C++
Executable File
1351 lines
47 KiB
C++
Executable File
#include <applicat.h>
|
|
#include <automask.h>
|
|
#include <config.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) {}
|
|
};
|
|
|
|
//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)
|
|
{
|
|
switch (o.dlg())
|
|
{
|
|
case F_DTDOC:
|
|
if (e == fe_modify)
|
|
{
|
|
const TDate oggi(TODAY);
|
|
if (get_date(F_DTDOC) <= oggi)
|
|
{
|
|
warning_box(TR("Attenzione: la data documento non può essere nel passato"));
|
|
o.reset();
|
|
}
|
|
}
|
|
break;
|
|
default: break;
|
|
}
|
|
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;
|
|
bool _has_gui;
|
|
|
|
private:
|
|
//Metodi per la generazione dei documenti
|
|
bool crea_documento_ritiro(const TISAM_recordset& ritiro, TLog_report& rep, int& numdocgen, TAssoc_array& documenti);
|
|
bool crea_documento_plan(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à 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_RITIRO: metodo che crea un nuovo documento di trasporto dai dati salvati
|
|
bool TGenera_documenti_app::crea_documento_ritiro(const TISAM_recordset& ritiro, 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 = ritiro.get(DOC_CODCF).as_int();
|
|
const long codcont = ritiro.get(DOC_CODCONT).as_int();
|
|
const TDate dtcons = ritiro.get("G1:DATAPRCO").as_date(); //che è anche la data documento
|
|
const int coditi = int(ritiro.get("CODITI").as_int());
|
|
TString8 codaut = ritiro.get(DOC_CODAG).as_string().right(5); codaut.trim();
|
|
const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons;
|
|
const int anno = datadoc.year();
|
|
const long ag_selected = _msk->get_long(F_CODAUT);
|
|
|
|
if (ag_selected > 0L && atol(codaut) != ag_selected)
|
|
return true;
|
|
|
|
//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à 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, tpdoc, statoi, 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;
|
|
|
|
//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 TString8 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);
|
|
|
|
if(codaut.empty())
|
|
codaut = cfven.get(CFV_CODAG);
|
|
|
|
//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");
|
|
}
|
|
break;
|
|
case 'N': //sconto non gestito
|
|
default: break;
|
|
}
|
|
|
|
//creo il documento corretto riempiendo i campi che già conosco
|
|
TDocumento doc('D', anno, codnum, 0L);
|
|
doc.put(DOC_TIPODOC, tpdoc);
|
|
doc.put(DOC_DATADOC, datadoc);
|
|
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(DOC_DATAPART, TDate(TODAY));
|
|
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à riportate sui documenti di ritiro, sui documenti di anticipo
|
|
const 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 TCodice_articolo 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, ' ', tplis, true, prinbo, doc, rep);
|
|
else
|
|
crea_riga(chiave, ' ', tplis, false, prinbo, doc, rep);
|
|
}
|
|
|
|
if (doc.rows() > 0)
|
|
{
|
|
TToken_string orderkey;
|
|
orderkey.add(RDOC_CODART);
|
|
doc.sort_rows(orderkey);
|
|
while (err = doc.write() == _isreinsert)
|
|
{
|
|
const long old_ndoc = doc.get_long(DOC_NDOC);
|
|
doc.renum_ndoc();
|
|
const long new_ndoc = doc.get_long(DOC_NDOC);
|
|
if (_has_gui)
|
|
lv_popup_msg("Attenzione documento numero %ld rinumerato in %ld", old_ndoc, new_ndoc);
|
|
}
|
|
++numdocgen;
|
|
}
|
|
else
|
|
doc.remove();
|
|
|
|
//scrivo sul planning il riferimento alla bolla che lo accompagna
|
|
if (err == NOERR)
|
|
{
|
|
//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_DOCUMENTO_PLAN: metodo che crea un nuovo documento di trasporto dai dati salvati
|
|
bool TGenera_documenti_app::crea_documento_plan(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 è anche la data documento
|
|
const char modpas = plan.get(LVRCONSPLAN_MODPASS).as_string()[0];
|
|
const int coditi = plan.get(LVRCONSPLAN_CODITI).as_int();
|
|
TString8 codaut = plan.get(LVRCONSPLAN_CODAUT).as_string().right(5); codaut.trim();
|
|
const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons;
|
|
const int anno = datadoc.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à 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, tpdoc, statoi, 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 TString8 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);
|
|
|
|
if(codaut.empty())
|
|
codaut = cfven.get(CFV_CODAG);
|
|
|
|
//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");
|
|
}
|
|
break;
|
|
case 'N': //sconto non gestito
|
|
default : break;
|
|
}
|
|
|
|
//creo il documento corretto riempiendo i campi che già conosco
|
|
TDocumento doc('D', anno, codnum, ++_ndoc);
|
|
doc.put(DOC_TIPODOC, tpdoc);
|
|
if(_msk->get_bool(F_DTEMIS))
|
|
doc.put(DOC_DATADOC, _msk->get_date(F_DTDOC));
|
|
else
|
|
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à 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)
|
|
{
|
|
//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 TCodice_articolo codart = chiave.get(0);
|
|
const TString4 causale = chiave.get(1);
|
|
|
|
//calcolo della quantità che va sulla bolla
|
|
|
|
//preparo la chiave per la tabella righe contratti
|
|
TLaundry_contract cont(codcli, codcont);
|
|
const TRectype& rcont = cont.row(codart);
|
|
const bool artbloc = rcont.get_int(LVRCONDV_ARTBLOC) > 0;
|
|
|
|
if (artbloc)
|
|
return;
|
|
|
|
//recupero i dati di interesse dalla riga del contratto
|
|
const bool arrot = rcont.get_int(LVRCONDV_CALCCONS) == 1;
|
|
|
|
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 long ppconf = anamag.get_real(ANAMAG_PPCONF) != 0 ? anamag.get_int(ANAMAG_PPCONF) : 1;
|
|
TString descrart;
|
|
descrart << anamag.get(ANAMAG_DESCR) << anamag.get(ANAMAG_DESCRAGG);
|
|
|
|
//recupero i valori delle dotazione temporanea dal magazzino del cliente
|
|
TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcli, 0);
|
|
//fisso l'anno esercizio
|
|
TEsercizi_contabili& esc = esercizi();
|
|
const int last_esc = esc.last();
|
|
|
|
//estraggo il record corrispondente su LF_CLIFOGIAC
|
|
const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc);
|
|
|
|
real dotod = reclav.get_real(CLIFOGIAC_DOTOD);
|
|
real dottmp = reclav.get_real(CLIFOGIAC_DOTTM);
|
|
|
|
//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à che ho ritirato e tengo traccia della cosa
|
|
if (qta >= dottmp)
|
|
{
|
|
qta -= dottmp;
|
|
rdoc.put(RDOC_QTAGG1, dottmp); //quantità 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 è stato ritirato completamente.";
|
|
rep.log(1, str);
|
|
}
|
|
else
|
|
{
|
|
dottmp -= qta;
|
|
dotod -= qta;
|
|
rdoc.put(RDOC_QTAGG1, qta); //quantità 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 è stato ritirato completamente."
|
|
<< " Mancano " << dottmp << "unità";
|
|
rep.log(1, str);
|
|
qta = ZERO;
|
|
}
|
|
|
|
//scrivo il magazzino
|
|
|
|
const TCausale_magazzino rit(caudt.causale_ritiro());
|
|
const TCausale_magazzino con(caudt.causale_consegna());
|
|
TString8 magazzino, 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);
|
|
|
|
//recupero l'unità 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));
|
|
rdoc.dirty_fields();
|
|
}
|
|
|
|
if (qta > ZERO || (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && 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;
|
|
//se sforo (arr > 0) allora calcolo quanti pezzi in più gli devo dare e aggiorno la quantità
|
|
if (arr > 0)
|
|
{
|
|
const int perarr = ini_get_int(CONFIG_DITTA, "lv", "Perarr");
|
|
if (arr > ppconf * perarr / 100) //arr <= ppconf*perarr/100 -> formula calcolo conguaglio di Tassan
|
|
{
|
|
arr = ppconf - arr;
|
|
quantita_arr += arr;
|
|
}
|
|
else
|
|
quantita_arr -= arr;
|
|
}
|
|
}
|
|
|
|
//scrivo le quantità
|
|
rdoc.put(RDOC_QTA, quantita_arr); //quantità consegnata eventualmente arrotondata
|
|
rdoc.put(RDOC_QTAGG2, conguaglio); //conguaglio
|
|
rdoc.put(RDOC_QTAGG3, quantita_arr); //copia della quantità consegnata
|
|
rdoc.put(RDOC_QTAGG4, quantita_noarr); //quantità 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 è 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à di " << quantita_arr << " unità"
|
|
<< " non è presente sul contratto del cliente " << codcli;
|
|
rep.log(1, str);
|
|
}
|
|
}
|
|
|
|
//essendo la dot tmp un di cui la quantità ritirata è sempre quella
|
|
if (cau.is_ritiro())
|
|
rdoc.put(RDOC_QTAGG1, qta1); //quantità 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 è 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'è 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à 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
|
|
const TCausale_magazzino rit(cau.causale_ritiro());
|
|
const 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);
|
|
rdoc.dirty_fields();
|
|
}
|
|
|
|
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ù
|
|
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 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\")&&(BETWEEN(CODCF," << codcli << ',' << codcli << "))&&"
|
|
<< "(ANSI(G1:DATAPRCO)<=#ADATA)&&"
|
|
<< "(CODNUM=\"" << codnum << "\")&&(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);
|
|
docritiri.set_var("#ADATA", data);
|
|
|
|
//per ogni documento che trovo, aggiorno la quantità, 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à in bolla ////
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
//CALCOLO_QUANTITA: questa funzione scorre tutte le righe documento di una bolla di ritiro, riempiendo un...
|
|
//TAssoc_array con le quantità 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_EACH_PHYSICAL_RDOC(doc, i, prdoc)
|
|
{
|
|
//instanzio la riga corrente
|
|
const TRiga_documento& rdoc = *prdoc;
|
|
//estraggo i dati di interesse
|
|
const TCodice_articolo 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 è una riga che riguarda un articolo e se la quantità su questa riga non è nulla, allora la elaboro
|
|
if (codart.full() && !qtardoc.is_zero())
|
|
{
|
|
TArticolo& art = rdoc.articolo();
|
|
//leggo se esiste già 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à convertendola all'unità 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à 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() - 1;
|
|
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(TR("Riepilogo associazioni"));
|
|
rep.kill_duplicates(true);
|
|
|
|
//preparo un recordset che contiene tutti planning per cui voglio creare i documenti relativi
|
|
TString4 codnum, tpdoc, statoi, statof;
|
|
numerazione_drit(0, codnum, tpdoc, statoi, statof);
|
|
|
|
int numdocgen = 0;
|
|
|
|
TAssoc_array documenti;
|
|
|
|
if (_msk->get_bool(F_NOTPLAN))
|
|
{
|
|
if (_msk->get_int(F_TPGEN) != 1)
|
|
dadata.addmonth(-1);
|
|
//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)&&"
|
|
<< "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&"
|
|
<< "(STATO=\"" << statoi <<"\")&&";
|
|
query << "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\n"
|
|
<< "FROM PROVV=\"D\" ANNO=" << dadata.year() << " CODNUM=\"" << codnum << "\"\n"
|
|
<< "TO PROVV=\"D\" ANNO=" << adata.year() << " CODNUM=\"" << codnum << "\"\n";
|
|
|
|
TISAM_recordset docritiri(query);
|
|
docritiri.set_var("#ADATA", adata);
|
|
docritiri.set_var("#CODCF", codcli);
|
|
|
|
TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso..."));
|
|
|
|
for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next())
|
|
{
|
|
_quantita.destroy();
|
|
_quantita_ritirata.destroy();
|
|
crea_documento_ritiro(docritiri, rep, numdocgen, documenti);
|
|
if (!pi.add_status())
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//TDate d(adata); d.addmonth(-1);
|
|
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)&&"
|
|
<< "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&"
|
|
<< "(STATO=\"" << statoi <<"\")&&"
|
|
<< "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\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);
|
|
docritiri.set_var("#CODCF", codcli);
|
|
|
|
TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso..."));
|
|
|
|
for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next())
|
|
{
|
|
if (!pi.add_status())
|
|
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";
|
|
query << "\nTO DTCONS=#ADATA";
|
|
|
|
TISAM_recordset plan(query);
|
|
plan.set_var("#DADATA", dadata);
|
|
if (_msk->get_int(F_TPGEN) == 0)
|
|
plan.set_var("#ADATA", adata);
|
|
else
|
|
plan.set_var("#ADATA", dadata);
|
|
|
|
if (plan.move_first())
|
|
{
|
|
_quantita.destroy();
|
|
_quantita_ritirata.destroy();
|
|
crea_documento_plan(plan, rep, numdocgen, documenti);
|
|
}
|
|
codcli = _msk->get_long(F_CODCF);
|
|
}
|
|
}
|
|
}
|
|
|
|
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; // Don't 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)
|
|
{
|
|
const 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();
|
|
}
|
|
/* Il 6-11-2015 ci siamo accorti che lv1 -3 non esiste (e nella 10.0 non lo chiamava nemmeno)
|
|
{
|
|
TString cmdline; cmdline << "lv1 -3 -i" << tmp;
|
|
TExternal_app app(cmdline);
|
|
app.run();
|
|
}
|
|
*/
|
|
tmp.fremove();
|
|
}
|
|
}
|
|
|
|
if (_has_gui)
|
|
{
|
|
if (documenti.items() == 0)
|
|
lv_popup_msg(TR("Non è stato possibile generare alcun documento:\nprobabilmente i documenti richiesti esistono già."));
|
|
else
|
|
{
|
|
if (adata < TDate(TODAY) && _msk->get_int(F_TPGEN) == 0)
|
|
lv_popup_msg(TR("Non è 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 << TR("Sono stati generati ") << numdocgen << TR(" buoni.");
|
|
else
|
|
str << TR("E' stato generato un buono.");
|
|
lv_popup_msg(str);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void TGenera_documenti_app::main_loop()
|
|
{
|
|
_has_gui = !(argc() >= 4 && xvt_str_same(argv(3), "-A"));
|
|
_msk->set(F_STAMPA, true);
|
|
_msk->set(F_NOTPLAN, true);
|
|
if (_has_gui)
|
|
{
|
|
while (_msk->run() == K_ENTER)
|
|
{
|
|
transfer();
|
|
_msk->set(F_NOTPLAN, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_msk->set(F_DTCONS, TDate(TODAY));
|
|
_msk->send_key(K_SPACE, DLG_OK);
|
|
if (_msk->run() == K_ENTER)
|
|
transfer();
|
|
}
|
|
}
|
|
|
|
int lv2400(int argc, char* argv[])
|
|
{
|
|
TGenera_documenti_app app;
|
|
app.run(argc, argv, TR("Generazione documenti"));
|
|
return 0;
|
|
}
|