git-svn-id: svn://10.65.10.50/branches/R_10_00@23175 c028cbd2-c16b-5b4b-a496-9718f37d4682
1716 lines
48 KiB
C++
Executable File
1716 lines
48 KiB
C++
Executable File
#include "velib05.h"
|
||
#include "ve1300a.h"
|
||
|
||
#include <applicat.h>
|
||
#include <automask.h>
|
||
#include <defmask.h>
|
||
#include <dongle.h>
|
||
#include <postman.h>
|
||
#include <progind.h>
|
||
#include <reprint.h>
|
||
#include <reputils.h>
|
||
#include <spotlite.h>
|
||
#include <statbar.h>
|
||
#include <textset.h>
|
||
#include <utility.h>
|
||
|
||
#include <clifo.h>
|
||
#include <cfven.h>
|
||
#include <comuni.h>
|
||
#include <nditte.h>
|
||
#include <multirel.h>
|
||
|
||
#include "../lv/lvlib.h"
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TDoc_recordset
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TDoc_recordset : public TISAM_recordset
|
||
{
|
||
TDocumentoEsteso* _doc;
|
||
TRecnotype _mypos, _lastpos;
|
||
|
||
protected:
|
||
virtual const TVariant& get_field(int logic, const char* field) const;
|
||
|
||
public:
|
||
virtual TRecnotype items() const { return _lastpos; }
|
||
virtual TRecnotype current_row() const { return _mypos; }
|
||
virtual bool move_to(TRecnotype pos);
|
||
|
||
TDocumentoEsteso& doc() { return *_doc; }
|
||
TRiga_documento& riga_doc(int r = 0) const;
|
||
|
||
TDoc_recordset(const TRecordset& doc, const TString& old_query);
|
||
virtual ~TDoc_recordset();
|
||
};
|
||
|
||
TRiga_documento& TDoc_recordset::riga_doc(int n) const
|
||
{
|
||
if (n < 0 || n > _doc->rows()) // Non dovrebbe succedere mai
|
||
{
|
||
n = _doc->new_row("05").numero(); // Crea una riga descrizione fittizia
|
||
((TDoc_recordset*)this)->_lastpos++;
|
||
}
|
||
if (n <= 0)
|
||
n = _mypos+1;
|
||
if (n <= 0)
|
||
n = 1;
|
||
return _doc->row(n);
|
||
}
|
||
|
||
bool TDoc_recordset::move_to(TRecnotype pos)
|
||
{
|
||
const bool ok = pos >= 0 && pos < items();
|
||
if (ok)
|
||
{
|
||
if (pos != _mypos)
|
||
{
|
||
_mypos = pos;
|
||
TRelation& rel = *relation();
|
||
rel.curr(LF_RIGHEDOC) = riga_doc(); // Copia riga corrente nella relazione
|
||
rel.update(1); // Aggiorna solo i file della relazione dipendenti da LF_RIGHEDOC
|
||
if (_mypos == 0)
|
||
{
|
||
doc().scadenze_reset();
|
||
doc().summary_reset(true);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (pos == items())
|
||
_mypos = pos;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
const TVariant& TDoc_recordset::get_field(int logic, const char* field) const
|
||
{
|
||
if (logic == 0 || logic == LF_DOC)
|
||
{
|
||
const TFieldref ref(field, LF_DOC);
|
||
return get_tmp_var() = ref.read(*_doc);
|
||
} else
|
||
if (logic == LF_RIGHEDOC)
|
||
{
|
||
const TFieldref ref(field, LF_RIGHEDOC);
|
||
return get_tmp_var() = ref.read(riga_doc());
|
||
}
|
||
return TISAM_recordset::get_field(logic, field);
|
||
}
|
||
|
||
static TToken_string _sortexpr;
|
||
|
||
static int compare_rdocs(const TObject** p1, const TObject** p2)
|
||
{
|
||
const TRectype& r1 = *(const TRectype*)(*p1);
|
||
const TRectype& r2 = *(const TRectype*)(*p2);
|
||
|
||
int cmp = 0;
|
||
FOR_EACH_TOKEN(_sortexpr, fld)
|
||
{
|
||
const TString& c1 = r1.get(fld);
|
||
const TString& c2 = r2.get(fld);
|
||
if (real::is_real(c1) && real::is_real(c2))
|
||
{
|
||
const real r1(c1);
|
||
const real r2(c2);
|
||
cmp = r1 == r2 ? 0 : (r1 < r2 ? -1 : +1);
|
||
}
|
||
else
|
||
cmp = c1.compare(c2);
|
||
if (cmp != 0)
|
||
break;
|
||
}
|
||
return cmp;
|
||
}
|
||
|
||
TDoc_recordset::TDoc_recordset(const TRecordset& doc, const TString& old_query)
|
||
: TISAM_recordset(old_query), _doc(NULL), _mypos(-1), _lastpos(-1)
|
||
{
|
||
TRectype curr(LF_DOC);
|
||
|
||
TToken_string query(old_query, '\n');
|
||
TToken_string new_query("", '\n');
|
||
TString line;
|
||
_sortexpr.cut(0);
|
||
|
||
FOR_EACH_TOKEN(query, tok)
|
||
{
|
||
line = tok;
|
||
line.trim();
|
||
if (line.starts_with("SORT "))
|
||
{
|
||
const int pos = line.find("BY ");
|
||
if (pos > 0)
|
||
{
|
||
TToken_string by(line.mid(pos + 3), ' ');
|
||
by.strip_double_spaces(); by.trim();
|
||
FOR_EACH_TOKEN(by, tok)
|
||
{
|
||
TString16 fld = tok;
|
||
if (fld.starts_with("34."))
|
||
fld.ltrim(3);
|
||
if (fld.starts_with("RDOC."))
|
||
fld.ltrim(5);
|
||
_sortexpr.add(fld);
|
||
}
|
||
}
|
||
line = query.get();
|
||
line.trim();
|
||
if (line.starts_with("JOIN TO"))
|
||
line.insert("34 ", 5);
|
||
new_query.add(line);
|
||
continue;
|
||
}
|
||
if (line.starts_with("USE "))
|
||
{
|
||
new_query.add(line);
|
||
|
||
for (int i = 0; i < 2; i++)
|
||
{
|
||
const char* key[4] = { DOC_PROVV, DOC_ANNO, DOC_CODNUM, DOC_NDOC };
|
||
line = (i == 0) ? "FROM " : "TO ";
|
||
for (int k = 0; k < 4; k++)
|
||
{
|
||
const TString& val = doc.get(key[k]).as_string();
|
||
line << key[k] << '=' << val << ' ';
|
||
if (i == 0)
|
||
curr.put(key[k], val);
|
||
}
|
||
new_query.add(line);
|
||
}
|
||
continue;
|
||
}
|
||
new_query.add(line);
|
||
}
|
||
|
||
|
||
set(new_query);
|
||
|
||
_doc = new TDocumentoEsteso(curr);
|
||
|
||
if (_sortexpr.full())
|
||
{
|
||
TRecord_array& rows = _doc->body();
|
||
rows.sort(compare_rdocs);
|
||
}
|
||
_doc->set_riga_conai();
|
||
_doc->set_riga_tic();
|
||
_doc->set_riga_split();
|
||
_lastpos = _doc->rows();
|
||
|
||
// Posiziona correttamente anche il cursore principale
|
||
*cursor() = 0L;
|
||
}
|
||
|
||
TDoc_recordset::~TDoc_recordset()
|
||
{
|
||
if (_doc != NULL)
|
||
delete _doc;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TTrans_recordset
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TTrans_recordset : public TAS400_recordset
|
||
{
|
||
protected:
|
||
virtual bool parse_query(const TString& query, TFilename& n);
|
||
virtual bool load_file(const TFilename& n);
|
||
|
||
public:
|
||
TTrans_recordset(const char* ininame);
|
||
};
|
||
|
||
bool TTrans_recordset::parse_query(const TString& query, TFilename& n)
|
||
{
|
||
n = query;
|
||
return n.exist() ? _qt_select : _qt_none;
|
||
}
|
||
|
||
bool TTrans_recordset::load_file(const TFilename& n)
|
||
{
|
||
TConfig ini(n, "33");
|
||
|
||
TToken_string dokey;
|
||
for (int idx = 0; ; idx++)
|
||
{
|
||
dokey = ini.get("Doc", NULL, idx);
|
||
if (dokey.blank())
|
||
break;
|
||
const TRectype& doc = cache().get(LF_DOC, dokey);
|
||
if (!doc.empty())
|
||
{
|
||
new_rec();
|
||
for (unsigned int c = 0; c < columns(); c++)
|
||
{
|
||
const TRecordset_column_info& ci = column_info(c);
|
||
const char* fldname = ci._name;
|
||
set(fldname, doc.get(fldname));
|
||
}
|
||
}
|
||
}
|
||
|
||
return items() > 0;
|
||
}
|
||
|
||
TTrans_recordset::TTrans_recordset(const char* ininame) : TAS400_recordset(ininame)
|
||
{
|
||
_info._width = 32;
|
||
create_field(DOC_PROVV, -1, 1, _alfafld, true);
|
||
create_field(DOC_ANNO, -1, 4, _intfld, true);
|
||
create_field(DOC_CODNUM, -1, 4, _alfafld, true);
|
||
create_field(DOC_NDOC, -1, 7, _longfld, true);
|
||
create_field(DOC_TIPODOC, -1, 4, _alfafld);
|
||
create_field(DOC_TIPOCF, -1, 1, _alfafld);
|
||
create_field(DOC_CODCF, -1, 6, _longfld);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TReport_doc
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TReport_doc : public TReport
|
||
{
|
||
size_t _first_msg;
|
||
int _extra_copies;
|
||
|
||
protected:
|
||
virtual void include_libraries(bool reload);
|
||
virtual size_t get_usr_words(TString_array& words) const;
|
||
virtual bool execute_usr_word(unsigned int opcode, TVariant_stack& stack);
|
||
virtual bool get_usr_val(const TString& name, TVariant& var) const;
|
||
virtual bool set_usr_val(const TString& name, const TVariant& var);
|
||
|
||
TVariant eval_rdoc(const TRiga_documento& rdoc, const TString& formula, TFieldtypes ft) const;
|
||
|
||
TDocumentoEsteso& doc();
|
||
TRiga_documento& riga_doc(int n = 0);
|
||
void output_values(const TRectype& rec, const TString& output);
|
||
void reset_values(const TString& output);
|
||
|
||
bool msg_cliente(TVariant_stack& stack);
|
||
bool msg_parent_doc(TVariant_stack& stack);
|
||
bool msg_parent_row(TVariant_stack& stack);
|
||
bool msg_riepilogo_iva(TVariant_stack& stack);
|
||
bool msg_scadenze(TVariant_stack& stack);
|
||
bool msg_tot_imponibili(TVariant_stack& stack);
|
||
bool msg_lv_dot(TVariant_stack& stack);
|
||
bool msg_add_row(TVariant_stack& stack);
|
||
|
||
int set_printed_status(TDocumento& doc) const;
|
||
|
||
public:
|
||
bool print(const TRecordset& doc, TReport_book& book, bool def, word copies,
|
||
bool alleg, bool arc, bool signature, word printed_copies = 0);
|
||
int extra_copies() const { return _extra_copies; }
|
||
|
||
TReport_doc(const char* name);
|
||
virtual ~TReport_doc();
|
||
};
|
||
|
||
int TReport_doc::set_printed_status(TDocumento& doc) const
|
||
{
|
||
int err = NOERR;
|
||
if (doc.get_char(DOC_PROVV) == 'D') // Se e' una numerazione definitiva
|
||
{
|
||
if (doc.stampabile()) // Controlla se non e' gia' nello stato si stampato in definitiva
|
||
{
|
||
const char sfs = doc.tipo().stato_finale_stampa();
|
||
if (doc.stato() < sfs)
|
||
doc.stato(sfs); // Se non e' gia' in definitiva aggiorna lo stato
|
||
err = doc.rewrite();
|
||
|
||
// Invia la transazione di cambio stato se necessario
|
||
if (::can_dispatch_transaction(doc))
|
||
{
|
||
TFilename tmpname; tmpname.temp();
|
||
{ // Parentesi strategiche
|
||
TConfig ini(tmpname, "Transaction");
|
||
ini.set("Action", "MODIFY");
|
||
ini.set("Firm", prefix().get_codditta());
|
||
ini.set("Mode", "A");
|
||
ini.set_paragraph(LF_DOC);
|
||
ini.set(DOC_PROVV, doc.get(DOC_PROVV));
|
||
ini.set(DOC_ANNO, doc.get(DOC_ANNO));
|
||
ini.set(DOC_CODNUM, doc.get(DOC_CODNUM));
|
||
ini.set(DOC_NDOC, doc.get(DOC_NDOC));
|
||
ini.set(DOC_STATO, doc.stato());
|
||
}
|
||
::dispatch_transaction(doc, tmpname);
|
||
::remove(tmpname);
|
||
}
|
||
}
|
||
}
|
||
else // Se e' una numerazione provvisoria
|
||
{
|
||
// Scrive il nuovo documento con lo stato, numero e flag di definitiva
|
||
TDocumento bak_doc;
|
||
bak_doc = doc; // Setta il flag di nuovo documento
|
||
bak_doc.put(DOC_STATO,doc.tipo().stato_finale_stampa());
|
||
bak_doc.put(DOC_PROVV,"D");
|
||
bak_doc.put(DOC_NDOC,-1L);
|
||
const int pr = bak_doc.physical_rows();
|
||
for (int i=1;i<=pr;i++)
|
||
bak_doc[i].put(DOC_PROVV,"D");
|
||
err = bak_doc.write(); // Esegue automagicamente rinumerazione di testata e righe nel caso di reinsert
|
||
if (err == NOERR) // Cancella il vecchio documento
|
||
doc.remove();
|
||
}
|
||
return err;
|
||
}
|
||
|
||
bool TReport_doc::print(const TRecordset& doc, TReport_book& book, bool definitive, word copie, bool can_allegate, bool arc, bool signature, word printed_copies)
|
||
{
|
||
bool printed = true;
|
||
|
||
const TString old_query = recordset()->query_text();
|
||
TDoc_recordset* rs = new TDoc_recordset(doc, old_query);
|
||
set_recordset(rs);
|
||
|
||
TDocumento& d = rs->doc();
|
||
if (!definitive || d.stampabile())
|
||
{
|
||
for (int c = 1; c <= copie; c++)
|
||
{
|
||
set_copy(c + printed_copies, copie + printed_copies);
|
||
// Tenta di stampare gli allegati solo sull'ultima copia definitiva
|
||
if (c == copie && can_allegate)
|
||
{
|
||
const TTipo_documento& tipodoc = d.tipo();
|
||
if (tipodoc.allega_documenti())
|
||
{
|
||
const long codcf = d.get_long(CLI_CODCF);
|
||
TString_array allegati;
|
||
for (bool ok = rs->move_first(); ok; ok = rs->move_next())
|
||
{
|
||
const TString& codart = rs->get("RDOC.CODARTMAG").as_string();
|
||
const TRectype& anamag = cache().get(LF_ANAMAG, codart);
|
||
TToken_string golem(anamag.get(ANAMAG_GOLEM), '\n');
|
||
if (!golem.empty_items())
|
||
{
|
||
TToken_string key;
|
||
key.add(d.get(DOC_PROVV));
|
||
key.add(d.get(DOC_ANNO));
|
||
key.add(d.get(DOC_CODNUM));
|
||
key.add(d.get(DOC_NDOC));
|
||
|
||
TLocalisamfile alleg(LF_MULTIREL);
|
||
alleg.put(MULTI_COD, "ALLEG");
|
||
alleg.put(MULTI_FIRST, codcf);
|
||
alleg.put(MULTI_SECOND, codart);
|
||
alleg.put(MULTI_DATA, key);
|
||
|
||
bool print_alleg = alleg.write() == NOERR; // Se riesco a scrivere vuol dire che non esisteva
|
||
|
||
if (!print_alleg)
|
||
{
|
||
alleg.put(MULTI_COD, "ALLEG");
|
||
alleg.put(MULTI_FIRST, codcf);
|
||
alleg.put(MULTI_SECOND, codart);
|
||
if (alleg.read() == NOERR)
|
||
print_alleg = alleg.get(MULTI_DATA) == key;
|
||
}
|
||
if (print_alleg)
|
||
{
|
||
FOR_EACH_TOKEN(golem, allegato)
|
||
{
|
||
TToken_string a(allegato);
|
||
TFilename name = a.get();
|
||
const bool link = a.get_char(2) > ' ';
|
||
if (!link)
|
||
{
|
||
TFilename golem_path = firm2dir(prefix().get_codditta());
|
||
golem_path.add("golem");
|
||
golem_path.add(name.name());
|
||
name = golem_path;
|
||
}
|
||
if (name.exist())
|
||
allegati.add(name);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
set_allegates(allegati);
|
||
}
|
||
}
|
||
|
||
printed = book.add(*this, false);
|
||
if (!printed)
|
||
break;
|
||
}
|
||
if (printed)
|
||
{
|
||
if (definitive)
|
||
set_printed_status(d);
|
||
if (arc)
|
||
archive(signature);
|
||
}
|
||
}
|
||
|
||
set_recordset(old_query);
|
||
return printed;
|
||
}
|
||
|
||
TDocumentoEsteso& TReport_doc::doc()
|
||
{
|
||
TDoc_recordset* rs = (TDoc_recordset*)recordset();
|
||
return rs->doc();
|
||
}
|
||
|
||
TRiga_documento& TReport_doc::riga_doc(int n)
|
||
{
|
||
TDoc_recordset* rs = (TDoc_recordset*)recordset();
|
||
return rs->riga_doc(n);
|
||
}
|
||
|
||
bool TReport_doc::msg_cliente(TVariant_stack& stack)
|
||
{
|
||
TReport_field& cf = *curr_field();
|
||
|
||
const TCli_for& cli_for = doc().clifor();
|
||
const TOccasionale& cli_occ = doc().occas();
|
||
const bool occasionale = cli_for.occasionale();
|
||
|
||
TString in = stack.pop().as_string(); // prende la macro o il fieldref
|
||
TString valore;
|
||
|
||
if (in[0] != '!')
|
||
{
|
||
// Controlla l'esistenza dei campi...
|
||
if (occasionale && cli_occ.exist(in))
|
||
valore = cli_occ.get(in);
|
||
|
||
if (!occasionale && cli_for.exist(in))
|
||
valore = cli_for.get(in);
|
||
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
in.ltrim(1);
|
||
if (in=="INDNUM")
|
||
{
|
||
valore = occasionale ? cli_occ.get(OCC_INDIR) : cli_for.get(CLI_INDCF);
|
||
valore << ' ';
|
||
valore << (occasionale ? cli_occ.get(OCC_CIV) : cli_for.get(CLI_CIVCF));
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in.find("COM") == 0)
|
||
{
|
||
const bool nascita = in[3] == 'N';
|
||
const int p = in.find("->");
|
||
if (p > 0)
|
||
in.ltrim(p + 2);
|
||
|
||
TString8 key;
|
||
if (nascita)
|
||
{
|
||
key = occasionale ? cli_occ.get(OCC_STATONASC) : cli_for.get(CLI_STATONASC);
|
||
key << '|' << (occasionale ? cli_occ.get(OCC_COMNASC) : cli_for.get(CLI_COMNASC));
|
||
}
|
||
else
|
||
{
|
||
key = occasionale ? cli_occ.get(OCC_STATO): cli_for.get(CLI_STATOCF);
|
||
key << '|' << (occasionale ? cli_occ.get(OCC_COM): cli_for.get(CLI_COMCF));
|
||
}
|
||
valore = cache().get(LF_COMUNI, key, in);
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in.find("CAP") == 0)
|
||
{
|
||
valore = occasionale ? cli_occ.get(OCC_CAP) : cli_for.get(CLI_CAPCF);
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in.find("TEL") == 0)
|
||
{
|
||
if (!occasionale)
|
||
{
|
||
if (in.len() == 3)
|
||
in << "1";
|
||
const TString num(cli_for.get(in));
|
||
in.insert("P");
|
||
valore = cli_for.get(in);
|
||
valore << "/" << num;
|
||
}
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in=="FAX")
|
||
{
|
||
if (!occasionale)
|
||
{
|
||
valore = cli_for.get("PFAX");
|
||
valore << "/" << cli_for.get("FAX");
|
||
}
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in=="RAGSOC")
|
||
{
|
||
valore = occasionale ? cli_occ.get(in) : cli_for.get(in);
|
||
valore.strip_double_spaces();
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void TReport_doc::output_values(const TRectype& rec, const TString& output)
|
||
{
|
||
TToken_string out(output, '!');
|
||
TString curr;
|
||
for (const char * str = out.get(0); str; str = out.get())
|
||
{ // scansione sugli elementi dell'output
|
||
curr = str;
|
||
int poseq = curr.find('='); // divide la stringa corrente in lvalue e rvalue
|
||
if (poseq < 0)
|
||
{
|
||
curr_field()->set(rec.get(curr));
|
||
}
|
||
else
|
||
{
|
||
int posrv = poseq+1;
|
||
if (poseq >= 0 && curr[posrv] == '=')
|
||
posrv++;
|
||
TString16 fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale
|
||
const TString& dat = rec.get(curr.mid(posrv)); // preleva il nome del campo del file alla destra dell'uguale e lo legge dal record
|
||
TReport_field* campo = field(fld);
|
||
if (campo != NULL)
|
||
campo->set(dat);
|
||
}
|
||
}
|
||
}
|
||
|
||
void TReport_doc::reset_values(const TString& output)
|
||
{
|
||
TToken_string out(output, '!');
|
||
TString curr;
|
||
for (const char * str = out.get(0); str; str = out.get())
|
||
{ // scansione sugli elementi dell'output
|
||
curr = str;
|
||
int poseq = curr.find('='); // divide la stringa corrente in lvalue e rvalue
|
||
if (poseq < 0)
|
||
{
|
||
curr_field()->set("");
|
||
}
|
||
else
|
||
{
|
||
TString16 fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale
|
||
TReport_field* campo = field(fld);
|
||
if (campo != NULL)
|
||
campo->set("");
|
||
}
|
||
}
|
||
}
|
||
|
||
bool TReport_doc::msg_parent_doc(TVariant_stack& stack)
|
||
{
|
||
TReport_field& cf = *curr_field();
|
||
|
||
const TRectype* rdoc = &riga_doc();
|
||
// Se il campo corrente non appartiene al body allora cerco la prima riga documento buona!
|
||
if (cf.section().type() != 'B')
|
||
{
|
||
const TRiga_documento* first_merc = NULL;
|
||
const TRiga_documento* first_desc = NULL;
|
||
for (int r = 1; r <= doc().physical_rows(); r++)
|
||
{
|
||
const TRiga_documento& row = riga_doc(r);
|
||
if (row.get(RDOC_DANDOC).not_empty())
|
||
{
|
||
if (row.is_descrizione())
|
||
{
|
||
if (first_desc == NULL)
|
||
first_desc = &row; // Non e' una riga buona, ma nemmeno da buttare!
|
||
}
|
||
else
|
||
{
|
||
first_merc = &row;
|
||
break; // Ho trovato la riga buona!
|
||
}
|
||
}
|
||
}
|
||
if (first_merc != NULL)
|
||
rdoc = first_merc;
|
||
else
|
||
{
|
||
if (first_desc != NULL)
|
||
rdoc = first_desc;
|
||
}
|
||
}
|
||
|
||
int level = stack.pop().as_int();
|
||
for (; rdoc != NULL && level > 0; level--)
|
||
rdoc = ((const TRiga_documento*)rdoc)->find_original_rdoc();
|
||
|
||
const TString& values = stack.pop().as_string();
|
||
const bool is_full = stack.peek().as_bool();
|
||
|
||
if (rdoc != NULL && rdoc->get(RDOC_PROVV).not_empty())
|
||
{
|
||
const char provv = rdoc->get_char(RDOC_PROVV);
|
||
const int anno = rdoc->get_int(RDOC_ANNO);
|
||
const TString4 codnum = rdoc->get(RDOC_CODNUM);
|
||
const long ndoc = rdoc->get_long(RDOC_NDOC);
|
||
|
||
if (is_full)
|
||
{
|
||
TDocumento doc(provv, anno, codnum, ndoc);
|
||
output_values(doc, values);
|
||
}
|
||
else
|
||
{
|
||
TToken_string key;
|
||
key.add(provv); key.add(anno); key.add(codnum); key.add(ndoc);
|
||
const TRectype& doc = cache().get(LF_DOC, key);
|
||
output_values(doc, values);
|
||
}
|
||
}
|
||
else
|
||
reset_values(values);
|
||
|
||
return true;
|
||
}
|
||
|
||
bool TReport_doc::msg_parent_row(TVariant_stack& stack)
|
||
{
|
||
const TRectype* rdoc = &riga_doc();
|
||
|
||
int level = stack.pop().as_int();
|
||
for (; rdoc != NULL && level > 0; level--)
|
||
rdoc = ((const TRiga_documento *) rdoc)->find_original_rdoc();
|
||
|
||
const TString& values = stack.pop().as_string();
|
||
const bool is_full = stack.peek().as_bool();
|
||
|
||
if (rdoc != NULL && rdoc->get(RDOC_PROVV).not_empty())
|
||
{
|
||
if (is_full)
|
||
{
|
||
const char provv = rdoc->get_char(RDOC_PROVV);
|
||
const int anno = rdoc->get_int(RDOC_ANNO);
|
||
const TString4 codnum = rdoc->get(RDOC_CODNUM);
|
||
const long ndoc = rdoc->get_long(RDOC_NDOC);
|
||
TDocumento doc(provv, anno, codnum, ndoc);
|
||
output_values(doc[rdoc->get_int(RDOC_NRIGA)], values);
|
||
}
|
||
else
|
||
output_values(*rdoc, values);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool TReport_doc::msg_riepilogo_iva(TVariant_stack& stack)
|
||
{
|
||
// tabella riepilogo aliquote iva e relative imposte
|
||
// sintassi: _RIEPILOGOIVA,<selettore>,<macro>,<cambio codice>
|
||
// dove: <selettore> <20> uno dei seguenti:
|
||
// 1 = codici IVA a regime normale
|
||
// 2 = codici IVA da ventilare
|
||
// 4 = codici IVA esenti
|
||
// 8 = codici IVA non imponibili
|
||
// 16 = codici IVA non soggetti
|
||
// oppure la combinazione di uno o piu' di essi:
|
||
// 12 = 4+8, 19 = 1+2+16, 29 = 1+4+8+16 ecc...
|
||
// dove: <macro> <20> uno dei seguenti:
|
||
// COD colonna dei codici
|
||
// IMP colonna degli imponibili
|
||
// IVA colonna delle imposte
|
||
// ALI colonna delle aliquote
|
||
// DES colonna delle descrizioni (stampata solo se il regime IVA non e' normale)
|
||
// dove: <cambio codice> <20> uno dei seguenti:
|
||
// 0 indica di non leggere il successivo codice IVA nella tabella riepilogativa
|
||
// 1 indica di leggere il successivo codice IVA nella tabella riepilogativa
|
||
|
||
const int selector = stack.pop().as_int();
|
||
if (selector != 0)
|
||
{
|
||
TDocumentoEsteso& d = doc();
|
||
d.summary_filter(selector);
|
||
|
||
const TString& what = stack.pop().as_string(); // cosa deve stampare ?
|
||
const TVariant value = d.summary_get(what); // Piglia il valore dalla riga selezionata sulla tabellina
|
||
curr_field()->set(value);
|
||
|
||
const bool next = stack.pop().as_bool(); // deve cambiare elemento ?
|
||
if (next) d.summary_set_next();
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool TReport_doc::msg_scadenze(TVariant_stack& stack)
|
||
{
|
||
const TString& what = stack.pop().as_string();
|
||
const TVariant value = doc().scadenze_get(what);
|
||
curr_field()->set(value);
|
||
|
||
const bool next = stack.pop().as_bool();
|
||
if (next) doc().scadenze_set_next();
|
||
return true;
|
||
}
|
||
|
||
bool TReport_doc::msg_tot_imponibili(TVariant_stack& stack)
|
||
{
|
||
TReport_field& cf = *curr_field();
|
||
|
||
// sintassi: _TOTIMPONIBILI,<selettore>
|
||
// dove: <selettore> funge da filtro per la somma degli imponibili
|
||
// se selettore vale 0 restituisce il tot. imponibili con le spese
|
||
// vedi _RIEPILOGOIVA per la spiegazione dei filtri selettivi
|
||
const int sel = stack.pop().as_int();
|
||
const TVariant x = (sel == 0) ? doc().imponibile(true) : doc().tot_imponibili(sel);
|
||
cf.set(x);
|
||
return true;
|
||
}
|
||
|
||
bool TReport_doc::msg_lv_dot(TVariant_stack& stack)
|
||
{
|
||
TReport_field& cf = *curr_field();
|
||
|
||
const TString& field = stack.pop().as_string();
|
||
if(field == "DOTOD" || field == "DOTMP" || field == "DOTIN")
|
||
{
|
||
const TRectype& rdoc = riga_doc();
|
||
const TDocumento& h = doc();
|
||
//instanzio un TArticolo_lavanderie per poter recuperare i dati di interesse
|
||
TArticolo_lavanderie& artrec = cached_article_laundry(rdoc.get(RDOC_CODARTMAG), h.get(DOC_TIPOCF)[0], h.get_long(DOC_CODCF), h.get_int(DOC_CODINDSP));
|
||
|
||
//setto datasc a oggi e fisso l'anno esercizio
|
||
TEsercizi_contabili& esc = esercizi();
|
||
const int last_esc = esc.last();
|
||
|
||
//estraggo il record corrispondente su LF_CLIFOGIAC
|
||
const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc);
|
||
TVariant x = reclav.get(field);
|
||
|
||
if(reclav.empty())
|
||
{
|
||
TArticolo_lavanderie& artrec1 = cached_article_laundry(rdoc.get(RDOC_CODARTMAG), h.get(DOC_TIPOCF)[0], h.get_long(DOC_CODCF), 0);
|
||
const TRecmag_lavanderie& reclav1 = artrec1.find_rec(last_esc);
|
||
x = reclav1.get(field);
|
||
}
|
||
cf.set(x);
|
||
}
|
||
else
|
||
cf.set("");
|
||
return true;
|
||
}
|
||
|
||
TVariant TReport_doc::eval_rdoc(const TRiga_documento& rdoc, const TString& formula, TFieldtypes ft) const
|
||
{
|
||
TExpr_documento expr(formula, _strexpr, &rdoc.doc(), &rdoc);
|
||
for (int v = expr.numvar()-1; v >= 0; v--)
|
||
{
|
||
const TFixed_string fld = expr.varname(v);
|
||
if (rdoc.TRectype::exist(fld))
|
||
expr.setvar(fld, rdoc.get(fld));
|
||
else
|
||
{
|
||
TVariant var;
|
||
if (get_usr_val(fld, var))
|
||
expr.setvar(fld, var.as_string());
|
||
}
|
||
}
|
||
TVariant tmp;
|
||
switch (ft)
|
||
{
|
||
case _boolfld: tmp.set(expr.as_bool()); break;
|
||
case _realfld: tmp.set(expr.as_real()); break;
|
||
default : tmp.set(expr.as_string()); break;
|
||
}
|
||
return tmp;
|
||
}
|
||
|
||
bool TReport_doc::msg_add_row(TVariant_stack& stack)
|
||
{
|
||
TString4 row_type;
|
||
TString codart_expr;
|
||
TString descr_expr;
|
||
TToken_string sum_fields;
|
||
|
||
for (int v = 0; !stack.empty(); v++)
|
||
{
|
||
const TString& riga = stack.pop().as_string();
|
||
switch (v)
|
||
{
|
||
case 0: row_type.strncpy(riga, 2); break;
|
||
case 1: codart_expr = riga; break;
|
||
case 2: descr_expr = riga; break;
|
||
default: sum_fields.add(riga); break;
|
||
}
|
||
}
|
||
|
||
TRiga_documento& curr_rdoc = riga_doc(0);
|
||
if (curr_rdoc.get(RDOC_TIPORIGA) == row_type)
|
||
return false; // Riga generata
|
||
|
||
const TCodice_articolo codart = eval_rdoc(curr_rdoc, codart_expr, _alfafld).as_string();
|
||
const int curr_riga = curr_rdoc.numero();
|
||
const int last_riga = doc().physical_rows();
|
||
int good_riga = 0;
|
||
for (int i = last_riga; i > curr_riga; i--)
|
||
{
|
||
const TRiga_documento& rdoc = riga_doc(i);
|
||
if (rdoc.get(RDOC_TIPORIGA) == row_type && rdoc.get(RDOC_CODART) == codart)
|
||
{
|
||
good_riga = i;
|
||
break;
|
||
}
|
||
}
|
||
if (good_riga <= curr_riga) // Nessuna riga compatibile
|
||
{
|
||
// Aggiungi riga vuota, se necessario
|
||
const TRiga_documento& urdoc = riga_doc(last_riga);
|
||
if (urdoc.get(RDOC_TIPORIGA) != row_type)
|
||
{
|
||
TRiga_documento& empty_rdoc = riga_doc(-1);
|
||
empty_rdoc.put(RDOC_TIPORIGA, row_type);
|
||
}
|
||
|
||
// Crea nuova riga ragggruppamento
|
||
TRiga_documento& new_rdoc = riga_doc(-1);
|
||
new_rdoc.put(RDOC_TIPORIGA, row_type);
|
||
new_rdoc.put(RDOC_CODART, codart);
|
||
good_riga = new_rdoc.numero();
|
||
}
|
||
|
||
TRiga_documento& good_rdoc = riga_doc(good_riga);
|
||
FOR_EACH_TOKEN(sum_fields, fld)
|
||
good_rdoc.add(fld, curr_rdoc.get_real(fld));
|
||
|
||
int open_brace = 0;
|
||
while ((open_brace = descr_expr.find('{')) >=0)
|
||
{
|
||
const int close_brace = descr_expr.find('}', open_brace);
|
||
if (close_brace < 0) break;
|
||
const TString& varname = descr_expr.sub(open_brace+1, close_brace);
|
||
TFieldtypes ft = curr_rdoc.type(varname); if (ft == _nullfld) ft = _alfafld;
|
||
TVariant var = eval_rdoc(good_rdoc, varname, ft);
|
||
const TString& after = descr_expr.mid(close_brace+1);
|
||
descr_expr.cut(open_brace)<< var.as_string() << after;
|
||
}
|
||
good_rdoc.set_descr(descr_expr);
|
||
|
||
return true;
|
||
}
|
||
|
||
size_t TReport_doc::get_usr_words(TString_array& words) const
|
||
{
|
||
TReport::get_usr_words(words);
|
||
|
||
const char* const name[] =
|
||
{
|
||
"DOC_CLIENTE",
|
||
"DOC_PARENT_DOC", "DOC_PARENT_ROW",
|
||
"DOC_RIEPILOGO_IVA",
|
||
"DOC_SCADENZE",
|
||
"DOC_TOT_IMPONIBILI",
|
||
"DOC_LV_DOT",
|
||
"DOC_ADD_ROW",
|
||
NULL
|
||
};
|
||
|
||
((TReport_doc*)this)->_first_msg = words.items(); // Calcola il primo numero disponibile
|
||
size_t i;
|
||
for (i = 0; name[i] != NULL; i++)
|
||
words.add(name[i]);
|
||
|
||
return words.items();
|
||
}
|
||
|
||
bool TReport_doc::execute_usr_word(unsigned int opcode, TVariant_stack& stack)
|
||
{
|
||
bool ok = true;
|
||
|
||
if (opcode >= _first_msg)
|
||
{
|
||
switch (opcode - _first_msg)
|
||
{
|
||
case 0: msg_cliente(stack); break;
|
||
case 1: msg_parent_doc(stack); break;
|
||
case 2: msg_parent_row(stack); break;
|
||
case 3: msg_riepilogo_iva(stack); break;
|
||
case 4: msg_scadenze(stack); break;
|
||
case 5: msg_tot_imponibili(stack); break;
|
||
case 6: msg_lv_dot(stack); break;
|
||
case 7: msg_add_row(stack); break;
|
||
default: ok = false; break;
|
||
}
|
||
stack.reset(); // Svuota eventuali parametri variabili inutilizzati
|
||
}
|
||
else
|
||
ok = TReport::execute_usr_word(opcode, stack);
|
||
|
||
return ok;
|
||
}
|
||
|
||
void TReport_doc::include_libraries(bool reload)
|
||
{
|
||
TReport::include_libraries(reload);
|
||
if (reload || !defined("MESSAGE_DESCRIGA"))
|
||
include("ve1300.alx");
|
||
}
|
||
|
||
bool TReport_doc::get_usr_val(const TString& name, TVariant& var) const
|
||
{
|
||
if (name == "#PRINT_EXTRA_COPIES")
|
||
{
|
||
var = long(_extra_copies);
|
||
return true;
|
||
}
|
||
return TReport::get_usr_val(name, var);
|
||
}
|
||
|
||
bool TReport_doc::set_usr_val(const TString& name, const TVariant& var)
|
||
{
|
||
if (name == "#PRINT_EXTRA_COPIES")
|
||
{
|
||
_extra_copies = var.as_int();
|
||
return true;
|
||
}
|
||
return TReport::set_usr_val(name, var);
|
||
}
|
||
|
||
TReport_doc::TReport_doc(const char* name) : _extra_copies(0)
|
||
{
|
||
// istanziamento e impostazione della relazione di gestione della ditta corrente
|
||
load(name); // Faccio la load altrimenti non include la libreria 1300.alx
|
||
}
|
||
|
||
TReport_doc::~TReport_doc()
|
||
{
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TDoc_book
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TDoc_book : public TReport_book
|
||
{
|
||
protected:
|
||
virtual void draw_link(const TReport_rct& rect, const char* text, const char* link);
|
||
};
|
||
|
||
void TDoc_book::draw_link(const TReport_rct& rect, const char* text, const char* link)
|
||
{
|
||
if (main_app().argc() < 6) // Vieta i link quando sono in batch
|
||
TReport_book::draw_link(rect, text, link);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TReport_doc_mask
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TReport_doc_mask : public TAutomask
|
||
{
|
||
protected:
|
||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
|
||
public:
|
||
TReport_doc_mask();
|
||
};
|
||
|
||
bool TReport_doc_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
||
{
|
||
switch (o.dlg())
|
||
{
|
||
case F_DA_NDOC:
|
||
if (e == fe_modify)
|
||
{
|
||
const long dal = get_long(F_DA_NDOC);
|
||
const long al = get_long(F_A_NDOC);
|
||
if (al < dal)
|
||
set(F_A_NDOC, dal);
|
||
}
|
||
break;
|
||
case DLG_CONFIG:
|
||
if (e == fe_button)
|
||
{
|
||
TMask m("ba0100m");
|
||
TConfig cfg(CONFIG_USER, "Mail");
|
||
FOR_EACH_MASK_FIELD(m, i, f) if (f->field())
|
||
f->set(f->field()->read(cfg, "Mail"));
|
||
if (m.run() == K_ENTER)
|
||
{
|
||
FOR_EACH_MASK_FIELD(m, i, f) if (f->field())
|
||
f->field()->write(cfg, "Mail", f->get());
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
TReport_doc_mask::TReport_doc_mask() : TAutomask("ve1300a")
|
||
{
|
||
hide(F_PROVV);
|
||
|
||
//abilita i bottoni della toolbar in base ai moduli presenti sulla chiave
|
||
TApplication& a = main_app();
|
||
const bool can_pdf = a.has_module(RSAUT);
|
||
const bool can_sign = can_pdf && a.has_module(FDAUT);
|
||
const int mail_client = xvt_mail_installed();
|
||
const bool can_mail = can_pdf && mail_client != 0;
|
||
enable(DLG_EMAIL, can_mail);
|
||
enable(DLG_SIGNMAIL, can_mail && can_sign);
|
||
enable(DLG_CONFIG, can_mail && (mail_client & 0x2) != 0);
|
||
enable(DLG_PDF, can_pdf);
|
||
enable(DLG_SIGNPDF, can_sign);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TReports_cache
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TReports_cache : TCache
|
||
{
|
||
protected:
|
||
virtual TObject* key2obj(const char* key) { return new TReport_doc(key); }
|
||
public:
|
||
TReport_doc& get(const TString& key) { return *(TReport_doc*)objptr(key); }
|
||
TReports_cache() : TCache(13) { }
|
||
};
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TReport_doc_app
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TReport_doc_app : public TSkeleton_application
|
||
{
|
||
enum TOutput_mode { out_preview, out_print, out_mail, out_signed_mail, out_pdf, out_signed_pdf };
|
||
|
||
TReport_doc_mask* _msk;
|
||
|
||
int _anno;
|
||
TString16 _codnum, _tipodoc; // codice numerazione / profilo
|
||
long _ndoc, _codcf;
|
||
char _tipocf;
|
||
bool _no_print_dlg;
|
||
|
||
protected:
|
||
void add_cli_filter(TString& query, bool from) const;
|
||
void add_data_filter(TString& query, bool from) const;
|
||
void add_ndoc_filter(TString& query, bool from) const;
|
||
void add_filter(TString& str, bool from) const;
|
||
bool print_loop(TRecordset& doc, TOutput_mode mode, bool is_definitive);
|
||
void print_selection(TOutput_mode mode);
|
||
void print_trans(const char* ininame);
|
||
TOutput_mode key2mode(KEY k) const;
|
||
|
||
void set_next_pdf(const TRecordset* doc);
|
||
virtual bool get_next_pdf(int anno, long ditta, const char* codnum, long numdoc, long codcf, TFilename& pdf) const;
|
||
bool get_mail_address(TToken_string& to, TToken_string& cc) const;
|
||
virtual bool get_next_mail(TToken_string& to, TToken_string& cc, TToken_string& ccn,
|
||
TString& subj, TString& text, TToken_string& attach, short& ui) const ;
|
||
void print_extra_copies(TReport_doc& report, const TRecordset& doc, TReport_book& book, word printed_copies) const;
|
||
bool nome_report(const TRecordset& doc, int quale, TFilename& profilo) const;
|
||
|
||
public:
|
||
virtual bool create();
|
||
virtual void main_loop();
|
||
virtual bool destroy();
|
||
};
|
||
|
||
void TReport_doc_app::set_next_pdf(const TRecordset* doc)
|
||
{
|
||
if (doc)
|
||
{
|
||
_anno = doc->get(DOC_ANNO).as_int();
|
||
_codnum = doc->get(DOC_CODNUM).as_string();
|
||
_ndoc = doc->get(DOC_NDOC).as_int();
|
||
_tipodoc= doc->get(DOC_TIPODOC).as_string();
|
||
_tipocf = doc->get(DOC_TIPOCF).as_string()[0];
|
||
_codcf = doc->get(DOC_CODCF).as_int();
|
||
}
|
||
else
|
||
{
|
||
_anno = 0;
|
||
_codnum = _tipodoc = "";
|
||
_ndoc = _codcf = 0L;
|
||
_tipocf = ' ';
|
||
}
|
||
}
|
||
|
||
bool TReport_doc_app::get_next_pdf(int anno, long ditta, const char* codnum, long ndoc, long codcf, TFilename& pdf) const
|
||
{
|
||
bool ok = false;
|
||
if (_anno > 0 && _codnum.full() && _ndoc > 0 && _codcf > 0)
|
||
ok = TSkeleton_application::get_next_pdf(_anno, ditta, _codnum, _ndoc, _codcf, pdf);
|
||
return ok;
|
||
}
|
||
|
||
bool TReport_doc_app::get_mail_address(TToken_string& to, TToken_string& cc) const
|
||
{
|
||
if (_tipodoc.full())
|
||
{
|
||
const TTipo_documento& tipo = cached_tipodoc(_tipodoc);
|
||
TFilename report; tipo.mail_print_profile(report);
|
||
report = report.name_only();
|
||
|
||
TString8 clifo; clifo.format("%c%06ld", _tipocf, _codcf);
|
||
TISAM_recordset contacts("USE MULTIREL\nFROM COD=BACON FIRST=#CLIFO\nTO COD=BACON FIRST=#CLIFO");
|
||
contacts.set_var("#CLIFO", clifo);
|
||
|
||
TToken_string data;
|
||
for (bool ok = contacts.move_first(); ok; ok = contacts.move_next())
|
||
{
|
||
data = contacts.get("DATA").as_string();
|
||
FOR_EACH_TOKEN(data, tok)
|
||
{
|
||
if (_tipodoc.match(tok, true) || report.match(tok, true))
|
||
{
|
||
const TRectype& rub = cache().get(LF_CONTACT, contacts.get("SECOND").as_int());
|
||
TString80 mail = rub.get("MAIL");
|
||
if (mail.blank())
|
||
mail = rub.get("MAIL2");
|
||
if (mail.full())
|
||
{
|
||
if (to.blank())
|
||
to = mail;
|
||
else
|
||
cc.add(mail);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (to.blank())
|
||
{
|
||
TString8 key; key << _tipocf << '|' << _codcf;
|
||
to = cache().get(LF_CLIFO, key, CLI_DOCMAIL);
|
||
}
|
||
return to.full();
|
||
}
|
||
|
||
bool TReport_doc_app::get_next_mail(TToken_string& to, TToken_string& cc, TToken_string& ccn,
|
||
TString& subj, TString& text, TToken_string& attach, short& ui) const
|
||
{
|
||
bool ok = TApplication::get_next_mail(to, cc, ccn, subj, text, attach, ui);
|
||
|
||
if (_ndoc > 0L)
|
||
{
|
||
ok = get_mail_address(to, cc);
|
||
if (ok)
|
||
{
|
||
const TDocumento doc('D', _anno, _codnum, _ndoc);
|
||
doc.riferimento(subj);
|
||
if (subj.blank())
|
||
subj = doc.tipo().descrizione();
|
||
subj << ' ' << _ndoc << TR(" del ") << doc.get(DOC_DATADOC)
|
||
<< ' ' << prefix().firm().ragione_sociale();
|
||
|
||
TString saluti = esc(ini_get_string(CONFIG_USER, "Mail", "Signature"));
|
||
if (saluti.full())
|
||
{
|
||
if (saluti.find('\n')<0 && fexist(saluti))
|
||
{
|
||
TScanner s(saluti);
|
||
while (!s.eof())
|
||
text << s.line() << '\n';
|
||
}
|
||
else
|
||
text << saluti << '\n';
|
||
}
|
||
else
|
||
{
|
||
text << TR("Cordiali Saluti ") << prefix().firm().ragione_sociale();
|
||
}
|
||
text.trim();
|
||
if (to.full())
|
||
ui &= ~0x1; // No user interface
|
||
ui |= 0x2; // Query receipt
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
void TReport_doc_app::add_cli_filter(TString& query, bool from) const
|
||
{
|
||
if (from)
|
||
{
|
||
query << " KEY 4 SELECT "
|
||
<< "(PROVV='" << _msk->get(F_PROVV)
|
||
<< "')&&(ANNO=" << _msk->get(F_ANNO)
|
||
<< ")&&(CODNUM='" << _msk->get(F_CODNUM) << "')";
|
||
}
|
||
query << '\n';
|
||
const TString4 tipocf = _msk->get(F_TIPOCFD);
|
||
const long cod = _msk->get_long(from ? F_DA_CLIFO : F_A_CLIFO);
|
||
if (cod > 0L)
|
||
query << (from ? "FROM" : "TO") << " TIPOCF=" << tipocf << " CODCF=" << cod;
|
||
}
|
||
|
||
void TReport_doc_app::add_data_filter(TString& query, bool from) const
|
||
{
|
||
if (from)
|
||
{
|
||
query << " KEY 3 SELECT "
|
||
<< "(PROVV='D')&&(ANNO=" << _msk->get(F_ANNO)
|
||
<< ")&&(CODNUM='" << _msk->get(F_CODNUM) << "')";
|
||
}
|
||
query << '\n';
|
||
const TDate d = _msk->get(from ? F_DA_DATADOC : F_A_DATADOC);
|
||
if (d.ok())
|
||
query << (from ? "FROM" : "TO") << " DATADOC=" << d.date2ansi();
|
||
}
|
||
|
||
void TReport_doc_app::add_ndoc_filter(TString& query, bool from) const
|
||
{
|
||
query << '\n' << (from ? "FROM" : "TO")
|
||
<< " PROVV='D' ANNO=" << _msk->get(F_ANNO)
|
||
<< " CODNUM='" << _msk->get(F_CODNUM) << '\'';
|
||
const long ndoc = _msk->get_long(from ? F_DA_NDOC : F_A_NDOC);
|
||
if (ndoc > 0)
|
||
query << " NDOC=" << ndoc;
|
||
}
|
||
|
||
void TReport_doc_app::add_filter(TString& query, bool from) const
|
||
{
|
||
const char tipost = _msk->get(F_ORDERING)[0];
|
||
switch (tipost)
|
||
{
|
||
case 'D': add_data_filter(query, from); break;
|
||
case 'C': add_cli_filter(query, from); break;
|
||
default : add_ndoc_filter(query, from); break;
|
||
}
|
||
}
|
||
|
||
bool TReport_doc_app::create()
|
||
{
|
||
if (!has_module(RSAUT))
|
||
return error_box(FR("Modulo non autorizzato: %s"), dongle().module_code2desc(RSAUT));
|
||
|
||
_msk = new TReport_doc_mask;
|
||
return TSkeleton_application::create();
|
||
}
|
||
|
||
bool TReport_doc_app::destroy()
|
||
{
|
||
delete _msk;
|
||
return TSkeleton_application::destroy();
|
||
}
|
||
|
||
void TReport_doc_app::print_extra_copies(TReport_doc& report, const TRecordset& doc,
|
||
TReport_book& book, word printed_copies) const
|
||
{
|
||
const int extra_copies = report.extra_copies();
|
||
if (extra_copies > 0)
|
||
report.print(doc, book, false, extra_copies, false, false, false, printed_copies);
|
||
}
|
||
|
||
// Quale 0=standard,1=aggiuntivo,2=mail
|
||
bool TReport_doc_app::nome_report(const TRecordset& doc, int quale, TFilename& profilo) const
|
||
{
|
||
const TString4 tipodoc = doc.get(DOC_TIPODOC).as_string();
|
||
const TTipo_documento& tipo = cached_tipodoc(tipodoc);
|
||
bool ok = false;
|
||
switch (quale)
|
||
{
|
||
case 1: ok = tipo.additional_print_profile(profilo, 2); break;
|
||
case 2: ok = tipo.mail_print_profile(profilo); break;
|
||
default: ok = tipo.main_print_profile(profilo, 2); break;
|
||
}
|
||
|
||
if (ok) // Cerca eventuale personalizzazione per il singolo cliente
|
||
{
|
||
TString8 codcf = doc.get(DOC_CODCF).as_string(); codcf.right_just(6, '0');
|
||
TFilename path = profilo.name_only();
|
||
path << '_' << doc.get(DOC_TIPOCF) << codcf << ".rep";
|
||
if (path.custom_path())
|
||
profilo = path;
|
||
}
|
||
|
||
return ok;
|
||
}
|
||
|
||
|
||
bool TReport_doc_app::print_loop(TRecordset& doc, TOutput_mode mode, bool final_print)
|
||
{
|
||
const int docs = doc.items();
|
||
if (docs <= 0)
|
||
return false;
|
||
|
||
if ((mode == out_signed_mail || mode == out_signed_pdf) && !xvt_sign_start())
|
||
{
|
||
if (yesno_box(TR("Si desidera generare comunque documenti non firmati?")))
|
||
mode = TOutput_mode(mode-1);
|
||
else
|
||
return false;
|
||
}
|
||
const bool signature = mode==out_signed_mail || mode==out_signed_pdf;
|
||
|
||
TReports_cache reports; // Cache degli ultimi reports usati
|
||
TDoc_book book; // Destinazione dell'intera stampa
|
||
TDoc_book* mail_book = NULL; // Destinazione della singola mail
|
||
TLog_report mail_log(TR("Invio documenti per email"));
|
||
|
||
bool attach_mail = mode==out_mail || mode==out_signed_mail;
|
||
if (attach_mail && is_power_station())
|
||
{
|
||
attach_mail =
|
||
#ifdef DBG
|
||
noyes_box
|
||
#else
|
||
yesno_box
|
||
#endif
|
||
(TR("Si desidera spedire veramente i documenti via mail?\n"
|
||
"Rispondendo NO verranno solo salvati gli allegati."));
|
||
}
|
||
|
||
if (docs > 0)
|
||
{
|
||
const bool mail_requested = (mode == out_mail || mode == out_signed_mail);
|
||
TProgress_monitor pi(docs, TR("Elaborazione documenti..."));
|
||
for (short loop = mail_requested ? 0 : 1; loop < 2; loop++)
|
||
{
|
||
const bool mail_loop = (loop == 0);
|
||
const bool print_loop = !mail_loop;
|
||
|
||
for (int i = 0; i < docs; i++)
|
||
{
|
||
if (!pi.add_status())
|
||
break;
|
||
|
||
doc.move_to(i);
|
||
|
||
const TString4 tipodoc = doc.get(DOC_TIPODOC).as_string();
|
||
const TTipo_documento& tipo = cached_tipodoc(tipodoc);
|
||
|
||
const bool final_doc = doc.get(DOC_STATO).as_string()[0] >= tipo.stato_finale_stampa();
|
||
if (final_print && final_doc && docs > 1) // Se docs==1 probabilmente stampo un sigolo documento comunque
|
||
continue; // Evita lavoro inutile!
|
||
|
||
bool arc = false;
|
||
if (final_print || final_doc)
|
||
{
|
||
const TString4 codnum = doc.get(DOC_CODNUM).as_string();
|
||
const TCodice_numerazione& cn = cached_numerazione(codnum);
|
||
arc = cn.auto_archive();
|
||
}
|
||
set_next_pdf(&doc);
|
||
|
||
TToken_string to, cc;
|
||
const bool send_mail = mail_requested && get_mail_address(to, cc);
|
||
const bool paperless = send_mail || mode == out_pdf || mode == out_signed_pdf;
|
||
|
||
// Tenta di costruirsi il nome del report: se non stampo su carta cerco di usare un profilo con sfondo
|
||
TFilename profilo;
|
||
const bool ok = nome_report(doc, paperless ? 2 : 0, profilo);
|
||
|
||
if (ok)
|
||
{
|
||
int copies = 1;
|
||
if (!paperless)
|
||
{
|
||
copies = _msk->get_int(F_NCOPIE);
|
||
if (copies <= 0 && final_print)
|
||
copies = tipo.ncopie();
|
||
if (copies <= 0)
|
||
copies = 1;
|
||
}
|
||
|
||
TReport_doc& report = reports.get(profilo);
|
||
if (send_mail)
|
||
{
|
||
if (mail_loop)
|
||
{
|
||
mail_book = new TDoc_book;
|
||
if (!report.print(doc, *mail_book, final_print, 1, true, false, false)) // Non archiviare per ora...
|
||
break;
|
||
if (arc) // ... eventualemte archivia direttamente il book senza passare per uno temporaneo
|
||
mail_book->archive(NULL, signature);
|
||
|
||
TString mesg;
|
||
TToken_string to, cc; get_mail_address(to, cc);
|
||
mesg << tipo.descrizione() << TR(" n. ") << doc.get(DOC_NDOC)
|
||
<< TR(" del ") << doc.get(DOC_DATADOC) << TR(" a ") << to;
|
||
mail_log.log(0, mesg);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (print_loop)
|
||
{
|
||
if (!report.print(doc, book, final_print, copies, true, arc, signature))
|
||
break;
|
||
if (!paperless)
|
||
print_extra_copies(report, doc, book, copies);
|
||
}
|
||
}
|
||
} //if(profilo.custom_path()...
|
||
else
|
||
{
|
||
TString msg; msg << TR("Report inesistente: ") << profilo;
|
||
xvtil_popup_error(msg);
|
||
continue;
|
||
}
|
||
|
||
// Stampa eventuali allegati
|
||
if (nome_report(doc, 1, profilo))
|
||
{
|
||
int copies = tipo.additional_ncopie();
|
||
if (copies <= 0) copies = 1;
|
||
|
||
TReport_doc& allegato = reports.get(profilo);
|
||
// Cambio _codnum per non sovrascrivere il pdf precedente
|
||
if (arc)
|
||
{
|
||
_codnum = profilo.name();
|
||
_codnum = _codnum.before(".");
|
||
}
|
||
// Il flag di definitivo deve essere false altrimenti riaggiorna lo stato e ristampa i documenti allegati
|
||
if (send_mail)
|
||
{
|
||
if (mail_loop)
|
||
allegato.print(doc, *mail_book, false, 1, false, false, false); // Non archivio gli allegati alla mail
|
||
}
|
||
else
|
||
{
|
||
if (print_loop)
|
||
{
|
||
allegato.print(doc, book, false, copies, false, arc, signature);
|
||
if (!paperless)
|
||
print_extra_copies(allegato, doc, book, copies);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (mail_book != NULL)
|
||
{
|
||
if (mail_book->pages() > 0)
|
||
{
|
||
TFilename attachment;
|
||
bool is_tmp = false;
|
||
|
||
// Se ho archiviato (arc==true) allora il file di attachment e' gia' pronto!
|
||
bool ok = arc && get_next_pdf(_anno, -1, _codnum, _ndoc, _codcf, attachment);
|
||
if (!ok || !attachment.exist()) // Altrimenti ne creo uno temporaneo
|
||
{
|
||
attachment.tempdir();
|
||
attachment << SLASH << _anno <<'_' << _codnum << '_' << _ndoc;
|
||
attachment.ext("pdf");
|
||
ok = mail_book->export_pdf(attachment, mode == out_signed_mail);
|
||
is_tmp = ok;
|
||
}
|
||
if (ok && attach_mail) // Ho chiesto la spedizione vera e propria
|
||
{
|
||
ok = spotlite_send_mail(attachment);
|
||
// Per ora non cancellare allegati mailsend.exe potrebbe non aver finito di scriverli 14/07/2015
|
||
// if (is_tmp) attachment.fremove();
|
||
TString mesg; mesg << "Invio allegato " << attachment;
|
||
if (!ok) mesg << " NON";
|
||
mesg << " riuscito";
|
||
mail_log.log(0, mesg);
|
||
}
|
||
}
|
||
delete mail_book;
|
||
mail_book = NULL;
|
||
}
|
||
}
|
||
}
|
||
} // if docs > 0
|
||
|
||
if (book.pages() > 0)
|
||
{
|
||
if (docs > 1)
|
||
set_next_pdf(NULL); //spegne l'archiviazione nell'esportazione;non si possono archiviare pi<70> docs in uno!!!
|
||
|
||
if (mail_log.recordset()->items() > 0)
|
||
book.add(mail_log);
|
||
switch (mode)
|
||
{
|
||
case out_preview: book.preview(); break;
|
||
case out_pdf:
|
||
case out_signed_pdf:
|
||
{
|
||
TFilename pdf; pdf.tempdir();
|
||
pdf << SLASH << _anno << '_' << _codnum << '_' << _ndoc;
|
||
pdf.ext("pdf");
|
||
if (book.export_pdf(pdf, mode == out_signed_pdf))
|
||
xvt_sys_goto_url(pdf, "open");
|
||
}
|
||
break;
|
||
default:
|
||
if (_no_print_dlg)
|
||
book.print(1, book.pages()); // Evita di chiedere da pag. a pag.
|
||
else
|
||
book.print();
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (mail_log.recordset()->items() > 0)
|
||
mail_log.preview();
|
||
}
|
||
|
||
if (mode == out_signed_mail || mode == out_signed_pdf)
|
||
xvt_sign_stop();
|
||
|
||
return true;
|
||
}
|
||
|
||
void TReport_doc_app::print_selection(TOutput_mode mode)
|
||
{
|
||
TString query;
|
||
query << "USE " << LF_DOC;
|
||
add_filter(query, true);
|
||
add_filter(query, false);
|
||
|
||
TISAM_recordset doc(query);
|
||
const TRecnotype docs = doc.items();
|
||
if (docs > 0)
|
||
{
|
||
bool is_definitive = false;
|
||
if (argc() > 7) // Batch
|
||
is_definitive = *argv(7) == 'D';
|
||
else
|
||
{
|
||
if (argc() < 6) // Vieta i link quando sono in batch
|
||
is_definitive = _msk->get(F_TIPOST) == "D";
|
||
else
|
||
{
|
||
const KEY k = yesnocancel_box(FR("Stampare in definitiva %ld documenti?"), docs);
|
||
if (k == K_ESC)
|
||
return;
|
||
is_definitive = k == K_YES;
|
||
}
|
||
}
|
||
print_loop(doc, mode, is_definitive);
|
||
}
|
||
}
|
||
|
||
// Elabora una transazione del tipo
|
||
// [Transaction]
|
||
// Action = Stampa
|
||
// Mode = D
|
||
// NoPrintDlg = X
|
||
// [33]
|
||
// Doc(0)=D|2009|F01|1
|
||
// Doc(1)=D|2009|A02|2
|
||
void TReport_doc_app::print_trans(const char* ininame)
|
||
{
|
||
TTrans_recordset doc(ininame);
|
||
if (doc.items() > 0)
|
||
{
|
||
char a='S', m='P';
|
||
if (ininame && *ininame) // Dummy test
|
||
{
|
||
TConfig ini(ininame, "Transaction");
|
||
a = ini.get("Action")[0]; // Stampa, Anteprima, Pdf, ...
|
||
m = ini.get("Mode")[0]; // Definitivo o Provvisori
|
||
_no_print_dlg = ini.get_bool("NoPrintDlg"); // Nascondi GUI di stampa
|
||
}
|
||
const TOutput_mode mode = key2mode(a);
|
||
const bool is_definitive = m == 'D';
|
||
print_loop(doc, mode, is_definitive);
|
||
}
|
||
else
|
||
cantread_box(ininame);
|
||
}
|
||
|
||
// Traduce un carattere ASCII nella corrispondente modalita' di stampa
|
||
TReport_doc_app::TOutput_mode TReport_doc_app::key2mode(KEY k) const
|
||
{
|
||
TOutput_mode mode = out_print;
|
||
|
||
if (k >= 'a' && !has_module(FDAUT))
|
||
k -= ' '; // toupper dei poveri
|
||
if (!has_module(RSAUT))
|
||
k = 'A';
|
||
|
||
switch (k)
|
||
{
|
||
case 'A': mode = out_preview; break;
|
||
case 'E': mode = out_mail; break;
|
||
case 'e': mode = out_signed_mail; break;
|
||
case 'P': mode = out_pdf; break;
|
||
case 'p': mode = out_signed_pdf; break;
|
||
case 'S':
|
||
default : mode = out_print; break;
|
||
}
|
||
return mode;
|
||
}
|
||
|
||
void TReport_doc_app::main_loop()
|
||
{
|
||
_no_print_dlg = false; // Normalmente mostra la GUI di stampa
|
||
const int a = argc();
|
||
if (a > 2)
|
||
{
|
||
const TFixed_string arg = argv(2);
|
||
|
||
// Gestione transazioni di stampa
|
||
if (arg.starts_with("-i"))
|
||
{
|
||
const TFilename ini = arg.mid(2);
|
||
if (ini.exist())
|
||
print_trans(ini);
|
||
return;
|
||
}
|
||
|
||
TString4 codnum = arg.left(4);
|
||
if (arg.len() > 4 || cache().get("%NUM", arg).empty())
|
||
{
|
||
const TToken_string tok(arg, ',');
|
||
TString16 paragraph, field;
|
||
tok.get(0, paragraph); tok.get(1, field);
|
||
if (field.blank()) field = DOC_CODNUM;
|
||
codnum = ini_get_string(CONFIG_DITTA, paragraph, field);
|
||
}
|
||
_msk->set(F_CODNUM, codnum); // Stampa da menu con numerazione imposta
|
||
}
|
||
|
||
if (a > 6) // Stampa da riga di comando
|
||
{
|
||
_msk->set(F_ORDERING, "N"); // Stampa per numero documento
|
||
_msk->set(F_ANNO, argv(3));
|
||
_msk->set(F_PROVV, argv(4));
|
||
|
||
// "883" = Stampa solo 883; "882-884" = stampa dal 882 al 884
|
||
const TToken_string strndoc(argv(5), '-');
|
||
long dandoc = 0, andoc = 0;
|
||
if (strndoc.get(0, dandoc))
|
||
{
|
||
if (!strndoc.get(1, andoc))
|
||
andoc = dandoc;
|
||
_msk->set(F_DA_NDOC, dandoc);
|
||
_msk->set(F_A_NDOC, andoc);
|
||
}
|
||
|
||
const TOutput_mode mode = key2mode(*argv(6)); // modo di 'S'tampa, 'A'nteprima, 'P'DF
|
||
// argv(7); // Provvisiorio o Definitivo testato altrove!
|
||
if (a > 8)
|
||
_msk->set(F_NCOPIE, argv(8)); // Numero copie
|
||
|
||
print_selection(mode);
|
||
return;
|
||
}
|
||
|
||
while (true)
|
||
{
|
||
const KEY k = _msk->run();
|
||
if (k == K_QUIT)
|
||
break;
|
||
print_selection(key2mode(k));
|
||
}
|
||
}
|
||
|
||
int ve1300(int argc, char* argv[])
|
||
{
|
||
TReport_doc_app a;
|
||
a.run(argc, argv, TR("Stampa documenti"));
|
||
return (0);
|
||
}
|