#include #include #include #include #include #include #include #include #include #include #include #include "velib02.h" #include "ve1100.h" #include "ve0100b.h" //////////////////////////////////////////////////////////////////////////// // classe TDocVen_Form customizzata dalla Form per i documenti di vendita //////////////////////////////////////////////////////////////////////////// class TDocVen_Form: public TForm { TRelation &_firmrel; // relazione di gestione dei dati della ditta corrente TString _module; // codice del modulo di carta associato a questo al form TCliFor *_cliente; // oggetto per le informazioni sul cliente TString_array _exclude_array; // array di coppie tipo/articolo da escludere dalla stampa TDocumentoEsteso * _doc; // oggetto bool _cli_loaded; // flag che indica se l'oggetto cliente è già 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 // Dove e' il numero del gruppo // e' il numero di decimali per i documenti in lire // 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 virtual word set_body(word p, bool u); // derivata per la gestione del totalizzatore void edit_picture(TForm_item & f, const int dec); void modify_pictures(); public: const TString &get_module_code() { return _module; } // ritorna il codice del modulo di carta TString_array & exclude_list() { return _exclude_array; } TDocVen_Form(const char *, TRelation &, TDocumentoEsteso * ); virtual ~TDocVen_Form(); }; TDocVen_Form::TDocVen_Form(const char* name, TRelation &rel, TDocumentoEsteso * doc): TForm(), _firmrel(rel) { read(name); _cliente= new TCliFor; _cli_loaded= FALSE; _doc = doc; 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 29: p.pri_lit = t.get_int(1);p.pri_val = t.get_int(2); break; case 30: p.qta_lit = t.get_int(1);p.qta_val = t.get_int(2); break; case 31: p.imp_lit = t.get_int(1);p.imp_val = t.get_int(2); break; // add other groups here default: break; } } _doc->set_decimals(p); } TDocVen_Form::~TDocVen_Form() { delete _cliente; if (_doc) delete _doc; } void TDocVen_Form::edit_picture(TForm_item & fi, const int dec) { TString old_picture(20); old_picture = fi.picture(); TString new_picture(20); 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 TString16 dec_to_add; for (int i = 0; i < dec; i++) dec_to_add << "@"; // aggiunge tanti "@" quanti sono i decimali voluti new_picture = old_picture; if (old_picture.find(',') > 0) 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 = fi.width(); // se la picture eccede la dimensione, 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); } fi.set_picture(new_picture); // setta la nuova picture } void TDocVen_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); 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 } } } } } } word TDocVen_Form::set_body(word p, bool u) { TPrint_section& body = section('B', p); return TForm::set_body(p, u); } void TDocVen_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(29);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(30);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(31);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(),','); _exclude_array.add(s); } } bool TDocVen_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== "_ISAMREAD") { // lettura generica di un file del database // sintassi: _ISAMREAD,,[!!...],{|[!!...]} // dove: è il numero logico del file o il nome della tabella // è un'espressione del tipo = // è un'espressione di costanti numeriche, stringhe e valori di campi della form (indicati con il loro numero preceduto da #) // è un'espressione del tipo = (se è un gruppo deve essere seguito da @) oppure solo (il campo della form è quello corrente) int i, j, poseq, posrv, itms; pagetype pt; char sec; TLocalisamfile *file; TString f_code(s.get()); // prende il codice del file da leggere if (atoi(f_code) != 0) file= new TLocalisamfile(atoi(f_code)); // se il codice è numerico allora è un file else file= new TTable(f_code); // altrimenti è una tabella file->zero(); // vuota il record corrente del file TToken_string in(s.get(), '!'); for (i=0; iput(fld, (const char *)rval); // scrive il risultato dell'espressione nel campo del file } if (file->read()== NOERR) { // tenta una lettura del file TToken_string out(s.get(), '!'); for (i=0; iget(curr); // preleva il nome del campo del file e lo legge dal record cf.set(dat); // setta il campo letto dal file nel campo corrente della form cf.put_paragraph(dat); cf.set(""); // Resetta il campo per la prossima stampa di questo item } else { TString fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale const TString &dat= file->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'è la a-commerciale è un gruppo if (fld.find("->") != -1) { // se nel gruppo c'è la freccia si riferisce ad un'altra sezione sec= fld[0]; if (fld[1] != '-') pt= char2page(fld[1]); else pt= even_page; itms= section(sec, pt).fields(); } else { // altrimenti si riferisce alla sezione corrente sec= cf.section().section_type(); pt= cf.section().page_type(); itms= cf.section().fields(); } for (j=0; j,, // dove: nome tabella da leggere // costante stringa o riferimento a campo della form (preceduto da '#') da usare come chiave di ricerca // identificativo del campo da leggere dalla tabella TTable tab(s.get()); // prende il nome della tabella tab.zero(); // vuota il record corrente della tabella TString in(s.get()); // prende il valore o il campo da usare come codice di ricerca if (in[0]== '#') { in.ltrim(1); TForm_item &fi= cf.find_field(in); in= fi.get(); } tab.put("CODTAB", in); // setta la chiave nella tabella if (tab.read()== NOERR) { const TString &fld= s.get(); // prende il nome del campo da leggere... valore = tab.get(fld); cf.set(tab.get(fld)); // ...e lo scrive nel campo del form cf.put_paragraph(valore); cf.set(""); // Resetta il campo per la prossima stampa di questo item } return (TRUE); } // fine _TABLEREAD 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) { TTextfile t; rdoc.get_memo("DESCEST",t); const long l = t.lines(); for (long i = 0; i[,][,...] // dove: è il campo della form (preceduto da '#') da cui prendere l'allineamento // è uno dei seguenti valori: // TOP allinea sulla riga d'inizio // MIDDLE allinea al centro (effettivo) // BOTTOM allinea sulla riga di fine (effettiva, non preimpostata) // LEFT allinea sulla colonna d'inizio // RIGHT allinea sulla colonna di fine TString in(s.get()); if (in[0]== '#') in.ltrim(1); TForm_item &fi= cf.find_field(in); const int width = cf.width(); valore = cf.get(); TString clear(width); TString picture(cf.picture()); clear.spaces(); int i= 2; short save_x = cf.x(); short save_y = cf.y(); short save_height = cf.height(); cf.height() = 2; // Solo temporaneamente per far si' che stampi alla giusta posizione cf.set(clear); cf.put_paragraph(clear); while (i|} // dove: è un riferimento alla relazione di gestione dei dati della ditta (es. 113@->DENCOM è la denominazione del comune di residenza della ditta) // è uno delle macro seguenti: // !RAGSOC ragione sociale // !IND indirizzo (fiscale se c'è, oppure di residenza) // !NUM numero civico (fiscale se c'è, oppure di residenza) // !CAP CAP (fiscale se c'è, oppure di residenza) // !COM comune (fiscale se c'è, oppure di residenza) // !PROV provincia (fiscale se c'è, 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 è così 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]=='!') { in.ltrim(1); bool _fisc= _firmrel.lfile(6).get("INDRF").not_empty(); if (in=="RAGSOC") cf.set(_firmrel.lfile().get("RAGSOC")); if (in=="IND") { if (_fisc) cf.set(_firmrel.lfile(6).get("INDRF")); else cf.set(_firmrel.lfile(6).get("INDRES")); } if (in=="NUM") { if (_fisc) cf.set(_firmrel.lfile(6).get("CIVRF")); else cf.set(_firmrel.lfile(6).get("CIVRES")); } if (in=="CAP") { if (_fisc) cf.set(_firmrel.lfile(6).get("CAPRF")); else cf.set(_firmrel.lfile(6).get("CAPRES")); } if (in=="COM") { if (_fisc) cf.set(_firmrel.lfile(-213).get("DENCOM")); else cf.set(_firmrel.lfile(-113).get("DENCOM")); } if (in=="PROV") { if (_fisc) cf.set(_firmrel.lfile(-213).get("PROVCOM")); else cf.set(_firmrel.lfile(-113).get("PROVCOM")); } if (in=="IVA") cf.set(_firmrel.lfile(6).get("PAIV")); if (in=="CF") cf.set(_firmrel.lfile(6).get("COFI")); if (in=="TEL") { TString tel(_firmrel.lfile().get("PTEL")); tel << "/" << _firmrel.lfile().get("TEL"); cf.set(tel); } if (in=="FAX") { TString tel(_firmrel.lfile().get("PFAX")); tel << "/" << _firmrel.lfile().get("FAX"); cf.set(tel); } if (in=="REGSOC") { TString reg(_firmrel[LF_UNLOC].get("REGTRIB")); reg << " Vol. " << _firmrel[LF_UNLOC].get("VOLTRIB"); reg << " Fasc. " << _firmrel[LF_UNLOC].get("FASCTRIB"); cf.set(reg); } if (in=="CCIAA") { TString cod(_firmrel[LF_UNLOC].get("NUMCCIAA")); cod << " del " << _firmrel[LF_UNLOC].get("DATAICCIAA"); cf.set(cod); } } else { TFieldref fref(s.get(), 0); cf.set(fref.read(_firmrel)); } valore = cf.get(); cf.put_paragraph(valore); cf.set(""); // Resetta il campo per la prossima stampa di questo item return (TRUE); } // fine _DITTA if (code== "_CIFRELET") { // conversione di un reale da cifre a lettere // sintassi: _CIFRELETTERE[,] // dove: è il campo della form (preceduto da '#') da cui prendere il valore, se non è specificato è sottointeso il campo corrente // nota: prende il valore del campo specificato e scrive la sua conversione in lettere nel campo corrente TString in; if (s.items()==2) { in= s.get(); if (in[0]== '#') in.ltrim(1); TForm_item &fi= cf.find_field(in); in= fi.get(); } else in= cf.get(); real n(in); valore = n.string("LETTERE"); cf.set(valore); cf.put_paragraph(valore); cf.set(""); // Resetta il campo per la prossima stampa di questo item return (TRUE); } // fine _CIFRELET if (code.left(6) == "_TOTAL") { // totalizzatori di testata/coda, riga e progressione // sintassi: _TOTAL_{CODA|RIGA|PROGRES},[,] // dove: è il codice del totalizzatore richiesto static real zero("0.0"); // 0 sotto forma di real per i casi in cui il totalizzatore non viene trovato if (!_doc->summary_compiled() &&_cli_loaded) _doc->set_condv(_cliente); TString tot= s.get(); // prende il codice del totalizzatore richiesto TForm_item *fi; // puntatore al campo della form in cui scrivere il valore del totalizzatore fi= &cf; // prende il puntatore al campo corrente if (code.mid(6) == "_CODA") { TString value; if (tot == "TOTDOC") value = _doc->tot_documento().string(); else if (tot == "TIMPNETTI") value = _doc->tot_importi_netti().string(); else if (tot == "TIMPOSTE") value = _doc->tot_imposte().string(); else if (tot == "TIMPONIBILI") { byte sel = atoi(s.get()); value = _doc->tot_imponibili(sel).string(); } else value = _doc->get_head_info(tot); if (value.not_empty()) fi->set(value); // setta il campo della form else fi->set(zero.string()); } if (code.mid(6) == "_RIGA") { TLocalisamfile &rdoc= (cursor())->file(LF_RIGHEDOC); TToken_string totriga(rdoc.get("G1"),'\n'); // prende il campo memo con i totalizzatori sotto forma di token string TString value; const int items = totriga.items(); for (int i = 0; iget(LF_CLIFO, "RAGSOC")); if (in=="IND") cf.set(_cliente->get(LF_CLIFO, "INDCF")); if (in=="NUM") cf.set(_cliente->get(LF_CLIFO, "CIVCF")); if (in=="INDNUM") { TString indnum(_cliente->get(LF_CLIFO, "INDCF")); indnum << " " << _cliente->get(LF_CLIFO,"CIVCF"); cf.set(indnum); } if (in=="LOC") cf.set(_cliente->get(LF_CLIFO, "LOCALITACF")); if (in=="CAP") cf.set(_cliente->get(LF_CLIFO, "CAPCF")); if (in=="COM") cf.set(_cliente->get(-(100+LF_COMUNI), "DENCOM")); if (in=="PROV") cf.set(_cliente->get(-(100+LF_COMUNI), "PROVCOM")); if (in=="IVA") cf.set(_cliente->get(LF_CLIFO, "PAIV")); if (in=="CF") cf.set(_cliente->get(LF_CLIFO, "COFI")); if (in=="PERS") cf.set(_cliente->get(LF_CLIFO, "TIPOPERS")); if (in=="DATANAS") cf.set(_cliente->get(LF_CLIFO, "DATANASC")); if (in=="COMNAS") cf.set(_cliente->get(-(200+LF_COMUNI), "DENCOM")); if (in=="TEL") { TString tel(_cliente->get(LF_CLIFO, "PTEL")); tel << "/" << _cliente->get(LF_CLIFO, "TEL"); cf.set(tel); } if (in=="TEL2") { TString tel2(_cliente->get(LF_CLIFO, "PTEL2")); tel2 << "/" << _cliente->get(LF_CLIFO, "TEL2"); cf.set(tel2); } if (in=="TEL3") { TString tel3(_cliente->get(LF_CLIFO, "PTEL3")); tel3 << "/" << _cliente->get(LF_CLIFO, "TEL3"); cf.set(tel3); } if (in=="FAX") { TString fax(_cliente->get(LF_CLIFO, "PFAX")); fax << "/" << _cliente->get(LF_CLIFO, "FAX"); cf.set(fax); } } else { TFieldref fref(s.get(), 0); cf.set(fref.read(*_cliente)); // l'oggetto cliente è figlio della TRelation, quindi lo passo al fieldref semplicemente con un typecast } valore = cf.get(); cf.put_paragraph(valore); cf.set(""); // Resetta il campo per la prossima stampa di questo item return (TRUE); } // fine _CLIENTE if (code== "_SCADENZE") { // messaggio per stampare le scadenze // sintassi: _SCADENZE,, // dove e' uno dei seguenti: // DATA : stampa la data di scadenza // IMPORTO : stampa l'importo in scadenza // dove 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)); cf.set(value); real x(value); if (x.is_real(value)) { TString picture(cf.picture()); if (x != 0.0) value = x.string(picture); // Riformatta il valore else value = ""; } what = s.get(); const bool next = what == "1"; if (next) _doc->scadenze_set_next(); cf.put_paragraph(value); cf.set(""); // Resetta il campo per la prossima stampa di questo item } } if (code== "_RIEPILOGOIVA") { // tabella riepilogo aliquote iva e relative imposte // sintassi: _RIEPILOGOIVA,,, // dove: è 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: è 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: è 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 (!_doc->summary_compiled() &&_cli_loaded) _doc->set_condv(_cliente); 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); TString what(s.get()); // cosa deve stampare ? TString value(_doc->summary_get(what)); // Piglia il valore dalla riga selezionata sullatabellina what = s.get(); const bool next = what == "1"; // deve cambiare elemento ? if (next) _doc->summary_set_next(); cf.set(value); real x(value); if (x.is_real(value)) { TString picture(cf.picture()); if (x != 0.0) value = x.string(picture); // Riformatta il valore else value = ""; } cf.put_paragraph(value); cf.set(""); // Resetta il campo per la prossima stampa di questo item } } else error_box("Numero di parametri non corretto in _RIEPILOGOIVA"); return (TRUE); } // fine _RIEPILOGOIVA // Messaggio per stampare il numero di pagina corrente if (code== "_PAGENO") { TString16 pg; pg << int(printer().getcurrentpage()); cf.set(pg); cf.put_paragraph(pg); cf.set(""); } return TForm::validate(cf, s); // se il codice del messaggio non è identificato viene passato alla funzione standard } ////////////////////////////////////////////////////////////////////////////////////////////// // classe TStampa_Doc_Vendita customizzata dalla TApplication per l'applicazione principale ////////////////////////////////////////////////////////////////////////////////////////////// enum behaviour { skip, go, cancel }; class TStampa_Doc_Vendita: public TApplication { TString _codnum; // codice di numerazione TString _provv; // stampa provvisioria int _anno; // anno della documentazione 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 _order_by_num; // flag che indica se e' stato selezionato l'ordine principale per numero documento bool _interattivo; // flag che indica se il prog. funziona in interattivo o in batch bool _definitiva; // flag che indica se la stampa è definitiva o no TRelation *_firmrel; // puntatore alla relazione che gestisce i dati della ditta corrente TDocVen_Form *_form; // puntatore al form di stampa protected: virtual bool create(void); virtual bool destroy(void); virtual bool menu(MENU_TAG); int select(void); virtual void print(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 è definitiva static bool date2num_handler(TMask_field& f, KEY key); static bool range_handler(TMask_field& f, KEY key); static bool filter_rows(const TRelation * r); }; inline TStampa_Doc_Vendita& app() { return (TStampa_Doc_Vendita&) main_app(); } bool TStampa_Doc_Vendita::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 TStampa_Doc_Vendita::range_handler(TMask_field& f, KEY key) { int rt = TRUE; TMask& m = f.mask(); if (key == K_TAB && f.focusdirty()) { const long lim_sup = atol(f.get()); const long lim_inf = m.get_long(F_DA_NDOC); if (lim_sup < lim_inf) { f.error_box("Il limite superiore deve essere maggiore del limite inferiore"); rt = FALSE; } } return rt; } bool TStampa_Doc_Vendita::filter_rows(const TRelation * r) { TLocalisamfile& righe = r->lfile(LF_RIGHEDOC); bool rt = TRUE; TString tiporiga(righe.get("TIPORIGA")); TString codart(righe.get("CODART")); TString_array& a = app()._form->exclude_list(); const int items = a.items(); for (int i = 0; i < items && rt; i++) { TToken_string& s=a.row(i); TString tr(s.get(0)); TString ar(s.get(1)); tr.trim();ar.trim(); if (tr.empty() && ar == codart) rt = FALSE; else if (tr == tiporiga) if (ar.empty() || (ar.not_empty() && ar == codart)) rt = FALSE; } return rt; } bool TStampa_Doc_Vendita::create() { TApplication::create(); _form = NULL; _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); if (argc()>2) { // lettura dei parametri iniziali dalla linea di comando _codnum= argv(2); // il primo parametro è il codice di numerazione _anno= atoi(argv(3)); // il secondo è l'anno _provv= argv(4); // il terzo è il flag di numerazione provvisoria _dalnum= atol(argv(5)); // il quarto è il numero di documento di partenza _alnum= atol(argv(6)); // il quinto è il numero di documento di fine _definitiva= (strcmp(argv(7), "D")==0); // il sesto è se la stampa è definitiva (rinumerazione dei documenti) _ncopie = atoi(argv(8)); _interattivo= FALSE; print(); } else { // oppure lancio della maschera _interattivo= TRUE; dispatch_e_menu(BAR_ITEM(1)); } return TRUE; } bool TStampa_Doc_Vendita::destroy() { if (_form) delete _form; delete _firmrel; // distruzione della relazione di gestione della ditta corrente return TApplication::destroy(); } void TStampa_Doc_Vendita::on_firm_change() { TLocalisamfile &firmfile= _firmrel->lfile(); firmfile.put("CODDITTA", get_firm()); _firmrel->read(); } int TStampa_Doc_Vendita::select() { TMask m("ve1100a"); TString wdate; m.set_handler(F_DA_DATADOC, date2num_handler); m.set_handler(F_A_DATADOC, date2num_handler); m.set_handler(F_A_NDOC, range_handler); if (m.run() == K_ENTER) { _codnum= m.get(F_CODNUM); // lettura dei dati dalla maschera _anno= m.get_int(F_ANNO); _provv= m.get(F_PROVV); _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; wdate = m.get(F_DA_DATADOC); if (wdate.not_empty()) _dadata = wdate; else _dadata = botime; wdate = m.get(F_A_DATADOC); if (wdate.not_empty()) _adata = wdate; else _adata = eotime; _order_by_num = m.get(F_DATA_O_NUM) == "N"; return 1; } else return 0; // 0 indica che non si è usciti con "Conferma" dalla maschera } bool TStampa_Doc_Vendita::menu(MENU_TAG) { // procedura di dispatch dei menu int s; while ((s= select()) != 0) if (s==1) print(); // se la selezione della maschera ritorna 1 viene lanciata la stampa return FALSE; } void TStampa_Doc_Vendita::print() { TFilename nomeform, profilo; // istanzia le stringhe per il nome del form di stampa e del profilo di configurazione TString modulo_prec; // istanzia la stringa per l'inseguimento del modulo di carta TTable tip("%TIP"); // istanzia la tabella dei tipi di documento per i profili TRelation rel(LF_DOC); // istanzia la relazione sul file principale TLocalisamfile righe(LF_RIGHEDOC); // cosi' i trecord_array non rompono i coglioni TCursor cur(&rel); // crea il cursore principale dalla relazione if (!_order_by_num) cur.setkey(3); // setta l'ordine per data. TLocalisamfile &doc= cur.file(); // prende il riferimento al file principale doc.zero(); // vuota il record del file doc.put("CODNUM", _codnum); // compone la chiave per il record di inizio cursore doc.put("ANNO", _anno); doc.put("PROVV", _provv); doc.put("NDOC", _dalnum); if (!_order_by_num) doc.put("DATADOC", _dadata); doc.read(); // posiziona il file sul record TRectype darec= doc.curr(); // copia il record di inizio cursore doc.zero(); // vuota il record del file doc.put("CODNUM", _codnum); // compone la chiave per il record di fine cursore doc.put("ANNO", _anno); doc.put("PROVV", _provv); doc.put("NDOC", _alnum); if (!_order_by_num) doc.put("DATADOC", _adata); const int err = doc.read(); // posiziona il file sul record if (err == _iseof) doc.last(); else if (err == _iskeynotfound) doc.prev(); const long num_lim_sup = doc.get_int("NDOC"); const TDate date_lim_sup = doc.get_date("DATADOC"); if (num_lim_sup > _alnum || (!_order_by_num && date_lim_sup < _adata)) { error_box("Non vi sono documenti da stampare nell'intervallo indicato"); return; } _definitiva= query_final_print(); // legge il flag di stampa definitiva printer().open(); // apre la stampante TRectype arec= doc.curr(); // copia il record di fine cursore cur.setregion(darec, arec); // imposta il filtro sul cursore di stampa (nell'ordine giusto :-) TProgind pi(cur.items(),"Stampa documenti in corso...",FALSE,TRUE,10); for (cur= 0; cur.pos()tipo().ncopie() : _ncopie; // Numero di copie da stampare per questo documento if (ncopie == 0) ncopie = 1; _form = new TDocVen_Form(nomeform, *_firmrel, doc_est); // istanzia il form, passandogli il documento. (la delete del documento e' nel ditruttore const TString &modulo= _form->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 if (modulo != modulo_prec) whattodo= on_module_change(modulo, modulo_prec); // se il modulo è cambiato dalla stampa precedente interroga la funzione per sapere che comportamento tenere if (whattodo==cancel) break; // se non si può procedere la stampa viene interrotta else if (whattodo==go) { // altrimenti prosegue TCursor &fcur= *(_form->cursor()); // ricava il riferimento al cursore originale del form TLocalisamfile &rdoc= fcur.file(LF_RIGHEDOC); // ricava il riferimento al file principale del cursore del form TRectype darec_r(rdoc.curr()); // istanzia il record di filtro per il cursore darec_r.zero(); // vuota il record darec_r.put("CODNUM", _codnum); // compone la chiave parziale per il filtro sul cursore dal file principale del cursore di selezione dei documenti darec_r.put("ANNO", _anno); darec_r.put("PROVV", _provv); darec_r.put("NDOC", doc.get("NDOC")); TRectype arec_r(darec_r); // istanzia il secondo record per il filtro sul cursore fcur.setregion(darec_r, arec_r); // setta il filtro sul cursore del form fcur.set_filterfunction(filter_rows); // setta il filtro per escludere alcuni tipi riga indicati nel form // Da implementare quando verra gestito il numero di copie for (int j=0; jprint(); // stampa il form corrente if (_definitiva && (numerazione_definitiva(doc) != NOERR)) { // se la stampa è definitiva viene lanciata la procedura di rinumerazione if (_interattivo) error_box("Non è possibile completare la procedura di numerazione definitiva dei documenti"); break; } } if (_form) { delete _form; _form = NULL; } } else { error_box("Il documento corrente non è stato trovato nella tabella dei tipi di documento (errore %d)", err); break; } } if (_form) { delete _form; _form = NULL; } printer().close(); // chiude la stampante } behaviour TStampa_Doc_Vendita::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("Il modulo di carta è cambiato: inserisci il modulo '%s' e premi 'Sì' per continuare, 'No' per saltare il documento o 'Cancel' per interrompere la stampa", modulo); behaviour ret; switch (risp) { case K_YES: modulo_prec= modulo; // aggiorna l'inseguitore dei moduli ret= go; // la stampa può 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 TStampa_Doc_Vendita::query_final_print() { if (_interattivo) { // se siamo in interattivo viene richiesto all'utente se la stampa è definitiva o meno if (yesno_box("E' una stampa definitiva?")) return TRUE; else return FALSE; } else return _definitiva; // altrimenti ritorna il valore letto dalla linea di comando } int ve1100(int argc, char* argv[]) { TStampa_Doc_Vendita a; a.run(argc, argv, "Stampa documenti di vendita"); return (0); }