// oggetto TCausale_magazzino // oggetto TMov_Mag , multirecord del movimento di magazzino // funzione di ricostruzione saldi #include #include #include "mglib.h" #include "movmag.h" #include "rmovmag.h" #ifndef __CGLIB01_H #include "..\cg\cglib01.h" #endif #ifndef __DBLIB_H #include "..\db\dblib.h" #endif // ********************* // movimenti di magazzino // causali int TCausale_magazzino::sgn(TTipo_saldomag tiposaldo) { static TString *segni=NULL; if (segni==NULL) segni=new TString80; *segni=get("S2"); switch (tiposaldo) { case s_giac: return atoi(segni->mid(0,2)); case s_acq: return atoi(segni->mid(2,2)); case s_ent: return atoi(segni->mid(4,2)); case s_ven: return atoi(segni->mid(6,2)); case s_usc: return atoi(segni->mid(8,2)); case s_ordc: return atoi(segni->mid(10,2)); case s_ordf: return atoi(segni->mid(12,2)); case s_incl: return atoi(segni->mid(14,2)); case s_acl: return atoi(segni->mid(16,2)); case s_prodc: return atoi(segni->mid(18,2)); case s_prodf: return atoi(segni->mid(20,2)); case s_rim: return atoi(segni->mid(22,2)); case s_scart: return atoi(segni->mid(24,2)); case s_label: return atoi(segni->mid(26,2)); case s_user1: return atoi(segni->mid(28,2)); case s_user2: return atoi(segni->mid(30,2)); case s_user3: return atoi(segni->mid(32,2)); case s_user4: return atoi(segni->mid(34,2)); case s_user5: return atoi(segni->mid(36,2)); case s_user6: return atoi(segni->mid(38,2)); default: return 0; } } bool TCausale_magazzino::is_fiscale() { return (tipomov()=='S' || tipomov()=='C' ); } TCausale_magazzino::TCausale_magazzino(const char * codice): TRectype(LF_TABCOM) { TTable f("%CAU"); settab("CAU"); put("CODTAB", codice); if (TRectype::read(f) != NOERR) zero(); } // movimenti // dati della linea di movimento di magazzino class TLine_movmag : public TObject { TString16 _codcaus; TString16 _um; real _quant; real _prezzo; public: const TString16 &codcaus() const {return _codcaus;} const TString16 &um() const {return _um;} const real &quant() const {return _quant;} const real &prezzo() const {return _prezzo;} void set(const TString16 cau,const TString16 um,const real q, const real p); int operator==(TLine_movmag &); virtual TObject* dup() const {return new TLine_movmag(*this);}; TLine_movmag() {}; TLine_movmag(const TLine_movmag &); virtual ~TLine_movmag() {}; }; void TLine_movmag ::set(const TString16 cau,const TString16 um,const real q, const real p) { _codcaus=cau; _um=um; _quant=q; _prezzo=p; } TLine_movmag ::TLine_movmag(const TLine_movmag &l) { _codcaus=l._codcaus; _um=l._um; _quant=l._quant; _prezzo=l._prezzo; } int TLine_movmag::operator==(TLine_movmag &l) { return (_codcaus==l._codcaus)&&(_um==l._um)&&(_quant==l._quant)&&(_prezzo==l._prezzo); } // ******************************** // TMov_mag TRecord_cache TMov_mag::cache_causali("%CAU"); TMov_mag::TMov_mag() : TMultiple_rectype(LF_MOVMAG), lines_to_add(), lines_to_subtract() { add_file(LF_RMOVMAG,"NRIG"); } TMov_mag::~TMov_mag() { } void TMov_mag::zero(char c) { TMultiple_rectype::zero(c); lines_to_add.destroy(); lines_to_subtract.destroy(); } // valuta il valore della chiave per un nuovo record bool TMov_mag::renum() { put(MOVMAG_NUMREG,get_next_key()); return TRUE; } // copia la chiave dal file principale a quello delle righe void TMov_mag::set_body_key(TRectype & rowrec) { rowrec.put(RMOVMAG_NUMREG,get(MOVMAG_NUMREG)); } void TMov_mag::synchronize_bodies() { TMultiple_rectype::synchronize_bodies(); // reset delle strutture per il controlli delle variazioni dei saldi if (autoload_enabled()) { _annoes=get(MOVMAG_ANNOES); lines_to_add.destroy(); lines_to_subtract.destroy(); const int nrows = rows(); for (int i = 1; i<= nrows; i++) line_deleted(line2key(i), line2data(i)); } } int TMov_mag::remove(TBaseisamfile& f) const { int res; if ((res=TMultiple_rectype::remove(f))==NOERR ) // effettua la variazione dei saldi ((TMov_mag *)this)->update_balances(); return res; } void TMov_mag::add_extrarows() const { add_autorows(); if (add_explrows()) add_autorows(); } bool TMov_mag::add_autorows() const { bool added=FALSE; // aggiunge le righe automatiche for (int r = rows(); r > 0; r--) { TRecord_array & b = body(); TRectype & row = b[r]; TString16 codcaus(row.get(RMOVMAG_CODCAUS)); if (codcaus.empty()) codcaus=get(MOVMAG_CODCAUS); TCausale_magazzino & cau=(TCausale_magazzino & )cache_causali.get(codcaus); codcaus=cau.caus_collegata(); if (codcaus.not_empty()) { TCausale_magazzino & cau_coll=(TCausale_magazzino & )cache_causali.get(codcaus); // if (!cau_coll.esplodente()) { // deve esserci una riga collegata if (!b.exist(r + 1) || b[r + 1].get_char(RMOVMAG_TIPORIGA) != riga_automatica) { // manca, la inserisco TRectype * linea_auto = new TRectype(row); const char * codmag = cau_coll.default_magdep(); if (codmag != NULL) linea_auto->put(RMOVMAG_CODMAG, codmag); const char * prezzo = prezzo_rauto(r); if (prezzo != NULL) linea_auto->put(RMOVMAG_PREZZO, prezzo); linea_auto->put(RMOVMAG_NRIG, r+1); linea_auto->put(RMOVMAG_TIPORIGA, (char) riga_automatica); linea_auto->put(RMOVMAG_CODCAUS, codcaus); b.insert_row(linea_auto); added=TRUE; } } } } // ciclo righe return added; } bool TMov_mag::add_explrows() const { TDistinta_tree distinta; TArray boom; bool added=FALSE; // aggiunge le righe da explosione distinta for (int r = rows(); r > 0; r--) { TRecord_array & b = body(); TRectype & row = b[r]; TString16 codcaus(row.get(RMOVMAG_CODCAUS)); if (codcaus.empty()) codcaus=get(MOVMAG_CODCAUS); TCausale_magazzino & cau=(TCausale_magazzino & )cache_causali.get(codcaus); if (cau.esplodente() && !b[r].get_bool(RMOVMAG_ESPLOSA)) { // devono esserci n righe automatiche esplose //if (!b.exist(r + 1) || !b[r + 1].get_bool(RMOVMAG_ESPLOSA)) { // mancano le righe, le inserisco distinta.set_root(row.get(RMOVMAG_CODART)); distinta.explode(boom); TString codmag(codmag_rauto(r)); real prezzo(prezzo_rauto(r)); TRectype * linea_auto; for (int newrow=0; newrow < boom.items() ; newrow++) { TRiga_esplosione & riga_esp=(TRiga_esplosione & )(boom[newrow]); linea_auto = new TRectype(row); linea_auto->put(RMOVMAG_CODART, riga_esp.articolo()); linea_auto->put(RMOVMAG_UM, riga_esp.um()); linea_auto->put(RMOVMAG_QUANT, riga_esp.val()*row.get_real(RMOVMAG_QUANT)); if (codmag.not_empty()) linea_auto->put(RMOVMAG_CODMAG, codmag); if (!prezzo.is_zero()) linea_auto->put(RMOVMAG_PREZZO, prezzo); linea_auto->put(RMOVMAG_NRIG, r+1+newrow); linea_auto->put(RMOVMAG_ESPLOSA, TRUE); //linea_auto->put(RMOVMAG_TIPORIGA, (char) riga_automatica); //linea_auto->put(RMOVMAG_CODCAUS, codcaus); b.insert_row(linea_auto); added=TRUE; } } // ora ci sono, mi basta eliminare la riga "padre" b.destroy_row(r,TRUE); } } // ciclo righe return added; } int TMov_mag::write(TBaseisamfile& f) const { int res; add_extrarows(); TMov_mag &myself=((TMov_mag &)*this); const int nrows = rows(); for (int i = 1; i <= nrows; i++) myself.line_inserted(line2key(i), line2data(i)); if ((res=TMultiple_rectype::write(f))==NOERR ) // effettua la variazione dei saldi myself.update_balances(); return res; } int TMov_mag::rewrite(TBaseisamfile& f) const { int res; add_extrarows(); // memorizza le variazioni const int nrows = rows(); for (int i = 1; i <= nrows; i++) ((TMov_mag *)this)->line_inserted(line2key(i), line2data(i)); if ((res=TMultiple_rectype::rewrite(f))==NOERR ) // effettua la variazione dei saldi ((TMov_mag *)this)->update_balances(); return res; } const char *TMov_mag::get_next_key() { static TString16 nextcod; TLocalisamfile f(LF_MOVMAG); f.last(); int a=atoi(f.get(MOVMAG_NUMREG))+1; return nextcod.format("%d",a); } //******* // gestione delle variazione dei saldi // // int TMov_mag::force_update_bal() { int res; // reset delle strutture per il controlli delle variazioni dei saldi _annoes=get(MOVMAG_ANNOES); lines_to_add.destroy(); lines_to_subtract.destroy(); // memorizza le variazioni const int nrows = rows(); for (int i= 1; i <= nrows; i++) line_inserted(line2key(i), line2data(i)); res=update_balances(); return res; } // restituisce il valore dei dati TLine_movmag & TMov_mag::line2data(int nrig) const { static TLine_movmag line; TRecord_array & b = body(); line.set(b.row(nrig).get(RMOVMAG_CODCAUS).blank() ? get(MOVMAG_CODCAUS) : b.row(nrig).get(RMOVMAG_CODCAUS) , b.row(nrig).get(RMOVMAG_UM), b.row(nrig).get_real(RMOVMAG_QUANT), b.row(nrig).get_real(RMOVMAG_PREZZO)); return line; } TToken_string & TMov_mag::line2key(int numriga) const { static TToken_string _key; TRecord_array & b = body(); TString16 nr; nr << numriga; _key.cut(0); _key.add(b.row(numriga).get(RMOVMAG_CODART)); _key.add(b.row(numriga).get(RMOVMAG_CODMAG)); _key.add(b.row(numriga).get(RMOVMAG_LIVGIAC)); _key.add(nr); return _key; } TString TMov_mag::key2field(TToken_string &key,const char *fieldname) { if (strcmp(fieldname,RMOVMAG_CODART)==0) return key.get(0); if (strcmp(fieldname,RMOVMAG_CODMAG)==0) return key.get(1); if (strcmp(fieldname,RMOVMAG_LIVGIAC)==0) return key.get(2); CHECKS(FALSE, "Nome di campo non appartenente al file righe mov ", fieldname); return ""; } int TMov_mag::line_inserted(TToken_string &k,TLine_movmag &r) { if (_annoes != get(MOVMAG_ANNOES)) lines_to_add.add(k,r); else { if (lines_to_subtract.is_key(k)&& (TLine_movmag &)lines_to_subtract[k]==r) // modifica annullata lines_to_subtract.remove(k); else // linea modificata lines_to_add.add(k,r); } return 0; } int TMov_mag::line_deleted(TToken_string &k,TLine_movmag &r) { if (_annoes != get(MOVMAG_ANNOES)) lines_to_subtract.add(k,r); else { if (lines_to_add.is_key(k)&& r==(TLine_movmag &)lines_to_add[k] ) // modifica annullata lines_to_add.remove(k); else // linea modificata lines_to_subtract.add(k,r); } return 0; } bool TMov_mag::unlock_anamag(const char *codart) { TLocalisamfile anamag(LF_ANAMAG); anamag.put(ANAMAG_CODART,codart); return (anamag.read(_isequal,_unlock)==NOERR); } bool TMov_mag::lock_anamag(const char *codart) { TLocalisamfile anamag(LF_ANAMAG); anamag.put(ANAMAG_CODART,codart); bool insert_new=TRUE; TString mess; mess << "Il record di anagrafica dell'articolo ''"<< codart << "'' risulta essere già in uso."; TTimed_breakbox bbox((const char *)mess,10); do { if (anamag.read(_isequal,_testandlock)==NOERR) return TRUE; } while (bbox.run()!=K_ESC); return FALSE; } void TMov_mag::giac_putkey(TLocalisamfile & mag,TString16 annoes,TToken_string curr_key) { mag.zero(' '); mag.put(MAG_ANNOES,annoes); mag.put(MAG_CODMAG,key2field(curr_key,RMOVMAG_CODMAG)); mag.put(MAG_CODART,key2field(curr_key,RMOVMAG_CODART)); mag.put(MAG_LIVELLO,key2field(curr_key,RMOVMAG_LIVGIAC)); } // aggiorna tutti i saldi in base alle modifiche fatte. // il lock su anagrafica dovrebbe garantire il lock su tutte le // giacenze dell'articolo int TMov_mag::update_balances() { bool updated_bal=TRUE; TLocalisamfile mag(LF_MAG); mag.setkey(2); TString_array keys_to_add,keys_to_remove; ((TMov_mag *)this)->lines_to_add.get_keys(keys_to_add); ((TMov_mag *)this)->lines_to_subtract.get_keys(keys_to_remove); // aggiunge i saldi nuovi keys_to_add.sort(); TToken_string * curr_key=(TToken_string *)keys_to_add.first_item(); while (curr_key) { const TString cod(key2field(*curr_key,RMOVMAG_CODART)) ; if (curr_art.lock_and_prompt(cod)) { // lock gained TLine_movmag & line_mov=(TLine_movmag &)lines_to_add[*curr_key]; TCausale_magazzino & causmag=(TCausale_magazzino &)cache_causali.get(line_mov.codcaus()); if (causmag.update_ultcos()) { curr_art.update_ultcosti(line_mov.prezzo(),get_date("DATACOMP")); curr_art.rewrite(); } giac_putkey(mag,get(MOVMAG_ANNOES),*curr_key); if (mag.read()!=NOERR) { // non trovato: aggiungo giac_putkey(mag,get(MOVMAG_ANNOES),*curr_key); mag.put(MAG_NRIGA,1+curr_art.mag(get(MOVMAG_ANNOES)).rows()); mag.write(); } // modifica questo record (e lo sblocca) update_balances(mag.curr(), line_mov, +1); /*// ottimizzazione :(cerca di sfruttare la lettura fatta per un eventuale saldo vecchio) // ciò causa la modifica dell'oggetto TMov_mag (il metodo non è più const) if (_annoes == get("ANNOES") && lines_to_subtract.is_key(*curr_key)) { update_balances(mag.curr(),(TLine_movmag &)lines_to_subtract[*curr_key],-1); ((TMov_mag *)this)->lines_to_add.remove(*curr_key); ((TMov_mag *)this)->lines_to_subtract.remove(*curr_key); }*/ mag.rewrite(); // conclude la TRANSAZIONE prima di sbloccare il record dell'articolo TToken_string *rem_key=(TToken_string *)keys_to_remove.first_item(); while ( rem_key) { if (key2field(*rem_key,RMOVMAG_CODART)==key2field(*curr_key,RMOVMAG_CODART)) { giac_putkey(mag,_annoes,*rem_key); if (mag.read()==NOERR) { update_balances(mag.curr(),(TLine_movmag &)lines_to_subtract[*rem_key],-1); mag.rewrite(); } keys_to_remove.remove_item(); } rem_key=(TToken_string *)keys_to_remove.succ_item(); } curr_art.unlock(); } else updated_bal=FALSE; curr_key=(TToken_string *)keys_to_add.succ_item(); } // togli i saldi vecchi curr_key=(TToken_string *)keys_to_remove.first_item(); while (curr_key) { if (curr_art.lock_and_prompt((const char *)key2field(*curr_key,RMOVMAG_CODART))) { giac_putkey(mag,_annoes,*curr_key); // modifica questo record (e lo sblocca) if (mag.read()==NOERR) { update_balances(mag.curr(),(TLine_movmag &)lines_to_subtract[*curr_key],-1); mag.rewrite(); } curr_art.unlock(); } else updated_bal=FALSE; curr_key=(TToken_string *)keys_to_remove.succ_item(); } return updated_bal; } // aggiorna i saldi del record corrente // in base alla causale e alla modifica fatta (con segno + o -) int TMov_mag::update_balances(TRectype & magrec, const TLine_movmag &l,int rett_sign) { TCausale_magazzino & caus=(TCausale_magazzino &)cache_causali.get(l.codcaus()); TLocalisamfile umart(LF_UMART); real diff,diff_val; umart.setkey(2); umart.put(UMART_CODART,magrec.get(MAG_CODART)); umart.put(UMART_UM , l.um()); umart.read(); real fc=umart.get_real("FC"); diff=((real)rett_sign) * l.quant() * fc; diff_val= ((real)rett_sign) * l.quant() * l.prezzo(); if (caus.update_qta()) { update_balance(magrec,"GIAC",diff* (real)caus.sgn(s_giac)); // update .. update_balance(magrec,"ACQ",diff* (real)caus.sgn(s_acq)); // update .. update_balance(magrec,"ENT",diff* (real)caus.sgn(s_ent)); update_balance(magrec,"VEN",diff* (real)caus.sgn(s_ven)); update_balance(magrec,"USC",diff* (real)caus.sgn(s_usc)); update_balance(magrec,"ORDC",diff* (real)caus.sgn(s_ordc)); update_balance(magrec,"ORDF",diff* (real)caus.sgn(s_ordf)); update_balance(magrec,"RIM",diff* (real)caus.sgn(s_rim)); update_balance(magrec,"SCARTI",diff* (real)caus.sgn(s_scart)); update_balance(magrec,"INCL",diff* (real)caus.sgn(s_incl)); update_balance(magrec,"ACL",diff* (real)caus.sgn(s_acl)); update_balance(magrec,"PRODCOMP",diff* (real)caus.sgn(s_prodc)); update_balance(magrec,"PRODFIN",diff* (real)caus.sgn(s_prodf)); update_balance(magrec,"NLABEL",diff* (real)caus.sgn(s_label)); update_balance(magrec,"USER1",diff* (real)caus.sgn(s_user1)); update_balance(magrec,"USER2",diff* (real)caus.sgn(s_user2)); update_balance(magrec,"USER3",diff* (real)caus.sgn(s_user3)); update_balance(magrec,"USER4",diff* (real)caus.sgn(s_user4)); update_balance(magrec,"USER5",diff* (real)caus.sgn(s_user5)); update_balance(magrec,"USER6",diff* (real)caus.sgn(s_user6)); } if (caus.update_val()) { update_balance(magrec,"VALACQ",diff_val* (real)caus.sgn(s_acq)); // update .. update_balance(magrec,"VALENT",diff_val* (real)caus.sgn(s_ent)); update_balance(magrec,"VALVEN",diff_val* (real)caus.sgn(s_ven)); update_balance(magrec,"VALUSC",diff_val* (real)caus.sgn(s_usc)); update_balance(magrec,"VALORDC",diff_val* (real)caus.sgn(s_ordc)); update_balance(magrec,"VALORDF",diff_val* (real)caus.sgn(s_ordf)); update_balance(magrec,"VALRIM",diff_val* (real)caus.sgn(s_rim)); update_balance(magrec,"VALSCARTI",diff_val* (real)caus.sgn(s_scart)); update_balance(magrec,"USERVAL1",diff* (real)caus.sgn(s_user1)); update_balance(magrec,"USERVAL2",diff* (real)caus.sgn(s_user2)); update_balance(magrec,"USERVAL3",diff* (real)caus.sgn(s_user3)); update_balance(magrec,"USERVAL4",diff* (real)caus.sgn(s_user4)); update_balance(magrec,"USERVAL5",diff* (real)caus.sgn(s_user5)); update_balance(magrec,"USERVAL6",diff* (real)caus.sgn(s_user6)); } return 0; } void TMov_mag::update_balance(TRectype & magrec, const char * fieldname, real diff) const { magrec.put(fieldname,magrec.get_real(fieldname)+diff); } HIDDEN TEsercizi_contabili _esercizi; int TMov_mag::codice_esercizio(TDate &d) { return _esercizi.date2esc(d); } void zero_balances(TRectype & mag) { mag.put(MAG_GIAC,0); mag.put(MAG_RIM,0);mag.put(MAG_VALRIM,0); mag.put(MAG_ACQ,0);mag.put(MAG_VALACQ,0); mag.put(MAG_ENT,0);mag.put(MAG_VALENT,0); mag.put(MAG_VEN,0);mag.put(MAG_VALVEN,0); mag.put(MAG_USC,0);mag.put(MAG_VALUSC,0); mag.put(MAG_ORDF,0);mag.put(MAG_VALORDF,0); mag.put(MAG_ORDC,0);mag.put(MAG_VALORDC,0); mag.put(MAG_SCARTI,0);mag.put(MAG_VALSCARTI,0); mag.put(MAG_PRODCOMP,0); mag.put(MAG_PRODFIN,0); mag.put(MAG_INCL,0); mag.put(MAG_ACL,0); mag.put(MAG_NLABEL,0); } void copy_oldbalances(TRectype & oldmag,TRectype & mag) { mag.put(MAG_GIAC,oldmag.get(MAG_GIAC)); mag.put(MAG_RIM,oldmag.get(MAG_RIM)); mag.put(MAG_VALRIM,oldmag.get(MAG_VALRIM)); mag.put(MAG_ACQ,0); mag.put(MAG_VALACQ,0); mag.put(MAG_ENT,0); mag.put(MAG_VALENT,0); mag.put(MAG_VEN,0); mag.put(MAG_VALVEN,0); mag.put(MAG_USC,0); mag.put(MAG_VALUSC,0); mag.put(MAG_ORDF,oldmag.get(MAG_ORDF)); mag.put(MAG_VALORDF,oldmag.get(MAG_VALORDF)); mag.put(MAG_ORDC,oldmag.get(MAG_ORDC)); mag.put(MAG_VALORDC,oldmag.get(MAG_VALORDC)); mag.put(MAG_SCARTI,0); mag.put(MAG_VALSCARTI,0); mag.put(MAG_PRODCOMP,oldmag.get(MAG_PRODCOMP)); mag.put(MAG_PRODFIN,oldmag.get(MAG_PRODFIN)); mag.put(MAG_INCL,oldmag.get(MAG_INCL)); mag.put(MAG_ACL,oldmag.get(MAG_ACL)); mag.put(MAG_NLABEL,0); } //********************** bool rebuild_balances(const TString16 annoes, const TTipo_valorizz tipo_valorizz, const char* catven, const char* codlis) { TRelation rel(LF_MOVMAG); // relazione con un solo file (LF_MOVMAG) ma col record Head_Body TMov_mag * m_m= new TMov_mag; // record del movimento di magazzino rel.lfile().set_curr(m_m); TRelation rel2(LF_ANAMAG); // relazione con un solo file (LF_ANAMAG) ma col record Head_Body TArticolo_giacenza * a_g= new TArticolo_giacenza; // record dell'articolo di magazzino rel2.lfile().set_curr(a_g); int ok=TRUE; // Aggiorna il cazzillo per caricare eventuali date di chiusura e altre amenita' simili _esercizi.update(); const int cod_pred_es = _esercizi.pred(atoi(annoes)); TString16 pred_es; pred_es.format("%d",cod_pred_es); const bool reset_giac = cod_pred_es != 0 ? _esercizi.esercizio(cod_pred_es).chiusura_mag() != TDate(NULLDATE) : TRUE; TString information; // azzera tutte giacenze (ciclo sulle giacenze) TCursor cur2(&rel2); const long maxart=cur2.objects(); information.format("Ricostruzione saldi esercizio %s: azzeramento...",(const char *)annoes); TProgind barra_art(maxart,information, TRUE, TRUE, 60); for (long a=0; aANNOES==" << annoes; TCursor cur(&rel,filterexpr); // cursore filtrato const long maxmov=cur.objects(); information.format("Ricostruzione saldi esercizio %s: ricalcolo ...",(const char *)annoes); TProgind barra_mov(maxmov,information,TRUE, TRUE, 60); for (long m=0; m