// gestione livelli di giacenza e articoli // oggetto movimento di magazzino // funzione di ricostruzione saldi #include #include #include #include #include #include "mglib.h" // ******************************* // ******************************* #define MAXSIMBOLS 256 #define MAXSTATES 25 class TStateset { unsigned char _container[MAXSTATES]; int _current; public: TStateset & empty(); TStateset & enclose(int e); TStateset & singleton(int e); TStateset & cap(TStateset & s); int get_first() ; int get_next() ; bool is_empty() const; bool is_member(int e) const; TStateset(); ~TStateset() {}; }; struct TAutoma_state { short _transaction[MAXSIMBOLS]; TString80 * _label; bool _final; }; // ******************************* // ******************************* // automa per il riconoscimento di metacaratteri #define EPSILON 0 #define FIRST_STATE 1 #define FIRST_NEMPTY_SYMBOL 1 // ******************************* // ******************************* // automa per il riconoscimento di metacaratteri class TR_automa { TAutoma_state st[MAXSTATES]; short _maxstate; protected: TStateset union_of_closures(TStateset &s); bool is_final(int statenum) const; bool is_final(TStateset states) const; TR_automa & set_label(int statenum, const char *label); bool is_state(int statenum); const char *label(int statenum); int label2state(const char * label); void del_trans(int statenum,unsigned char symbol); int trans_to(int statenum,unsigned char symbol); bool _isdeterministic; public: TR_automa & reset_state(int statenum=-1); void add_tran(int statenum,unsigned char symbol,int next);// aggiunge una transizione int add_state(const char * label);// aggiunge uno stato TR_automa & set_final(int statenum,bool v=TRUE); // pone lo stato come finale bool is_deterministic() {return _isdeterministic;}; // bool recognized(const char * s); // tenta di riconoscere la stringa passata TR_automa(TR_automa *a=NULL,bool makedet=FALSE); // duplica un automa (e lo rende deterministico) ~TR_automa(); static void set2label(const TStateset ss,TString & label); static void label2set(const TString & label,TStateset & ss); }; // ******************************* TStateset::TStateset() { empty(); } TStateset & TStateset::empty() { _current=0; for (int i= 0; i< MAXSTATES; _container[i++]=0); return *this; } TStateset & TStateset::enclose(int el) { if (el< MAXSTATES && el>=0) _container[el]=1; return *this; } TStateset & TStateset::singleton(int el) { empty(); _container[el]=1; return *this; } TStateset & TStateset::cap(TStateset & s) { for (int i= 0; i< MAXSTATES; i++) _container[i]|=s._container[i]; return *this; } bool TStateset::is_empty() const { for (int i= 0; i< MAXSTATES; i++) if (_container[i]) return FALSE; return TRUE; } bool TStateset::is_member(int e) const { return (e >= 0 && e < MAXSTATES) ? (_container[e] != 0) : FALSE; } int TStateset::get_first() { _current=-1; return(get_next()); } int TStateset::get_next() { while (_current+1 < MAXSTATES) if (_container[++_current]) return _current; return (-1); } // labels and states bool TR_automa::is_state(int statenum) { return(statenum<=_maxstate && statenum>0); } // restituisce il numero dello stato con quella etichetta int TR_automa::label2state(const char *label) { for (int s=0; s<_maxstate;s++) if (*(st[s]._label)==label) return(s+1); return(0); } // resetta uno stato dell'automa (senza eliminarlo) TR_automa & TR_automa::reset_state(int statenum) { int _from,_to; if (statenum>0 && statenum<=_maxstate) { _from=statenum; _to=statenum; } else { _maxstate=0; _isdeterministic=TRUE; _from=1; _to=MAXSTATES; } for (int i=_from; i<=_to;i++) { set_label(i,""); set_final(i,FALSE); for (int j=0; j0); return retv; } TR_automa & TR_automa::set_final(int statenum,bool v) { st[statenum-1]._final=v; return *this; } //******************* // bows void TR_automa::add_tran(int statenum, unsigned char symbol,int next) { st[statenum-1]._transaction[symbol]=next; if (symbol==EPSILON) _isdeterministic=FALSE; } void TR_automa::del_trans(int statenum, unsigned char symbol) { st[statenum-1]._transaction[symbol]=0; } int TR_automa::trans_to(int statenum, unsigned char symbol) { return (st[statenum-1]._transaction[symbol]); } // costruttore "di copi": crea un automa non deterministico // (transazioni Epsilon ma nessuna transazione multipla) // o ne crea l'equivalente automa deterministico TR_automa::TR_automa(TR_automa * aa,bool makedet) { TStateset arrival; TStateset newstateset; TString80 tmplabel; int curr_new_state; for (int i=0; iunion_of_closures(newstateset.singleton(FIRST_STATE)),tmplabel); add_state(tmplabel); curr_new_state=FIRST_STATE; while (is_state(curr_new_state)) { // determina l'insieme degli stati dell'automa non deterministico // che corrispondono a questo stato dell'automa deterministico label2set(label(curr_new_state),newstateset); // lo stato è finale se include stati finali dell'automa non det. set_final(curr_new_state,aa->is_final(newstateset)); // determina tutte le transazioni for (short symbol=FIRST_NEMPTY_SYMBOL; symboltrans_to(old_state,(unsigned char)symbol)) arrival.enclose(old_next); } while ((old_state=newstateset.get_next())>0); if (!arrival.is_empty()) { // crea il nuovo arco nell'automa deterministico set2label(aa->union_of_closures(arrival),tmplabel); if (!(new_next=label2state(tmplabel))) new_next=add_state(tmplabel); add_tran(curr_new_state,(unsigned char)symbol,new_next); } } // loop symbol curr_new_state++; } _isdeterministic=TRUE; } // fine conversione else { *this=*aa; for (int i=0; ist[i]._label; } } TR_automa::~TR_automa() { for (int i=0; i0); } while (toadd) ; u_of_clo.cap(clo); } while ((_state=start_set.get_next())>0); return u_of_clo; } // tenta di riconoscere la stringa passata bool TR_automa::recognized(const char * t_str) { if (_isdeterministic) { // ricoNosce la stringa di token int curr_state=FIRST_STATE; for (int i=0; t_str[i]; i++) if (!(curr_state=trans_to(curr_state,t_str[i]))) return FALSE; // fine per mancanza di trasizioni // fine per mancanza di caratteri di input della stringa return (is_final(curr_state)); } else return FALSE; // ?? } // ******************************* // gestione di stringhe di metacaratteri // ******************************* #define C_ESCAPEMETA '\\' #define S_BLANK 1 #define S_DIGIT 2 #define S_LETTER 3 #define S_ANY 4 // ******************************* // ******************************* // riconoscimento di metacaratteri class TR_automa; bool TMetachar::recognized(const char * s) { return(_au->recognized(s)); } void TMetachar::add_tran(int s,unsigned char metasymbol, int nextstate) { unsigned char c; switch (metasymbol) { case EPSILON:// blank _au->add_tran(s,EPSILON,nextstate); break; case S_BLANK:// blank _au->add_tran(s,' ',nextstate); break; case S_DIGIT:// cifra for (c='0';c<='9';c++) _au->add_tran(s,c,nextstate); break; case S_LETTER: // lettera for (c='a';c<='z';c++) _au->add_tran(s,c,nextstate); for (c='A';c<='Z';c++) _au->add_tran(s,c,nextstate); break; case S_ANY: // qualsiasi carattere for (c=MAXSIMBOLS-1;c>=FIRST_NEMPTY_SYMBOL;c--) _au->add_tran(s,c,nextstate); break; default: _au->add_tran(s,metasymbol,nextstate); break; } } // restituisce la stringa di metacaratteri del linguaggio riconosciuto const char * TMetachar::language() const { return(_language); } void TMetachar::set_language(const char * language) { int s; bool escaped_char=FALSE; TString label("-"),nextlabel("-"); // crea gli insiemi di metacaratteri standard strcpy(_metach_mand,"0LA&"); strcpy(_metach_opz,"#9?ac"); _language=language; // crea l'automa _au->reset_state(); for (int i=0; language[i]; i++) { label[0]='a'+i; nextlabel[0]='a'+i+1; if (language[i]!=C_ESCAPEMETA) { if (!escaped_char) { // meta-caratteri e literal fuori set s=_au->add_state(label); switch (language[i]) { case '#':// cifra o blank opzionale add_tran(s,S_BLANK,s+1); add_tran(s,'-',s+1); add_tran(s,'+',s+1); case '9':// cifra opzionale add_tran(s,EPSILON,s+1); case '0':// cifra obbligatoria add_tran(s,S_DIGIT,s+1); break; case '?': // lettera opzionale add_tran(s,EPSILON,s+1); case 'L': // lettera obbligatoria add_tran(s,S_LETTER,s+1); break; case 'a': // lettera o numero opzionale add_tran(s,EPSILON,s+1); case 'A': // lettera o numero obbligatorio add_tran(s,S_LETTER,s+1); add_tran(s,S_DIGIT,s+1); break; case 'c': // qualsiasi carattere opzionale add_tran(s,EPSILON,s+1); case '&': // qualsiasi carattere obbligatorio add_tran(s,S_ANY,s+1); break; default: _au->add_tran(s,language[i],s+1); break; } } else { // escaped char s=_au->add_state(label); _au->add_tran(s,language[i],s+1); } } escaped_char=(language[i]==C_ESCAPEMETA); } // end of loop // aggiunge lo stato finale s=_au->add_state(nextlabel); _au->set_final(s); } // ricerca caratteri del set opzionale bool TMetachar::has_opzchars(const char * pattern) { int i=0; bool next_literal=FALSE; while (pattern[i]) { if (!next_literal && strchr(_metach_opz,pattern[i])) return(TRUE); next_literal=(!next_literal && pattern[i]==C_ESCAPEMETA); i++; } return(FALSE); } // ricerca caratteri del set opzionale bool TMetachar::has_mandchars(const char * pattern) { int i=0; bool next_literal=FALSE; while (pattern[i]) { if (next_literal || strchr(_metach_mand,pattern[i])) return(TRUE); next_literal=(!next_literal && pattern[i]==C_ESCAPEMETA); i++; } return(FALSE); } // stabilisce la lunghezza della stringa di metacaratteri int TMetachar::maxstrlen(const char * pattern) { int i=0,l=0; bool next_literal=FALSE; while (pattern[i]) { if (!next_literal) l++; next_literal=(!next_literal && pattern[i]==C_ESCAPEMETA); i++; } return(l); } // costruttore e distruttore TMetachar::TMetachar () { _au = new TR_automa; set_language(""); } TMetachar::TMetachar (const char * metastr) { // crea l'automa e lo trasforma in deterministico // TR_automa auxau; // set_language(&auxau,metastr); _au=new TR_automa; set_language(metastr); if (!_au->is_deterministic()) { TR_automa * auxau = new TR_automa(_au,TRUE); delete _au; _au=auxau; } } TMetachar::~TMetachar () { delete _au; } // ************************** // classe codice a livelli void TCodice_livelli::update_firm() { _last_firm = prefix().get_codditta(); } void TCodice_livelli::test_firm() { long firm = prefix().get_codditta(); if (firm > 0 && firm != _last_firm) { init(); update_firm(); // Lo dovrebbe gia' fare la init } } void TCodice_livelli::load(bool enabled, const char *tabname,const char *tabgrp) { TTable _tabformato(tabname); int e; _lev_enabled = enabled; _last_level=0; for (int i=0; i < max_levels(); i++) { _name[i]=""; _code_length[i]=0; _picture[i]=""; _autoinsert[i]=FALSE; _codiceadata[i]=FALSE; } if (_lev_enabled) { e = _tabformato.first(); for (int i=0; e == NOERR && i < max_levels(); i++) { _name[i]=_tabformato.get("S0"); _picture[i]=_tabformato.get("S1"); _autoinsert[i]=_tabformato.get_bool("B0"); _codiceadata[i]=_tabformato.get_bool("B1"); _code_length[i]=TMetachar::maxstrlen(_picture[i]); _last_level=i+1; e = _tabformato.next(); } } if (_gruppi == NULL) _gruppi = new TDecoder(tabgrp); } const char *TCodice_livelli::code_format(int levnum) const { if (levnum<0) levnum=last_level(); CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; CHECK(enabled(), "iu chent get de code format if levels ar disebold"); ((TCodice_livelli *)this)->add_metachar(levnum); return ((TMetachar*)_metachars.objptr(levnum-1))->language(); } bool TCodice_livelli::fit_to_format(const char *codepart,int levnum) const { if (levnum<0) levnum=last_level(); CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; CHECK(enabled(), "iu chent cec ueter de format fits if levels ar disebold"); ((TCodice_livelli *)this)->add_metachar(levnum); return ((TMetachar*)_metachars.objptr(levnum-1))->recognized(codepart); } void TCodice_livelli::add_metachar(int levnum) { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; if (_metachars.objptr(levnum-1)==NULL) _metachars.add(new TMetachar(picture(levnum)),levnum-1); } const bool TCodice_livelli::enabled() const { return _lev_enabled && enabled(1); } const bool TCodice_livelli::enabled(int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; return (_lev_enabled && levnum<=max_levels() && levnum>0 && levnum<=_last_level); } const int TCodice_livelli::code_start(int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; return packed_length(levnum-1)+1; } const int TCodice_livelli::code_length(int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; /* if (_lev_enabled && levnum <= max_levels() && levnum > 0) return(_code_length[levnum-1]); else return(0); */ return enabled(levnum) ? _code_length[levnum-1] : 0; } const int TCodice_livelli::packed_length(int levnum) const { CHECK(levnum<=max_levels() ,"I codici livello arrivano fino a max_levels()") ; int start=0; for (int i=0; _lev_enabled && i0,"I codici livello partono da 1") ; return(_name[levnum-1]); } const bool TCodice_livelli::autoinsert(int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; return _autoinsert[levnum-1]; } const bool TCodice_livelli::codiceadata(int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; return _codiceadata[levnum-1]; } const bool TCodice_livelli::autoinsert( int levnum, TMask_field & fld) const { TString16 value(fld.get()); if (!fit_to_format(value,levnum)) { fld.error_box("Codice non corrispondente al formato previsto (%s)",(const char *)code_format(levnum)); return FALSE; } bool result = autoinsert( levnum, value); // if (!result) // fld.set(""); fld.set_focus(); return result; } const bool TCodice_livelli::autoinsert(int levnum, TString & newcode) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; const int result=group_search(newcode, levnum); if (result == _iskeynotfound || result == _iseof || result == _iskeyerr) { TString grpcode; grpcode << levnum; grpcode << newcode; // auto inserimento TFilename ininame; ininame.tempdir(); ininame.add("mglib01g.ini"); { remove(ininame); TConfig action(ininame,"Transaction"); action.set("Action","INSERT"); action.set("Firm", main_app().get_firm()); action.set("CODTAB", grpcode , "5"); } TString cmd("mg0.exe -0 GCG -i"); cmd << ininame; TExternal_app gesttab(cmd); gesttab.run(); TConfig action(ininame,"Transaction"); if (action.get("Result")!="OK") { newcode=""; return FALSE; } else { newcode=action.get("CODTAB","5").sub(1); } } return TRUE; } const TString & TCodice_livelli::picture(int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; return(_picture[levnum-1]); } void TCodice_livelli::pack_maskgrpcodes(TString & pc, const TMask & mask, int field1, int levnum) { for (int l=0 ; l0,"I codici livello partono da 1") ; pc.overwrite(codlev.left(_code_length[levnum-1]),packed_length(levnum-1)); } TString TCodice_livelli::unpack_grpcode(const TString& pc, const int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; int start=0; for (int i=1; _lev_enabled && i= pc.len() || levnum < 1 || levnum > _last_level) return EMPTY_STRING; return pc.mid(start,levnum == _last_level ? -1 : _code_length[levnum-1]); } TString TCodice_livelli::build_tabcode(const TString & gcode, const int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; TString valore; valore << levnum; valore << gcode; if (!(_lev_enabled && valore.len()>1)) valore.cut(0); return valore; } TString TCodice_livelli::build_tabcode_packed(const TString & pack, const int levnum) const { CHECK(levnum<=max_levels() && levnum>0,"I codici livello partono da 1") ; return build_tabcode(unpack_grpcode(pack,levnum),levnum); } const TString & TCodice_livelli::group_descr(const char * group_code, int levnum) const { return _gruppi->decode(build_tabcode(group_code,levnum)); } const TString & TCodice_livelli::group_descr_packed(const char * packed_code, int levnum) const { return _gruppi->decode(build_tabcode_packed(packed_code,levnum)); } const int TCodice_livelli::group_search(const char * group_code, int levnum) const { int res; _gruppi->decode(build_tabcode(group_code,levnum)).empty(); res=_gruppi->io_result(); if (res!=NOERR) _gruppi->discard(build_tabcode(group_code,levnum)); return res; } const int TCodice_livelli::group_search_packed(const char * packed_code, int levnum) const { _gruppi->decode(build_tabcode_packed(packed_code,levnum)); return _gruppi->io_result(); } void TCodice_livelli::set_sheetcolumn(TSheet_field &fld_righe,int field, int lev) const { TMask& sm = fld_righe.sheet_mask(); TEdit_field& fld = sm.efield(field); if (enabled(lev)) { const TString& header = name(lev); fld.set_prompt(header); fld.show(); const int len = header.len() + 1; const int f_len = code_length(lev); fld_righe.set_column_header(field, header); fld_righe.set_column_width(field, (len > f_len ? len : f_len) * 8); } else { fld.hide(); fld_righe.delete_column(field); } } void TCodice_livelli::set_sheet_columns(TSheet_field &sht, short dlg) const { for (int l = 0; l < max_levels(); l++) set_sheetcolumn(sht, dlg+l, l+1); } void TCodice_livelli::set_mask_fields(TMask &m,int firstfield) const { for (int l = max_levels(); l>=1 ; l--) set_mask_field(m,firstfield+l-1,l) ; } void TCodice_livelli::set_mask_field(TMask &m,int field, int l) const { if (enabled(l)) { if (strlen(m.field(field).prompt()) > (unsigned int)name(l).len()) m.field(field).set_prompt(name(l)); } m.field(field).show(enabled(l)); } TCodice_livelli::TCodice_livelli() : _last_firm(-1), _gruppi(NULL) {} TCodice_livelli::~TCodice_livelli() { if (_gruppi) delete _gruppi; } void TCodart_livelli::init() { TConfig mgconfig(CONFIG_DITTA, "mg"); load(mgconfig.get_bool("GESLIVART"), "FCA","GCA"); // imposta il riconoscimento dei caratteri del formato dell'ultima parte dell'articolo TString80 format; TTable tabfca("FCA"); if (tabfca.last() == NOERR) format = tabfca.get("S1"); _metachars.destroy(); _metachars.add(new TMetachar(format),max(last_level()-1,0)); update_firm(); } TCodart_livelli ::TCodart_livelli() { init(); } TCodart_livelli::~TCodart_livelli() { } void TCodgiac_livelli::init() { TConfig mgconfig(CONFIG_DITTA, "mg"); load(mgconfig.get_bool("GESLIVGIAC"),"FCG","GCG"); update_firm(); } TCodgiac_livelli::TCodgiac_livelli() { init(); } static TCodgiac_livelli *_livelli_giacenza=NULL; static TCodart_livelli *_livelli_articolo=NULL; TCodgiac_livelli &livelli_giacenza() { if (_livelli_giacenza==NULL) _livelli_giacenza=new TCodgiac_livelli(); return *_livelli_giacenza; } TCodart_livelli &livelli_articolo() { if (_livelli_articolo==NULL) _livelli_articolo=new TCodart_livelli(); return *_livelli_articolo; } TMagazzini::TMagazzini() : TRecord_cache("MAG") , _mgconfig(NULL),_last_firm(-1) { init(); } TMagazzini::~TMagazzini() { if (_mgconfig) delete _mgconfig; } void TMagazzini::init() { if (_mgconfig) delete _mgconfig; _mgconfig = new TConfig(CONFIG_DITTA, "mg"); _gestmag=_mgconfig->get_bool("GESMAG"); _gestdep=_gestmag && _mgconfig->get_bool("GESDEPOSITI"); _gestmultimag=_gestmag && _mgconfig->get_bool("GESMULTIMAG"); _gestubi=_mgconfig->get_char("GESUBICAZ"); TTable mag("MAG"); mag.first(); // look for standard mag & dep while (!mag.eof() && !mag.get_bool("B1")) mag.next(); if (!mag.eof()) { const TString& codtab = mag.get("CODTAB"); _stdmag = codtab.left(3); _stddep = codtab.mid(3); } else _stdmag.cut(0); _last_firm = prefix().get_codditta(); } void TMagazzini::test_firm() const { long firm = prefix().get_codditta(); if (firm > 0 && firm != _last_firm) ((TMagazzini *)this)->init(); } bool TMagazzini::gestmag(bool verbose) const { test_firm() ; if (!_gestmag && verbose) warning_box("La ditta corrente non gestisce il magazzino"); return _gestmag; } bool TMagazzini::gestdep() const { test_firm() ; return _gestdep; } bool TMagazzini::gestubi_man() const { test_firm() ; return _gestubi=='M'; } bool TMagazzini::gestubi_tab() const { test_firm() ; return _gestubi=='T'; } bool TMagazzini::gestmultimag() const { test_firm() ; return _gestmultimag; } const char * add_magcode(TString & str, const char * m) { str = m; str.rpad(3); return str; } const char * add_depcode(TString & str, const char * d) { str << d; return str.trim(); } bool riporta_ordinato() { static bool __riporta_ordinato = FALSE; static long __firm = -883; const long cur_firm = prefix().get_codditta(); if (__firm != cur_firm) { __firm = cur_firm; TConfig c(CONFIG_DITTA, "mg"); __riporta_ordinato = c.get_bool("RIPORD"); } return __riporta_ordinato; } const char * get_magcode(TString & codmagdep) { return codmagdep.left(3); } const char * get_depcode(TString & codmagdep) { return codmagdep.mid(3); }