72f13d5022
Files correlati : lv2 Ricompilazione Demo : [ ] Commento : Corretto il controllo sulle righe da fatturare; prima se la causale movimentava sia la dotazione iniziale che il consegnato mese faceva due righe di fattura distinte; adesso per la stessa causale fattura solo la dotazione iniziale git-svn-id: svn://10.65.10.50/trunk@19437 c028cbd2-c16b-5b4b-a496-9718f37d4682
930 lines
37 KiB
C++
Executable File
930 lines
37 KiB
C++
Executable File
#include <progind.h>
|
||
#include <config.h>
|
||
|
||
#include "lvlib.h"
|
||
#include "lv2500a.h"
|
||
|
||
#include "cfven.h"
|
||
#include "lvcondv.h"
|
||
#include "lvrcondv.h"
|
||
#include "rdoc.h"
|
||
|
||
#include "../ve/ve6200.h"
|
||
#include "../ve/ve6200a.h"
|
||
|
||
////////////////////////////////////////
|
||
//// TFatturazione_lavanderie ////
|
||
////////////////////////////////////////
|
||
|
||
//Classe TFatturazione_lavanderie
|
||
class TFatturazione_lavanderie:public TFatturazione_bolle
|
||
{
|
||
TDate _data_elab;
|
||
TToken_string _campi_raggruppamento;
|
||
|
||
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_out) {}
|
||
virtual void post_process_output(TLista_documenti& doc_out);
|
||
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);
|
||
|
||
public:
|
||
virtual bool elabora(TLista_documenti& doc_in, TLista_documenti& doc_out,
|
||
const TDate& data_elab, bool interattivo = false);
|
||
|
||
TFatturazione_lavanderie(const char* cod);
|
||
~TFatturazione_lavanderie() {}
|
||
};
|
||
|
||
TFatturazione_lavanderie::TFatturazione_lavanderie(const char* cod)
|
||
: TFatturazione_bolle(cod)
|
||
|
||
{
|
||
}
|
||
|
||
//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;
|
||
}
|
||
|
||
//POST_PROCESS_OUTPUT: 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_output(TLista_documenti& doc_out)
|
||
{
|
||
//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");
|
||
|
||
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();
|
||
doc.put(DOC_NOTE, descr);
|
||
doc.destroy_row(1, true);
|
||
}
|
||
|
||
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
|
||
|
||
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);
|
||
|
||
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[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
|
||
{
|
||
//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
|
||
TArticolo_lavanderie artlav(codart, 'C', clifo, indsped);
|
||
|
||
//cerco la giacenza per articolo dell'articolo esaminato
|
||
const int index = artlav.find_clifomag(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 (index >=0)
|
||
{
|
||
if (tipodot=="I")
|
||
dot=artlav.clifomag(annoes)[index].get_real("DOTIN");
|
||
else
|
||
dot=artlav.clifomag(annoes)[index].get_real("DOTOD");
|
||
}
|
||
|
||
//leggo dalla riga contratto il tipo forfait
|
||
const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF);
|
||
|
||
switch (tipoforf)
|
||
{
|
||
case 0: //forfait = NESSUNO
|
||
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
|
||
TRiga_documento& nolorow = doc.insert_row(++i, "01");
|
||
doc.copy_data(nolorow, rout);
|
||
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;
|
||
}
|
||
nolorow.put(RDOC_DESCR,descr);
|
||
|
||
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;
|
||
|
||
//se il consumo <20> minore del ciclaggio, allora
|
||
if (consumo < impconv)
|
||
{
|
||
const bool cicl2rig = contr.get_bool(LVCONDV_CICLAGGIO);
|
||
//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
|
||
if (cicl2rig)
|
||
{
|
||
TRiga_documento& congrow = doc.insert_row(++i, "01");
|
||
doc.copy_data(congrow, rout);
|
||
congrow.put(RDOC_DESCR, "Conguaglio valore convenzionale");
|
||
congrow.put(RDOC_QTA, UNO);
|
||
congrow.put(RDOC_PREZZO, impconv - consumo);
|
||
}
|
||
else
|
||
{
|
||
rout.put(RDOC_QTA, UNO);
|
||
rout.put(RDOC_PREZZO, impconv);
|
||
}
|
||
}
|
||
}
|
||
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;
|
||
|
||
//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);
|
||
if (tipvalconvcli == 'C')
|
||
{
|
||
impconvtot += dot * rcont.get_real(LVRCONDV_VALCONV) * rcont.get_real(LVRCONDV_FORFPERCL);
|
||
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);
|
||
//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)
|
||
{
|
||
TRiga_documento& congrow=doc.insert_row(++i, "01");
|
||
doc.copy_data(congrow, rout);
|
||
congrow.put(RDOC_DESCR, "Conguaglio valore convenzionale");
|
||
congrow.put(RDOC_QTA, UNO);
|
||
congrow.put(RDOC_PREZZO, impconvtot - consumotot);
|
||
}
|
||
else
|
||
{
|
||
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);
|
||
if (tipvalconvcli == 'C')
|
||
doc.destroy_row(k, true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case 5: //forfait = FISSO SU DOTAZIONE INIZIALE
|
||
{
|
||
|
||
rout.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_IMPFISART));
|
||
rout.put(RDOC_QTA, artlav.clifomag(annoes)[index].get_real("DOTIN"));
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//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
|
||
{
|
||
//richiamo la funzione standard
|
||
TFatturazione_bolle::campi_raggruppamento_righe(campi_riga);
|
||
//se lo standard lascia campi_riga vuota, allora la pongo uguale a "CODART|UMQTA"
|
||
//che sono sicuramente sempre uguali
|
||
if (campi_riga.empty())
|
||
campi_riga = "CODART|UMQTA"; // Uguali sempre
|
||
}
|
||
|
||
//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");
|
||
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);
|
||
}
|
||
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(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_int(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.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);
|
||
}
|
||
}
|
||
|
||
//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())
|
||
{
|
||
TRiga_documento& rc = find_or_create_row(doc_out, rin, 'I');
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//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);
|
||
return TFatturazione_bolle::elabora(doc_in, doc_out, data_elab, interattivo);
|
||
}
|
||
|
||
/////////////////////////////////
|
||
//// TFatturazione_msk ////
|
||
/////////////////////////////////
|
||
|
||
//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_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);
|
||
}
|
||
}
|
||
|
||
/////////////////////////////////////
|
||
//// TFatturazione_lav_app ////
|
||
/////////////////////////////////////
|
||
|
||
//classe TFatturazione_lav_app
|
||
class TFatturazione_lav_app: public TSkeleton_application
|
||
{
|
||
protected:
|
||
virtual void main_loop();
|
||
};
|
||
|
||
void TFatturazione_lav_app::main_loop()
|
||
{
|
||
//instanzio la maschera
|
||
TFatturazione_msk msk;
|
||
|
||
//instanzio i localisamfile che mi servono
|
||
TLocalisamfile doc(LF_DOC);
|
||
TLocalisamfile rdoc(LF_RIGHEDOC);
|
||
|
||
while (msk.run()!=K_QUIT)
|
||
{
|
||
//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));
|
||
//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_int(F_DACODCF) << ',' << msk.get_int(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;
|
||
//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);
|
||
docsout.write();
|
||
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);
|
||
docsout.write();
|
||
docsout.destroy(-1);
|
||
docsin.rewrite();
|
||
docsin.destroy(-1);
|
||
}
|
||
}
|
||
}
|
||
|
||
int lv2500(int argc, char *argv[])
|
||
{
|
||
TFatturazione_lav_app a;
|
||
a.run (argc, argv, "Fatturazione lavanderie");
|
||
return TRUE;
|
||
}
|