82b76f399a
Aggiunto nuovo tipo di fatturazione con importo totale minimo Aggiunto flag per non riportare le note da bolla a fattura Aggiunte colonne di dotazione a buoni di ritiro Aggiunta nuova proposta causale di consegna su nuovo documento git-svn-id: svn://10.65.10.50/branches/R_10_00@22806 c028cbd2-c16b-5b4b-a496-9718f37d4682
2586 lines
88 KiB
C++
Executable File
2586 lines
88 KiB
C++
Executable File
#include <dongle.h>
|
||
#include <progind.h>
|
||
#include <reputils.h>
|
||
#include <utility.h>
|
||
|
||
#include "lvlib.h"
|
||
#include "lv2500a.h"
|
||
|
||
#include "../pr/agenti.h"
|
||
#include "../pr/percprov.h"
|
||
#include "../cg/cfban.h"
|
||
#include "../cg/cglib03.h"
|
||
|
||
#include "clifo.h"
|
||
#include "comuni.h"
|
||
#include "cfven.h"
|
||
#include "lvcondv.h"
|
||
#include "lvrcondv.h"
|
||
|
||
#include "../ve/ve6200.h"
|
||
#include "../ve/ve6200a.h"
|
||
|
||
#define DOC_DEST "DEST" //c campo virtuale per la destinazone
|
||
|
||
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;
|
||
TLog_report * _log;
|
||
bool _solototali;
|
||
|
||
protected:
|
||
virtual void main_loop();
|
||
|
||
void genera_bolle_nolo(TAssoc_array& cliela, TFatturazione_lavanderie& elab, int& numdocgen, real& totimp, real& imposta, real& totdoc, real& spese);
|
||
bool controlli_preliminari();
|
||
bool copy_file(const TFilename& src, const TFilename& dst) const;
|
||
bool copy_tree(const char* src_study, const char* dst_study) const;
|
||
};
|
||
|
||
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;
|
||
long _last_cli_damn;
|
||
int _art_damn;
|
||
int _cli_damn;
|
||
|
||
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:
|
||
bool is_document_compatible(const TRectype & doc) const;
|
||
int write_fatt_ragg(const bool solotot);
|
||
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);
|
||
long & last_cli_damn() {return _last_cli_damn;}
|
||
int & cli_damn() {return _cli_damn;}
|
||
int & art_damn() {return _art_damn;}
|
||
|
||
TFatturazione_lavanderie(const char* cod, bool prova = false);
|
||
~TFatturazione_lavanderie() {}
|
||
};
|
||
|
||
TFatturazione_lavanderie::TFatturazione_lavanderie(const char* cod, bool prova)
|
||
: TFatturazione_bolle(cod), _prova(prova)
|
||
{
|
||
}
|
||
|
||
bool TFatturazione_lavanderie::is_document_compatible(const TRectype & doc) const
|
||
{
|
||
bool ok = false;
|
||
const TString4 codnum(doc.get(DOC_CODNUM));
|
||
const TString4 tipodoc(doc.get(DOC_TIPODOC));
|
||
const char stato(doc.get_char(DOC_STATO));
|
||
const TString& codnumel = codice_numerazione_iniziale();
|
||
|
||
if (codnumel.blank() || codnum == codnumel)
|
||
{
|
||
for (int i = 0; !ok && i < TElaborazione::_max_tipi_doc_elab; i++)
|
||
{
|
||
const TString & tipel = tipo_iniziale(i);
|
||
if (tipel.blank())
|
||
break;
|
||
if (tipodoc == tipel)
|
||
ok = true;
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
//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;
|
||
|
||
//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
|
||
{
|
||
const TString& 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();
|
||
|
||
TString str_real;
|
||
for (int i = 1; i <= rows; i++)
|
||
{
|
||
TRiga_documento& row = doc[i];
|
||
str_real = row.get(RDOC_QTAREALE);
|
||
if (str_real.full())
|
||
{
|
||
const 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())
|
||
{
|
||
const real qta_real(decode(str_real));
|
||
row.put(RDOC_QTAGG1, qta_real);
|
||
row.zero(RDOC_QTARITREALE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//aggiunge una riga fittizia al documento con qta a zero per gli articoli per cui <20> previsto il forfait
|
||
//e che non sono stati consegnati
|
||
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, 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, cached_article(codart).first_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(const bool solotot)
|
||
{
|
||
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 && !solotot)
|
||
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)
|
||
{
|
||
const bool use_indsp = ini_get_bool(CONFIG_DITTA, "mg", "MOV_INDSPED");
|
||
const bool riftest = ini_get_bool(CONFIG_DITTA, "lv", "RifTest");
|
||
const bool zero_note = ini_get_bool(CONFIG_DITTA, "lv", "ZeroNote");
|
||
|
||
//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);
|
||
|
||
const int alleg = doc.clifor().get_int(CLI_ALLEG);
|
||
const bool liqdiff = alleg == 7 && doc.clifor().vendite().get_bool(CFV_FATTSOSP);
|
||
real consvconv;
|
||
real impvconv;
|
||
TAssoc_array nolo_computed;
|
||
|
||
doc.zero(DOC_LIQDIFF);
|
||
doc.zero(DOC_IVAXCASSA);
|
||
if (liqdiff)
|
||
{
|
||
doc.put(DOC_LIQDIFF, "X");
|
||
}
|
||
else
|
||
{
|
||
if ((alleg < 5 || alleg == 7) && doc.clifor().get(CLI_PAIV).full() &&
|
||
gestione_IVAxCassa(doc.get_date(DOC_DATADOC)))
|
||
{
|
||
doc.put(DOC_IVAXCASSA, "X");
|
||
}
|
||
}
|
||
if (doc.physical_rows() > 0 && doc[1].is_descrizione())
|
||
{
|
||
if (elcons)
|
||
{
|
||
TRiga_documento& rout = doc[1];
|
||
rout.put(RDOC_DESCR, TR("COME DA ELENCO CONSEGNE"));
|
||
rout.put(RDOC_DESCLUNGA, false);
|
||
rout.put(RDOC_DESCEST, "");
|
||
}
|
||
else
|
||
if (!rifbol)
|
||
doc.destroy_row(1, true);
|
||
}
|
||
|
||
if (zero_note)
|
||
doc.zero(DOC_NOTE);
|
||
|
||
//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);
|
||
}
|
||
aggiorna_fattura(doc, contr.get_int(LVCONDV_CODCONT));
|
||
if (doc.physical_rows() > 0)
|
||
doc.sort_rows(RDOC_CODART "|LVTYPE");
|
||
|
||
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);
|
||
const TString descragg = cache().get(LF_ANAMAG, codartcfg, ANAMAG_DESCRAGG);
|
||
|
||
// 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);
|
||
if (descragg.full())
|
||
{
|
||
riga.put(RDOC_DESCLUNGA, "X");
|
||
riga.put(RDOC_DESCEST, descragg);
|
||
}
|
||
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 = cached_article(codartcfg).get(ANAMAG_DESCR);
|
||
const TString descragg = cached_article(codartcfg).get(ANAMAG_DESCRAGG);
|
||
|
||
// 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);
|
||
if (descragg.full())
|
||
{
|
||
fixrow.put(RDOC_DESCLUNGA, "X");
|
||
fixrow.put(RDOC_DESCEST, descragg);
|
||
}
|
||
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);
|
||
const int annoes = _data_elab.year();
|
||
real dot;
|
||
|
||
//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 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.is_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) / CENTO;
|
||
|
||
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);
|
||
const 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 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 dell'importo convenzionale, 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);
|
||
const TString descragg = cached_article(codart).get(ANAMAG_DESCRAGG);
|
||
|
||
rout.put(RDOC_DESCR, descr);
|
||
if (descragg.full())
|
||
{
|
||
rout.put(RDOC_DESCLUNGA, "X");
|
||
rout.put(RDOC_DESCEST, descragg);
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
if (tipocan == 3)
|
||
{
|
||
const real canfis = contr.get_real(LVCONDV_IMPFIX);
|
||
const real imponibile = doc.imponibile();
|
||
if (canfis > imponibile)
|
||
{
|
||
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);
|
||
|
||
TString4 codiva = doc.clifor().vendite().get(CFV_ASSFIS);
|
||
if (codiva.blank())
|
||
codiva = cache().get(LF_ANAMAG, codartcon, ANAMAG_CODIVA);
|
||
|
||
congrow.put(RDOC_CODIVA, codiva);
|
||
|
||
congrow.put(RDOC_PREZZO, canfis - imponibile);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//se il consumo <20> minore del ciclaggio, allora
|
||
if (impvconv > consvconv)
|
||
{
|
||
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 || redditivita >= CENTO) && (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(wkey1);
|
||
const long ndoc = bolkey.get_long(3);
|
||
const long id = bolkey.get_long(4);
|
||
|
||
for (int i = 0; i < doc_in.items(); i++)
|
||
{
|
||
TDocumento& docb = doc_in[i];
|
||
|
||
if (docb.get_long(DOC_NDOC) == ndoc)
|
||
{
|
||
TRiga_documento * bolrow = (TRiga_documento *) docb.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_reccli = cache().get(LF_CLIFO, key);
|
||
const TRectype & new_reccliven = cache().get(LF_CFVEN, key);
|
||
TLaundry_contract contr(new_cli, doc.get_long(DOC_CODINDSP), _data_elab);
|
||
|
||
if (new_reccli.get_int(CLI_ALLEG) == 7 && new_reccliven.get_bool(CFV_FATTSOSP))
|
||
doc.put(DOC_LIQDIFF, "X");
|
||
doc.put(DOC_CODINDSP, new_reccliven.get(CFV_CODINDDOC));
|
||
|
||
TString descr;
|
||
|
||
if (ini_get_bool(CONFIG_DITTA, "lv", "DestHead"))
|
||
{
|
||
descr << reccli.get(CLI_RAGSOC) << ", ";
|
||
descr << reccli.get(CLI_INDCF) << ' ' << reccli.get(CLI_CIVCF) << ", ";
|
||
descr << reccli.get(CLI_LOCCF) << ", ";
|
||
TToken_string keyc = reccli.get(CLI_STATOCF);
|
||
|
||
keyc.add(reccli.get(CLI_COMCF));
|
||
const TRectype & com = cache().get(LF_COMUNI, keyc);
|
||
descr << reccli.get(CLI_CAPCF) << ' ' << com.get(COM_DENCOM);
|
||
doc.put(DOC_DEST, descr);
|
||
}
|
||
else
|
||
{
|
||
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);
|
||
}
|
||
|
||
}
|
||
}
|
||
if (fatt_02())
|
||
{
|
||
for (int id = doc_in.items() - 1; id >= 0 ; id--)
|
||
{
|
||
TDocumento & doc = doc_in[id];
|
||
const long clifo = doc.get_long(DOC_CODCF);
|
||
const int indsped = doc.get_int(DOC_CODINDSP);
|
||
TLaundry_contract contr(clifo,indsped,_data_elab);
|
||
const real redditivita = contr.get_real(LVCONDV_REDDI);
|
||
|
||
if (redditivita >= CENTO)
|
||
{
|
||
doc_in[id].remove();
|
||
doc_in.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));
|
||
if (cau.get_int("I2") > 0)
|
||
{
|
||
rd.put(RDOC_QTAGG1, cau.get("I0"));
|
||
rd.put(RDOC_QTAGG2, cau.get("I1"));
|
||
rd.put(RDOC_QTAGG3, cau.get("I2"));
|
||
}
|
||
if (clifo != _last_cli_damn)
|
||
_cli_damn++;
|
||
_last_cli_damn = clifo;
|
||
_art_damn++;
|
||
}
|
||
|
||
//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, real& totimp, real& imposta, real& totdoc, real& spese)
|
||
{
|
||
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);
|
||
|
||
//il nolo deve esserci sempre, il ciclaggio solo se fattnocons -> per me l'if diventa:
|
||
//if (tipoforf > 0 && (tipoforf != 2 && fattnocons))
|
||
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));
|
||
real r = UNO;
|
||
if(tipoforf == 3 || tipoforf == 4)
|
||
r = ZERO;
|
||
rdoc.put(RDOC_QTA, r);
|
||
rdoc.put(RDOC_QTAGG1, r);
|
||
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));
|
||
if (!_solototali)
|
||
int err = doc_out.write();
|
||
numdocgen += doc_out.items();
|
||
|
||
if (doc_out.items() > 0)
|
||
{
|
||
totimp += doc_out[0].imponibile();
|
||
imposta += doc_out[0].imposta();
|
||
totdoc += doc_out[0].totale_doc();
|
||
spese += doc_out[0].spese();
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
bool TFatturazione_lav_app::copy_file(const TFilename& src, const TFilename& dst) const
|
||
{
|
||
// Crea la cartella di destinazione se necessario
|
||
const char* dstdir = dst.path();
|
||
if (*dstdir && !xvt_fsys_mkdir(dstdir))
|
||
return error_box(FR("Impossibile creare la cartella %s"), dst.path());
|
||
|
||
// Copia veramente il file
|
||
return ::fcopy(src, dst);
|
||
}
|
||
|
||
bool TFatturazione_lav_app::copy_tree(const char* src_study, const char* dst_study) const
|
||
{
|
||
xvt_fsys_save_dir();
|
||
TFilename mask(src_study); mask.add("*.");
|
||
SLIST dlist = xvt_fsys_list_files(DIR_TYPE, mask, TRUE);
|
||
xvt_fsys_restore_dir();
|
||
TProgind pd(xvt_slist_count(dlist), TR("Copia cartelle"), true, true);
|
||
|
||
TString msg; // Messaggio di progresso
|
||
|
||
bool go_on = true;
|
||
for (SLIST_ELT d = xvt_slist_get_first(dlist); d && go_on; d = xvt_slist_get_next(dlist, d))
|
||
{
|
||
if (!pd.addstatus(1))
|
||
{
|
||
go_on = false;
|
||
break;
|
||
}
|
||
|
||
const TFilename dir = xvt_slist_get(dlist, d, NULL);
|
||
|
||
TString name = dir.name(); name.lower();
|
||
if (name == "cesp") // Ignora la vetusta cartella Cespiti in FoxPro
|
||
continue;
|
||
|
||
msg.cut(0) << TR("Copia di ") << name;
|
||
pd.set_text(msg);
|
||
|
||
mask = dir; mask.add("*.*");
|
||
TString_array files; list_files(mask, files);
|
||
|
||
TProgind pi(files.items(), "Copia file", true, true);
|
||
|
||
TFilename dst;
|
||
FOR_EACH_ARRAY_ROW(files, i, f)
|
||
{
|
||
if (!pi.addstatus(1))
|
||
{
|
||
go_on = false;
|
||
break;
|
||
}
|
||
TFilename src(*f);
|
||
TString16 ext(src.ext()); ext.lower();
|
||
if (ext != "zip" && ext != "rar" && ext != "mdb" && ext != "inf")
|
||
{
|
||
msg.cut(0) << TR("Copia di ") << src;
|
||
pi.set_text(msg);
|
||
|
||
dst = dst_study;
|
||
dst.add(name);
|
||
dst.add(src.name());
|
||
copy_file(src, dst);
|
||
}
|
||
}
|
||
}
|
||
xvt_slist_destroy(dlist);
|
||
|
||
return go_on;
|
||
}
|
||
|
||
void TFatturazione_lav_app::main_loop()
|
||
{
|
||
bool prova = false;
|
||
const bool use_indsp = ini_get_bool(CONFIG_DITTA, "mg", "MOV_INDSPED");
|
||
const bool prezzo_da_contratto = ini_get_int(CONFIG_DITTA, "lv", "Tipopr") == 0;
|
||
const bool agghead = prezzo_da_contratto || ini_get_bool(CONFIG_DITTA, "lv", "AggHead");
|
||
const TString4 num_buoni = ini_get_string(CONFIG_DITTA, "lv", "NUM_GEN");
|
||
const TString4 tipo_buoni = ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_GEN");
|
||
|
||
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();
|
||
_msk->show(F_SAVEDATA, lv_is_02_active());
|
||
|
||
|
||
//instanzio i localisamfile che mi servono
|
||
TLocalisamfile doc(LF_DOC);
|
||
TLocalisamfile rdoc(LF_RIGHEDOC);
|
||
|
||
while (_msk->run()!= K_QUIT)
|
||
{
|
||
_solototali = _msk->get_bool(F_SOLOTOTALI);
|
||
const int annoes = _msk->get_date(F_DATAFAT).year();
|
||
|
||
|
||
if (!controlli_preliminari())
|
||
{
|
||
TString str;
|
||
str << "Prima di poter eseguire la fatturazione <20> necessario correggere tutti gli errori segnalati.\n"
|
||
<< "Si prega di controllare i dati di configurazione.";
|
||
warning_box(str);
|
||
return;
|
||
}
|
||
_log = new TLog_report("Fatturazione");
|
||
|
||
if (_msk->get_bool(F_SAVEDATA))
|
||
{
|
||
TFilename src = firm2dir(-1);
|
||
TFilename dst = ini_get_string(CONFIG_DITTA, "lv", "Backup");
|
||
|
||
copy_tree(src, dst);
|
||
}
|
||
//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;
|
||
TToken_string tipi;
|
||
TToken_string stati;
|
||
TString stato_min("Z");
|
||
|
||
elab.last_cli_damn() = -1L;
|
||
elab.cli_damn() = 0;
|
||
elab.art_damn() = 0;
|
||
elab.tipi_stati_iniziali(tipi, stati);
|
||
|
||
for (const char * s = stati.get(); s > " "; s = stati.get())
|
||
if (stato_min > s)
|
||
stato_min = s;
|
||
|
||
//preparo la query
|
||
TString query;
|
||
const TString& fromcod = _msk->get(F_DACODCF);
|
||
const TString& tocod = _msk->get(F_ACODCF);
|
||
|
||
//&&(BETWEEN(DATADOC,#DADATA,#ADATA))&&(STATO==\"2\")&&(TIPODOC==\"B01\")
|
||
query << "USE DOC KEY 3 SELECT (TIPOCF==\"C\")&&"
|
||
<< "STR(BETWEEN(CODCF,\"" << fromcod << "\",\"" << tocod << "\"))\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 recordset011
|
||
|
||
TISAM_recordset recset(query);
|
||
recset.set_var("#DAL", dal);
|
||
recset.set_var("#AL", al);
|
||
TProgind pi(recset.items(), TR("Fatturazione"), true, true);
|
||
long last_clifo = 0;
|
||
int numdocgen = 0;
|
||
int numdocscart = 0;
|
||
bool space = true;
|
||
real totimp;
|
||
real imposta;
|
||
real totdoc;
|
||
real spese;
|
||
TToken_string key;
|
||
|
||
//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)
|
||
{
|
||
key.format("C|%ld", clifo);
|
||
TString str;
|
||
str << TR("Cliente") << ' ' << clifo << ' ' << cache().get(LF_CLIFO, key, CLI_RAGSOC);
|
||
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)
|
||
{
|
||
if (!_solototali)
|
||
docsout.write();
|
||
numdocgen += items;
|
||
TString8 tmp;
|
||
tmp << lastcli;
|
||
cliela.add(tmp, tmp);
|
||
}
|
||
else if (!_solototali && docsout.items() == 0) //il messaggio deve comparire solo se non ho generato fatture
|
||
{
|
||
key.format("C|%ld", lastcli);
|
||
TString str;
|
||
str << "Cli. " << lastcli << ' ' << cache().get(LF_CLIFO, key, CLI_RICALT) << " non ha generato la fattura pur avendo bolle";
|
||
_log->log(0, str);
|
||
numdocscart++;
|
||
}
|
||
|
||
//solo totali
|
||
if(_solototali)
|
||
{
|
||
for (int i = 0; i < items; i++)
|
||
{
|
||
const TDocumento & doc = docsout[i];
|
||
|
||
totimp += doc.imponibile();
|
||
imposta += doc.imposta();
|
||
totdoc += doc.totale_doc();
|
||
spese += doc.spese();
|
||
}
|
||
}
|
||
|
||
docsout.destroy(-1);
|
||
if (!_solototali)
|
||
docsin.rewrite();
|
||
docsin.destroy(-1);
|
||
}
|
||
lastcli = clifo;
|
||
space = true;
|
||
}
|
||
|
||
//preparo la chiave e recupero da CFVEN i dati di quel cliente
|
||
key.format("C|%ld", clifo);
|
||
const TRectype& clienti = cache().get(LF_CFVEN,key);
|
||
const TRectype& docrec = recset.cursor()->curr();
|
||
const TRectype& clirec = cache().get(LF_CLIFO,key);
|
||
|
||
//se il documento che sto analizzando <20> corretto, allora:
|
||
bool cliok = elab.is_document_ok(docrec);
|
||
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 maschera (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 maschera (V o F)
|
||
const TString& codcat = clienti.get(CFV_CODCATC);
|
||
cliok = (codcat == mskcat);
|
||
}
|
||
}
|
||
else
|
||
if (!_solototali && elab.is_document_compatible(docrec) && docrec.get(DOC_STATO) < stato_min)
|
||
{
|
||
if (space)
|
||
//_log->log(0, "");
|
||
space = false;
|
||
TString msg;
|
||
msg << "Cli. " << clifo << ' ' << clirec.get(CLI_RICALT) << " Bolla n. " << docrec.get(DOC_NDOC) << " del " << docrec.get(DOC_DATADOC) << " in stato " << docrec.get(DOC_STATO);
|
||
_log->log(0, msg);
|
||
}
|
||
|
||
//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);
|
||
if(!contr.ok())
|
||
{
|
||
TString msg;
|
||
msg << TR("Non ci sono contratti in essere per il cliente ") << clifo << " " << clirec.get(CLI_RICALT) << TR(" in data ") << datafat.string();
|
||
_log->log(0, msg);
|
||
}
|
||
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 documenti da elaborare
|
||
if (!contr.get_bool(LVCONDV_FATTSOSP) && contrper <= period)
|
||
{
|
||
TDocumento * doc = new TDocumento(recset.cursor()->curr());
|
||
|
||
if (agghead && !_solototali && doc->get(DOC_CODNUM) == num_buoni && doc->tipo().codice() == tipo_buoni)
|
||
{
|
||
|
||
bool doc_updated = false;
|
||
// banche
|
||
|
||
key.cut(0);
|
||
key.add(clirec.get(CLI_TIPOCF));
|
||
key.add(clirec.get(CLI_CODCF));
|
||
key.add("V");
|
||
key.add("1");
|
||
|
||
const TRectype & cfban = cache().get(LF_CFBAN, key);
|
||
TString8 abi;
|
||
TString8 cab;
|
||
TString iban;
|
||
|
||
if (cfban.empty())
|
||
{
|
||
abi = clirec.get(CLI_CODABI);
|
||
cab = clirec.get(CLI_CODCAB);
|
||
iban = clirec.get(CLI_IBAN);
|
||
}
|
||
else
|
||
{
|
||
abi = cfban.get(CFBAN_ABI);
|
||
cab = cfban.get(CFBAN_CAB);
|
||
iban = cfban.get(CFBAN_IBAN);
|
||
}
|
||
if (cab.full() && cab != "00000")
|
||
{
|
||
doc_updated |= (doc->get(DOC_CODABIA) != abi) || (doc->get(DOC_CODCABA) != cab);
|
||
doc->put(DOC_CODABIA, abi);
|
||
doc->put(DOC_CODCABA, cab);
|
||
doc->put(DOC_IBAN, iban);
|
||
}
|
||
key.cut(0);
|
||
key.add(clirec.get(CLI_TIPOCF));
|
||
key.add(clirec.get(CLI_CODCF));
|
||
key.add("N");
|
||
key.add("1");
|
||
|
||
const TRectype & cfbanpr = cache().get(LF_CFBAN, key);
|
||
int progbnp = 0;
|
||
|
||
if (cfbanpr.empty())
|
||
{
|
||
abi = clienti.get(CFV_CODABIPR);
|
||
cab = clienti.get(CFV_CODCABPR);
|
||
}
|
||
else
|
||
{
|
||
abi = cfbanpr.get(CFBAN_ABI);
|
||
cab = cfbanpr.get(CFBAN_CAB);
|
||
progbnp = cfbanpr.get_int(CFBAN_PROGPR);
|
||
}
|
||
|
||
if (cab.full() && cab != "00000")
|
||
{
|
||
doc_updated |= (doc->get(DOC_CODABIP) != abi) || (doc->get(DOC_CODCABP) != cab);
|
||
doc->put(DOC_CODABIP, abi);
|
||
doc->put(DOC_CODCABP, cab);
|
||
doc->put(DOC_PROGBNP, progbnp);
|
||
}
|
||
const TString8 codpag = clirec.get(CLI_CODPAG);
|
||
if (codpag.full())
|
||
{
|
||
doc_updated |= (doc->get(DOC_CODPAG) != codpag);
|
||
doc->put(DOC_CODPAG, codpag);
|
||
}
|
||
const TString8 spinc = clienti.get(CFV_PERCSPINC);
|
||
if (spinc.full())
|
||
{
|
||
doc_updated |= (doc->get(DOC_PERCSPINC) != spinc);
|
||
doc->put(DOC_PERCSPINC, spinc);
|
||
}
|
||
const bool addbolli = clienti.get_bool(CFV_ADDBOLLI);
|
||
doc_updated |= (doc->get_bool(DOC_ADDBOLLI) != addbolli);
|
||
doc->put(DOC_ADDBOLLI, addbolli);
|
||
const TString agente1 = clienti.get(CFV_CODAG1);
|
||
if (agente1.full())
|
||
{
|
||
doc_updated |= (doc->get(DOC_CODAGVIS) != agente1);
|
||
doc->put(DOC_CODAGVIS, agente1);
|
||
}
|
||
if (doc_updated)
|
||
{
|
||
if (space)
|
||
//_log->log(0, "");
|
||
space = false;
|
||
|
||
TString msg(" Cli.");
|
||
msg << clifo << " " << clirec.get(CLI_RICALT) << "Bolla " << docrec.get(DOC_CODNUM) << ' ' << docrec.get(DOC_TIPODOC) << ' ' << docrec.get(DOC_NDOC) << " del " << docrec.get(DOC_DATADOC) << " aggiornata la testata ";
|
||
_log->log(0, msg);
|
||
}
|
||
}
|
||
for (int r = 1; !_solototali && r <= doc->physical_rows(); r++)
|
||
{
|
||
const TRiga_documento& rdoc = (*doc)[r];
|
||
const TString80 codart = rdoc.get(RDOC_CODARTMAG);
|
||
|
||
if (codart.full())
|
||
{
|
||
const TRectype & rcont = contr.row(codart);
|
||
const 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);
|
||
|
||
if (space)
|
||
//_log->log(0, "");
|
||
space = false;
|
||
|
||
TString str;
|
||
str << "Cli." << clifo << ' ' << clirec.get(CLI_RICALT) << " Bolla " << docrec.get(DOC_CODNUM) << ' ' << docrec.get(DOC_TIPODOC)
|
||
<< ' ' << docrec.get(DOC_NDOC) << " del " << docrec.get(DOC_DATADOC) << " art." << codart << " - ";
|
||
|
||
if (rec.get_real("DOTOD") < ZERO)
|
||
{
|
||
TString msg;
|
||
msg << str << " Dot.odier.negativa";
|
||
_log->log(0, msg);
|
||
}
|
||
if (rec.get_real("DOTIN") < ZERO)
|
||
{
|
||
TString msg;
|
||
msg << str << " Dot.iniz.negativa";
|
||
_log->log(0, msg);
|
||
}
|
||
|
||
bool prezzo_nullo = false;
|
||
if (prezzo_da_contratto)
|
||
{
|
||
// Segnalo prezzo nullo solo se il contratto non <20> ad importo fisso (07/11/2011)
|
||
prezzo_nullo = rcont.get_real(LVRCONDV_PREZZO).is_zero() && contr.get_real(LVCONDV_IMPFIX).is_zero();
|
||
}
|
||
else
|
||
{
|
||
prezzo_nullo = rdoc.get_real(RDOC_PREZZO).is_zero(); // Prezzo sulla bolla
|
||
}
|
||
if (prezzo_nullo)
|
||
{
|
||
const TString8 causale = rdoc.get(RDOC_CODAGG1);
|
||
const TCausale_lavanderie& cau = cached_causale_lavanderie(causale);
|
||
if (!cau.ignora_prezzo_zero()) // Segnalo anomalia solo se la causale lo prevede (07/11/2011)
|
||
{
|
||
TString msg;
|
||
msg << str << " Prezzo zero ";
|
||
if (prezzo_da_contratto)
|
||
msg << "sul contratto";
|
||
else
|
||
msg << "sulla bolla";
|
||
_log->log(0, msg);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
docsin.add(doc);
|
||
}
|
||
}
|
||
}
|
||
|
||
//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)
|
||
{
|
||
if (!_solototali)
|
||
docsout.write();
|
||
numdocgen += items;
|
||
TString tmp;
|
||
tmp << lastcli;
|
||
cliela.add(tmp, tmp);
|
||
for (int i = 0; i < items; i++)
|
||
{
|
||
const TDocumento & doc = docsout[i];
|
||
|
||
totimp += doc.imponibile();
|
||
imposta += doc.imposta();
|
||
totdoc += doc.totale_doc();
|
||
spese += doc.spese();
|
||
}
|
||
}
|
||
else
|
||
if (!_solototali)
|
||
{
|
||
if (space)
|
||
//_log->log(0, "");
|
||
space = false;
|
||
|
||
TString str;
|
||
TToken_string key;
|
||
|
||
key.add('C');
|
||
key.add(lastcli);
|
||
str << "Cli." << lastcli << ' ' << cache().get(LF_CLIFO, key, CLI_RICALT) << " non ha generato la fattura pur avendo bolle";
|
||
_log->log(0, str);
|
||
numdocscart++;
|
||
}
|
||
docsout.destroy(-1);
|
||
if (!_solototali)
|
||
docsin.rewrite();
|
||
docsin.destroy(-1);
|
||
}
|
||
|
||
genera_bolle_nolo(cliela, elab, numdocgen, totimp, imposta, totdoc, spese);
|
||
numdocgen += elab.write_fatt_ragg(_solototali);
|
||
|
||
TString str;
|
||
const char* const parolapl = _solototali ? TR("generate") : TR("elaborate");
|
||
const char* const parolasi = _solototali ? TR("generata") : TR("elaborata");
|
||
|
||
switch (numdocgen)
|
||
{
|
||
case 0: str << TR("Non <20> stata ") << parolasi << TR(" alcuna fattura"); break;
|
||
case 1: str << TR("E' stata ") << parolasi << TR(" una fattura"); break;
|
||
default: str << TR("Sono state ") << parolapl << ' ' << numdocgen << TR(" fatture"); break;
|
||
}
|
||
if (numdocgen <= 0)
|
||
warning_box(str);
|
||
else
|
||
message_box(str);
|
||
|
||
message_box(TR("Elaborazione terminata"));
|
||
str = TR("Clienti Danneggati Articoli danneggiati");
|
||
_log->log(0, str);
|
||
str.format(" %5d %5d", elab.cli_damn(), elab.art_damn());
|
||
_log->log(0, str);
|
||
str = "Numero fatture Imponibile Imposta Totale Spese";
|
||
_log->log(0, str);
|
||
str.format(" %5d", numdocgen);
|
||
str << totimp.stringa(17) << imposta.stringa(16) << totdoc.stringa(15) << spese.stringa(17);
|
||
_log->log(0, str);
|
||
str = TR("Numero fatture scartate");
|
||
_log->log(0, str);
|
||
str.format(" %5d", numdocscart);
|
||
_log->log(0, str);
|
||
_log->print_or_preview();
|
||
delete _log;
|
||
}
|
||
}
|
||
|
||
int lv2500(int argc, char *argv[])
|
||
{
|
||
TFatturazione_lav_app a;
|
||
a.run (argc, argv, TR("Fatturazione lavanderie"));
|
||
return TRUE;
|
||
}
|