campo-sirio/lv/lv2500.cpp
alex b9a6166637 Patch level : 10.0 742
Files correlati     : lv2.exe
Ricompilazione Demo : [ ]
Commento

Se richiedo i riferimenti in testata ora viene aggiunto il contenuto del campo note della prima bolla del mese se compilato
Modificato il calcolo del valore convenzionale per articolo nella fatturazione, ora fa una sola riga di conguaglio per tutti gli articoli che hanno questo forfait


git-svn-id: svn://10.65.10.50/trunk@20452 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-05-14 13:56:19 +00:00

2072 lines
72 KiB
C++
Executable File
Raw Blame History

#include <progind.h>
#include <config.h>
#include <dongle.h>
#include <modaut.h>
#include <utility.h>
#include "lvlib.h"
#include "lv2500a.h"
#include "../pr/agenti.h"
#include "../pr/percprov.h"
#include "clifo.h"
#include "cfven.h"
#include "lvcondv.h"
#include "lvrcondv.h"
#include "doc.h"
#include "rdoc.h"
#include "../db/dblib.h"
#include "../mg/mglib.h"
#include "../ve/ve6200.h"
#include "../ve/ve6200a.h"
class TFatturazione_lavanderie;
////////////////////////////////////////
//// classe TFatturazione_msk ////
////////////////////////////////////////
class TFatturazione_msk: public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o,TField_event e,long jolly){return true;}
public:
TFatturazione_msk();
};
////////////////////////////////////////
//// TFatturazione_lavanderie app ////
////////////////////////////////////////
//Classe TFatturazione_lavanderie_app
class TFatturazione_lav_app: public TSkeleton_application
{
TFatturazione_msk* _msk;
protected:
virtual void main_loop();
void genera_bolle_nolo(TAssoc_array& cliela, TFatturazione_lavanderie& elab, int& numdocgen);
bool controlli_preliminari();
};
TFatturazione_lav_app & app() { return (TFatturazione_lav_app &) main_app();}
////////////////////////////////////////
//// TCalc_02_data ////
////////////////////////////////////////
//Classe TCalc_02_data
class TCalc_02_data : public TObject
{
TString _key;
TGeneric_distrib _distr;
TGeneric_distrib _distr_rit;
TAssoc_array _bol_rows;
virtual TObject* dup() const;
void copy(const TCalc_02_data & d);
public:
TCalc_02_data & operator = (const TCalc_02_data & d) { copy(d); return *this; }
const TString & key() const { return _key; }
TGeneric_distrib & distr() { return _distr; }
TGeneric_distrib & distr_rit() { return _distr_rit; }
TAssoc_array & bol_rows() { return _bol_rows; }
TCalc_02_data(const char * key) : _key(key) {}
TCalc_02_data(const TCalc_02_data & d) {copy(d);}
};
void TCalc_02_data::copy(const TCalc_02_data & d)
{
_key = d._key;
_distr = d._distr;
_bol_rows = d._bol_rows;
}
TObject* TCalc_02_data::dup() const
{
TCalc_02_data* o = new TCalc_02_data(*this);
return o;
}
////////////////////////////////////////
//// TFatturazione_lavanderie ////
////////////////////////////////////////
//Classe TFatturazione_lavanderie
class TFatturazione_lavanderie:public TFatturazione_bolle
{
TDate _data_elab;
TToken_string _campi_raggruppamento;
TAssoc_array _output_rows_02;
TAssoc_array _doc_grouped;
bool _prova;
protected:
virtual void add_rows(TRiga_documento & rout, TRiga_documento & rin);
virtual void create_row(TDocumento& doc_out, const TRiga_documento & rin);
virtual void pre_process_input(TLista_documenti& doc_in);
virtual void post_process_input(TLista_documenti& doc_in) {}
virtual void post_process(TLista_documenti& doc_out, TLista_documenti& doc_in);
virtual bool da_raggruppare(const TRiga_documento & rin);
virtual bool doc_raggruppabili(const TDocumento& doc_in, const TDocumento& doc_out, TToken_string& campi) const ;
virtual bool doc_raggruppabile(const TDocumento & doc) const { return true; }
virtual void campi_raggruppamento_righe(TToken_string& campi_riga) const;
virtual bool gestione_riferimenti() const { return true; }
virtual bool riferimenti_in_testa() const { return true; }
virtual TRiga_documento& find_or_create_row(TDocumento& doc_out, const TRiga_documento & rin,const char lavtype);
void aggiorna_fattura(TDocumento & doc, int codcont);
bool fatt_02() const { return !_prova &&lv_is_02_active(); }
void add_doc_to_list(const TString & key, const TDocumento & doc);
real get_percprovv(const TRiga_documento & row, char tipoprovv, const TString & codpr, bool first, const TRectype & age) const;
public:
int write_fatt_ragg();
void set_perc_provv(TRiga_documento & row, bool prima = true);
virtual bool elabora(TLista_documenti& doc_in, TLista_documenti& doc_out,
const TDate& data_elab, bool interattivo = false);
TFatturazione_lavanderie(const char* cod, bool prova = false);
~TFatturazione_lavanderie() {}
};
TFatturazione_lavanderie::TFatturazione_lavanderie(const char* cod, bool prova)
: TFatturazione_bolle(cod), _prova(prova)
{
}
//DOC_RAGGRUPPABILI: metodo che restituisce true se i documenti sono raggruppabili sulla base dei campi
//contenuti nella stringa campi
bool TFatturazione_lavanderie::doc_raggruppabili(const TDocumento& doc_in, const TDocumento& doc_out, TToken_string& campi) const
{
if (doc_in.ha_riga_esenzione() != doc_out.ha_riga_esenzione())
return false;
bool ok = true;
TString campo;
//scorro tutti i campi contenuti nella TToken_string
//se sto controllando i campi CODABI e CODCAB, allora il controllo
//deve essere numerico e non tra stringhe
for (const char* c = campi.get(0); c && ok; c = campi.get())
{
if (strncmp(c, "CODABI", 6) == 0 || strncmp(c, "CODCAB", 6) == 0)
{
long cod = doc_in.get_long(c);
ok &= (cod == doc_out.get_long(c));
}
else
{
campo = doc_in.get(c);
ok &= campo == doc_out.get(c);
}
}
return ok;
}
//DA_RAGGRUPPARE: per adesso segnaposto: resituisce sempre false
bool TFatturazione_lavanderie::da_raggruppare(const TRiga_documento & rin)
{
/* const long clifo = rin.doc().get_long(DOC_CODCF);
const int indsped = rin.doc().get_int(DOC_CODINDSP);
TLaundry_contract contr(clifo, indsped, _data_elab);
const TString80 codart = rin.get(RDOC_CODART);
const TRectype & rcont = contr.row(codart);
const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF);
// return tipoforf > 1; // Test originale
if (tipoforf > 1)
return true;
// Da qui in poi e' sottinteso tipoforf == 1
if (ini_get_int(CONFIG_DITTA, "lv", "TipoPr") == 1)
return false;
// Test GUY
const TString8 causale = rin.get(RDOC_CODAGG1);
const TCausale_lavand cau = cache().get("&CAU", causale);
if (cau.get_bool("B1"))
{
const TCausale_magazzino& con = cached_causale_magazzino(cau.get("S2"));
if (con.sgn(s_dottm)) // Causale di incremento sotazione temporanea
return true;
}
if (cau.get_bool("B4")) // Causale di rotto
return true; */
return false;
}
void TFatturazione_lavanderie::pre_process_input(TLista_documenti& doc_in)
{
for (int id = 0; id < doc_in.items(); id++)
{
TDocumento& doc = doc_in[id];
const int rows = doc.physical_rows();
for (int i = 1; i <= rows; i++)
{
TRiga_documento & row = doc[i];
TString str_real = row.get(RDOC_QTAREALE);
if (str_real.full())
{
real qta_real(decode(str_real));
row.put(RDOC_QTA, qta_real);
row.zero(RDOC_QTAREALE);
}
str_real = row.get(RDOC_QTARITREALE);
if (str_real.full())
{
real qta_real(decode(str_real));
row.put(RDOC_QTAGG1, qta_real);
row.zero(RDOC_QTARITREALE);
}
}
}
}
void TFatturazione_lavanderie::aggiorna_fattura(TDocumento & doc, int codcont)
{
const int nrows = doc.physical_rows();
const long codcf = doc.get_long(DOC_CODCF);
TString str;
str << "USE LVRCONDV\n"
<< "FROM CODCF=" << codcf << " CODCONT=" << codcont << "\n"
<< "TO CODCF=" << codcf << " CODCONT=" << codcont;
TISAM_recordset rcont(str);
for(bool ok = rcont.move_first(); ok; ok = rcont.move_next())
{
TRectype& riga = rcont.cursor()->curr();
int forfait = riga.get_int(LVRCONDV_TIPOFORF);
const TString & codart = riga.get(LVRCONDV_CODART);
bool to_add = forfait != 0;
for (int i = 1; to_add && i <= nrows ; i++)
{
TRiga_documento& rout = doc[i];
const TString80 codart_contr = rout.get(RDOC_CODART);
if (codart == codart_contr)
to_add = false;
}
if (to_add)
{
TRiga_documento& rdoc = doc.new_row("21");
rdoc.put(RDOC_CODART, codart);
rdoc.put(RDOC_CODARTMAG, riga.get(LVRCONDV_CODART));
rdoc.put(RDOC_DESCR, cached_article(codart).get(ANAMAG_DESCR));
rdoc.put(RDOC_CHECKED, true);
rdoc.put(RDOC_QTA, 0);
rdoc.put(RDOC_QTAGG1, 0);
rdoc.put(RDOC_UMQTA, riga.get(LVRCONDV_UM));
TToken_string key;
key.add('C');
key.add(codcf);
TString8 codiva = cache().get(LF_CFVEN, key, CFV_ASSFIS);
if (codiva.blank())
codiva = cache().get(LF_ANAMAG, riga.get(LVRCONDV_CODART), ANAMAG_CODIVA);
rdoc.put(RDOC_CODIVA, codiva);
rdoc.put(RDOC_CODAGG1, ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV"));
set_perc_provv(rdoc);
set_perc_provv(rdoc, false);
}
}
}
void TFatturazione_lavanderie::add_doc_to_list(const TString & key, const TDocumento & doc)
{
TDocumento * doc_cli = (TDocumento *) _doc_grouped.objptr(key);
if (doc_cli == NULL)
_doc_grouped.add(key, doc);
else
{
const int nrows = doc.physical_rows();
for (int r = 1; r <=nrows; r++)
{
const TRiga_documento & row = doc[r];
TRiga_documento & new_row = doc_cli->new_row(row.get(RDOC_TIPORIGA));
doc_cli->copy_data(new_row, row);
}
}
}
real TFatturazione_lavanderie::get_percprovv(const TRiga_documento & row, char tipoprovv, const TString & codpr, bool first, const TRectype & age) const
{
real val = ZERO;
const TDocumento & doc = row.doc();
const TRectype & anamag = cache().get(LF_ANAMAG, row.get(RDOC_CODARTMAG));
switch (tipoprovv)
{
case 'A':
val = age.get_real(AGE_PERCPROVV);
break;
case 'M':
val = anamag.get_real(ANAMAG_PERCPROVV);
break;
case 'C':
val = doc.clifor().vendite().get_real(first ? CFV_PERCPROVV : CFV_PERCPROVV1);
break;
case 'V':
{
const TString16 catven = doc.get(DOC_CATVEN);
if (catven.not_empty())
val = real(cache().get("CVE", catven, "R0"));
}
break;
case 'O':
// val = _rcondv.get_real("PERCPROVV");
break;
case '1':
case '2':
case '3':
case '4':
{
const TString16 ord = cache().get("APR", codpr, "S3");
int len = ord.len();
TString key;
TString80 campo;
for (int i = 0; i < len; i++)
{
switch (ord[i])
{
case 'C':
campo = doc.clifor().get(CLI_CODCF);
campo.lpad(doc.clifor().length(CLI_CODCF));
break;
case 'V':
campo = doc.get(DOC_CATVEN);
campo.rpad(doc.length(DOC_CATVEN));
break;
case 'A':
campo = doc.get(DOC_CODAG);
campo.rpad(doc.length(DOC_CODAG));
break;
case 'P':
campo = doc.get(DOC_CODPAG);
campo.rpad(doc.length(DOC_CODPAG));
break;
case 'S':
campo = doc.clifor().vendite().get(CFV_CODSCC);
campo.rpad(doc.clifor().length(CFV_CODSCC));
break;
case 'Z':
campo = doc.get(DOC_ZONA);
campo.rpad(doc.length(DOC_ZONA));
break;
case 'M':
campo = row.get( RDOC_CODARTMAG );
campo.rpad(row.length(RDOC_CODARTMAG));
break;
case 'E':
campo = anamag.get(ANAMAG_GRMERC);
campo.rpad(anamag.length(ANAMAG_GRMERC));
campo.cut(3);
break;
case 'R':
campo = anamag.get(ANAMAG_GRMERC);
campo.rpad(anamag.length(ANAMAG_GRMERC));
break;
case 'F':
campo = anamag.get(ANAMAG_RAGGFIS);
campo.rpad(anamag.length(ANAMAG_RAGGFIS));
break;
default:
campo.cut(0);
break;
}
key << campo;
}
TLocalisamfile perc(LF_PERCPROV);
perc.put(PER_CODPR, codpr);
perc.put(PER_KEYORD, key);
if (perc.read() == NOERR)
val= perc.get_real(PER_PERCPROVV);
}
break;
default:
break;
}
return val;
}
void TFatturazione_lavanderie::set_perc_provv(TRiga_documento & row, bool prima)
{
const TString & codage = row.doc().get(prima ? DOC_CODAG : DOC_CODAGVIS);
if (codage.full())
{
const TRectype & age = cache().get(LF_AGENTI, codage);
if (!age.empty())
{
TString16 seqric(age.get(AGE_SEQRIC));
real percprovv;
if (seqric[0] == '-')
seqric = ini_get_string(CONFIG_DITTA, "ve", "AGETIPOPERC");
int len = seqric.len();
int i;
for (i = 0; percprovv.is_zero() && seqric[i] != '\0' && seqric[i] != '-'; i++)
{
TString16 codric;
if (isdigit(seqric[i]))
codric = age.get(format("CODRICPR%d", i+1));
percprovv = get_percprovv(row, seqric[i], codric, prima, age);
}
real percalt;
seqric = age.get(AGE_SEQALT);
for (i = 0; percalt.is_zero() && seqric[i] != '\0' && seqric[i] != '-'; i++)
{
TString16 codric;
if (isdigit(seqric[i]))
codric = age.get(format("CODALTPR%d", i+1));
percalt = get_percprovv(row, seqric[i], codric, prima, age);
}
percprovv += percalt;
row.put(prima ? RDOC_PERCPROV : RDOC_PERCPROV1, percprovv);
}
}
}
int TFatturazione_lavanderie::write_fatt_ragg()
{
int items = _doc_grouped.items();
TString_array kl;
_doc_grouped.get_keys(kl);
kl.sort();
FOR_EACH_ARRAY_ROW(kl, r, key)
{
TDocumento * d = (TDocumento *)_doc_grouped.objptr(*key);
if (d != NULL)
d->write();
}
_doc_grouped.destroy();
return items;
}
//POST_PROCESS: metodo che elabora i documenti di output dopo che si sono svolte
//le operazioni di base sugli stessi, in modo da raggruppare le righe raggruppabili
//e/o eliminare quelle inutili e/o aggiungere quelle per il ciclaggio su 2 linee
void TFatturazione_lavanderie::post_process(TLista_documenti& doc_out, TLista_documenti& doc_in)
{
bool use_indsp = ini_get_bool(CONFIG_DITTA, "mg", "MOV_INDSPED");
//scorro tutti i documenti di output generati precedentemente
for (int id = 0; id < doc_out.items(); id++)
{
//instanzio il documento e recupero le variabili di interesse per recuperare
//il contratto del cliente in questione
TDocumento& doc = doc_out[id];
const long clifo = doc.get_long(DOC_CODCF);
const int indsped = doc.get_int(DOC_CODINDSP);
TLaundry_contract contr(clifo,indsped,_data_elab);
//flag per il calcolo sul valore convenzionale e sul fisso per dotazione iniziale
bool valconvcli = false;
bool fixdotin = false;
bool elcons = contr.get_bool(LVCONDV_ELCONS);
bool rifbol = contr.get_bool(LVCONDV_RIFBOL);
bool riftest = ini_get_bool(CONFIG_DITTA, "lv", "RifTest");
bool liqdiff = doc.clifor().get_int(CLI_ALLEG) == 7 && doc.clifor().vendite().get_bool(CFV_FATTSOSP);
real consvconv;
real impvconv;
TAssoc_array nolo_computed;
if (liqdiff)
doc.put(DOC_LIQDIFF, "X");
else
doc.zero(DOC_LIQDIFF);
if (doc.physical_rows() > 0 && doc[1].is_descrizione())
{
if (elcons)
{
TRiga_documento& rout = doc[1];
rout.put(RDOC_DESCR, "COME DA ELENCO CONSEGNE");
rout.put(RDOC_DESCLUNGA, false);
rout.put(RDOC_DESCEST, "");
}
else
if (!rifbol)
doc.destroy_row(1, true);
}
//se devo mettere i riferimenti della bolla in testata, prendo la descrizione della prima riga
//e la metto sulla testata del documento, poi cancello la prima riga del documento
if (rifbol && riftest)
{
TRiga_documento& rout = doc[1];
TString descr = rout.get(RDOC_DESCR);
descr << ' ' << rout.get(RDOC_DESCEST);
descr.ltrim(21);
//sostituisco la stringa " - n. " e la sostituisco con la stringa " - " su tutta la stringa descrizione
int pos = descr.find(" - n. ");
while (pos > 0)
{
descr.overwrite(" - ", pos, 7);
pos = descr.find(" - n. ", pos + 1);
}
descr.strip_double_spaces();
const TString original_notes = doc.get(DOC_NOTE);
if (original_notes.full())
descr << '\n' << original_notes;
doc.put(DOC_NOTE, descr);
doc.destroy_row(1, true);
}
if (doc.physical_rows() > 0)
doc.sort_rows("LVTYPE|" RDOC_CODART);
const bool ragart = contr.get_bool(LVCONDV_RAGART); // leggo il flag di testata raggruppa su unico articolo
const int tipocan = contr.get_int(LVCONDV_TIPOCAN); // leggo il tipo canone
const real redditivita = contr.get_real(LVCONDV_REDDI);
if (ragart)
{
real totmerc;
const int rows = doc.physical_rows();
for (int i=1; i <= rows; i++) //calcolo totale merce
{
const TRiga_documento& riga = doc[i];
if (riga.is_merce())
totmerc += riga.importo(true,false);
}
const int rigamerce = doc[1].is_descrizione() ? 2 : 1;
for (int i=rigamerce; i <= rows; i++)
doc.destroy_row(i);
TRiga_documento& riga = doc.new_row("01");
const TString80 codartcfg = ini_get_string(CONFIG_DITTA, "lv", "Codartcafix");
const TString80 descart = cache().get(LF_ANAMAG, codartcfg, ANAMAG_DESCR);
// istanzio una token string e poi una cache per estrarre l'unit<69> di misura dell articolo in configurazione da UMART
TToken_string key;
key.add(codartcfg);
key.add(1);
const TRectype& umart = cache().get(LF_UMART,key);
const TString4 umcodart = umart.get(UMART_UM);
/* estraggo il codice IVA istanziando in primis una cache su CFVEN per analizzare il codice esenzione iva
del cliente in questione. Se <20> >0 imposto il codiva a tale valore, altrimenti se <20> uguale a 0 istanzio
un altra cache su ANAMAG e imposto il codiva uguale al codice iva dell articolo in questione */
key = doc.get(DOC_TIPOCF);
key.add(clifo);
const TRectype& cfven = cache().get(LF_CFVEN,key);
TString8 codiva = cfven.get(CFV_ASSFIS);
if (codiva.blank())
{
const TRectype& anamag = cache().get(LF_ANAMAG,codartcfg);
codiva = anamag.get(ANAMAG_CODIVA);
}
riga.put(RDOC_QTA,UNO);
riga.put(RDOC_UMQTA,umcodart);
riga.put(RDOC_PREZZO,totmerc);
riga.put(RDOC_CODART,codartcfg);
riga.put(RDOC_DESCR,descart);
riga.put(RDOC_CODIVA,codiva);
set_perc_provv(riga);
set_perc_provv(riga, false);
break;
}
else // se non <20> selezionato raggrupa su unico articolo controllo il tipo canone se <20> impostato a importo fisso
if (tipocan == 1) //se <20> selezionato tipo canone = importo fisso
{
// estraggo il canone fisso e l'articolo in configurazione
const real canfis=contr.get_real(LVCONDV_IMPFIX);
const TString80 codartcfg = ini_get_string(CONFIG_DITTA, "lv", "Codartfix");
const TString80 descart = cache().get(LF_ANAMAG, codartcfg, ANAMAG_DESCR);
// istanzio una token string e poi una cache per estrarre l'unit<69> di misura dell articolo in configurazione da UMART
TToken_string key;
key.add(codartcfg);
key.add(1);
const TRectype& umart = cache().get(LF_UMART,key);
const TString4 umcodart = umart.get(UMART_UM);
/* estraggo il codice IVA istanziando in primis una cache su CFVEN per analizzare il codice esenzione iva
del cliente in questione. Se <20> >0 imposto il codiva a tale valore, altrimenti se <20> uguale a 0 istanzio
un altra cache su ANAMAG e imposto il codiva uguale al codice iva dell articolo in questione */
key = doc.get(DOC_TIPOCF);
key.add(clifo);
const TRectype& cfven = cache().get(LF_CFVEN,key);
TString8 codiva = cfven.get(CFV_ASSFIS);
if (codiva.blank())
{
const TRectype& anamag = cache().get(LF_ANAMAG,codartcfg);
codiva = anamag.get(ANAMAG_CODIVA);
}
const int rigamerce = doc.physical_rows() > 0 && doc[1].is_descrizione()?2:1;
TRiga_documento& fixrow=doc.insert_row(rigamerce, "01"); // creo una nuova riga in cima al documento e imposto i valori appena estratti
fixrow.put(RDOC_QTA,UNO);
fixrow.put(RDOC_UMQTA,umcodart);
fixrow.put(RDOC_PREZZO,canfis);
fixrow.put(RDOC_CODART,codartcfg);
fixrow.put(RDOC_DESCR,descart);
fixrow.put(RDOC_CODIVA,codiva);
int tipocanfix = contr.get_int(LVCONDV_CANFIX);
const int rows = doc.physical_rows();
switch (tipocanfix)
{
case 0:
for (int k = rigamerce+1; k <= rows; k++)
doc.destroy_row(k);
break;
case 1:
for (int k = rigamerce+1; k <= rows; k++)
{
TRiga_documento& rout = doc[k];
rout.zero(RDOC_PREZZO);
}
break;
case 2:
for (int k = rigamerce+1; k <= rows; k++)
{
TRiga_documento& rout = doc[k];
rout.zero(RDOC_PREZZO);
rout.zero(RDOC_QTA);
}
break;
default: break;
}
break;
}
else // se il tipo canone <20> impostato a nessuno o % sul valore convenzionale per cliente vado in ambedue i casi ad eseguire il ciclo che analizza i tipi forfait
{
if (!contr.get_bool(LVCONDV_FORFNOCONS))
aggiorna_fattura(doc, contr.get_int(LVCONDV_CODCONT));
//per ogni documento, scorro tutte le sue righe
for (int i = 1; i <= doc.physical_rows() ; i++)
{
TRiga_documento& rout = doc[i];
const TString80 codart = rout.get(RDOC_CODART);
//leggo dalla riga del contratto di questo articolo il tipo dotazione e
//la scelta per la % sul val.conv su articolo <A> o cliente <C>
const TRectype& rcont = contr.row(codart);
const TString4 tipodot = rcont.get(LVRCONDV_NOLCIC);
const TString4 artcli = rcont.get(LVRCONDV_VCARTCLI);
real dot;
const int annoes = _data_elab.year();
//instanzio il TArticolo_lavanderia
//cerco la giacenza per articolo dell'articolo esaminato
TArticolo_lavanderie& artlav = cached_article_laundry(codart, 'C', clifo, use_indsp ? indsped : 0);
//estraggo il record corrispondente su LF_CLIFOGIAC
const TRecmag_lavanderie& reclav = artlav.find_rec(annoes);
//se lo trovo e se il tipo dotazione <20> iniziale 'I', allora leggo la dotazione iniziale
//dalle giacenze articolo per cliente, altrimenti leggo la dotazione odierna
if (tipodot == "I")
dot = reclav.get_real("DOTIN");
else
dot = reclav.get_real("DOTOD");
//leggo dalla riga contratto il tipo forfait
const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF);
switch (tipoforf)
{
case 0: //forfait = NESSUNO
{
//gestione fatturazione a kg
const bool fatkg = rcont.get_bool(LVRCONDV_FATTKG);
//se devo fatturare a kg
if(fatkg)
{
const TString4 umkg = ini_get_string(CONFIG_DITTA, "lv", "UmKg");
const TString4 umri = rout.get(RDOC_UMQTA);
//se la riga <20> gi<67> espressa in kg non devo fare niente, altrimenti:
if(umri != umkg)
{
//leggo e controllo l'unit<69> di misura del peso
const TString4 ump = artlav.get(ANAMAG_UMP);
if(ump.empty())
{
warning_box(TR("Manca l'unit<69> di misura del peso"));
break;
}
//leggo e controllo il peso dell'articolo
const real peso = artlav.get_real(ANAMAG_PESO);
if(peso == ZERO)
{
warning_box(TR("Manca il peso"));
break;
}
//leggo l'unit<69> di misura dell'articolo e la quantit<69> convertita all'unit<69> di misura dell'articolo
const TString4 umart = artlav.um()[1].get(UMART_UM);
const real qta = artlav.convert_to_um(rout.get_real(RDOC_QTA), umart, umri, false);
//se l'articolo non <20> espresso in kg, allora:
if(umart != umkg)
{
//preparo una cache sulla tabella delle unit<69> di misura
const TRectype& unita = cache().get("%UMS", ump);
real fatconv = UNO;
if (ump != umkg)
{
//leggo e controllo se esiste l'unit<69> di misura di riferimento
const TString4 umrif = unita.get("S7");
if(umrif.empty())
{
warning_box(TR("Manca l'unit<69> di misura di riferimento"));
break;
}
if(umrif != umkg)
{
warning_box(TR("L'unit<69> di misura di riferimento non <20> quella dei Kg"));
break;
}
//leggo e controllo il fattore di conversione
fatconv = unita.get_real("R10");
if(fatconv == ZERO)
{
warning_box(TR("Manca il fattore di conversione"));
break;
}
}
//se tutti i controlli sono andati a buon fine, converto la quantit<69> e la scrivo sulla riga documento
const real qtaconv = qta * fatconv * peso;
rout.put(RDOC_UMQTA, umkg);
rout.put(RDOC_QTA, qtaconv);
}
}
}
}
break;
case 1: //forfait = A VALORE FISSO
{
rout.put(RDOC_QTA, UNO); //qta fissa a UNO
rout.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_IMPFISART)); //prezzo letto dalla riga contratto
// gestione in base codice per valore fisso ??? tolta la scelta dell'articolo o del cliente
}
break;
case 2: //forfait = NOLO
{
//aggiungo una riga tipo merce, che contiene tutti i dati della riga del documento
//di partenza, poi costruisco la descrizione in base alla periodicit<69> di fatturazione,
//metto la qta uguale alla dotazione che ho appena letto
//e prendo il prezzo nolo dalla riga contratto
if (dot != ZERO && nolo_computed.objptr(codart) == NULL)
{
TRiga_documento& nolorow = doc.insert_row(++i, "01");
nolo_computed.add(codart, codart);
doc.copy_data(nolorow, rout);
const TString descrart = rout.get(RDOC_DESCR);
TString80 descr("Nolo");
const int contrper = contr.get_int(LVCONDV_PERFAT);
switch (contrper)
{
case 0: descr << " per il giorno "; break;
case 1: descr << " per la settimana "; break;
case 2: descr << " per la quindicina "; break;
case 3: descr << " per il mese "; break;
default: break;
}
descr << descrart;
int split_pos = descr.find('\n');
const int descr_len = nolorow.length(RDOC_DESCR);
if (split_pos < 0 && descr.len() > descr_len)
split_pos = descr_len;
if (split_pos > descr_len)
split_pos = descr_len;
if (split_pos > 0)
{
nolorow.put(RDOC_DESCR, descr.left(split_pos));
const TString& dest = descr.mid(split_pos);
nolorow.put(RDOC_DESCLUNGA, "X");
nolorow.put(RDOC_DESCEST, dest);
}
else
{
nolorow.put(RDOC_DESCR, descr);
nolorow.zero(RDOC_DESCLUNGA);
nolorow.zero(RDOC_DESCEST);
}
nolorow.put(RDOC_QTA, dot);
nolorow.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZNOL));
}
}
break;
case 3: //forfait = CICLAGGIO
{
//leggo la quantit<69> consegnata e calcolo consumo e ciclaggio secondo le formule
//CONSUMO = QTA * PREZZO(dalla riga documento)
//CLICLAGGIO = DOT * PREZZO(dalla riga contratto) * MINIMO CICLAGGIO
const real qta = rout.get_real(RDOC_QTA);
const real consumo = qta * rout.get_real(RDOC_PREZZO);
const real ciclaggio = dot * rcont.get_real(LVRCONDV_PREZZO) * rcont.get_real(LVRCONDV_MINCIC);
//se il consumo <20> minore del ciclaggio, allora
if (consumo < ciclaggio)
{
//leggo il flag del tipo ciclaggio
const bool cicl2rig = contr.get_bool(LVCONDV_CICLAGGIO);
//calcolo il valore cicl secondo la formula CICL = MINIMO CICLAGGIO * DOT
const real cicl = rcont.get_real(LVRCONDV_MINCIC) * dot;
//se il ciclaggio <20> su due linee, allora aggiungo una riga merce, per pareggiare il minimo ciclaggio
//che ha come quantit<69> la differenza tra la quantit<69> di minimo cilcaggio
//e la quantit<69> effettivamente consegnata e come prezzo il prezzo preso dalla riga contratto;
//altimenti correggo quantit<69> e prezzo direttamente sulla riga documento che sto analizzando
if (cicl2rig)
{
TRiga_documento& congrow = doc.insert_row(++i, "01");
doc.copy_data(congrow,rout);
congrow.put(RDOC_DESCR,"Pareggio minimo ciclaggio");
congrow.put(RDOC_QTA, cicl - qta);
congrow.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZZO));
}
else
{
rout.put(RDOC_QTA, cicl);
rout.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZZO));
}
}
}
break;
case 4: //forfait = % SUL VALORE CONVENZIONALE
{
//leggo dalla riga contratto la % sul val.conv su articolo <A> o cliente <C>
const char tipovalconv = rcont.get_char(LVRCONDV_VCARTCLI);
//se la percentuale sul valore convenzionale <20> sull'articolo, allora:
if (tipovalconv == 'A')
{
//leggo la quantit<69> consegnata e calcolo consumo e importo convenzionale secondo le formule
//CONSUMO = QTA * PREZZO(dalla riga documento)
//IMPCONV = DOT * PREZZO(dalla riga contratto) * PERCENTUALE DI FORFAIT CLIENTE
const real qta = rout.get_real(RDOC_QTA);
const real consumo = qta * rout.get_real(RDOC_PREZZO);
const real impconv = dot * rcont.get_real(LVRCONDV_VALCONV) * rcont.get_real(LVRCONDV_FORFPERCL) / 100;
impvconv += impconv;
consvconv += consumo;
}
else
{
//se la percentuale sul valore convenzionale <20> sul cliente, allora se il flag valconvcli <20> false
if (!valconvcli)
{
//pongo valconvcli a true in modo da non tornare pi<70> in questo if
valconvcli = true;
//instanzio i due real che andranno a contenere l'importo covenzionale totale e il consumo totale
real impconvtot;
real consumotot;
TAssoc_array arts;
//scorro tutte le righe documento dalla riga in esame fino alla fine
for (int j = i; j < doc.physical_rows(); j++)
{
//instanzio la riga documento e sommo ai totali gli importi solo se
//la percentuale sul valore convenzionale <20> sul cliente
TRiga_documento& riga = doc[j];
const TString80 codart = riga.get(RDOC_CODART);
const TRectype & rcont = contr.row(codart);
const char tipvalconvcli = rcont.get_char(LVRCONDV_VCARTCLI);
char lavtype = riga.get_char("LVTYPE");
if (tipvalconvcli == 'C' && lavtype != 'D')
{
if (arts.objptr(codart) == NULL)
{
const TString4 tipodot = rcont.get(LVRCONDV_NOLCIC);
TArticolo_lavanderie& art = cached_article_laundry(codart, 'C', clifo, use_indsp ? indsped : 0);
//estraggo il record corrispondente su LF_CLIFOGIAC
const TRecmag_lavanderie& rec = art.find_rec(annoes);
//se lo trovo e se il tipo dotazione <20> iniziale 'I', allora leggo la dotazione iniziale
//dalle giacenze articolo per cliente, altrimenti leggo la dotazione odierna
if (tipodot == "I")
dot = rec.get_real("DOTIN");
else
dot = rec.get_real("DOTOD");
const real impconv = dot * rcont.get_real(LVRCONDV_VALCONV) * rcont.get_real(LVRCONDV_FORFPERCL) / CENTO;
impconvtot += impconv;
arts.add(codart, codart);
}
consumotot += riga.get_real(RDOC_QTA) * riga.get_real(RDOC_PREZZO);
}
}
//se il consumo <20> minore del ciclaggio, allora
if (consumotot < impconvtot)
{
const bool cicl2rig=contr.get_bool(LVCONDV_CICLAGGIO);
const TString80 codartcon = ini_get_string(CONFIG_DITTA, "lv", "Codartcofix");
//se il ciclaggio <20> su due linee, allora aggiungo una riga merce, che contiene
//il conguaglio al valore convenzionale, che ha come quantit<69> la costante UNO
//e come prezzo la differenza tra l'importo convenzionale totale e il consumo totale;
//altimenti correggo quantit<69> e prezzo direttamente sulla riga documento che sto analizzando
//e elimino tutte le righe che vanno a comporre il totale in modo che rimanga una riga sola
//per mostrare l'importo del conguaglio al valore convenzionale
if (cicl2rig)
{
i++;
TRiga_documento& congrow=doc.new_row("01");
doc.copy_data(congrow, rout);
congrow.put(RDOC_CODART, codartcon);
congrow.put(RDOC_CHECKED, "X");
congrow.put(RDOC_CODARTMAG, codartcon);
congrow.put(RDOC_DESCR, "Conguaglio valore convenzionale");
congrow.put(RDOC_QTA, UNO);
congrow.put(RDOC_PREZZO, impconvtot - consumotot);
set_perc_provv(congrow);
set_perc_provv(congrow, false);
}
else
{
rout.put(RDOC_CODART, codartcon);
rout.put(RDOC_CHECKED, "X");
rout.put(RDOC_CODARTMAG, codartcon);
rout.put(RDOC_DESCR, "Valore convenzionale");
rout.put(RDOC_QTA, UNO);
rout.put(RDOC_PREZZO, impconvtot);
for (int k = doc.physical_rows(); k > i; k--)
{
TRiga_documento& delrow = doc[k];
const TString80 codart = delrow.get(RDOC_CODART);
const TRectype& rcont = contr.row(codart);
const char tipvalconvcli = rcont.get_char(LVRCONDV_VCARTCLI);
char lavtype = delrow.get_char("LVTYPE");
if (tipvalconvcli == 'C' && lavtype != 'D')
doc.destroy_row(k, true);
}
}
}
}
}
}
break;
case 5: //forfait = FISSO SU DOTAZIONE INIZIALE
{
rout.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_IMPFISART));
const real dotin = reclav.get_real("DOTIN");
rout.put(RDOC_QTA, dotin);
if (rout.get(RDOC_DESCR).blank())
{
const TString & descr = cached_article(codart).get(RDOC_DESCR);
rout.put(RDOC_DESCR, descr);
}
const TString80 codartorig=rout.get(RDOC_CODART);
for (int h = doc.physical_rows(); h > i; h--)
{
TRiga_documento& delrow = doc[h];
const TString80 codart=delrow.get(RDOC_CODART);
if ( codartorig == codart)
doc.destroy_row(h, true);
}
}
break;
default: break;
}
}
//se il consumo <20> minore del ciclaggio, allora
if (impvconv - consvconv > ZERO)
{
const bool cicl2rig = contr.get_bool(LVCONDV_CICLAGGIO);
const int rows = doc.physical_rows();
//se il ciclaggio <20> su due linee, allora aggiungo una riga merce, che contiene
//il conguaglio al valore convenzionale, che ha come quantit<69> la costante UNO
//e come prezzo la differenza tra l'importo convenzionale e il consumo;
//altimenti correggo quantit<69> e prezzo direttamente sulla riga documento che sto analizzando
TRiga_documento& congrow = doc.new_row("01");
const TString80 codartcon = ini_get_string(CONFIG_DITTA, "lv", "Codartcofix");
congrow.put(RDOC_CODART, codartcon);
congrow.put(RDOC_CHECKED, "X");
congrow.put(RDOC_CODARTMAG, codartcon);
congrow.put(RDOC_DESCR, "Conguaglio valore convenzionale");
congrow.put(RDOC_QTA, UNO);
TString8 codiva = doc.clifor().vendite().get(CFV_ASSFIS);
if (codiva.blank())
codiva = cache().get(LF_ANAMAG, codartcon, ANAMAG_CODIVA);
congrow.put(RDOC_CODIVA, codiva);
if (cicl2rig)
congrow.put(RDOC_PREZZO, impvconv - consvconv);
else
{
congrow.put(RDOC_PREZZO, impvconv);
for (int k = rows - 1; k >= 1; k--)
{
TRiga_documento& delrow = doc[k];
const TString80 codart = delrow.get(RDOC_CODART);
const TRectype& rcont = contr.row(codart);
const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF);
char lavtype = delrow.get_char("LVTYPE");
if (tipoforf == 4 && lavtype != 'D')
doc.destroy_row(k, true);
}
}
}
}
if (redditivita > ZERO && fatt_02() && !ragart && tipocan != 1)
{
const real totdoc = doc.totale_doc();
const real provvigione1 = doc.provvigione();
const real provvigione2 = doc.provvigione(false);
doc.put(RDOC_TOTREALE, encode(totdoc.string()));
doc.put(RDOC_PROVV1REALE, encode(provvigione1.string()));
doc.put(RDOC_PROVV2REALE, encode(provvigione2.string()));
for(int j = doc.physical_rows(); j > 0; j--)
{
TRiga_documento& rdoc = doc[j];
const TString80 codart = rdoc.get(RDOC_CODARTMAG);
const TRectype& rcont = contr.row(codart);
const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF);
long ppconf = cached_article(codart).get_long(ANAMAG_PPCONF);
const real real_qta = rdoc.get(RDOC_QTA);
if (rcont.get_int(LVRCONDV_CALCCONS) != 1 || ppconf == 0)
ppconf = 1;
const char lvtype = rdoc.get_char("LVTYPE");
bool row_has_02 = (tipoforf == 0) && (real_qta / ppconf > UNO) && (lvtype == 'C');
// 0 forfait = NESSUN FORFAIT SI
// 1 forfait = A VALORE FISSO NO
// 2 forfait = NOLO NO
// 3 forfait = CICLAGGIO NO
// 4 forfait = % SUL VALORE CONVENZIONALE NO
// 5 forfait = FISSO SU DOTAZIONE INIZIALE NO
if (row_has_02)
{
const TString key = format("%04d%04d", doc.get_int("FATID"), rdoc.get_int(RDOC_IDRIGA));
real new_qta = real_qta;
TCalc_02_data * data = (TCalc_02_data *) _output_rows_02.objptr(key);
rdoc.put(RDOC_QTAREALE, encode(real_qta.string()));
if (data != NULL)
{
new_qta /= ppconf;
real test = new_qta;
test.ceil();
if (test * ppconf != real_qta)
{
warning_box(FR("L'articolo %s per il cliente %ld ha una quantit<69> %s\nnon coincidente coi pacchi. Controllare le bolle"),
(const char *)codart, doc.get_long(DOC_CODCF), real_qta.string());
ppconf = 1;
}
new_qta *= (CENTO - redditivita) / CENTO;
new_qta.round();
data->distr() = new_qta;
new_qta *= ppconf;
rdoc.put(RDOC_QTA, new_qta);
real new_qta_rit = rdoc.get_real("TOTRIT");
new_qta_rit *= (CENTO - redditivita) / CENTO;
new_qta_rit.round();
data->distr_rit() = new_qta_rit;
TAssoc_array & bol_rows = data->bol_rows();
FOR_EACH_ASSOC_OBJECT(bol_rows, obj, wkey, item)
{
TToken_string bolkey(wkey);
const long ndoc = bolkey.get_long(3);
const long id = bolkey.get_long(4);
for (int i = 0; i < doc_in.items(); i++)
{
TDocumento& doc = doc_in[i];
if (doc.get_long(DOC_NDOC) == ndoc)
{
TRiga_documento * bolrow = (TRiga_documento *) doc.get_row_id(id);
if (bolrow != NULL)
{
const TString8 causale = bolrow->get(RDOC_CODAGG1);
const TCausale_lavanderie & cau = cached_causale_lavanderie(causale);
if (cau.is_rotto())
break;
bool fatturo_ritirato = cau.is_ritiro();
bool fatturo_consegnato = cau.is_consegna();
if (fatturo_ritirato)
{
const TCausale_magazzino& rit = cau.causale_ritiro();
fatturo_ritirato = rit.sgn(s_consmese) != 0;
}
if (fatturo_consegnato)
{
const TCausale_magazzino& con = cau.causale_consegna();
fatturo_consegnato = con.sgn(s_consmese) != 0;
}
TString str_real = bolrow->get(RDOC_QTA);
real qta = real(str_real) / ppconf;
qta.round();
if (str_real.full())
bolrow->put(RDOC_QTAREALE, encode(str_real));
str_real = bolrow->get(RDOC_QTAGG1);
real qtarit = real(str_real);
data->distr_rit().add(qtarit);
if (str_real.full())
bolrow->put(RDOC_QTARITREALE, encode(str_real));
if (fatturo_ritirato && !fatturo_consegnato) // ! fatturo il ritirato o fatturo il consegnato
{
qtarit = real(str_real) / ppconf;
qtarit.round();
data->distr().add(qtarit);
}
else
data->distr().add(qta);
}
else
message_box("Riga_bolla smarrita %d - %s - %ld - id = %ld", bolkey.get_int(1), bolkey.get(0), bolkey.get(3), bolkey.get(4));
break;
}
}
}
FOR_EACH_ASSOC_OBJECT(bol_rows, obj1, wkey1, item1)
{
TToken_string bolkey(wkey);
const long ndoc = bolkey.get_long(3);
const long id = bolkey.get_long(4);
for (int i = 0; i < doc_in.items(); i++)
{
TDocumento& doc = doc_in[i];
if (doc.get_long(DOC_NDOC) == ndoc)
{
TRiga_documento * bolrow = (TRiga_documento *) doc.get_row_id(id);
if (bolrow != NULL)
{
const TString8 causale = bolrow->get(RDOC_CODAGG1);
const TCausale_lavanderie & cau = cached_causale_lavanderie(causale);
if (cau.is_rotto())
break;
bool fatturo_ritirato = cau.is_ritiro();
bool fatturo_consegnato = cau.is_consegna();
if (fatturo_ritirato)
{
const TCausale_magazzino& rit = cau.causale_ritiro();
fatturo_ritirato = rit.sgn(s_consmese) != 0;
}
if (fatturo_consegnato)
{
const TCausale_magazzino& con = cau.causale_consegna();
fatturo_consegnato = con.sgn(s_consmese) != 0;
}
const real qta = data->distr().get() * ppconf;
const real qtarit = data->distr_rit().get();
bolrow->put(RDOC_QTAGG1, qtarit);
if ((!fatturo_ritirato) || (fatturo_consegnato)) // ! fatturo il ritirato o fatturo il consegnato
bolrow->put(RDOC_QTA, qta);
else
int c = 1; // placeholder
}
else
message_box("Riga_bolla smarrita %d - %s - %ld - id = %ld", bolkey.get_int(1), bolkey.get(0), bolkey.get(3), bolkey.get(4));
break;
}
}
}
}
}
}
}
for(int h = doc.physical_rows(); h > 0; h--)
{
TRiga_documento& rdoc = doc[h];
if (rdoc.get(RDOC_DESCR).empty() || ((rdoc.imponibile() == ZERO && rdoc.get_real(RDOC_QTA) == ZERO)))
doc.destroy_row(h, true);
}
}
for (int id = doc_out.items() - 1; id >= 0 ; id--)
{
TDocumento& doc = doc_out[id];
const int rows = doc.physical_rows();
bool to_delete = true;
for (int i = rows; to_delete && i > 0; i--)
{
const TRiga_documento& riga = doc[i];
if (!riga.is_descrizione())
to_delete = (riga.imponibile() == ZERO && riga.get_real(RDOC_QTA) == ZERO);
}
if (to_delete || doc.totale_doc() == ZERO)
doc_out.destroy(id);
}
for (int id = doc_out.items() - 1; id >= 0 ; id--)
{
TDocumento& doc = doc_out[id];
const TString4 tipocf = doc.get(DOC_TIPOCF);
const int act_cli = doc.get_long(DOC_CODCF);
TToken_string key(tipocf);
key.add(act_cli);
const TRectype & reccli = cache().get(LF_CLIFO, key);
const long new_cli = reccli.get_long(CLI_CODCFFATT);
if (new_cli > 0L)
{
doc.put(DOC_CODCF, new_cli);
key = tipocf;
key.add(new_cli);
const TRectype & new_reccliven = cache().get(LF_CFVEN, key);
TLaundry_contract contr(new_cli, doc.get_long(DOC_CODINDSP), _data_elab);
doc.put(DOC_CODINDSP, new_reccliven.get(CFV_CODINDDOC));
TString descr;
TRiga_documento & r = doc.insert_row(1, "05");
r.put(RDOC_DESCR, "Consegne effettuate presso\n");
descr << act_cli << " " << reccli.get(CLI_RAGSOC);
r.put(RDOC_DESCLUNGA, "X");
r.put(RDOC_DESCEST, descr);
if (contr.get_bool(LVCONDV_RAGGCGRUP))
{
add_doc_to_list(key, doc);
doc_out.destroy(id);
}
}
}
}
//ADD_ROWS: per adesso un segnaposto
void TFatturazione_lavanderie::add_rows(TRiga_documento & rout, TRiga_documento & rin)
{
/*const TString8 causale = rin.get(RDOC_CODAGG1);
const TRectype& cau = cache().get("&CAU", causale);
const TCausale_magazzino& rit = cached_causale_magazzino(cau.get("S1"));
const TCausale_magazzino& con = cached_causale_magazzino(cau.get("S2")); //movimento o meno la dotazione temporanea/odierna a seconda di cosa prevede la causale
const long clifo = rin.doc().get_long(DOC_CODCF);
const int indsped = rin.doc().get_int(DOC_CODINDSP);
TLaundry_contract contr(clifo, indsped, _data_elab);
if (cau.get_bool("B4") && contr.get_int(LVCONDV_ADDCAPROT)) // Guardo se <20> una causale di rotto e se <20> abilitato nella testata del contratto la fatturazione dei rotti
{
const real qta = rit.sgn(s_consmese) * rin.get_real(RDOC_QTA);
rout.put(RDOC_PREZZO,contr.get_int(LVCONDV_PREZROT));
rout.add(RDOC_QTA, qta);
}
else
{
if (cau.get_bool("B0"))
{
const real qta = rit.sgn(s_consmese) * rin.get_real(RDOC_QTA);
rout.add(RDOC_QTA, qta);
}
if (cau.get_bool("B1"))
{
const real qta = con.sgn(s_consmese) * rin.get_real(RDOC_QTA);
rout.add(RDOC_QTA, qta);
}
} */
}
//CAMPI_RAGGRUPPAMENTO_RIGHE: ridefinisco il metodo campi_raggruppamento_righe della TFatturazione_bolle
void TFatturazione_lavanderie::campi_raggruppamento_righe(TToken_string& campi_riga) const
{
campi_riga = RDOC_CODART"|"RDOC_UMQTA; // Uguali sempre
const bool ragg_rig = raggruppa_righe();
if (ragg_rig)
{
// Uguali se commesse attive
if (dongle().active(CAAUT) || dongle().active(CMAUT))
{
campi_riga.add(RDOC_CODCMS);
campi_riga.add(RDOC_FASCMS);
campi_riga.add(RDOC_CODCOSTO);
}
// Uguali opzionalmente
if (riga_uguale(0)) campi_riga.add(RDOC_CODMAG);
if (riga_uguale(1)) campi_riga.add(RDOC_CODIVA);
if (riga_uguale(2))
{
const int tipoprezzo = ini_get_int(CONFIG_DITTA, "lv", "TipoPr");
if(tipoprezzo == 0)
campi_riga.add(RDOC_SCONTO);
else
campi_riga.add(RDOC_PREZZO"|"RDOC_SCONTO);
}
}
}
//FIND_OR_CREATE_ROW: questo metodo cerca tra tutte le righe documento della fattura prodotta
//una eventuale riga lavanderia raggruppabile; se la trova restituiace quella riga, altrimenti
//ne crea una nuova
TRiga_documento& TFatturazione_lavanderie::find_or_create_row(TDocumento& doc_out, const TRiga_documento& rin, const char lavtype)
{
int r;
//scorro le righe documetno
for (r = doc_out.physical_rows(); r > 0; r--)
{
//se trovo una riga raggruppabile e di lavanderia, allora interrompo il ciclo
if (doc_out[r].raggruppabile(rin, _campi_raggruppamento) && (doc_out[r].get_char("LVTYPE") == lavtype))
break;
}
//se non ho trovato la riga, ne creo una nuova
if (r <= 0)
{
TRiga_documento& row = doc_out.new_row("01");
doc_out.copy_data(row, rin);
row.put(RDOC_TIPORIGA, "01");
set_perc_provv(row);
set_perc_provv(row, false);
const TRectype& anamag = cache().get(LF_ANAMAG, rin.get(RDOC_CODART));
row.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA));
row.zero(RDOC_CODAGG1);
row.zero(RDOC_QTA);
row.zero(RDOC_QTAGG1);
row.zero(RDOC_CODMAGC);
row.put("LVTYPE", lavtype);
r = row.get_int(RDOC_NRIGA);
}
if (fatt_02())
{
doc_out.set_row_ids();
const TString key = format("%04d%04d", doc_out.get_int("FATID"), doc_out[r].get_int(RDOC_IDRIGA));
TCalc_02_data * data = (TCalc_02_data *) _output_rows_02.objptr(key);
if (data == NULL)
{
data = new TCalc_02_data(key);
_output_rows_02.add(key, data);
}
TString bolkey = rin.get_rdoc_key();
data->bol_rows().add(bolkey, bolkey);
}
return doc_out[r];
}
//CREATE_ROW: metodo che crea fisicamente la riga sul documento di uscita partendo dal documento di ingresso (bolla)
void TFatturazione_lavanderie::create_row(TDocumento& doc_out, const TRiga_documento & rin)
{
//leggo la causale della riga del documento di ingresso
const TString8 causale = rin.get(RDOC_CODAGG1);
const TCausale_lavanderie & cau = cached_causale_lavanderie(causale);
//recupero i dati cliente dalla testata del documento e instanzio il contratto
const long clifo = rin.doc().get_long(DOC_CODCF);
const int indsped = rin.doc().get_int(DOC_CODINDSP);
TLaundry_contract contr(clifo, indsped, _data_elab);
//leggo dal documento i valori che vanno riportati sulla fattura e recupero la riga contratto
//di quell'articolo
const TString80 codart = rin.get(RDOC_CODARTMAG); // non <20> gestito il caso di un articolo fuori contratto
const real qta = rin.get_real(RDOC_QTA);
const real qta1 = rin.get_real(RDOC_QTAGG1);
const TRectype& rcont = contr.row(codart);
//leggo dalla configurazione da dove va preso il prezzo
const int tipoprezzo = ini_get_int(CONFIG_DITTA, "lv", "TipoPr");
real prezzo;
//se tipoprezzo == 0 (prezzo da contratto), allora cerco il prezzo sul contratto; se l'articolo
//non esiste sul contratto, allora cerco il suo prezzo sull'anagrafica di magazzino.
//Se tipoprezzo == 1 (prezzo da bolla), allora leggo il prezzo sulla riga della bolla
if (tipoprezzo == 0)
{
if (!rcont.empty())
prezzo = rcont.get_real(LVRCONDV_PREZZO);
}
else
prezzo = rin.get_real(RDOC_PREZZO);
//se <20> una causale di rotto e se <20> abilitato nella testata del contratto la fatturazione dei rotti
//e se sto ritirando una quantit<69> di merce diversa da zero, allora:
if (cau.is_rotto() && contr.get_bool(LVCONDV_ADDCAPROT) && !qta1.is_zero())
{
//se passo le condizioni iniziali cerco eventualmente una riga che possa essere raggruppata con quella
//che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantit<69> da ritirare
//al prezzo segnato in contratto
TRiga_documento& rd = find_or_create_row(doc_out, rin ,'D');
rd.put(RDOC_DESCLUNGA, "X");
rd.put(RDOC_DESCEST, "\nper addebito biancheria");
rd.add(RDOC_QTA, qta1);
rd.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZDAN));
}
//se <20> una causale di ritirato e se sto ritirando una quantit<69> di merce diversa da zero, allora:
if (cau.is_ritiro() && !qta1.is_zero())
{
//leggo la casuale di magazzino associata al ritiro e il suo segno sul consegnato mese
const TCausale_magazzino& rit = cau.causale_ritiro();
const real sgnrit = rit.sgn(s_consmese);
//se movimenta il consegnato mese, cerco eventualmente una riga che possa essere raggruppata con quella
//che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantit<69> che sto ritirando moltiplicata
//per il suo segno al prezzo ricavato sopra o da contratto (o da magazzino), o da bolla
if (!sgnrit.is_zero())
{
TRiga_documento& rr = find_or_create_row(doc_out, rin, 'C');
rr.add(RDOC_QTA, sgnrit * qta1);
rr.put(RDOC_PREZZO, prezzo);
rr.add("TOTRIT", qta1);
}
}
//se <20> una causale di consegnato e se sto consegnando una quantit<69> di merce diversa da zero, allora:
if (cau.is_consegna() && !qta.is_zero())
{
//leggo la casuale di magazzino associata al ritiro e i suoi segni sul consegnato mese,
//sulla dotazione temporanea e sulla dotazione iniziale
const TCausale_magazzino& con = cau.causale_consegna();
const real sgntmp=con.sgn(s_dottm);
const real sgndotin=con.sgn(s_dotin);
const real sgncons=con.sgn(s_consmese);
//se movimenta la dotazione temporanea e <20> previsto l'addebito dotazione temporanea con prezzo diverso,
//cerco eventualmente una riga che possa essere raggruppata con quella che sto guardando adesso,
//altrimenti la creo; in ogni caso aggiungo la quantit<69> che sto consegnando moltiplicata
//per il suo segno al prezzo scritto sul contratto per la dotazine temporanea
if (!sgntmp.is_zero() && contr.get_bool(LVCONDV_DOTTMPPRZD))
{
TRiga_documento& rt = find_or_create_row(doc_out, rin, 'T');
rt.add(RDOC_QTA, sgntmp * qta);
rt.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PRZDTTMP));
}
//se movimenta la dotazione iniziale, cerco eventualmente una riga che possa essere raggruppata con quella
//che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantit<69> che sto consegnando moltiplicata
//per il suo segno al prezzo ricavato sopra o da contratto (o da magazzino), o da bolla
if (!sgndotin.is_zero() && !sgncons.is_zero())
{
TRiga_documento& rc = find_or_create_row(doc_out, rin, 'C');
rc.add(RDOC_QTA, sgndotin * qta);
rc.put(RDOC_PREZZO, prezzo);
}
else
{
//se movimenta il consegnato mese, cerco eventualmente una riga che possa essere raggruppata con quella
//che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantit<69> che sto consegnando moltiplicata
//per il suo segno al prezzo ricavato sopra o da contratto (o da magazzino), o da bolla
if (!sgncons.is_zero())
{
TRiga_documento& rc = find_or_create_row(doc_out, rin, 'C');
rc.add(RDOC_QTA, sgncons * qta);
rc.put(RDOC_PREZZO, prezzo);
rc.add("TOTRIT", qta1);
}
}
}
}
//ELABORA: metodo che esegue alcune operazioni prliminari, quali settare la data elaborazione e trovare i campi
//in base ai quali <20> possibile raggruppare le righe documetno, e poi chiama l'elaborazione standard per la fatturazione
bool TFatturazione_lavanderie::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out,
const TDate& data_elab, bool interattivo)
{
_data_elab = data_elab;
campi_raggruppamento_righe(_campi_raggruppamento);
_output_rows_02.destroy();
return TFatturazione_bolle::elabora(doc_in, doc_out, data_elab, interattivo);
}
/////////////////////////////////
//// TFatturazione_msk ////
/////////////////////////////////
TFatturazione_msk::TFatturazione_msk():TAutomask("lv2500a")
{
//imposto il periodo di fatturazione dal primo del mese precedente all'ultimo del mese precedente
//se la data odierna <20> inferiore al 10 del mese corrente
//altrimenti la imposto dal primo del mese corrente alla data odierna
TDate data(TODAY);
if (data.day() <= 10)
{
data.addmonth(-1);
data.set_day(1);
set(F_DADATA, data);
data.set_end_month();
set(F_ADATA, data);
}
else
{
set(F_ADATA, data);
data.set_day(1);
set(F_DADATA, data);
}
if (main_app().argc() > 2)
{
TString16 tpela = main_app().argv(2);
tpela = tpela.mid(4);
TString8 codela = ini_get_string(CONFIG_DITTA, "lv", tpela);
set(F_COD_ELAB, codela);
field(F_COD_ELAB).check();
disable(F_COD_ELAB);
disable(F_DESC_ELAB);
}
}
/////////////////////////////////////
//// TFatturazione_lav_app ////
/////////////////////////////////////
//GENERA_BOLLE_NOLO: metodo che genera le fatture di solo nolo per quei clienti a cui non <20> stato consegnato niente
void TFatturazione_lav_app::genera_bolle_nolo(TAssoc_array& cliela, TFatturazione_lavanderie& elab, int& numdocgen)
{
TString4 codnum = ini_get_string(CONFIG_DITTA, "lv", "NUM_GEN");
TString4 tipodoc = ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_GEN");
char stato = cache().get("%TIP", tipodoc, "S2").mid(1,1)[0];
//preparo la query sui contratti
TString str;
str << "USE LVCONDV";
if (_msk->get_long(F_DACODCF) > 0)
str << "\nFROM CODCF=" << _msk->get_long(F_DACODCF);
if (_msk->get_long(F_ACODCF) > 0)
str << "\nTO CODCF=" << _msk->get_long(F_ACODCF);
TISAM_recordset contr(str);
TLista_documenti doc_in;
TLista_documenti doc_out;
TProgind pi(contr.items(), "Fatturazione", true, true);
for(bool ok = contr.move_first(); ok; ok = contr.move_next())
{
pi.set_text(TR("Elaborazione Nolo"));
if (!pi.addstatus(1))
break;
//scarto i contratti scaduti
if (contr.get(LVCONDV_DATASC).as_date().ok())
if (_msk->get_date(F_DADATA) <= contr.get(LVCONDV_DATAIN).as_date() || _msk->get_date(F_ADATA) >= contr.get(LVCONDV_DATASC).as_date())
continue;
//scarto tutti quelli che non sono in periodo di fatturazione corretto
if (contr.get(LVCONDV_PERFAT).as_int() > _msk->get_int(F_PERFAT))
continue;
// scarto i clienti sospesi
if (contr.get(LVCONDV_FATTSOSP).as_bool())
continue;
if(cliela.is_key(contr.get(LVCONDV_CODCF).as_string()))
continue;
TDocumento *pdoc= new TDocumento('D', _msk->get_date(F_DATAFAT).year(), codnum, 0);
doc_in.add(pdoc);
TDocumento& doc = *pdoc;
doc.put(DOC_TIPODOC, tipodoc);
doc.put(DOC_STATO, stato);
doc.put(DOC_TIPOCF, 'C');
TLaundry_contract contratto(contr.cursor()->curr());
const long codcf = contratto.get_long(LVCONDV_CODCF);
const int codcont = contratto.get_int(LVCONDV_CODCONT);
const bool fattnocons = !contratto.get_bool(LVCONDV_FORFNOCONS);
doc.put(DOC_CODCF, codcf);
TToken_string key("C");
key.add(codcf);
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);
//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 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;
}
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_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_PERCSPINC, speseinc);
doc.put(DOC_ADDBOLLI, addbolli);
doc.put(DOC_SCONTOPERC, sconto);
TString str;
str << "USE LVRCONDV\n"
<< "FROM CODCF=" << codcf << " CODCONT=" << codcont << "\n"
<< "TO CODCF=" << codcf << " CODCONT=" << codcont;
TISAM_recordset rcont(str);
for(bool ok = rcont.move_first(); ok; ok = rcont.move_next())
{
TRectype& riga = rcont.cursor()->curr();
const int tipoforf = riga.get_int(LVRCONDV_TIPOFORF);
if (tipoforf > 0 &&
((tipoforf == 2) ||
(tipoforf != 2 && fattnocons)))
{
TRiga_documento& rdoc = doc.new_row("21");
rdoc.put(RDOC_CODART, riga.get(LVRCONDV_CODART));
rdoc.put(RDOC_CODARTMAG, riga.get(LVRCONDV_CODART));
rdoc.put(RDOC_QTA, UNO);
rdoc.put(RDOC_QTAGG1, UNO);
rdoc.put(RDOC_PREZZO, riga.get_real(LVRCONDV_PREZNOL));
rdoc.put(RDOC_CHECKED, true);
rdoc.put(RDOC_UMQTA, riga.get(LVRCONDV_UM));
TToken_string key;
key.add('C');
key.add(codcf);
TString8 codiva = cache().get(LF_CFVEN, key, CFV_ASSFIS);
if (codiva.blank())
codiva = cache().get(LF_ANAMAG, riga.get(LVRCONDV_CODART), ANAMAG_CODIVA);
rdoc.put(RDOC_CODIVA, codiva);
rdoc.put(RDOC_CODAGG1, ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV"));
elab.set_perc_provv(rdoc);
elab.set_perc_provv(rdoc, false);
}
}
if (ini_get_bool(CONFIG_DITTA, "lv", "RifTest"))
elab.put("B15", true); //forzo la descrizione abbreviata
if (doc.physical_rows() > 0)
{
elab.elabora(doc_in, doc_out, _msk->get_date(F_DATAFAT));
int err = doc_out.write();
numdocgen += doc_out.items();
}
doc_out.destroy(-1);
doc_in.destroy(-1);
}
}
//CONTROLLI PRELIMINARI: metodo che si preoccupa di ferivicare la presenza in configurazione di tutti
//i dati necessari alla fatturazione
bool TFatturazione_lav_app::controlli_preliminari()
{
bool corretto = true;
//controllo se il tipo documento <20> configurato
if (ini_get_string(CONFIG_DITTA, "lv", "NUM_FAT").empty() || ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_FAT").empty())
{
warning_box(TR("Il Tipo documento fattura non <20> configurato correttamente"));
corretto = false;
}
//controllo se le causali di dafault sono configurate
if (ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV").empty())
{
warning_box(TR("La causale di default non <20> configurata correttamente"));
corretto = false;
}
if (ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT").empty())
{
warning_box(TR("La causale di default non <20> configurata correttamente"));
corretto = false;
}
//controllo se l'articolo per il canone fisso <20> configurato
if (ini_get_string(CONFIG_DITTA, "lv", "Codartfix").empty())
{
warning_box(TR("L'articolo per canone fisso non <20> configurato correttamente"));
corretto = false;
}
//controllo se l'articolo per il raggruppamento <20> configurato
if (ini_get_string(CONFIG_DITTA, "lv", "Codartcafix").empty())
{
warning_box(TR("L'articolo per il raggruppamento non <20> configurato correttamente"));
corretto = false;
}
//controllo se l'articolo per il raggruppamento <20> configurato
if (ini_get_string(CONFIG_DITTA, "lv", "Codartcofix").empty())
{
warning_box(TR("L'articolo per il valore convenzionale non <20> configurato correttamente"));
corretto = false;
}
//controllo se l'unit<69> di misura per la fatturazioni a Kg <20> settata
if(ini_get_string(CONFIG_DITTA, "lv", "UmKg").empty())
{
warning_box(TR("L'unit<69> di misura per la fatturazione a Kg non <20> configurata correttamente"));
corretto = false;
}
return corretto;
}
void TFatturazione_lav_app::main_loop()
{
bool prova = false;
if (main_app().argc() > 2)
{
TString16 tpela = main_app().argv(2);
tpela = tpela.mid(4);
prova = (tpela == "FatPro");
}
//instanzio la maschera
_msk = new TFatturazione_msk();
if (lv_is_02_active())
_msk->field(F_COD_ELAB).set_prompt("@BTipo Fatturazione ");
//instanzio i localisamfile che mi servono
TLocalisamfile doc(LF_DOC);
TLocalisamfile rdoc(LF_RIGHEDOC);
while (_msk->run()!= K_QUIT)
{
if (!controlli_preliminari())
{
TString str;
str << "Prima di poter eseguire la fatturazione <20> necessario correggre tutti gli errori segnalati. "
<< "Si prega di controllare i dati di configurazione";
warning_box(str);
return;
}
//leggo i dati di primo interesse
const TString4 mskzona = _msk->get(F_CODZONA);
const TString4 mskcat = _msk->get(F_CODCATC);
//preparo le date estremi (dal - al) della query e l'anno dell'esercizio
TDate al = _msk->get_date(F_ADATA);
//se la data "al" non <20> corretta, la pongo uguale alla data fattura
if (!al.ok())
al = _msk->get_date(F_DATAFAT);
const long year = al.year();
TDate dal = _msk->get_date(F_DADATA);
//se la data "dal" non <20> corretta, la pongo uguale a 1/1/annoes
if (!dal.ok())
{
dal.set_day(1);
dal.set_month(1);
dal.set_year(year);
}
//instanzio una TFatturaziome_lavanderie
TFatturazione_lavanderie elab(_msk->get(F_COD_ELAB), prova);
//preparo le variabili di interesse
TLista_documenti docsin;
TLista_documenti docsout;
long lastcli = 0;
const int period = _msk->get_int(F_PERFAT);
const TDate datafat = _msk->get_date(F_DATAFAT);
long indsped;
//preparo la query
TString query;
//&&(BETWEEN(DATADOC,#DADATA,#ADATA))&&(STATO==\"2\")&&(TIPODOC==\"B01\")
query << "USE DOC KEY 3 SELECT (TIPOCF==\"C\")&&"
<< "(BETWEEN(CODCF," << _msk->get_long(F_DACODCF) << ',' << _msk->get_long(F_ACODCF) << "))\n"
<< "BY TIPOCF CODCF DATADOC\n"
<< "FROM DATADOC=" << dal << " PROVV=D ANNO=" << year << "\n"
<< "TO DATADOC=" << al << " PROVV=D ANNO=" << year << "\n";
// query << "USE DOC KEY 2 SELECT BETWEEN(DATADOC,#DADATA,#ADATA)&&STATO==\"2\")&&(TIPODOC==\"B01\")\n"
// << "FROM " << "TIPOCF=C PROVV=D ANNO=#ANNO DATADOC=#DADATA \n"
// << "TO " << "TIPOCF=C PROVV=D ANNO=#ANNO DATADOC=#ADATA \n";
//instanzio il recordset
TISAM_recordset recset(query);
TProgind pi(recset.items(), "Fatturazione", true, true);
long last_clifo = 0;
int numdocgen = 0;
//TAssoc_array dei clienti per cui ho generato dei documenti
TAssoc_array cliela;
//scorro tutti documenti che la query mi restiuisce
for (bool ok = recset.move_first(); ok; ok = recset.move_next())
{
//leggo il codcf
const long clifo = recset.get(DOC_CODCF).as_int();
if (clifo != last_clifo)
{
TString80 str;
str << TR("Elaborazione Cliente ") << clifo;
pi.set_text(str);
last_clifo=clifo;
}
if (!pi.addstatus(1))
break;
//se non <20> l'ultimo cliente, allora:
if (clifo != lastcli)
{
//se effettivamente devo elaborare delle bolle per questo cliente, allora:
if (docsin.items()!= 0)
{
//elaboro tutti i documenti, li salvo nei file di Campo e svuoto le TList_file
elab.put("B15", 'X');
elab.elabora(docsin, docsout, datafat);
const int items = docsout.items();
if (items > 0)
{
docsout.write();
numdocgen += items;
TString tmp;
tmp << lastcli;
cliela.add(tmp, tmp);
}
docsout.destroy(-1);
docsin.rewrite();
docsin.destroy(-1);
}
lastcli = clifo;
}
//preparo la chiave e recupero da CFVEN i dati di quel cliente
TToken_string key;
key.add('C');
key.add(clifo);
const TRectype& clienti = cache().get(LF_CFVEN,key);
//se il documento che sto analizzando <20> corretto, allora:
bool cliok = elab.is_document_ok(recset.cursor()->curr());
if (cliok)
{
//se il codice di zona <20> pieno, allora:
if (mskzona.full())
{
//leggo il codice di zona standard di quel cliente e lo confronto con quello della mascera (V o F)
const TString& codzona = clienti.get(CFV_CODZONA);
cliok = (codzona == mskzona);
}
//se il codice categoria economica <20> pieno e ho passato il test sul codice di zona, allora:
if (cliok && mskcat.full())
{
//leggo il codice categoria economica standard di quel cliente e lo confronto con quello della mascera (V o F)
const TString& codcat = clienti.get(CFV_CODCATC);
cliok = (codcat == mskcat);
}
}
//se ho passato tutti e due i test, allora:
if (cliok)
{
//cerco sul contratto qual'<27> il periodo di fatturazione di quel cliente
indsped = recset.get(DOC_CODINDSP).as_int();
TLaundry_contract contr(clifo, indsped, datafat);
const int contrper = contr.get_int(LVCONDV_PERFAT);
//se il cliente non <20> sospeso e se si <20> nel periodo di fatturazione giusto, aggiungo il documento alla
//lista dei documetni da elaborare
if (!contr.get_bool(LVCONDV_FATTSOSP) && contrper <= period)
docsin.add(new TDocumento(recset.cursor()->curr()));
}
}
//se ho dei documenti in lista li elaboro e poi svuoto le TList_file
if (docsin.items() != 0)
{
if (ini_get_bool(CONFIG_DITTA, "lv", "RifTest"))
elab.put("B15", true); //forzo la descrizione abbreviata
elab.elabora(docsin, docsout, datafat);
const int items = docsout.items();
if (items > 0)
{
docsout.write();
numdocgen += items;
TString tmp;
tmp << lastcli;
cliela.add(tmp, tmp);
}
docsout.destroy(-1);
docsin.rewrite();
docsin.destroy(-1);
}
genera_bolle_nolo(cliela, elab, numdocgen);
numdocgen += elab.write_fatt_ragg();
TString str;
if (numdocgen > 1 || numdocgen == 0)
str << "Sono state generate " << numdocgen << " fatture";
else
str << "E' stata generata " << numdocgen << " fattura";
message_box(str);
message_box(TR("Elaborazione terminata"));
}
}
int lv2500(int argc, char *argv[])
{
TFatturazione_lav_app a;
a.run (argc, argv, "Fatturazione lavanderie");
return TRUE;
}