campo-sirio/ve/ve1100.cpp
guy 2cbda4933f Patch level : 2.0 614
Files correlati     : ve1.exe
Ricompilazione Demo : [ ]
Commento            :

EP20128
Da file impostazioni stampanti seleziono la satmpante Pippo con font arial
caratte 10 e do registra. Vado in stampa documenti e nell'ultima maschera
di impostazioni della stampante che viene proposta prima dell'esecuzione
della stampa stessa viene riportata la stampante Pippo ma font roman
10cpi carattere 12.

EP20134
Lavorando su postazioni client windows 2000 in rete con programmi in locale
e dati su server dedicato, pur inpostando da file impostazione stampante una
stampsante diversa da quella predefinita in Windows nell'ultima maschera
presentata prima dell'esecuzione della stampa a video documenti di vendita
viene riportata la stampante predefinita di Windows


git-svn-id: svn://10.65.10.50/trunk@11524 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-10-23 10:33:56 +00:00

1973 lines
61 KiB
C++
Executable File
Raw Blame History

//////////////////////////////////////////////////////////////
// Stampa documenti
//////////////////////////////////////////////////////////////
#include <applicat.h>
#include <config.h>
#include <defmask.h>
#include <form.h>
#include <msksheet.h>
#include <printer.h>
#include <progind.h>
#include <sheet.h>
#include "velib.h"
#include "sconti.h"
#include "ve1100.h"
#include "ve0100b.h"
#define LISTADOC "listadoc"
#define FAKETOTFLD 9999
// Queste classi (TDocisamfile e TRDocisamfile) servono nel costruttore di TDocumento_form
// in modo da sostituire i file della relazione, ovvero LF_DOC e LF_RIGHEDOC.
// Facendo in questo modo ogni get() del record, viene reindirizzata alla get() dei
// TVariable_recfield, in modo da utilizzare nel form le istruzioni FIELD anche per i campi
// virtuali.
class TDocisamfile : public TLocalisamfile
{
TDocumentoEsteso *_doc;
public:
virtual TRectype& curr() const { return (TRectype&) *_doc; }
virtual int readat(TRecnotype nrec, word lockop = _nolock);
TDocisamfile(TDocumentoEsteso* doc) : TLocalisamfile(LF_DOC) { _doc = doc;}
virtual ~TDocisamfile() {};
};
int TDocisamfile::readat(TRecnotype nrec, word lockop)
{
int err = TBaseisamfile::readat(nrec, _nolock);
if (err == NOERR)
{
err = _doc->read(curr());
if (err == NOERR)
{
_doc->summary_reset(TRUE); // forza il ricalcolo perche' trattasi di documento diverso
_doc->summary_filter(1);
}
}
return err;
}
class TRDocisamfile : public TLocalisamfile
{
TDocumento *_doc;
bool _normal_next;
int _row;
protected:
TDocumento& doc() const { return *_doc;}
public:
void set_normal_next(const bool b = TRUE) { _normal_next = TRUE; }
virtual int next(word lockop = _nolock) { return _normal_next ? TLocalisamfile::next(lockop) : NOERR; }
virtual TRectype& curr() const ;
void set_row(int r) { _row = r;}
TRDocisamfile(TDocumento* doc) : TLocalisamfile(LF_RIGHEDOC) { _doc = doc; _row = 1; _normal_next = FALSE;}
virtual ~TRDocisamfile() {};
};
TRectype& TRDocisamfile::curr() const
{
TRectype& rr = ((_row > 0 && _row <= _doc->rows()) ? (TRectype&) doc()[_row] : TLocalisamfile::curr());
return rr;
}
////////////////////////////////////////////////////////////////////////////
// classe TDocumento_form customizzata dalla Form per i documenti
////////////////////////////////////////////////////////////////////////////
class TDocumento_form : public TForm
{
static TDocumento_form* _form;
TDocisamfile* _docfile;
TRDocisamfile* _rdocfile;
TSorted_cursor * _sorted_cur; // Valido solo per i form di lista documenti
TRelation &_firmrel; // relazione di gestione dei dati della ditta corrente
TString _module; // codice del modulo di carta associato a questo al form
TString_array _exclude_array_t; // array di tipi riga da escludere dalla stampa
TString_array _exclude_array_a; // array di articoli da escludere dalla stampa
TDocumentoEsteso * _doc; // Documento da stampare
TAssoc_array _doc_totals; // Assocarray per codice numerazione contenente i totali nel caso di stampa lista documenti
bool _valid, _cli_loaded; // flag che indica se il form e' valido | se l'oggetto cliente <20> gi<67> stato caricato
TString_array _group_decimals; // Array di TToken_string per ogni gruppo definito in GENERAL.
// Il primo elelemento della token_string conterra' il numero del gruppo
// il secondo il n.ro di decimali per importi in lire ed il terzo il n.ro
// di decimali per gli importi in valuta
// I gruppi sono cosi' predefiniti:
// PRI_DECIMALS corrisponde al gruppo 29
// QTA_DECIMALS corrisponde al gruppo 30
// IMP_DECIMALS corrisponde al gruppo 31
// Altri gruppi definiti dall'utente saranno cosi' sintatticamente impostati:
// NEW_GROUP <n> <lit_dec> <val_dec>
// Dove <n> e' il numero del gruppo
// <lit_dec> e' il numero di decimali per i documenti in lire
// <val_dec> e' il numero di decimali per i documenti in valuta
// ATTENZIONE: e' importante che i nomi dei gruppi utilizzati per modificare le pictures non siano usati per
// per altri messaggi. Inoltre un TForm_item che appartiene ad un gruppo di modifica picture
// non puo' appartenere ad un altro gruppo dello stesso tipo, ad esempio i gruppi 29 e 30 contemporaneamente.
// Puo' pero' appartenere anche ad altri gruppi che non siano utilizzati per lo scopo qui definito
protected:
virtual void extended_parse_general(TScanner &); // gestione dei parametri estesi nella sezione general
virtual bool validate(TForm_item &, TToken_string &); // gestione dei messaggi estesi nei campi
bool print_on_body(int r); // Trascrive la riga 'r' del documento sul body. Ritorna TRUE se va stampata, FALSE se va saltata
void print_header(TPrinter& p); // Stampa la testata
void print_footer(TPrinter& p); // Stampa la pedata
static void doc_header_handler(TPrinter& p);
static void doc_footer_handler(TPrinter& p);
void output_values(const TRectype & rec, const char * output, TForm_item & cf);
public:
void edit_picture(TForm_item & f, const int dec);
void modify_pictures();
virtual TCursor* cursor() const { return _sorted_cur ? _sorted_cur : TForm::cursor(); }
void hide_sections();
bool is_faketotfld();
void print_documento();
bool valid() const { return _valid; }
bool doc_arrange();
int ncopie() const { return _doc->tipo().ncopie(); }
const TString &get_module_code() const { return _module; } // ritorna il codice del modulo di carta
TString_array& exclude_list_t() { return _exclude_array_t; }
TString_array& exclude_list_a() { return _exclude_array_a; }
TDocumentoEsteso& doc() { return *_doc; }
void set_doc_ext(TRectype* doc);
TDocumento_form(TRectype& doc, TRelation& rel, bool definitiva, bool interattivo, bool aggiuntivo);
TDocumento_form(const char* form, TRelation& rel);
virtual ~TDocumento_form();
};
TDocumento_form* TDocumento_form::_form = NULL;
void TDocumento_form::set_doc_ext(TRectype* doc)
{
CHECK(_doc == NULL, "Doppio documeto esteso");
if (doc != NULL)
_doc = new TDocumentoEsteso(*doc);
else
_doc = new TDocumentoEsteso;
_docfile = new TDocisamfile(_doc);
_rdocfile = new TRDocisamfile(_doc);
_rdocfile->set_normal_next();
relation()->replace(_docfile,0);
relation()->replace(_rdocfile,1);
if (_doc->physical_rows() > 0)
relation()->update();
}
TDocumento_form::TDocumento_form(TRectype& doc, TRelation& rel, bool definitiva, bool interattivo, bool aggiuntivo)
: _firmrel(rel), _valid(FALSE), _sorted_cur(NULL), _doc(NULL), _docfile(NULL), _rdocfile(NULL)
{
_form = this;
//const TString codnum(doc.get(DOC_CODNUM));
//const TString numdoc(doc.get(DOC_NDOC));
const TString8 tipodoc(doc.get(DOC_TIPODOC));
TFilename nomeform;
const TRectype rec = cache().get("%TIP", tipodoc);
if (!rec.empty())
{ // se non ci sono errori procede con la stampa
nomeform = aggiuntivo ? rec.get("S5").mid(8) : rec.get("S5").left(8); // legge il nome del form di stampa
nomeform.trim();
TFilename test(nomeform); test.ext("frm");
test.custom_path();
if (!test.exist())
{
error_box(FR("Nome form di stampa '%s' non valido per il tipo documento %s"), (const char*)nomeform, (const char*)tipodoc);
return;
}
}
else
{
error_box(FR("Tipo di documento non valido: '%s'"), (const char*)tipodoc);
return;
}
_valid = TRUE;
read(nomeform);
_cli_loaded= FALSE;
set_doc_ext(&doc); // istanzia TDocumentoEsteso
modify_pictures();
dec_parm p;
const int items = _group_decimals.items();
for (int i = 0; i< items; i++)
{
TToken_string& t = _group_decimals.row(i);
int gruppo = t.get_int(0);
switch (gruppo)
{
case GROUP_QTA : p.qta_lit = t.get_int(1);p.qta_val = t.get_int(2);
break;
// add other groups here
default:
break;
}
}
_doc->set_decimals(p);
// Inizializza lo sfondo delle pagine normali
set_background(3, TRUE);
TPrinter& pr = printer();
pr.setheaderhandler(doc_header_handler);
TPrint_section& head = section('H');
pr.headerlen(head.height());
pr.setfooterhandler(doc_footer_handler);
const TPrint_section& foot = section('F');
pr.footerlen(foot.height());
}
// costruttore per stampa lista documenti (uso convenzionale dei forms)
TDocumento_form::TDocumento_form(const char* form, TRelation& rel)
: TForm(form), _firmrel(rel), _valid(FALSE), _doc(NULL), _docfile(NULL), _rdocfile(NULL)
{
_cli_loaded= FALSE;
_sorted_cur = new TSorted_cursor(relation(), "PROVV|ANNO|CODNUM|STATO|DATADOC|NDOC");
}
TDocumento_form::~TDocumento_form()
{
// Membri di cui NON va fatta la delete:
// _docfile : perche' viene fatta dal distruttore di TRelation
// _rdocfile : perche' viene fatta dal distruttore di TRelation
if (_doc) delete _doc;
if (_sorted_cur) delete _sorted_cur;
}
void TDocumento_form::hide_sections()
{
// Scorre tutte le sezioni e nasconde gli items
const char s[3] = { 'B', 'G', 'H' };
for (int sn = 0; sn < 3 ; sn++)
{
const char sc = s[sn];
for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
{
TPrint_section* sec = exist(sc, pt);
if (sec == NULL)
continue;
TForm_item* f;
for(word i = 0; i < sec->fields(); i++)
{
f = &(sec->field(i));
f->hide();
}
}
}
}
bool TDocumento_form::is_faketotfld()
{
TPrint_section* fl = exist('F',last_page);
if (fl != NULL)
{
TForm_item* f;
for(word i = 0; i < fl->fields(); i++)
{
f = &(fl->field(i));
if (f->id() == FAKETOTFLD)
return TRUE;
}
}
return FALSE;
}
bool TDocumento_form::doc_arrange()
{
TPrinter& pr = printer();
if (char_to_pos() != '\0' || (ipx()+ipy()+fpx()) != 0)
{
if (offset_x() != 0 || offset_y() != 0)
{
error_box(FR("Non e' possibile settare contemporaneamente gli offset"
" e i parametri di posizionamento del modulo %s."), (const char*)name());
return FALSE;
}
else
if (pr.printtype() == winprinter)
_form->arrange_form();
}
else
pr.set_offset(_form->offset_y(), _form->offset_x());
return TRUE;
}
void TDocumento_form::print_documento()
{
TPrinter& pr = printer();
// stampa tutte le righe
TPrint_section& body = section('B');
TPrint_section& foot = section('F');
TPrint_section* sect = exist('B', last_page);
TString last_section;
const int righe = _doc->rows();
bool one_row_printed = FALSE;
set_last_page(FALSE); // E' importante settare questo flag, per evitare "Falli di Piede" eheh :-)
for (int r=1; r<=righe; r++)
{
_rdocfile->set_row(r);
// Questo if non c'era e quindi, a causa della next_match ignorava sempre la prima riga.
// Ora la next_match non viene mai fatta: a cosa serve allora tutto cio'?
//if (cursor()->curr(LF_RIGHEDOC).get_int(RDOC_NRIGA) < r)
// cursor()->next_match(LF_RIGHEDOC);
if (!print_on_body(r))
continue;
if (sect)
{
sect->update();
const TString& curr_section = sect->field(0).get();
if (r == 1 || curr_section != last_section)
{
last_section = curr_section;
const word h = sect->height();
for (word j = 0; j < h; j++)
pr.print(sect->row(j));
}
}
const word h = body.height();
for (word j = 0; j < h; j++)
pr.print(body.row(j));
if (!one_row_printed)
one_row_printed = TRUE;
if ((*_doc)[r].tipo().formfeed())
pr.formfeed();
}
if (!one_row_printed)
{
// Riga fasulla... per stampare l'intestazione obbligatoriamente,
// anche in caso che non vi siano righe nel documento o che siano tutte escluse
TPrintrow r;
pr.print(r);
}
if (_doc->tipo().add_conai() && _doc->clifor().vendite().get_bool("CONAIASS"))
{
TRiga_documento last_row(_doc);
TConfig c(CONFIG_DITTA);
last_row = _rdocfile->curr();
_rdocfile->zero();
TString80 desc(c.get("DESCCONAIASS"));
if (desc.empty())
desc = "Contributo CONAI assolto";
_rdocfile->put(RDOC_DESCR, desc);
body.update();
const word h = body.height();
if (pr.rows_left() <= h+1) // salto pagina
pr.formfeed();
for (word j = 0; j < h; j++)
pr.print(body.row(j));
_rdocfile->curr() = last_row;
}
TPrint_section* last_foot = exist('F', last_page, FALSE);
if (last_foot != NULL)
{
const word lfh = last_foot->height();
const word left = pr.rows_left() + pr.footersize();
if (lfh > left) // Se l'ultimo footer e' troppo grande ...
pr.formfeed(); // Stampa il footer normale
pr.footerlen(lfh); // Fondamentale!
}
set_last_page(TRUE);
pr.formfeed(); // Stampa l'ultimo footer
// Rimette ad 1 il numero della pagina
pr.setcurrentpage(1);
}
void TDocumento_form::print_header(TPrinter& pr)
{
TPrint_section& head = section('H');
head.update();
const word r = head.height()-1;
for (word j = 0; j <= r; j++)
pr.setheaderline(j, head.row(j));
}
void TDocumento_form::print_footer(TPrinter& pr)
{
const bool p = _form->page(pr)>0;
TPrint_section& foot = section('F',p ? odd_page : last_page);
foot.update();
word r = foot.height();
for (word j = 0; j < r; j++)
pr.setfooterline(j, foot.row(j));
}
void TDocumento_form::doc_header_handler(TPrinter& pr)
{
pr.resetheader();
_form->print_header(pr);
}
void TDocumento_form::doc_footer_handler(TPrinter& pr)
{
pr.resetfooter();
_form->print_footer(pr);
}
void TDocumento_form::edit_picture(TForm_item & fi, const int dec)
{
const TString old_picture = fi.picture();
TString new_picture(20);
const int comma_pos = old_picture.find(',');
const int stop_pos = old_picture.find('.');
char migliaia_char = '.';
if (comma_pos > 0 && stop_pos > 0)
{
if (stop_pos > comma_pos)
migliaia_char = ',';
}
if (old_picture.empty()) // picture di default
{
new_picture = "."; // in lire
if (dec > 0) new_picture << dec; // in valuta
}
else
{
if (dec == 0) return; // 0 non cambia la picture
new_picture = old_picture;
// Resetta la picture: toglie eventuali decimali gia' presenti...
const int pos = new_picture.rfind(migliaia_char == '.' ? ',' : '.');
if (pos >= 0)
new_picture.cut(pos);
// Se si decide di metterne... altrimenti ndec -1 lascia la picture senza decimali
if (dec > 0)
{
TString16 dec_to_add;
for (int i = 0; i < dec; i++)
dec_to_add << "@"; // aggiunge tanti "@" quanti sono i decimali voluti
if (migliaia_char == ',')
new_picture << "."; // se ha trovato la virgola come separatore di migliaia significa che deve aggiungere il punto decimale
else
new_picture << ","; // altrimenti aggiunge la solita virgola
new_picture << dec_to_add; // infine aggiunge i decimali richiesti
}
}
const int w = old_picture.len(); // se la picture eccede la dimensione della picture, toglie i caratteri piu' a sx
int exceed = w - new_picture.len();
if (exceed<0 && w>0)
{
exceed=::abs(exceed);
new_picture = new_picture.mid(exceed,new_picture.len()-exceed);
if (new_picture[0] == migliaia_char)
new_picture.ltrim(1);
}
fi.set_picture(new_picture); // setta la nuova picture
}
void TDocumento_form::modify_pictures()
{
const bool valuta = _doc->in_valuta();
const char sechar[4] = { 'B', 'F', 'G', 'H' };
for (int sn = 0; sn < 4 ; sn++)
{
const char sc = sechar[sn];
for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
{
TPrint_section* sec = exist(sc, pt);
if (sec != NULL)
for (word i = 0; i < sec->fields() ; i++)
{
TForm_item& fi = sec->field(i);
if (fi.in_group(GROUP_PRICES))
edit_picture(fi, _doc->decimals(TRUE));
else
if (fi.in_group(GROUP_IMPORTI))
edit_picture(fi, _doc->decimals());
else
{
const int items = _group_decimals.items(); // numero di gruppi definiti
for (int j = 0; j < items; j++)
{
TToken_string& r = _group_decimals.row(j);
const int group = r.get_int(0);
if (fi.in_group(group)) // trova se appartiene al gruppo, modifica la picture
{
edit_picture(fi,valuta ? r.get_int(2) : r.get_int(1));
break; // considera solo il primo gruppo trovato
}
}
}
}
}
}
}
bool TDocumento_form::print_on_body(int r)
{
TPrint_section& body = section('B');
TRiga_documento& riga = doc()[r];
const TString & tiporiga = riga.get(RDOC_TIPORIGA);
bool ok = _exclude_array_t.find(tiporiga) < 0;
if (ok)
{
const TString & codart = riga.get(RDOC_CODART);
ok = _exclude_array_a.find(codart) < 0;
}
if (ok)
body.update(); // Crea la vera riga di stampa, eventuali allineamenti avverranno nella validate(), come al solito.
return ok;
}
void TDocumento_form::extended_parse_general(TScanner &scanner)
{
// se viene riconosciuto il token per l'impostazione del modulo legge il codice...
if (scanner.key() == "MO")
_module= scanner.string();
// Legge i decimali necessari per gli arrotondamenti (il primo per gli importi in lire, l'altro per quelli in valuta)
// if (scanner.key() == "PR")
// {
// TToken_string t;
// t.add(GROUP_PRICES);t.add(scanner.integer());t.add(scanner.integer());
// _group_decimals.add(t);
// }
// Stessa cosa per le quantita'
if (scanner.key() == "QT")
{
TToken_string t;
t.add(GROUP_QTA);t.add(scanner.integer());t.add(scanner.integer());
_group_decimals.add(t);
}
// Stessa cosa per gli importi in genere
// if (scanner.key() == "IM")
// {
// TToken_string t;
// t.add(GROUP_IMPORTI);t.add(scanner.integer());t.add(scanner.integer());
// _group_decimals.add(t);
// }
if (scanner.key() == "NE")
{
TToken_string t;
t.add(scanner.integer());t.add(scanner.integer());t.add(scanner.integer());
_group_decimals.add(t);
}
// Esclude certi tipi riga e codici articolo
if (scanner.key() == "EX")
{
TToken_string s(scanner.string(),',');
const char * i = s.get();
if (i)
{
if (*i)
_exclude_array_t.add(i);
i = s.get();
if (i && *i)
_exclude_array_a.add(i);
}
}
}
void TDocumento_form::output_values(const TRectype & rec, const char * output, TForm_item & cf)
{
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)
cf.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
if (fld[0] == '#') fld.ltrim(1);
if (fld.right(1) == "@")
{ // se c'<27> la a-commerciale <20> un gruppo
char sec = cf.section().section_type();
pagetype pt = cf.section().page_type();
int group = atoi(fld);
if (fld.find("->") >= 0)
{ // se nel gruppo c'<27> la freccia si riferisce ad un'altra sezione
sec = fld[0];
pt= (fld[1] != '-') ? char2page(fld[1]) : even_page;
}
TPrint_section &fs = section(sec, pt);
word itms = fs.fields();
for (word j=0; j<itms; j++)
{
TForm_item & fi = fs.field(j);
if (fi.in_group(group))
fi.set(dat);
}
}
else
{
TForm_item & fi= cf.find_field(fld);
fi.set(dat);
}
}
}
}
bool TDocumento_form::validate(TForm_item &cf, TToken_string &s)
{
const TString code(s.get(0)); // prende il primo parametro, il codice del messaggio
TString valore;
if (code== "_DITTA")
{
// lettura dei dati della ditta
// sintassi: _DITTA,{<campo relazione>|<macro>}
// dove: <campo relazione> <20> un riferimento alla relazione di gestione dei dati della ditta (es. 113@->DENCOM <20> la denominazione del comune di residenza della ditta)
// <macro> <20> uno delle macro seguenti:
// !RAGSOC ragione sociale
// !IND indirizzo (fiscale se c'<27>, oppure di residenza)
// !NUM numero civico (fiscale se c'<27>, oppure di residenza)
// !CAP CAP (fiscale se c'<27>, oppure di residenza)
// !COM comune (fiscale se c'<27>, oppure di residenza)
// !PROV provincia (fiscale se c'<27>, oppure di residenza)
// !IVA partita iva
// !CF codice fiscale
// !TEL numero di telefono (con prefisso)
// !FAX numero di fax (con prefisso)
// !REGSOC numero di registrazione presso il Tribunale
// !CCIAA numero di registrazione presso la camera di commercio
// nota: la relazione della ditta <20> cos<6F> strutturata:
// %NDITTE (9) Dati ditte
// + %ANAGR (6) Anagrafica generale (indirizzo, ecc.)
// + %COMUNI (113@) Comune di residenza
// + %COMUNI (213@) Comune di residenza fiscale
TString in(s.get());
if (in[0]!='!')
{
cf.set(_firmrel.curr().get(in));
return TRUE;
}
else
{
in.ltrim(1);
bool _fisc= _firmrel.lfile(6).get("INDRF").not_empty();
if (in=="RAGSOC")
{
cf.set(_firmrel.lfile().get("RAGSOC"));
return TRUE;
}
if (in=="IND")
{
if (_fisc)
cf.set(_firmrel.lfile(6).get("INDRF"));
else
cf.set(_firmrel.lfile(6).get("INDRES"));
return TRUE;
}
if (in=="NUM")
{
if (_fisc)
cf.set(_firmrel.lfile(6).get("CIVRF"));
else
cf.set(_firmrel.lfile(6).get("CIVRES"));
return TRUE;
}
if (in=="CAP")
{
if (_fisc)
cf.set(_firmrel.lfile(6).get("CAPRF"));
else
cf.set(_firmrel.lfile(6).get("CAPRES"));
return TRUE;
}
if (in=="COM")
{
if (_fisc)
cf.set(_firmrel.lfile(-213).get("DENCOM"));
else
cf.set(_firmrel.lfile(-113).get("DENCOM"));
return TRUE;
}
if (in=="PROV")
{
if (_fisc)
cf.set(_firmrel.lfile(-213).get("PROVCOM"));
else
cf.set(_firmrel.lfile(-113).get("PROVCOM"));
return TRUE;
}
if (in=="IVA")
{
cf.set(_firmrel.lfile(6).get("PAIV"));
return TRUE;
}
if (in=="CF")
{
cf.set(_firmrel.lfile(6).get("COFI"));
return TRUE;
}
if (in=="TEL")
{
valore = _firmrel.lfile().get("PTEL");
valore << "/" << _firmrel.lfile().get("TEL");
cf.set(valore);
return TRUE;
}
if (in=="FAX")
{
valore = _firmrel.lfile().get("PFAX");
valore << "/" << _firmrel.lfile().get("FAX");
cf.set(valore);
return TRUE;
}
if (in=="REGSOC")
{
valore = _firmrel[LF_UNLOC].get("REGIMP");
valore.insert(" ", 2); valore.insert(" ", 6);
valore.insert(" ", 11); valore.insert(" ", 21);
valore.insert("Reg.Imp. ", 0);
cf.set(valore);
return TRUE;
}
if (in=="CCIAA")
{
valore = _firmrel[LF_UNLOC].get("NUMCCIAA");
const TString & data = _firmrel[LF_UNLOC].get("DATAICCIAA");
if (data.not_empty())
valore << " del " << data;
cf.set(valore);
return TRUE;
}
}
} // fine _DITTA
if (code== "_CLIENTE")
{
// lettura dei dati del cliente
// sintassi: _CLIENTE,{<campo relazione>|<macro>}
// dove: <campo relazione> <20> un riferimento alla relazione di gestione dei dati del cliente
// <macro> <20> uno delle macro seguenti:
// !RAGSOC ragione sociale
// !CAP Codice Avviamento Postale (viene implementato un messaggio perche' sugli occasionali ha un nome campo diverso!!)
// !IND indirizzo
// !NUM numero civico
// !INDNUM indirizzo + numero civico
// !COM comune
// !PROV provincia
// !TEL primo numero di telefono (con prefisso)
// !TEL2 secondo numero di telefono (con prefisso)
// !TEL3 terzo numero di telefono (con prefisso)
// !FAX numero di fax (con prefisso)
// !COM-><FIELD> accede ai campi del comune di residenza cliente
// !COMN-><FIELD> accede ai campi del comune di nascita del cliente
TCli_for & cli_for = _doc->clifor();
TOccasionale & cli_occ = _doc->occas();
const bool occasionale = cli_for.occasionale();
TString in(s.get()); // prende la macro o il fieldref
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);
TLocalisamfile com(LF_COMUNI);
if (nascita)
{
com.put("STATO", occasionale ? cli_occ.get(OCC_STATONASC) : cli_for.get(CLI_STATONASC));
com.put("COM", occasionale ? cli_occ.get(OCC_COMNASC) : cli_for.get(CLI_COMNASC));
}
else
{
com.put("STATO", occasionale ? cli_occ.get(OCC_STATO): cli_for.get(CLI_STATOCF));
com.put("COM", occasionale ? cli_occ.get(OCC_COM): cli_for.get(CLI_COMCF));
}
if (com.read() == NOERR)
cf.set(com.get(in));
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_d_spaces();
cf.set(valore);
return TRUE;
}
} // fine _CLIENTE
if (code == "_DESCRIGA")
{
// Messaggio per reperire la descrizione estesa sulle righe del documento
TLocalisamfile &rdoc= (cursor())->file(LF_RIGHEDOC);
TString descrizione = rdoc.get("DESCR");
const bool desclunga = rdoc.get_bool("DESCLUNGA");
if (desclunga)
{
const TString & dest = rdoc.get("DESCEST");
descrizione << dest;
}
int nfields = s.items();
for (int j = 1; j < nfields; j++)
{
const TString & fld = s.get(j);
TForm_item & f = cf.find_field(fld);
const TString & val = f.get();
if (val.not_empty())
descrizione << " " << val;
}
cf.set(descrizione);
TParagraph_string p(descrizione, cf.width());
const int h = cf.height();
for (int i=0; p.get() != NULL && i < h; i++);
// cf.put_paragraph(descrizione);
// Setta l'altezza effettiva del body, per evitare sprechi di righe
cf.section().set_height(p.empty() ? 1 : i);
return TRUE;
}
if (code== "_RIEPILOGOIVA")
{
// 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
if (s.items() == 4)
{
byte selector = byte(atoi(s.get())); // il primo parametro e' il selettore del tipo di codice
if (selector != 0)
{
_doc->summary_filter(selector);
TString16 what = s.get(); // cosa deve stampare ?
TString value(_doc->summary_get(what)); // Piglia il valore dalla riga selezionata sulla tabellina
what = s.get();
const bool next = what == "1"; // deve cambiare elemento ?
if (next) _doc->summary_set_next();
cf.set(value);
}
}
else
error_box("Numero di parametri non corretto in _RIEPILOGOIVA");
return TRUE;
} // fine _RIEPILOGOIVA
if (code == "_TOTIMPONIBILI")
{
// 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
byte sel = atoi(s.get());
real x = sel == 0 ? _doc->imponibile(TRUE) : _doc->tot_imponibili(sel);
cf.set(x.string());
return (TRUE);
} // fine _TOTIMPONIBILI
if (code== "_SCADENZE")
{
// messaggio per stampare le scadenze
// sintassi: _SCADENZE,<macro>,<cambio codice>
// dove <macro> e' uno dei seguenti:
// DATA : stampa la data di scadenza
// IMPORTO : stampa l'importo in scadenza
// dove <cambio codice> vale 0 o 1 se indica di rendere corrente la prossima scadenza
if (s.items() == 3)
{
TString what(s.get());
TString value(_doc->scadenze_get(what));
what = s.get();
const bool next = what == "1";
if (next) _doc->scadenze_set_next();
cf.set(value);
}
return TRUE;
}
if (code == "_EDITPICTURE")
{
const int flds2set = s.items() -1;
// TString16 val(cursor()->file(LF_DOC).get(DOC_CODVAL));
// const bool valuta = val.not_empty() && val != "LIT";
const int ndec = _doc->decimals();
for (int i = 1; i<=flds2set; i++)
{
const short fld = s.get_int(i);
edit_picture(cf.section().find_field(fld), ndec);
}
}
if (code == "_SEPARATOR") // Riempitore
{
TString sep;
sep.fill('-',s.get_int(1));
cf.set(sep);
return TRUE;
}
if (code == "_WEEK" || code == "_YEAR")
{
const TString16 which(s.get());
TString16 data;
if (which == RDOC_DATACONS)
{
const TRectype& rdoc= cursor()->curr(LF_RIGHEDOC);
data = rdoc.get(which);
}
if (data.empty())
data = _doc->get(which);
TDate d(data);
const char * c = s.get();
bool complete = c != NULL && *c != '\0';
int week;
int year;
d.get_week_year(week, year, complete);
if (code == "_WEEK")
cf.set(data.format("%d", week));
else
cf.set(data.format("%d", year));
}
if (code== "_PARENTDOC")
{
const TRectype* rdoc = &cursor()->curr(LF_RIGHEDOC);
int level = s.get_int(1);
for (; rdoc != NULL && level > 0; level--)
rdoc = ((const TRiga_documento*)rdoc)->find_original_rdoc();
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 TString8 codnum = rdoc->get(RDOC_CODNUM);
const long ndoc = rdoc->get_long(RDOC_NDOC);
if (s.get(3) != NULL) // "FULL"
{
TDocumento doc(provv, anno, codnum, ndoc);
output_values(doc, s.get(2), cf);
}
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, s.get(2), cf);
}
}
}
if (code== "_PARENTROW")
{
const TRectype * rdoc = & cursor()->file(LF_RIGHEDOC).curr();
int level = s.get_int(1);
for (; rdoc != NULL && level > 0; level--)
rdoc = ((const TRiga_documento *) rdoc)->find_original_rdoc();
if (rdoc != NULL && rdoc->get(RDOC_PROVV).not_empty())
{
if (s.get(3) != NULL) // "FULL"
{
const char provv = rdoc->get_char(RDOC_PROVV);
const int anno = rdoc->get_int(RDOC_ANNO);
const TString8 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)], s.get(2), cf);
}
else
output_values(*rdoc, s.get(2), cf);
}
}
if (code == "_LISTADOC") // Messaggio per riepilogo lista documenti
{
const TString16 what(s.get(1));
TString16 which(s.get(2));
if (what == "STORE")
{
if (which[0] == '#')
which.ltrim(1); // Toglie il #
const TString16 codnum(cf.section().find_field(atoi(which)).get());
const real r(cf.get());
real* v = (real*)_doc_totals.objptr(codnum);
if (v == NULL)
{
v = new real(ZERO);
_doc_totals.add(codnum, v);
}
if (_doc->is_nota_credito())
*v -= r;
else
*v += r;
} else
if (what == "ADDTOT")
{
const real r = cf.get();
if (!r.is_zero())
{
TForm_item& tot = cf.find_field(which);
real v = tot.get();
if (_doc->is_nota_credito())
v -= r;
else
v += r;
tot.set(v.string());
}
}
else
{
TString_array k;
_doc_totals.get_keys(k);
const int index = atoi(which)-1;
if (index < k.items())
{
TString16 codnum(k.row(index));
if (what == "CODICE")
cf.set(codnum);
else
if (what == "TOTALE")
{
real& r = (real&) _doc_totals[codnum];
cf.set(r.string());
}
}
}
}
return TForm::validate(cf, s); // se il codice del messaggio non <20> identificato viene passato alla funzione standard
}
//////////////////////////////////////////////////////////////////////////////////////////////
// classe TStampaDoc_application customizzata dalla TApplication per l'applicazione principale
//////////////////////////////////////////////////////////////////////////////////////////////
enum behaviour
{
skip,
go,
cancel
};
// Chiavi di ordinamento LF_DOC:
// Chiave 1: ordinamento per Provvisorio + Anno + Codice numerazione + Numero documento
// Chiave 3: ordinamento per Data documento + Provvisorio + Anno + Codice numerazione + Numero documento
#define BY_NUM_KEY 1
#define BY_DATE_KEY 3
class TStampaDoc_application: public TSkeleton_application
{
TString _codnum; // codice di numerazione
char _provv; // stampa documenti provvisiori o definitivi (D o P)
int _anno; // anno della documentazione
int _key; // chiave per scorrere i documenti (1 o 3, vedi sopra)
int _ncopie; // numero di copie per ogni documento
long _dalnum, _alnum; // estremi di numerazione dei documenti
TDate _dadata, _adata; // estremi di data dei documenti
bool _interattivo; // flag che indica se il prog. funziona in interattivo o in batch
bool _is_lista; // flga che indica se e' stata selezionata la lista documenti
bool _definitiva; // flag che indica se la stampa <20> definitiva o no
TRelation *_firmrel; // puntatore alla relazione che gestisce i dati della ditta corrente
TMask * _selection_mask;
TRelation* _clifo_rel;
TCursor* _clifo_cur;
TCursor_sheet* _clifo_sheet; // Array sheet per la selezione cli/fo
TAssoc_array _clifo_sel; // Assoc array con solo i cli/fo selezionati. Facilita il filtro...
protected:
virtual bool create();
virtual bool destroy();
virtual void main_loop();
bool select(void);
virtual void on_firm_change(void);
virtual behaviour on_module_change(const TString &, TString &); // funzione chiamata ad ogni cambio modulo durante la stampa
virtual bool query_final_print(void); // funzione chiamata all'inizializzazione per sapere se la stampa <20> definitiva
void set_filter(TDocumento_form& frm);
static bool date2num_handler(TMask_field& f, KEY key);
static bool range_handler(TMask_field& f, KEY key);
static bool tipocf_handler (TMask_field& f, KEY k);
static bool fr_cod_handler (TMask_field& f, KEY k);
static bool to_cod_handler (TMask_field& f, KEY k);
static bool select_button (TMask_field& f, KEY k);
static bool reset_button (TMask_field& f, KEY k);
static bool tipodoc_handler (TMask_field& f, KEY k);
static bool filter_clifo(const TRelation* r);
long select_cod_range(long from, long to);
void reset_choices(TMask& m);
void set_choice_limits(TMask& m);
void build_clifo_list(const char c='C');
public:
void print_documento(TDocumento_form& frm);
void print_selected();
TStampaDoc_application() : _key(BY_NUM_KEY) {};
virtual ~TStampaDoc_application() {};
};
inline TStampaDoc_application& app() { return (TStampaDoc_application&) main_app(); }
void TStampaDoc_application::print_selected()
{
TRelation rel(LF_DOC);
rel.add(LF_RIGHEDOC,"CODNUM==CODNUM|ANNO==ANNO|PROVV==PROVV|NDOC==NDOC");
TCursor cur(&rel);
cur.setkey(_key);
TLocalisamfile& doc = cur.file();
TRectype darec(LF_DOC),arec(LF_DOC); // Estremi filtro
TString modulo_prec;
const bool order_by_num = _key == BY_NUM_KEY;
if (!_is_lista)
{
doc.put(DOC_CODNUM, _codnum); // compone la chiave per il record di inizio cursore
doc.put(DOC_ANNO, _anno);
doc.put(DOC_PROVV, _provv);
arec = doc.curr();
if (order_by_num)
doc.put(DOC_NDOC, _dalnum);
else
doc.put(DOC_DATADOC, _dadata);
//doc.setkey(_key);
doc.read(); // trova il record iniziale
darec = doc.curr();
doc.curr() = arec;
if (order_by_num)
{
doc.put(DOC_NDOC, _alnum);
if (doc.read() == _iskeynotfound) // trova il record finale
doc.prev();
}
else
{
doc.put(DOC_DATADOC, _adata); // trova il record finale
doc.put(DOC_NDOC, 999999L);
int err = doc.read(_isgteq);
if (err == NOERR)
err = doc.prev();
}
arec = doc.curr();
if (arec < darec)
{
error_box("Non vi sono documenti da stampare nell'intervallo indicato");
return;
}
_definitiva= query_final_print(); // legge il flag di stampa definitiva
}
TPrinter& pr = printer();
pr.open();
TProgind* pi = pr.printtype() != screenvis ?
new TProgind(cur.items(), TR("Stampa documenti in corso..."),FALSE,TRUE) :
NULL;
if (!_is_lista)
{
cur.setregion(darec, arec);
if (!order_by_num)
{
TString80 filter;
filter.format("(CODNUM==\"%s\")&&(PROVV==\"%c\")", (const char*)_codnum, _provv);
cur.setfilter(filter);
}
const long items = cur.items();
behaviour whattodo = go;
bool first_inst = TRUE;
real totdocumenti = ZERO;
//TDocumentoEsteso *documento = new TDocumentoEsteso;
//cur.file().set_curr(documento);
for (long i = 0; i < items; i++)
{
cur = i; // Posiziona il documento
if (_definitiva && !((TDocumento &) cur.curr()).stampabile())
continue;
// Istanzia il form principale
TDocumento_form* mainform = new TDocumento_form(cur.curr(), *_firmrel, _definitiva, _interattivo, FALSE);
if (!mainform->valid()) break; // interrompe la stampa se il doc corrente non e' tra i tipi validi
const TString &modulo= mainform->get_module_code(); // legge dal form il codice del modulo di carta per la stampa
if (modulo_prec.empty()) modulo_prec = modulo; // se siamo al primo passaggio la variabile di modulo precedente viene riempita
else first_inst = FALSE;
const bool module_changed = modulo != modulo_prec;
if (first_inst || module_changed)
if (!mainform->doc_arrange()) // Setta l'offset o posiziona manualmente
break; // Se vi sono errori interrompe la stampa
if (module_changed) whattodo = on_module_change(modulo, modulo_prec); // se il modulo <20> cambiato dalla stampa precedente interroga la funzione per sapere che comportamento tenere
if (whattodo==cancel) break; // se non si pu<70> procedere la stampa viene interrotta
if (whattodo==skip)
continue; // Salta il documento corrente
// altrimenti prosegue
// Carica il numero di copie da stampare per questo form
int ncopie = _ncopie <= 0 ? mainform->ncopie() : _ncopie; // Numero di copie da stampare per questo documento
if (ncopie <= 0) ncopie = 1;
for (int n=0; n < ncopie; n++)
{
TDocumentoEsteso& extdoc = mainform->doc();
print_documento(*mainform);
extdoc.summary_reset();
extdoc.scadenze_reset();
// Stampa eventuali documenti allegati
const TFilename formagg = extdoc.tipo().get("S5").mid(8);
const int ncopie2 = extdoc.tipo().get_int("I2");
if (!formagg.blank() && ncopie2 > 0) // Se esiste un tipo documento da accodare
{
TDocumento_form* secform = new TDocumento_form(cur.curr(), *_firmrel, _definitiva, _interattivo, TRUE);
for (int i = 0; i < ncopie2; i++)
{
print_documento(*secform);
extdoc.summary_reset();
extdoc.scadenze_reset();
}
delete secform;
}
}
// se la stampa <20> definitiva viene lanciata la procedura di rinumerazione
if (_definitiva && _interattivo)
{
if (numerazione_definitiva(mainform->doc()) != NOERR)
{
error_box(FR("Non <20> possibile completare la procedura di numerazione definitiva dei documenti. Errore %d"), doc.status());
break;
}
}
// Totalizza gli importi per eventuale stampa su FAKETOTFLD
totdocumenti += mainform->doc().totale_doc();
if (i == items - 1 && mainform->is_faketotfld())
{
mainform->hide_sections();
TForm_item& fk = mainform->find_field('F', last_page, FAKETOTFLD);
fk.show();
fk.set(totdocumenti.string());
print_documento(*mainform);
}
delete mainform;
}
}
else // Lista documenti
{
TDocumento_form* mainform = new TDocumento_form(LISTADOC,*_firmrel);
TCursor& cur = *mainform->cursor();
cur.setkey(_key);
darec.put(DOC_DATADOC, _dadata);
darec.put(DOC_PROVV, _provv);
darec.put(DOC_ANNO, _anno);
arec = darec;
arec.put(DOC_DATADOC, _adata);
cur.setregion(darec,arec);
const bool dettaglio = _selection_mask->get_bool(F_DETTAGLIO);
mainform->find_field('B', odd_page, "H_RIGHE").enable(dettaglio); // Visualizza i dettagli righe se richiesto
mainform->find_field('B', odd_page, "RIGHE").enable(dettaglio);
set_filter(*mainform);
const TRecnotype items = cur.items();
if (items > 0)
{
cur.freeze();
mainform->set_doc_ext(NULL); // Setta il documento esteso DOPO aver fatto il filtro
mainform->print();
}
delete mainform;
}
if (pi != NULL) delete pi;
printer().close();
}
void TStampaDoc_application::print_documento(TDocumento_form& f)
{
const TRectype& doc = f.cursor()->curr();
const bool is_vis = printer().printtype() == screenvis;
if (!is_vis)
{
TString80 status(TR("Documento: "));
status << doc.get(DOC_CODNUM);
status << '\\' << doc.get(DOC_NDOC);
xvt_statbar_set(status);
}
f.print_documento();
if (!is_vis)
xvt_statbar_set(NULL);
}
behaviour TStampaDoc_application::on_module_change(const TString &modulo, TString &modulo_prec)
{
if (!_interattivo) return skip; // se siamo in interattivo il documento viene saltato...
else
{ // ...altrimenti viene chiesto all'utente il da farsi
int risp= yesnocancel_box(FR("Il modulo di carta <20> cambiato: inserire il modulo '%s' e premere 'Si' per continuare,"
"'No' per saltare il documento o 'Annulla' per interrompere la stampa"), (const char*) modulo);
behaviour ret;
switch (risp)
{
case K_YES:
modulo_prec= modulo; // aggiorna l'inseguitore dei moduli
ret= go; // la stampa pu<70> continuare
break;
case K_NO:
ret= skip; // il documento viene saltato
break;
case K_ESC:
ret= cancel; // la stampa viene interrotta
break;
}
return ret;
}
}
bool TStampaDoc_application::query_final_print()
{
if (_interattivo)
{ // se siamo in interattivo viene richiesto all'utente se la stampa <20> definitiva o meno
if (yesno_box(TR("E' una stampa definitiva?"))) return TRUE;
else return FALSE;
} else return _definitiva; // altrimenti ritorna il valore letto dalla linea di comando
}
void TStampaDoc_application::set_filter(TDocumento_form& frm)
{
TCursor* cur = frm.cursor();
TString filtro,e1,e2,sw;
// Compone la lista dei clienti/forntitori selezionati
_clifo_sel.destroy();
TString16 key;
const long items = _clifo_sheet->items();
for (long i = 0L; i<items; i++)
if (_clifo_sheet->checked(i))
{
key.format("%06ld", _clifo_sheet->row(i).get_long(1)); // Formatta il codice
_clifo_sel.add(key, NULL);
}
// NB: se _clifo_sel non contiene nulla, non viene effettuato alcun filtro su CLI/FO (non setta la funzione!!)
filtro.format("TIPOCF==\"%c\"", _selection_mask->get(F_TIPOCF)[0]);
const int selval = _selection_mask->get_int(F_SELVAL);
const TString16 val = _selection_mask->get(F_VALUTA);
const int ndec = TCurrency::get_firm_dec();
frm.edit_picture(frm.find_field('F',last_page, 6), ndec); // pictures per totali finali
frm.edit_picture(frm.find_field('F',last_page, 8), ndec);
frm.edit_picture(frm.find_field('F',last_page, 10), ndec);
frm.edit_picture(frm.find_field('F',last_page, 12), ndec);
frm.edit_picture(frm.find_field('F',last_page, 16), ndec);
frm.edit_picture(frm.find_field('F',last_page, 17), ndec);
if (selval == 1) //In Lire
{
const TString16 firm_val(TCurrency::get_firm_val());
const bool not_empty = firm_val.not_empty();
filtro << "&&";
if (not_empty)
filtro << "((CODVAL==\"" << firm_val << "\")||";
filtro << "(CODVAL==\"\")";
if (not_empty)
filtro << ")";
}
else
if (selval == 2) // nella valuta specificata
filtro << "&&(CODVAL==\"" << val << "\")";
else
frm.find_field('B',odd_page,35).set("1"); // Cosi' effettua i totali generali in lire ?????
// Compone l'espressione filtro...
// prende tutte le righe dello spreasheet che non sono totalmente vuote:
// (CODNUM=="xxx"&&(STATO=="x"||STATO=="y"||STATO=="z"...)) ---> questo per una singola riga...
// se vi sono piu' righe, lo si ripete aggiungendo prima un bellissimo "||"
bool put_parentheses = FALSE;
TSheet_field& sf = (TSheet_field&)_selection_mask->field(F_SHEETNUMS);
const int rows = sf.items();
for (int j=0; j<rows; j++)
{
TToken_string& riga = sf.row(j);
sw = riga.get(0);sw.trim();
if (riga.empty_items() || sw.empty())
break; // Interrompe alla prima riga vuota...
e1.format("((CODNUM==\"%s\")", (const char*)sw);
TString4 td = riga.get(1);td.trim();
if (td.not_empty())
{
e1 << "&&(TIPODOC==\"" << td <<"\")";
}
e2 = "";
for (int k=2; k<=7; k++) // Famme vede' li stati generali... Aho' A BURINO! Che e' la Rivoluzione Francese?
{
const char c = riga.get(k)[0];
if (c == '\0' || c == ' ')
break; // Interrompe al primo blank...
e2.format("(STATO==\"%c\")",c);
// Se k vale 3 o piu' significa ke gli stati prec erano != "" no!?
if (k == 2)
e1 << "&&(";
else
e1 << "||";
e1 << e2;
}
if (e2.not_empty())
e1 << ")";
e1 << ")"; // Piazza la parentesi finale
put_parentheses = TRUE;
if (j == 0)
filtro << "&&(";
else
filtro << "||";
filtro << e1;
}
if (put_parentheses)
filtro << ")"; // Parentesi finale
cur->setfilter(filtro);
cur->set_filterfunction(_clifo_sheet->checked() > 0 ? filter_clifo : NULL);
}
////////////////////////////////////////////////////////////////
// Handlers della maschera
////////////////////////////////////////////////////////////////
long TStampaDoc_application::select_cod_range(long from, long to)
{
TWait_cursor hourglass;
if (to <= 0l) to = 999999L;
for (int i = 0; i < _clifo_sheet->items(); i++)
{
TToken_string& c = _clifo_sheet->row(i);
const long cod = c.get_long(1);
if (cod >= from && cod <= to)
_clifo_sheet->check(i);
else
_clifo_sheet->uncheck(i);
}
return _clifo_sheet->checked();
}
void TStampaDoc_application::build_clifo_list(const char c)
{
// Semplice ed efficace
TRectype rec(LF_CLIFO);
rec.put(CLI_TIPOCF, c);
_clifo_cur->setregion(rec, rec);
}
bool TStampaDoc_application::tipocf_handler(TMask_field& f, KEY key)
{
if (f.to_check(key) && key == K_TAB)
{
TWait_cursor hourglass;
app().reset_choices(f.mask());
app().build_clifo_list(f.get()[0]);
}
return TRUE;
}
bool TStampaDoc_application::fr_cod_handler(TMask_field& f, KEY key)
{
TMask& m = f.mask();
if (key == K_F9)
{
TMask& m = f.mask();
TCursor_sheet* sh = app()._clifo_sheet;
sh->disable_check();
sh->disable(DLG_USER);
if (sh->run() == K_ENTER)
{
app().select_cod_range(sh->row(sh->selected()).get_long(1), m.get_long(F_CODTO));
app().set_choice_limits(m);
}
sh->enable(DLG_USER);
}
else if (key == K_TAB && f.focusdirty())
{
const long l = app().select_cod_range(m.get_long(F_CODFR), m.get_long(F_CODTO));
app().set_choice_limits(m);
m.set(F_SELECTED, l);
}
return TRUE;
}
bool TStampaDoc_application::to_cod_handler(TMask_field& f, KEY key)
{
TMask& m = f.mask();
if (key == K_F9)
{
TCursor_sheet* sh = app()._clifo_sheet;
TMask& m = f.mask();
sh->disable_check();
sh->disable(DLG_USER);
if (sh->run() == K_ENTER)
{
app().select_cod_range(m.get_long(F_CODFR),sh->row(sh->selected()).get_long(1));
app().set_choice_limits(m);
}
sh->enable(DLG_USER);
}
if (key == K_TAB && f.focusdirty())
{
const long l = app().select_cod_range(m.get_long(F_CODFR),
m.get_long(F_CODTO));
app().set_choice_limits(m);
m.set(F_SELECTED, l);
}
return TRUE;
}
bool TStampaDoc_application::select_button(TMask_field& f, KEY key)
{
if (key == K_SPACE)
{
app()._clifo_sheet->enable_check();
if (app()._clifo_sheet->run() == K_ENTER)
app().set_choice_limits(f.mask());
}
return TRUE;
}
void TStampaDoc_application::reset_choices(TMask& m)
{
m.reset(F_SELECTED);
m.reset(F_CODFR);
m.reset(F_CODTO);
_clifo_sheet->check(-1, FALSE);
}
bool TStampaDoc_application::reset_button(TMask_field& f, KEY key)
{
if (key == K_SPACE)
app().reset_choices(f.mask());
return TRUE;
}
void TStampaDoc_application::set_choice_limits(TMask& m)
{
TWait_cursor hourglass;
long first = -1l, last = -1l;
for (int i = 0; i < _clifo_sheet->items(); i++)
{
if (_clifo_sheet->checked(i))
{
const long cf = _clifo_sheet->row(i).get_long(1);
if (first == -1l)
first = cf;
if (last < cf)
last = cf;
}
}
if (first != -1)
m.set(F_CODFR, first);
if (last != -1)
m.set(F_CODTO, last);
m.set(F_SELECTED, _clifo_sheet->checked());
}
bool TStampaDoc_application::date2num_handler(TMask_field& f, KEY key)
{
TMask& m = f.mask();
if (key == K_TAB && f.focusdirty())
{
short dlg = f.dlg();
TLocalisamfile doc(LF_DOC);
doc.setkey(3);
TString codnum1(m.get(F_CODNUM)),codnum2;
TString anno1(m.get(F_ANNO)),anno2;
TString provv1(m.get(F_PROVV)),provv2;
TDate data1(m.get_date(dlg)),data2;
long numdoc;
doc.zero();
doc.put("CODNUM", codnum1);
doc.put("ANNO", anno1);
doc.put("PROVV", provv1);
doc.put("DATADOC", data1);
if (doc.read(_isgteq) == NOERR)
{
codnum2 = doc.get("CODNUM");
anno2 = doc.get("ANNO");
provv2 = doc.get("PROVV");
data2 = doc.get_date("DATADOC");
if (codnum1 == codnum2 && anno1 == anno2 && provv1 == provv2 && data1 == data2)
{
numdoc = doc.get_long("NDOC");
m.set(dlg == F_DA_DATADOC ? F_DA_NDOC : F_A_NDOC, numdoc);
}
}
}
return TRUE;
}
bool TStampaDoc_application::range_handler(TMask_field& f, KEY key)
{
bool rt = TRUE;
TMask& m = f.mask();
if (key == K_TAB && f.focusdirty())
{
const long lim_sup = atol(f.get());
const long lim_inf = f.mask().get_long(F_DA_NDOC);
if (lim_sup < lim_inf)
rt = f.error_box(TR("Il limite superiore deve essere maggiore del limite inferiore"));
}
return rt;
}
bool TStampaDoc_application::tipodoc_handler(TMask_field& f, KEY key)
{
TMask& m = f.mask();
switch (key)
{
case K_F9: //caso del bottone di selezione
{
TArray_sheet as(-1,-1,70,20,TR("Tipi documento"),"Codice|Descrizione@50"); //costruisce uno sheet di selezione dei tipi doc
const TRectype& recnum = cache().get("%NUM",m.get(101)); //cache sulla tabella numerazione documento con il numero doc immesso nella maschera
const TString80 s2 = recnum.get("S2"); //prende tutto il contenuto del campo S2 della tabella %NUM (numerazione docs)
for (int i = 0; i < s2.len(); i+=4)
{
const TString4 tipodoc = s2.mid(i,4); //si va di 4 in 4, x' cosi' sono ordinati i tipidoc nel campo S2
if (!tipodoc.blank()) //ovviamente si procede solo se il tipodoc esiste
{
TToken_string row; //classica token_string con codice e descrizione del tipodoc: questa viene scelta nella tabella
row.add(tipodoc); //dei tipi docs %TIP
row.add(cache().get("%TIP", tipodoc, "S0"));
as.add(row); //..e viene aggiunta allo sheet di selezione
}
}
if (as.run() != K_ESC)
{
TToken_string& riga = as.row(-1); //setta sul campo a maschera il codice della riga selezionata di as
f.set(riga.get(0));
}
}
break;
case K_ENTER: //caso del bottone invio; + o - come sopra; deve xo' verificare che l'eventuale codice di tipodoc digitato
if (!f.empty()) //sia valido (esista nel campo S2 della tabella NUM)
{
const TRectype& recnum = cache().get("%NUM",m.get(101));
const TString80 s2 = recnum.get("S2");
for (int i = 0; i < s2.len(); i+=4)
{
TString4 tipodoc = s2.mid(i,4);
tipodoc.trim();
if (tipodoc == f.get())
return TRUE;
}
return f.error_box(FR("Tipo documento non valido per la numerazione %s"), (const char*)m.get(101));
}
break;
default:
break;
}
return TRUE;
}
////////////////////////////////////////////////////////////////
// Filtro per cli/fo sul cursore della lista documenti
////////////////////////////////////////////////////////////////
bool TStampaDoc_application::filter_clifo(const TRelation* r)
{
const long codcf = r->lfile().get_long(CLI_CODCF);
TString16 key;
key.format("%06ld", codcf);
return app()._clifo_sel.is_key(key);
}
////////////////////////////////////////////////////////////////
// Funzioni rimanenti
////////////////////////////////////////////////////////////////
bool TStampaDoc_application::create()
{
_firmrel= new TRelation(LF_NDITTE); // istanziamento e impostazione della relazione di gestione della ditta corrente
_firmrel->add(LF_ANAG, "TIPOA=TIPOA|CODANAGR=CODANAGR");
_firmrel->add(LF_UNLOC,"CODDITTA=CODDITTA"); // si posiziona sulla prima unita' locale della ditta
_firmrel->add(LF_COMUNI, "COM=STATORES+COMRES", 1, LF_ANAG, 100+LF_COMUNI);
_firmrel->add(LF_COMUNI, "COM=STATORES+COMRF", 1, LF_ANAG, 200+LF_COMUNI);
open_files(LF_TABCOM, LF_TAB, LF_OCCAS, LF_CLIFO, LF_INDSP, LF_CFVEN, LF_MOVMAG, LF_RMOVMAG, LF_CONDV, LF_ANAMAG , LF_SVRIEP, LF_AGENTI, LF_PERCPROV, LF_CAUSALI, 0);
const int argc = TApplication::argc();
_is_lista = argc == 3 && argv(2)[0] == 'L';
on_firm_change();
_selection_mask = new TMask(_is_lista ? "ve1100b" : "ve1100a");
if (!_is_lista)
{
_clifo_sheet = NULL;
_selection_mask->set_handler(F_DA_DATADOC, date2num_handler);
_selection_mask->set_handler(F_A_DATADOC, date2num_handler);
_selection_mask->set_handler(F_A_NDOC, range_handler);
}
else
{
_clifo_rel = new TRelation(LF_CLIFO);
_clifo_cur = new TCursor(_clifo_rel);
_clifo_sheet = new TCursor_sheet(_clifo_cur, " |CODCF|RAGSOC", TR("Selezione Clienti/Fornitori"),
"@1|Codice@6R|Descrizione@50", 0, 1);
build_clifo_list(); // Costruisce l'array sheet dei clienti (si parte!!)
_selection_mask->set_handler(F_TIPOCF, tipocf_handler);
_selection_mask->set_handler(F_CODFR, fr_cod_handler);
_selection_mask->set_handler(F_CODTO, to_cod_handler);
_selection_mask->set_handler(BUT_SEL, select_button);
_selection_mask->set_handler(BUT_ANN, reset_button);
_selection_mask->sfield(F_SHEETNUMS).sheet_mask().set_handler(102, tipodoc_handler);
}
if (argc>3)
{ // lettura dei parametri iniziali dalla linea di comando
_codnum= argv(2); // il primo parametro <20> il codice di numerazione
_anno= atoi(argv(3)); // il secondo <20> l'anno
_provv= argv(4)[0]; // il terzo <20> il flag di numerazione provvisoria
_dalnum= atol(argv(5)); // il quarto <20> il numero di documento di partenza
_alnum = _dalnum;
_definitiva = FALSE;
_ncopie = 1;
_interattivo= FALSE;
if (argc > 6)
{
_alnum= atol(argv(6)); // il quinto <20> il numero di documento di fine
if (argc > 7)
{
_definitiva= (strcmp(argv(7), "D")==0); // il sesto <20> se la stampa <20> definitiva (rinumerazione dei documenti)
if (argc > 8)
_ncopie = atoi(argv(8));
}
else _interattivo = TRUE;
}
print_selected();
return FALSE;
}
else
{
if (argc == 2 || _is_lista)
{ // oppure lancio della maschera
_interattivo= TRUE;
TSkeleton_application::create();
}
else
return error_box("Usage: ve1 -0 {[codnum anno {D|P} dalnum alnum {D|P} [ncopie]] | [L]}");
}
return TRUE;
}
bool TStampaDoc_application::destroy()
{
delete _firmrel; // distruzione della relazione di gestione della ditta corrente
delete _selection_mask;
if (_clifo_sheet != NULL)
{
delete _clifo_sheet;
delete _clifo_cur;
delete _clifo_rel;
}
return TApplication::destroy();
}
void TStampaDoc_application::on_firm_change()
{
TLocalisamfile &firmfile= _firmrel->lfile();
firmfile.put("CODDITTA", get_firm());
_firmrel->read();
}
bool TStampaDoc_application::select()
{
TMask & m = * _selection_mask;
m.reset();
if (_is_lista)
reset_choices(m);
const bool ok = m.run() == K_ENTER;
if (ok)
{
if (!_is_lista)
{
_codnum= m.get(F_CODNUM); // lettura dei dati dalla maschera
_dalnum= m.get_long(F_DA_NDOC);
_alnum= m.get_long(F_A_NDOC);
_ncopie = m.get_int(F_NCOPIE);
if (_alnum == 0)
_alnum = 9999999L;
/* Per ora disabilitamo questa feature, che forse deve essere studiata meglio
TString16 config; config << "NUM" << _codnum;
printer().read_configuration(config);
*/
}
_anno= m.get_int(F_ANNO);
_provv= m.get(F_PROVV)[0];
_dadata = m.get_date(F_DA_DATADOC);
if (!_dadata.ok())
_dadata = TDate(1,1,_anno);
_adata = m.get_date(F_A_DATADOC);
if (!_adata.ok())
_adata = TDate(31,12,_anno);
if (_is_lista || m.get(F_DATA_O_NUM) == "D")
_key = BY_DATE_KEY;
else
_key = BY_NUM_KEY;
}
return ok;
}
void TStampaDoc_application::main_loop()
{
while (select())
print_selected();
}
// Do all the work!
int ve1100(int argc, char* argv[])
{
TStampaDoc_application a;
const bool riep = argc == 4 && argv[2][0] == 'L'; // Lista documenti
a.run(argc, argv, riep ? TR("Lista documenti") : TR("Stampa documenti"));
return 0;
}