#include #include #include #include #include #include #include #include #include #include #include #include #include "righedoc.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 //////////////////////////////////////////////////////////////////////////// // 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 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); } 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 } bool TDocVen_Form::validate(TForm_item &cf, TToken_string &s) { const TString code(s.get(0)); // prende il primo parametro, il codice del messaggio 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 } 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... cf.set(tab.get(fld)); // ...e lo scrive nel campo del form } return (TRUE); } // fine _TABLEREAD if (code== "_ALIGN") { // allineamento della posizione di un campo rispetto ad un altro // sintassi: _ALIGN,[,][,...] // 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); int i= 2; 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) // 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); } } else { TFieldref fref(s.get(), 0); cf.set(fref.read(_firmrel)); } 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); cf.set(n.string("LETTERE")); return (TRUE); } // fine _CIFRELETTERE 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()); } 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 // !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=="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 } 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; iadd(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); 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() { _definitiva= query_final_print(); // legge il flag di stampa definitiva printer().open(); // apre la stampante 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 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()