#include #include #include #include #include #include #include #include #include #include #include #include #include "righedoc.h" #include "sconti.h" #include "tclifor.h" #include "ve1100.h" #include "ve0100b.h" #include "ve0100c.h" // !! Attenzione: per la compilazione di questo programma deve essere definito il simbolo // !! __VE1100_DOWNSIZE, altrimenti in righedoc.cpp si creano degli // !! unresolved reference in fase di link struct num_of_decimals_to_round { int pri_lit, pri_val, qta, imp_lit, imp_val; }; //////////////////////////////////////////////////////////////////////////// // 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 TPiede_documento *_total_prog; // oggetto per i totalizzatori progressivi TRiga *_riga; // oggetto per la gestione della singola riga del documento TCliFor *_cliente; // oggetto per le informazioni sul cliente bool _cli_loaded; // flag che indica se l'oggetto cliente è già stato caricato num_of_decimals_to_round par_dec; // struct che contiene il numero di decimali che servono per l'arrotondamento 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 public: const TString &get_module_code() { return _module; } // ritorna il codice del modulo di carta TDocVen_Form(const char *, TRelation &); virtual ~TDocVen_Form(); }; TDocVen_Form::TDocVen_Form(const char* name, TRelation &rel): TForm(), _firmrel(rel) { read(name); _total_prog= new TPiede_documento; _riga= new TRiga; _cliente= new TCliFor; _cli_loaded= FALSE; } TDocVen_Form::~TDocVen_Form() { delete _total_prog; delete _riga; delete _cliente; } word TDocVen_Form::set_body(word p, bool u) { if (u) { // se si sta effettivamente generando il body viene fatto anche il calcolo del totalizzatore TLocalisamfile &rdoc= (cursor())->file(LF_RIGHEDOC); TRectype &recriga= rdoc.curr(); _riga->load(rdoc.curr()); _riga->somma(*_total_prog); } TPrint_section& body = section('B', p); return TForm::set_body(p, u); } void TDocVen_Form::extended_parse_general(TScanner &scanner) { if (scanner.popkey() == "MO") _module= scanner.string(); // se viene riconosciuto il token per l'impostazione del modulo legge il codice... else scanner.push(); // ...altrimenti rimette il token nella coda dello scanner // Legge i decimali necessari per gli arrotondamenti (il primo per gli importi in lire, l'altro per quelli in valuta) if (scanner.popkey() == "PR") { par_dec.pri_lit = scanner.integer(); par_dec.pri_val = scanner.integer(); } else scanner.push(); // Stessa cosa per le quantita' if (scanner.popkey() == "QT") par_dec.qta = scanner.integer(); else scanner.push(); // Stessa cosa per gli importi in genere if (scanner.popkey() == "IM") { par_dec.imp_lit = scanner.integer(); par_dec.imp_val = scanner.integer(); } else scanner.push(); } 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.lfile().get("REGTRIB")); reg << " Vol. " << _firmrel.lfile().get("VOLTRIB"); reg << " Fasc. " << _firmrel.lfile().get("FASCTRIB"); cf.set(reg); } if (in=="CCIAA") { TString cod(_firmrel.lfile().get("NUMCCIAA")); cod << " del " << _firmrel.lfile().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 // è il campo della form che riceve il valore del totalizzatore, se non è specificato è scritto nel campo corrente static real zero("0.0"); // 0 sotto forma di real per i casi in cui il totalizzatore non viene trovato 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 if (s.items()==2) { TString c= s.get(); // prende il codice del campo della form if (c[0]== '#') c.ltrim(1); fi= &(cf.find_field(c)); // prende il puntatore al campo specificato } else fi= &cf; // prende il puntatore al campo corrente if (code.mid(6) == "_CODA") { TLocalisamfile &doc= (cursor())->file(LF_DOC); TToken_string totcoda(doc.get("G1")); // prende il campo memo con i totalizzatori sotto forma di token string int pos= totcoda.get_pos(tot); // cerca il totalizzatore richiesto, il suo valore è nel token successivo if (pos>=0) fi->set(totcoda.get(pos+1)); // 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")); // prende il campo memo con i totalizzatori sotto forma di token string int pos= totriga.get_pos(tot); // cerca il totalizzatore richiesto, il suo valore è nel token successivo if (pos>=0) fi->set(totriga.get(pos+1)); // setta il campo della form else fi->set(zero.string()); } if (code.mid(6) == "_PROGRES") { TString16 tot16(tot); fi->set(_total_prog->get(tot16).string()); } valore = fi->get(); fi->put_paragraph(valore); fi->set(""); // Resetta il campo per la prossima stampa di questo item return (TRUE); } // fine _TOTAL_xxx if (code== "_CLIENTE") { // lettura dei dati del cliente // sintassi: _CLIENTE,{|} // dove: è un riferimento alla relazione di gestione dei dati del cliente // è uno delle macro seguenti: // !RAGSOC ragione sociale // !IND indirizzo // !NUM numero civico // !INDNUM indirizzo + numero civico // !LOC località // !CAP CAP // !COM comune // !PROV provincia // !IVA partita iva // !CF codice fiscale // !PERS se persona fisica, se giuridica // !DATANAS data di nascita // !COMNAS comune di nascita // !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) // nota: la relazione del cliente è così strutturata: // CLIFO (20) Clienti/fornitori // + CFVEN (17) Clienti/fornitori per vendite // + %COMUNI (113@) Comune di residenza // + %COMUNI (213@) Comune di nascita TLocalisamfile &doc= (cursor())->file(LF_DOC); TString16 tipocf= doc.get("TIPOCF"), codcf= doc.get("CODCF"), ocfpi= doc.get("OCFPI"); if (!_cli_loaded ) { // il cliente è sulla testata del documento di vendita, quindi può essere caricato una volta sola per tutte _cliente->load(tipocf[0], atol(codcf), ocfpi); _cliente->add(LF_COMUNI, "COM=STATOCF+COMCF", 1, LF_CLIFO, 100+LF_COMUNI); _cliente->add(LF_COMUNI, "COM=STATONASC+COMNASC", 1, LF_CLIFO, 200+LF_COMUNI); _cli_loaded= TRUE; } TString in(s.get()); // prende la macro o il fieldref if (in[0]=='!') { in.ltrim(1); if (in=="RAGSOC") cf.set(_cliente->get(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== "_RIEPILOGOIVA") { // tabella riepilogo aliquote iva e relative imposte // sintassi: _RIEPILOGOIVA, // dove: è uno dei seguenti: // !IMPONIB colonna degli imponibili // !ALIQ colonna delle aliquote // !IMPOSTE colonna delle imposte // !DESCR colonna delle descrizioni TString in= s.get(); // prende l'indicatore della colonna da creare TLocalisamfile &doc= (cursor())->file(LF_DOC); TToken_string totaliz(doc.get("G1")); // prende il campo memo con i totalizzatori sotto forma di token string if (in[0]=='!') { in.ltrim(1); int w= cf.width(), num= totaliz.items(); TString out, curr, tot; for (int i=0; iRighe TCliFor* _cli; // Oggetto cliente fornitore per elaborare gli sconti TTable* _iva; // Tabella codici IVA TCond_vendita* _condv; // Condizioni di vendita per lo sconto bool _is_valuta; // flag per saper se il documento e' in valuta protected: void update_summary(const TRectype& riga); // Aggiorna la tabella riepilogativa public: int rows() { return _rows.items() - 1 ; } // Meno 1 perche' il primo e' la testata del documento bool is_valuta() { return _is_valuta; } const TRectype& header() const { return *_header ; } // Ritorna la testata del documento const TRectype& operator[] (int index) const { return (const TRectype&)_rows[index];} // Ritorna la riga n-esima del documento void add(const TRectype& riga, bool force = FALSE); // Aggiunge la riga in memoria e aggiorna la tabella riepilogativa per aliquota. force serve a forzare la lettura dal record passato void replace(const TRectype& riga, int n) {_rows.add(riga,n);} // sostituisce la riga n-esima void remove(int n) { _rows.remove(n); } // cancella la riga n-esima void insert(const TRectype& riga, int n) { _rows.insert(riga,n); } // inserisce la riga n-esima //const Riepilogo_Iva& get(int index) {return (const Riepilogo_Iva&)_summary_table[index];} // Ritorna l'elemento void set_decimals(num_of_decimals_to_round* parm) { _parm = parm ; } void set_relation(TRelation* rel) { _rel = rel ; } void set_clifor(TCliFor* cli); void set_header(const TRectype& h) { *_header = h; } void destroy() { _rows.destroy(); _summary_table.destroy(); } // Azzera il contenuto TDoc_vendita (num_of_decimals_to_round* parm = NULL, TRelation* rel = NULL, TCliFor* cli = NULL) ; ~TDoc_vendita(); }; void TDoc_vendita::update_summary(const TRectype& riga) { TRectype r(_rel == NULL ? riga : _rel->lfile(LF_RIGHEDOC).curr()); if (r.num() == LF_RIGHEDOC) { int nriga = r.get_int("NRIGA"); real price = r.get_real("PREZZO"); real qta = r.get_real("QTA"); real aliquota, sc, imponibile, iva; TString sconto(r.get("SCONTO")); TString codiva(r.get("CODIVA")); _iva->put("CODTAB", codiva); if (_iva->read() != NOERR) { warning_box("Codice iva %s non trovato relativamente alla riga %d.", (const char*) codiva, nriga); return ; } aliquota = _iva->get_real("R0"); _condv->set_sconto(sconto); sc = 100.0 - _condv->sconto_val(); price = ((price * sc) / 100.0); price.round(_is_valuta ? _parm->pri_val : _parm->pri_lit); // prezzo scontato qta.round(_parm->qta); imponibile = price * qta; imponibile.round (_is_valuta ? _parm->imp_val : _parm->imp_lit); // imponibile di riga iva = (imponibile * aliquota) / 100.0; iva.ceil(_is_valuta ? _parm->imp_val : _parm->imp_lit); // imposta calcolata Riepilogo_Iva riepilogo; const bool exists = _summary_table.is_key(codiva); Riepilogo_Iva& riepilogo_tmp = (exists ? (Riepilogo_Iva&)_summary_table[codiva] : riepilogo); riepilogo_tmp._imp += imponibile; riepilogo_tmp._iva += iva; riepilogo_tmp._ali = aliquota; if (_iva->get("S1").not_empty()) // Se non e' regime normale salva anche la descrizione riepilogo_tmp._des = _iva->get("S0"); _summary_table.add(codiva,riepilogo_tmp,exists); } } void TDoc_vendita::add(const TRectype& riga, bool force) // force forza la memorizzazione della riga passata { // Memorizza i record se la relazione non e' valida (righe e testata vengono passati dall'esterno) if (force || _rel == NULL) { const bool is_doc = riga.num() == LF_DOC; // Flag per vedere se il record passato e' di testata if (is_doc) { *_header = riga; TString valuta(riga.get("CODVAL")); _is_valuta = valuta.trim().not_empty(); } else { if (_rows.items() == 0) // Se l'array e' vuoto ed il record passato e' una riga { // memorizza prima una testata vuota TRectype r(LF_DOC); *_header = r; } _rows.add(riga); } } else // Memorizza i record se la relazione e' valida (si accorge da solo se la testata e' gia' presente) { const bool store_header = _rows.items() == 0; TRectype r(_rel->lfile(store_header ? LF_DOC : LF_RIGHEDOC).curr()); if (store_header) // Se non c'e' la testata la memorizza e poi aggiunge la riga { *_header = r; r = _rel->lfile(LF_RIGHEDOC).curr(); } _rows.add(r); } if (_parm != NULL && _cli != NULL) // Se sono stati impostati i parametri necessari alla compilazione del riepilgo update_summary(riga); // effettua i calcoli } void TDoc_vendita::set_clifor(TCliFor* cli) { _cli = cli ; if (_condv != NULL) delete _condv; _condv = new TCond_vendita(*_cli); } TDoc_vendita::TDoc_vendita(num_of_decimals_to_round* parm, TRelation* rel, TCliFor* cli) { _parm = parm; _rel = rel; _cli = cli; _condv = NULL; _is_valuta = FALSE; destroy(); _header = new TRectype(LF_DOC); _iva = new TTable("%IVA"); if (_cli != NULL) _condv = new TCond_vendita(*_cli); } TDoc_vendita::~TDoc_vendita() { if (_header != NULL) delete _header; if (_iva != NULL) delete _iva; if (_condv != NULL) delete _condv; } ////////////////////////////////////////////////////////////////////////////////////////////// // 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 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 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); }; 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::create() { TApplication::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_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) _interattivo= FALSE; print(); } else { // oppure lancio della maschera _interattivo= TRUE; dispatch_e_menu(BAR_ITEM(1)); } return TRUE; } bool TStampa_Doc_Vendita::destroy() { 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); 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 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); doc.read(); // posiziona il file sul record 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 :-) for (cur= 0; cur.pos()