// Stampa esplosione distinte // Ma ke freddo fa!? // ... // & God took away Ish 2 create Isha // Warning: TAssoc_array heavily used in this App // ... // Seņor... donde esta El Jefe!? // Ola! Estrella querida... Yo soy El Jefe! #include #include #include #include "../cg/cglib01.h" #include "../mg/mglib.h" #include "../ve/velib.h" #include "dblib.h" #include "dist.h" #include "rdist.h" #include "../mg/anamag.h" #include "db1100a.h" #define DIST_HEAD 0 ///////////////////////////////////////////////////////// // Inizio ammenicoli di supporto ///////////////////////////////////////////////////////// enum seltype { by_num, by_date }; enum expltype { mat_base, scalare}; struct _ParmStruct { seltype _selections; expltype _explosion; valtype _valorization; bool _advanced_val; TExplosion_grouping _group_by; TString_array _numerazioni; TString16 _anno_es, _catven, _codlist, _from_num, _to_num, _sl_mag, _mb_mag; // Ma perche'... TDate _from_date, _to_date, _obs_date; long _from_doc, _to_doc; int _year, _periods, _det_lev, _ordering; bool _last_qta, _vis_art, _vis_lav, _vis_vir, _vis_gho, _fabbisogno, _no_fabbis_fin, _no_zero_ord, _val_magmb, _val_depmb, _newpage, _det_ord_for, _sort_for, _separate_dist, _separate_giac, _add_orc, _add_orf, _add_prf, _add_prc, _add_acl, _add_incl, _normal_disp; char _liv_attenzione; }; struct _CallBackStruct { _ParmStruct* _p; TAssoc_array* _a; }; static TString __key; static TDate __last_period; static TDate __current_period; static TString __current_art; /////////////////////////////////////////////////////////// // TArticolo_giacenza_static /////////////////////////////////////////////////////////// // // Particolarita' della classe: il metodo "vero" per calcolare // la disponibilita' viene chiamato solo la prima volta, poi viene sempre // tenuto in memoria per eventuali aggiornamenti sulle qta, in modo // da non fare calcoli pocciosi sul file delle giacenza class TArticolo_giacenza_static : public TArticolo_giacenza { bool _calc; real _disp; // Disponibilita': sempre espressa in UM base!! // Prima di effettuare addizioni/sottrazioni ricordarsi di convertire TArray _ordinato_fornitori; // Array di real per l'ordinato fornitori (espressi in UM BASE) TString16 _umbase; protected: void calc_ordinato_fornitori(_ParmStruct *p, const char * codmag, const char * livello); void calcola_ordinato_documento(TRectype& rec); public: const real & ordinato_fornitori(const int p); // ritorna l'ordinato fornitori per il periodo indicato const real get_scmin(const char * annoes, const char * codmag, const char * livello); real& static_disp(_ParmStruct* p, const char * codmag, const char * livello); TArticolo_giacenza_static(const char* codice = NULL); TArticolo_giacenza_static(const TRectype& rec); virtual ~TArticolo_giacenza_static() {} }; /////////////////////////////////////////////////////////// // TArticolo_cache /////////////////////////////////////////////////////////// class TArticolo_cache : public TRecord_cache { protected: virtual TObject* rec2obj(const TRectype& rec) const; public: TArticolo_giacenza_static& art(const char* key); TArticolo_cache(); virtual ~TArticolo_cache() { } }; TArticolo_cache::TArticolo_cache() : TRecord_cache(LF_ANAMAG, 1) { } TObject* TArticolo_cache::rec2obj(const TRectype& curr) const { TArticolo_giacenza_static * a = new TArticolo_giacenza_static(curr); return a; } TArticolo_giacenza_static& TArticolo_cache::art(const char* key) { TArticolo_giacenza_static& art = (TArticolo_giacenza_static&)query(key); return art; } /////////////////////////////////////////////////////////// // TRiga_esplosione2print /////////////////////////////////////////////////////////// class TRiga_esplosione2print : public TRiga_esplosione { real _fabbisogno; real _disponibilita; real _value, _unitario; real _qta2order; real _residuo; real _ordfor; real _totordfor; TDate _dtacons; TString8 _codmag; TToken_string _cod_corr; public: const TString& mag() const { return _codmag; } const TDate& datacons() const { return _dtacons; } const real& fabbisogno() const { return _fabbisogno; } const real& disponibilita() const { return _disponibilita; } const real& value() const { return _value; } const real& unitary_value() const { return _unitario; } const real& qta2order() const { return _qta2order; } const real& residuo() const { return _residuo; } const real& ordfor() const { return _ordfor; } const real& totordfor() const { return _totordfor; } void set_mag(const char *s) { _codmag = s; } void set_datacons(const TDate& d) { _dtacons = d; } void set_fabbisogno(const real& r) { _fabbisogno = r; } void set_disponibilita(const real& r) { _disponibilita = r; } void set_value(const real& r) { _value = r; } void set_unitary_value(const real& r) { _unitario = r; } void set_residuo(const real& r) { _residuo = r; } void set_qta2order(const real& r) { _qta2order = r; } void set_ordfor(const real& r) { _ordfor = r; } void set_totordfor(const real& r) { _totordfor = r; } const TString& codici_corrispontenti(char tipo) const; TRiga_esplosione2print() : _cod_corr(80, '\n') {}; TRiga_esplosione2print(const TDistinta_tree& tree, const char *codmag); TRiga_esplosione2print(const TRiga_esplosione& re, const char *codmag); ~TRiga_esplosione2print() {}; }; const TString& TRiga_esplosione2print::codici_corrispontenti(char tipo) const { TRectype key(LF_CODCORR); key.put("CODART", articolo()); TRecord_array a(key, "NRIGA"); TToken_string& lista = (TToken_string&)_cod_corr; // Fool the compiler lista.cut(0); const int last = a.last_row(); for (int i = a.first_row(); i > 0 && i <= last; i = a.succ_row(i)) { const TRectype& row = a.row(i); if (tipo < ' ' || row.get_char("TIPO") == tipo) lista.add(row.get("CODARTALT")); } return lista; } TRiga_esplosione2print::TRiga_esplosione2print(const TDistinta_tree& tree, const char *codmag) : TRiga_esplosione(tree), _codmag(codmag), _cod_corr(80, '\n') { } TRiga_esplosione2print::TRiga_esplosione2print(const TRiga_esplosione& re, const char *codmag) : TRiga_esplosione(re), _codmag(codmag), _cod_corr(80, '\n') { } /////////////////////////////////////////////////////////// // TDist2Explode /////////////////////////////////////////////////////////// class TDist2Explode : public TObject { TCodice_articolo _cod; TString16 _livgiac; TCodice_um _um; TString8 _imp, _lin, _mag; real _qta; TDate _datacons; TDate _data_per; // Data limite del periodo del quale fa parte questa distinta da esplodere bool _acq_ven; protected: void set(const TMask& msk); public: TRiga_esplosione* head_obj(); void set(const TRiga_documento& r, const TMask& msk); void set(TToken_string& t, const TMask& msk); void set_cod(const char* c) { _cod = c; } void set_liv(const char* l) { _livgiac = l; } void set_imp(const char* i) { _imp = i; } void set_lin(const char* l) { _lin = l; } void set_mag(const char* m) { _mag = m; } void set_um (const char* u) { _um = u;} void set_qta(const real& q) { _qta = q;} void set_datacons(const TDate& d) { _datacons = d; } void set_acq(const bool b) { _acq_ven = b; } real& qta() { return _qta;} const TDate& datacons() { return _datacons;} const TDate& data_per() { return _data_per;} const bool& acqven() { return _acq_ven; } const TString& imp() { return _imp; } const TString& lin() { return _lin; } const TString& mag() { return _mag; } const TCodice_um& um() { return _um; } const TString& liv() { return _livgiac; } const TCodice_articolo& cod() { return _cod; } const char * key(); TDist2Explode () {}; virtual ~TDist2Explode() {}; }; /////////////////////////////////////////////////////////// // TExplode_distinta_form /////////////////////////////////////////////////////////// class TExplode_distinta_form : public TForm { static TExplode_distinta_form *_f; // Yes, I am THIS. TDistinta_tree _distinta; // Albero della distinta TArticolo_cache _art_cache; // Cache di articoli con disponibilita TArray _exploded_tree; // Righe di eplosione TAssoc_array _valori; // Righe dei valori dei nodi e delle foglie TAssoc_array _prodorder; // Righe dei residui (solo semilavorati/nodi) TAssoc_array _prodordert; // Righe dei residui (solo semilavorati/nodi) TAssoc_array _disponib; // Righe dei residui (solo semilavorati/nodi) TDist2Explode *_d; // Distinta corrente da esplodere _ParmStruct *_p; // Struttura dei parametri int _curr_row; // Riga corrente della distinta esplosa da stampare protected: void print_header(TPrinter& p); void print_footer(TPrinter& p); static void dist_header_handler(TPrinter& p); static void dist_footer_handler(TPrinter& p); virtual bool validate(TForm_item &, TToken_string &); void set_explosion_rows(const TArray& exp_array); real res2produce_by_father(const TRiga_esplosione& re) const; public: void print_explosion_rows(); void reset_rows(bool firsttime = TRUE); void set_distinta(TDist2Explode* dd) { _d = dd; } void set_parameters(_ParmStruct* ps); void explode_and_print(); void reset_cache() { _art_cache.destroy(); } static TArticolo_cache& cache_articoli() { return _f->_art_cache; } TExplode_distinta_form(const char *); virtual ~TExplode_distinta_form(); }; TExplode_distinta_form* TExplode_distinta_form::_f = NULL; /////////////////////////////////////////////////////////// // TEsplosione_distinta_app /////////////////////////////////////////////////////////// class TEsplosione_distinta_app : public TSkeleton_application { TMask *_mask; TDocumento *_doc; TExplode_distinta_form *_form; TAssoc_array _dist_list; TArray _date_array; TCodgiac_livelli *_liv_giac; // Dati "i/n/m/putati" ma non ancora condannati... _ParmStruct _parameters; int _default_code_width; protected: static bool sheet_notify(TSheet_field& s, int r, KEY key); virtual bool create(); virtual bool destroy(); virtual void main_loop(); static bool check_articoli(TMask_field& f, KEY k); void compile_list(); void compile_periods(); void compile_numeration_list(); virtual void print(); public: const int date2period(const TDate&); const TDate& date_period(const TDate&); TEsplosione_distinta_app() {}; virtual ~TEsplosione_distinta_app() {}; }; inline TEsplosione_distinta_app& app() { return (TEsplosione_distinta_app&)main_app(); } /////////////////////////////////////////////////////////////////// // Callback & funzione per valorizzazione nodi /////////////////////////////////////////////////////////////////// static real valorizza_nodo(TDistinta_tree & node, _CallBackStruct & c) { TAssoc_array* valori = c._a; TToken_string path; node.curr_id(path); real * valore = (real *) valori->objptr(path); if (valore != NULL) return *valore; _ParmStruct * pp = c._p; real totale; TCodice_articolo codart; TString16 liv; TCodice_um um; const TString& annoes = pp->_anno_es; const TString& catven = pp->_catven; TString16 codmag; TString& codlist = pp->_codlist; const bool dettagliata = pp->_advanced_val; bool valorizzato = false; const char tipo = node.curr_type(); real valore_un; node.curr_um(um); node.curr_code(codart); node.curr_giaclev(liv); if (pp->_val_magmb) // Se non c'e' _val_magmb non c'e' nemmeno _val_depmb { // Quindi codmag rimane a zero e la valorizzazione viene fatta su tutti i mag. codmag = pp->_mb_mag; if (!pp->_val_depmb && codmag.len() > 3) codmag.cut(3); // se non deve valorizzare sul deposito lo accorciamo } if (dettagliata && tipo == 'A') { TArticolo_giacenza & art = TExplode_distinta_form::cache_articoli().art(codart); const valtype art_tipo = (valtype)art.get_int(ANAMAG_VALDIST); if (art_tipo > no_val) { const TDate inizio_val = art.get_date(ANAMAG_DATAVDIST); if (pp->_obs_date >= inizio_val) { switch (art_tipo) { case last_cost: valore_un = art.ultimo_costo(annoes); break; case last2cost: valore_un = art.media_costi(annoes); break; case std_cost: valore_un = art.costo_standard(annoes); break; case average_cost: valore_un = art.costo_medio(annoes, codmag, liv); break; case pond_cost: valore_un = art.costo_mediopond(annoes, codmag, liv); break; case LIFO_annuale: valore_un = art.LIFO_annuale(annoes, codmag, liv); break; case FIFO_annuale: valore_un = art.FIFO_annuale(annoes, codmag, liv); break; case LIFO_storico: valore_un = art.LIFO(annoes, codmag, liv); break; case FIFO_storico: valore_un = art.FIFO(annoes, codmag, liv); break; case prezzo_listino: valore_un = art.prezzo_listino(annoes, catven, codlist); break; default: NFCHECK("Tipo valorizzazione errato: %d", (valtype) art_tipo); } valore_un = art.convert_to_um(valore_un, um); valorizzato = true; } } } if (!valorizzato) { if (node.has_son()) { for (bool ok = node.goto_firstson(); ok ; ok = node.goto_rbrother()) valore_un += valorizza_nodo(node, c); node.goto_father(); } else { switch (tipo) { case 'A': { TArticolo_giacenza & art = TExplode_distinta_form::cache_articoli().art(codart); const valtype val = pp->_valorization; switch (val) { case last_cost: valore_un = art.ultimo_costo(annoes); break; case last2cost: valore_un = art.media_costi(annoes); break; case std_cost: valore_un = art.costo_standard(annoes); break; case average_cost: valore_un = art.costo_medio(annoes, codmag, liv); break; case pond_cost: valore_un = art.costo_mediopond(annoes, codmag, liv); break; case LIFO_annuale: valore_un = art.LIFO_annuale(annoes, codmag, liv); break; case FIFO_annuale: valore_un = art.FIFO_annuale(annoes, codmag, liv); break; case LIFO_storico: valore_un = art.LIFO(annoes, codmag, liv); break; case FIFO_storico: valore_un = art.FIFO(annoes, codmag, liv); break; case prezzo_listino: valore_un = art.prezzo_listino(annoes, catven, codlist); break; default: NFCHECK("Tipo valorizzazione errato: %d", val); break; } valore_un = art.convert_to_um(valore_un, um); } break; case 'L': { TLavorazione lav(codart); valore_un = lav.prezzo(); } break; case 'D': valore_un = real(cache().get(LF_DIST, codart, "PREZZO")); break; case 'V': NFCHECK("L'articolo %s porca COVER", (const char*)codart); break; default : NFCHECK("L'articolo %s non esiste", (const char*)codart); break; } } } valori->add(path, valore_un); const real qta = node.last_qta(); // NON node.curr_qta(); const real valore_totale = valore_un * qta; return valore_totale; } ///////////////////////////////////////////////////////////// // Implementazione metodi di TArticolo_giacenza_static ///////////////////////////////////////////////////////////// TArticolo_giacenza_static::TArticolo_giacenza_static(const char* codice) : TArticolo_giacenza(codice), _calc(FALSE) { } TArticolo_giacenza_static::TArticolo_giacenza_static(const TRectype& rec) : TArticolo_giacenza(rec), _calc(FALSE) { } const real & TArticolo_giacenza_static::ordinato_fornitori(const int p) { // con p ==0 ritorna il totale ordinato fornitori const real * r = (real *)_ordinato_fornitori.objptr(p); return r ? *r : ZERO; } const real TArticolo_giacenza_static::get_scmin(const char * annoes, const char * codmag, const char * livello) { real r; const int i = find_mag(annoes, codmag, livello); if (i > 0) { TRecord_array& ra = mag(annoes); r = ra[i].get_real("SCORTAMIN"); } return r; } void TArticolo_giacenza_static::calcola_ordinato_documento(TRectype& rec) { CHECK(rec.num() == LF_DOC, "E' necessario passare un record di LF_DOC"); TRectype from(LF_RIGHEDOC); from.put(RDOC_CODNUM, rec.get(DOC_CODNUM)); from.put(RDOC_ANNO, rec.get(DOC_ANNO)); from.put(RDOC_PROVV, rec.get(DOC_PROVV)); TString filter; int nkey = 1; // Se NDOC non č settato effettua il filtro su tutti i documenti di questa numerazione const long ndoc = rec.get_long(DOC_NDOC); if (ndoc > 0) { from.put(RDOC_NDOC, ndoc); filter = "CODART==\""; filter << codice() << "\""; } else { nkey = 2; from.put(RDOC_CODART, codice()); } TRelation rdoc(LF_RIGHEDOC); TCursor cur(&rdoc, filter, nkey, &from, &from); const TRecnotype items = cur.items(); if (items > 0) { TWait_cursor hourglass; cur.freeze(); filter = TR("Calcolo ordinato fornitori "); filter << rec.get(DOC_CODNUM); filter << "/" << codice(); TProgind *pi = items > 32 ? new TProgind(items, filter, FALSE, TRUE) : NULL; for (cur = 0L; cur.pos() < items; ++cur) { // Calcola la qta residua if (pi) pi->addstatus(1L); const TRectype& rec = cur.curr(); if (!rec.get_bool(RDOC_RIGAEVASA)) { real val = rec.get_real(RDOC_QTA) - rec.get_real(RDOC_QTAEVASA); // Converte il valore della quantitā in UM base val = convert_to_um(val, _umbase, rec.get(RDOC_UMQTA)); if (val > ZERO) { // Aggiorna il valore ordinato del periodo relativo real& rr = (real&) _ordinato_fornitori[app().date2period(rec.get_date(RDOC_DATACONS))]; rr += val; } } } if (pi) delete pi; } } void TArticolo_giacenza_static::calc_ordinato_fornitori(_ParmStruct* p, const char * codmag, const char * livello) { // Calcolo del dettaglio ordinato fornitori, chiamata UNA sola volta per ogni articolo // ad ogni stampa TEsercizi_contabili ese; // Toglie l'ordinato fornitori dalla disponibilita if (p->_add_orf) { TString16 annoes(p->_anno_es); TRecord_array & rmag = mag(annoes); for (int i = find_mag(annoes, codmag, livello); i > 0; i = find_mag(annoes, codmag, livello, i)) _disp -= rmag.row(i).get_real(MAG_ORDF); int prev = ese.pred(atoi(annoes)); // Controllo anche l'anno precedente while (prev > 0) { TString16 oldannoes; oldannoes.format("%04d", prev); TRecord_array & rmag = mag(oldannoes); for (int i = find_mag(oldannoes, codmag, livello); i > 0; i = find_mag(oldannoes, codmag, livello, i)) _disp -= rmag.row(i).get_real(MAG_ORDF); prev = ese.pred(prev); } } // Rimuove eventuali elementi rimasti, anche se questo metodo viene effettivamente chiamato una sola // volta per articolo. _ordinato_fornitori.destroy(); // Azzera l'array... int i; for (i = 0; i <= p->_periods; i++) _ordinato_fornitori.add(new real); //Scorre tutte le numerazioni TString_array& a = p->_numerazioni; for (i = a.last(); i >= 0; i--) { TToken_string& t = (TToken_string&) a[i]; const int items = t.items(); if (items == 2) // Un solo tipo documento: scorre solo le righe di questa numerazione { int eser = atoi(p->_anno_es); TRectype doc(LF_DOC); while (eser > 0) { doc.put(DOC_CODNUM, t.get(0)); doc.put(DOC_ANNO, eser); doc.put(DOC_PROVV, "D"); calcola_ordinato_documento(doc); eser = ese.pred(eser); } } else // Se invece vi sono piu' tipi doc. per questa numerazione e' necessario considerare le testate doc. if (items >= 3) { int eser = atoi(p->_anno_es); TRectype from(LF_DOC), to(LF_DOC); TString filter; while (eser > 0) { from.zero(); from.put(DOC_CODNUM, t.get(0)); from.put(DOC_ANNO, eser); from.put(DOC_PROVV, "D"); to = from; for (int j=2; j<=items; j++) { filter << "(TIPODOC==\""; filter << t.get(j-1); filter << "\")||"; } filter.rtrim(2); TRelation doc(LF_DOC); TCursor cur(&doc, filter, 1, &from, &to); for (cur = 0L; cur.pos() < cur.items(); ++cur) // Per ogni documento scorre le sue righe calcola_ordinato_documento(cur.curr()); eser = ese.pred(eser); } } } // Progressivizza gli importi const int periods = p->_periods; if (periods > 1) { for (i=2; i <= periods ; i++) { real& rr = (real&)_ordinato_fornitori[i]; rr += (real&)_ordinato_fornitori[i-1]; if (i== periods) { real& zz = (real&)_ordinato_fornitori[0]; // Totale... zz += rr; } } } else { real& rr = (real&)_ordinato_fornitori[1]; real& zz = (real&)_ordinato_fornitori[0]; // Totale... zz += rr; } } real& TArticolo_giacenza_static::static_disp(_ParmStruct* p, const char * codmag, const char * livello) { if (!_calc) { _calc =TRUE; const char * annoes = p->_anno_es; _disp = ZERO; TRecord_array & rmag = mag(annoes); for (int i = find_mag(annoes, codmag, livello); i > 0; i = find_mag(annoes, codmag, livello, i)) { const TRectype & rec = rmag.row(i); _disp += rec.get_real(MAG_GIAC); if (p->_add_orf) _disp += rec.get_real(MAG_ORDF); if (p->_add_orc) _disp -= rec.get_real(MAG_ORDC); if (p->_add_prf) _disp += rec.get_real(MAG_PRODFIN); if (p->_add_prc) _disp -= rec.get_real(MAG_PRODCOMP); if (p->_add_acl) _disp += rec.get_real(MAG_ACL); if (p->_add_incl) _disp -= rec.get_real(MAG_INCL); } if ((p->_add_orc || p->_add_orf) && !riporta_ordinato()) // Se l-ordinato viene riportato { TEsercizi_contabili ese; const int prev = ese.pred(atoi(annoes)); // Controllo anche l'anno precedente if (prev > 0) { TString4 oldannoes; oldannoes.format("%04d", prev); const TRecord_array& oldrmag = mag(oldannoes); for (int i = find_mag(oldannoes, codmag, livello); i > 0; i = find_mag(oldannoes, codmag, livello, i)) { const TRectype& rec = oldrmag.row(i); if (p->_add_orf) _disp += rec.get_real(MAG_ORDF); // Sommo l'ordinato fornitori if (p->_add_orc) _disp -= rec.get_real(MAG_ORDC); // Sottraggo l'ordinato clienti } } } _umbase = ((TRectype&)(um()[1])).get("UM"); // Calcola ordinato fornitori di questo articolo, suddividendo per periodi // L'ordinato viene espresso nell'unitā di misura principale, per poi essere riconvertita in // quella esplicitata nella riga di esplosione if (p->_det_ord_for) calc_ordinato_fornitori(p, codmag, livello); } return _disp; } ///////////////////////////////////////////////////////////// // Implementazione metodi di TExplode_distinta_form ///////////////////////////////////////////////////////////// TExplode_distinta_form::TExplode_distinta_form(const char * n) : TForm(n) { _d = NULL; _p = NULL; _f = this; TPrinter& pr = printer(); pr.setheaderhandler(dist_header_handler); TPrint_section& head = section('H'); pr.headerlen(head.height()); pr.setfooterhandler(dist_footer_handler); const TPrint_section& foot = section('F'); pr.footerlen(foot.height()); } TExplode_distinta_form::~TExplode_distinta_form() { } void TExplode_distinta_form::set_parameters(_ParmStruct* ps) { _p = ps; // Accende o spegne le colonne a seconda di stampa disponibilita/valorizzazione for (short i = 7; i<=9; i++) find_field('B',odd_page,i).enable(_p->_fabbisogno); // Colonne disponibilita... find_field('B',odd_page,10).enable(_p->_valorization != no_val); // Valorizzazione find_field('B',odd_page,11).enable(_p->_valorization != no_val); // Valore unitario find_field('B',odd_page,12).enable(_p->_det_ord_for); // Dettaglio ord. fornitori find_field('B',odd_page,13).enable(_p->_det_ord_for); // Dettaglio ord. fornitori find_field('B',odd_page,14).enable(_p->_det_ord_for); // Codice fornitore } void TExplode_distinta_form::print_header(TPrinter& pr) { TPrint_section& head = section('H'); head.update(); const word r = head.height()-1; for (word j = 0; j <= r; j++) pr.setheaderline(j, head.row(j)); } void TExplode_distinta_form::print_footer(TPrinter& pr) { const bool p = page(pr)>0; TPrint_section& foot = section('F',p ? odd_page : last_page); foot.update(); word r = foot.height(); for (word j = 0; j < r; j++) pr.setfooterline(j, foot.row(j)); } void TExplode_distinta_form::dist_header_handler(TPrinter& pr) { pr.resetheader(); _f->print_header(pr); } void TExplode_distinta_form::dist_footer_handler(TPrinter& pr) { pr.resetfooter(); _f->print_footer(pr); } bool TExplode_distinta_form::validate(TForm_item &f, TToken_string &t) { const TString16 subcommand(t.get(0)); // Sub-comandante Marcos if (subcommand != "_DISTINTA") return TForm::validate(f, t); const TString16 code(t.get(1)); // codice del messaggio TString256 valore; const TRiga_esplosione2print& re = (const TRiga_esplosione2print&) _exploded_tree[_curr_row]; const char tipo = re.tipo(); if (code[0] != '_') { const char tiporiga = t.get()[0]; if (tipo == tiporiga) { switch (tipo) { case 'A': { valore = cache().get(LF_ANAMAG, re.articolo(), code); break; } case 'L': { const TLavorazione lav(re.articolo()); valore = lav.get(code); break; } case 'V': { TLocalisamfile& dist = relation()->lfile(); dist.put("CODDIST", re.articolo()); if (dist.read() == NOERR) valore = dist.get(code); break; } default: break; } } } else { if (code == "_COD") { int liv = re.livello(); if (liv > 0) // Calcola indentazione { if (_p->_separate_dist) { if (liv > 10) liv = 10; if (_p->_ordering) valore.format("%8ld%*s", re.ordinamento(), liv, ""); else valore.spaces(liv); } } else valore = "@B"; // Radice in grassetto valore << re.articolo(); } else if (code == "_DES") { switch (tipo) { case 'L': { const TLavorazione lav(re.articolo()); valore = lav.descr(); } break; case 'V': valore = cache().get(LF_DIST, re.articolo(), "DESCR"); break; default: valore = cache().get(LF_ANAMAG, re.articolo(), ANAMAG_DESCR); break; } if (livelli_giacenza().enabled()) { TString lv = re.giacenza(); for (int l = livelli_giacenza().last_level(); l > 0 ; l--) lv.insert(" ",livelli_giacenza().packed_length(l)); if (lv.full()) valore.insert(lv); } } else if (code == "_LIV") { if (_p->_separate_dist && re.livello() > 0) valore << re.livello(); } else if (code == "_DCO") { //if (re.articolo() == _d->cod()) valore = re.datacons(); } else if (code == "_UM") { valore = re.um(); } else if (code == "_FAB") { valore = re.fabbisogno().string(); } else if (code == "_DIS") { valore = re.disponibilita().string(); } else if (code == "_ORDPROD") { valore = re.qta2order().string(); } else if (code == "_RESIDUO") { valore = re.residuo().string(); } else if (code == "_VALORE") { valore = re.value().string(); } else if (code == "_VALOREUNIT") { valore = re.unitary_value().string(); } else if (code == "_ORDFOR") { valore = re.ordfor().string(); } else if (code == "_TOTORDFOR") { valore = re.totordfor().string(); } else if (code == "_CODFORN") { valore = cache().get(LF_ANAMAG, re.articolo(), ANAMAG_CODFORN); } else if (code == "_CODCORR") { const char tipo = t.get()[0]; valore = re.codici_corrispontenti(tipo); } } f.set(valore); return true; } real TExplode_distinta_form::res2produce_by_father(const TRiga_esplosione& re) const { real r; if (!_p->_fabbisogno) // Se non e' abilitata il calcolo del fabbisogno/disponibilita r = _d->qta(); // ritorna la qta della distinta come residuo da produrre else { // Se sta esaminando la riga della "radice"ritorna la qta richiesta, altrimenti : // per esplosione ai mat.base, ritorna il residuo da produrre per la distinta "radice"; // per l'esplosione e' scalare ritorna il residuo del padre di questo nodo. if (re.livello() == 0) r = _d->qta(); else { TToken_string pstr; if (_p->_explosion == mat_base) re.path().get(0, pstr); else { TString16 fi; if (_p->_vis_art) fi << 'A'; if (_p->_vis_lav) fi << 'L'; if (_p->_vis_vir) fi << 'V'; if (_p->_vis_gho) fi << 'G'; pstr = re.father(fi); } TString8 codmag = _distinta.path_depth(pstr) < 1 ? (TString &)_d->mag() : (TString &)_p->_sl_mag; if (codmag.blank()) codmag = _d->mag(); TString g; TCodice_articolo a; _distinta.path_code(a, pstr); _distinta.path_giaclev(g, 0, pstr); TString80 key; key.format("%-20s|%-15s|%-5s", (const char*)a, (const char*)g, (const char*)codmag); real * rs = (real*)_prodorder.objptr(key); r = rs != NULL ? *rs : ZERO; // Se er padre non ha residui... smette de fatica' } } return r; } void TExplode_distinta_form::set_explosion_rows(const TArray& exp_array) { TString noexplode_path("*****"); const bool dettagliata = _p->_advanced_val; const int rows = exp_array.items(); for (int i = 0; i < rows; i++) { const TRiga_esplosione& re = (const TRiga_esplosione&) exp_array[i]; const char tipo = re.tipo(); const bool is_head = i == DIST_HEAD; // Se si tratta dell'articolo distinta da esplodere, calcola la disponibilita' // prendendo il magazzino indicato sulla riga stessa // Se invece e' un componente, prende cio' che e' stato indicato dall'utente per quanto // riguarda se e' materiale di base o semilavorato // Il livello di giacenza lo si prende dall'articolo distinta da esplodere // oppure dalla riga esplosione se non stiamo stampando la testata della distinta // il cod. esercizio e' calc. come sempre TString8 codmag = is_head ? _d->mag() : re.mat_base() ? (const TString&)_p->_mb_mag : (const TString&)_p->_sl_mag; if (codmag.blank()) codmag = _d->mag(); const TString& liv = is_head ? _d->liv() : re.giacenza(); // Il fabbisogno e': nr. componenti di questo articolo per residuo da produrre del padre if (dettagliata && re.path().starts_with(noexplode_path)) continue; if (re.articolo() == "00.73.00.0010") int cazzone = 1; real r = res2produce_by_father(re); if (_p->_fabbisogno && _p->_explosion == scalare) r *= re.last_qta(); // In UM locale... else r *= re.val(); // In UM locale... if (dettagliata && tipo == 'A') { TArticolo_giacenza& art = TExplode_distinta_form::cache_articoli().art(re.articolo()); const valtype art_tipo = (valtype)art.get_int(ANAMAG_VALDIST); if (art_tipo > no_val) { const TDate inizio_val = art.get_date(ANAMAG_DATAVDIST); if (_p->_obs_date >= inizio_val) noexplode_path = re.path(); } } if (r.is_zero()) { if (_p->_fabbisogno) // Calcolo disponibilita' { // Compone la chiave da cercare nella cache: CODART|CODMAG|LIVELLO // ovvio che tutti i campi debbono essre paddati alla loro massima lunghezza // Al TArticolo_cache importa solo del CODART in ricerca... i campi seguenti vengono ignorati // anche se nel TAssoc_array interno vengono cmq memorizzati come chiave __key.format("%-20s|%-15s|%-5s", (const char*)re.articolo(), (const char*) liv, (const char*) codmag); _prodorder.add(__key, ZERO, TRUE); } continue; // Don't store in _exploded_tree if there's no need } TRiga_esplosione2print* r2p = NULL; int pos = -1; if (!_p->_separate_dist) { for (pos = _exploded_tree.items()-1; pos>=0; pos--) { r2p = (TRiga_esplosione2print *)_exploded_tree.objptr(pos); if (re.articolo() == r2p->articolo() && re.um() == r2p->um() && (re.giacenza() == r2p->giacenza()) && codmag == r2p->mag()) break; } } if (pos <0) { r2p = new TRiga_esplosione2print(re, codmag); _exploded_tree.add(r2p,pos); } r2p->set_fabbisogno(r + r2p->fabbisogno()); if (_p->_fabbisogno) // Calcolo disponibilita' { // Compone la chiave da cercare nella cache: CODART|CODMAG|LIVELLO // ovvio che tutti i campi debbono essre paddati alla loro massima lunghezza // Al TArticolo_cache importa solo del CODART in ricerca... i campi seguenti vengono ignorati // anche se nel TAssoc_array interno vengono cmq memorizzati come chiave __key.format("%-20s|%-15s|%-5s", (const char*)re.articolo(), (const char*) liv, (const char*) codmag); TArticolo_giacenza_static& aaa = _art_cache.art(__key); // Si ricorda che la disponibilita' e' calcolata in UM base!! // Quindi e' opportuno effettuare la conversione nell'unita' di misura // del presente articolo.... const bool is_new = _prodordert.objptr(__key)==NULL; real sottostock = is_new ? ZERO : (real &)_prodordert[__key] ; if (tipo != 'A') { // Distinte Virtuali e Lavorazioni non hanno disponibilita', quindi sono sempre da produrre r2p->set_disponibilita(ZERO); r2p->set_residuo(ZERO); if (tipo == 'V') { TQuantita q (r2p->articolo(), r2p->um(), r); q.convert2umbase(); _prodorder.add(__key, q.val(), TRUE); // Memorizza nei residui... q += sottostock; _prodordert.add(__key, q.val(), TRUE); // Memorizza nei residui... } } else { // Disponibilita, qta da ordinare e residuo vengono calcolati solo per le righe Articolo const real min_ref = _p->_liv_attenzione == 'S' ? aaa.get_scmin(_p->_anno_es, codmag, liv) : ZERO; const real zero_ref = aaa.convert_to_um(min_ref, re.um()); real qta2order,disponib; if (is_new) { if (re.livello()==0 && _p->_no_fabbis_fin) disponib = ZERO; else disponib = aaa.static_disp(_p, codmag, liv); } else disponib = (real &)_disponib[__key]; if (is_new || _p->_separate_dist) r2p->set_disponibilita(disponib); disponib -= sottostock; // Converte in UM della riga attuale disponib = aaa.convert_to_um(disponib, re.um()); if (_d->acqven()) disponib += r; else disponib -= r; if (disponib > zero_ref && r > ZERO) // Aggiunto r>0 il 28-09-2012 per GF { disponib -= zero_ref; qta2order = ZERO; } else { qta2order = zero_ref - disponib; disponib = ZERO; } r2p->set_residuo(disponib); r2p->set_qta2order(qta2order); // Ri-Converte in UM base per aggiornare gli Assocarray disponib = aaa.convert_to_um(disponib, ""); qta2order = aaa.convert_to_um(qta2order, ""); _disponib.add (__key, disponib, TRUE); _prodorder.add(__key, real(qta2order - sottostock), TRUE); _prodordert.add(__key, qta2order, TRUE); if (_p->_det_ord_for) { real of; of = aaa.ordinato_fornitori(app().date2period(_d->data_per())); of = aaa.convert_to_um(of, re.um()); r2p->set_ordfor(of); // Ordinato fornitori per questo periodo espresso in UM esplicitata dalla riga esplosione of = aaa.ordinato_fornitori(0); of = aaa.convert_to_um(of, re.um()); r2p->set_totordfor(of); // Ordinato fornitori totale espresso in UM esplicitata dalla riga esplosione } } } // Il valore lo calcola per qualsiasi tipo riga if (_p->_valorization > no_val) { const TString k = re.path(); // I nodi sono cachati con tutto il path in modo da essere univoci if (_valori.objptr(k) == NULL) r2p->set_unitary_value(ZERO); else r2p->set_unitary_value(*((real*)_valori.objptr(k))); if (_p->_fabbisogno) r = r2p->unitary_value() * r2p->qta2order(); else r = r2p->unitary_value() * r2p->fabbisogno(); r2p->set_value(r); } if (is_head) r2p->set_datacons(_d->datacons()); } } void TExplode_distinta_form::reset_rows(bool firsttime) { _exploded_tree.destroy(); _valori.destroy(); _prodorder.destroy(); if (firsttime) { _prodordert.destroy(); _disponib.destroy(); } } void TExplode_distinta_form::explode_and_print() { // Explode & deflagrate... _distinta.clear_globals(); _distinta.set_global("_IMPIANTO", _d->imp()); _distinta.set_global("_LINEA", _d->lin()); _distinta.set_global( "_MAGDEP", _d->mag()); if (!_distinta.set_root(_d->cod(), _d->um(), 1.0, _d->liv())) return; TWait_cursor clepsy; // Inizializza lo sfondo delle pagine normali se no col piffero che stampa la fincatura... set_background(3, TRUE); _distinta.restart(); if (_distinta.goto_root()) { // Reset delle righe in caso di dist separate o cambio periodo if (_p->_separate_dist || (_p->_separate_giac && _d->cod() != __current_art) || (__current_period.ok() && _d->data_per() > __current_period)) print_explosion_rows(); __current_art = _d->cod(); __current_period = _d->data_per(); TString16 fi; if (_p->_vis_art) fi << 'A'; if (_p->_vis_lav) fi << 'L'; if (_p->_vis_vir) fi << 'V'; if (_p->_vis_gho) fi << 'G'; TArray explosion_array; _distinta.curr_code((TCodice_articolo& )_d->cod()); _distinta.explode(explosion_array, _p->_explosion == mat_base, _p->_group_by, _p->_det_lev, fi, _p->_ordering); // Dopo l'esplosione mette in testa all'array la riga di definizione della Distinta stessa: // codice + UM + Fabbisogno (sostanzialmente si tratta di un TRiga_esplosione) explosion_array.insert(_d->head_obj(), 0); // Effettua la valorizzazione scorrendo i nodi... if (_p->_valorization > no_val) { _CallBackStruct setter; // // Dog programming on... setter._p = _p; // setter._a = &_valori; // _distinta.set_root(_d->cod(), "", 1.0, _d->liv()); valorizza_nodo(_distinta, setter); } // Ora scorre l'array locale delle righe esplosione, settando quello // vero (_exploded_tree) con le TRiga_esplosione2print necessarie // ed i valori corretti (fabbisogno, disponibilita, residuo, da ordinare e valore) set_explosion_rows(explosion_array); } else error_box(TR("Impossibile posizionare l'albero")); } // Ordina le righe di esplosione per livello/articolo/giacenza int compare_print_rows(const TObject** o1, const TObject** o2) { TRiga_esplosione2print & r1 =(TRiga_esplosione2print &)(**o1); TRiga_esplosione2print & r2 =(TRiga_esplosione2print &)(**o2); const int l1 = r1.livello(); const int l2 = r2.livello(); int diff = 0; if (l1 == 0 || l2 == 0) diff = l1 - l2; if (diff == 0) diff = r1.articolo().compare(r2.articolo()); if (diff == 0) diff = r1.giacenza().compare(r2.giacenza()); return diff ; } // Ordina le righe di esplosione per fornitore/articolo/giacenza int compare_print_rows_forn(const TObject** o1, const TObject** o2) { TRiga_esplosione2print & r1 =(TRiga_esplosione2print &)(**o1); TRiga_esplosione2print & r2 =(TRiga_esplosione2print &)(**o2); const int l1 = r1.livello(); const int l2 = r2.livello(); int diff = 0; if (l1 == 0 || l2 == 0) diff = l1-l2; if (diff == 0) { TArticolo_cache& ac = TExplode_distinta_form::cache_articoli(); long f1 = atol(ac.get(r1.articolo()).get(ANAMAG_CODFORN)); long f2 = atol(ac.get(r2.articolo()).get(ANAMAG_CODFORN)); diff = f1 < f2 ? -1 : (f1 == f2 ? 0 : +1); } if (diff == 0) diff = r1.articolo().compare(r2.articolo()); if (diff == 0) diff = r1.giacenza().compare(r2.giacenza()); return diff ; } void TExplode_distinta_form::print_explosion_rows() { const int righe = _exploded_tree.items(); if (righe <= 0) return; if (!_p->_separate_dist) { if (_p->_sort_for) _exploded_tree.sort(compare_print_rows_forn); else _exploded_tree.sort(compare_print_rows); } // Inizializza lo sfondo delle pagine normali se no col piffero che stampa la fincatura... set_background(3, TRUE); TArray explosion_array; TPrintrow p; TString16 fi; TPrint_section& body = section('B'); TPrinter& pr = printer(); // Setta pure la data sul form item di testa... // Se e' cambiato il periodo effettua un form feed di separazione TPrint_section& head = section('H'); head.find_field(4).set(_d->data_per()); // Ad ogni cambio periodo effettua un formfeed... // Be careful: evitare di stampare doppio form feed di separazione in caso // di Separa distinte e cambio periodo contemporaneamente if (!_p->_newpage && __last_period.ok() && __last_period < __current_period) pr.formfeed(); __last_period = __current_period; set_last_page(FALSE); // This is GoodStuff... browse all rows & print'em for (_curr_row=0; _curr_row_fabbisogno && _p->_no_zero_ord) { const real fabb = body.find_field(8).get(); if (fabb.is_zero()) continue; } const word h = body.height(); if (pr.rows_left() <= (h+1)) pr.formfeed(); for (word j = 0; j < h; j++) { TPrintrow& r = body.row(j); const TFixed_string t(r.row()); if (!t.blank()) pr.print(r); } } set_last_page(TRUE); // form feed su opzione parametro... if (_p->_newpage) pr.formfeed(); else // Altrimenti aggiunge una riga mezza ciucciata... pr.print(p); // Reset delle righe in caso di dist separate o cambio periodo reset_rows(FALSE); return ; } /////////////////////////////////////////////////////////// // TDist2Explode /////////////////////////////////////////////////////////// // // Implementation of base object used in skantacazz 2 be stored in a TAssoc_array so we can order it // TRiga_esplosione * TDist2Explode::head_obj() { TDistinta_tree tree; TQuantita qta(_cod, _um, real(1.00)); tree.set_root(qta, liv()); TRiga_esplosione * re = new TRiga_esplosione(tree); return re; } void TDist2Explode::set(const TMask& msk) { if (_imp.blank()) _imp = msk.get(F_IMPIANTO); if (_lin.blank()) _lin = msk.get(F_LINEA); } void TDist2Explode::set(const TRiga_documento& r, const TMask& msk) { _cod = r.get(RDOC_CODART); _livgiac = r.get(RDOC_LIVELLO); _um = r.get(RDOC_UMQTA); _mag = r.get(RDOC_CODMAG); _imp = r.get(RDOC_IMPIANTO); _lin = r.get(RDOC_LINEA); _qta = r.get_real("QTARES"); // Virtual field... must exist!! _datacons = r.get_date(RDOC_DATACONS); if (!_datacons.ok()) _datacons = r.doc().get_date(DOC_DATACONS); _acq_ven = r.doc().get(DOC_TIPOCF) == "F" ? TRUE : FALSE; _data_per = app().date_period(_datacons); set(msk); } void TDist2Explode::set(TToken_string& t, const TMask& msk) { _cod = t.get(0); _livgiac = t.get(1); _livgiac << t.get(2); _livgiac << t.get(3); _livgiac << t.get(4); _livgiac.trim(); _imp = t.get(5); _lin = t.get(6); _mag.format("%3s", (const char*)t.get(7)); _mag << t.get(8); _mag.trim(); _um = t.get(9); _qta = t.get(10); _datacons = t.get(12); _acq_ven = t.get_char(13) == 'X' ? TRUE : FALSE; _data_per = app().date_period(_datacons); set(msk); } const char* TDist2Explode::key() { __key.format("%3d%-20s%-15s%-2s%-5s%-5s%-5s", app().date2period(_datacons), (const char*)_cod, (const char*) _livgiac, (const char*)_um, (const char*)_mag, (const char*)_imp, (const char*)_lin); return (const char*)__key; } /////////////////////////////////////////////////////////////////// // Implementazione metodi di TEsplosione_distinta_app /////////////////////////////////////////////////////////////////// bool TEsplosione_distinta_app::sheet_notify(TSheet_field& s, int r, KEY key) { if (key==(K_CTRL+K_INS)) { const TDate d(TODAY); TToken_string& t = s.row(r); t.add(d.string(),s.cid2index(F_DATACONS)); } return TRUE; } const int TEsplosione_distinta_app::date2period(const TDate& d) { const int items = _date_array.items(); int i; for (i = 0; isfield(F_SHEETART); sa.sheet_mask().set_handler(F_QTA, check_articoli); sa.set_notify(sheet_notify); _mask->set(F_ARTICOLI, "X"); _mask->set(F_LAVORAZIONI, "X"); _mask->set(F_VIRTUALI, "X"); if (!livelli_giacenza().enabled()) //TBI _mask->hide(F_SEPARATE_GIAC); rec_cache(LF_TAB).test_file_changes(FALSE); const int lf[] = { LF_UMART, LF_ANAMAG, LF_DIST, LF_RDIST, 0 }; for (int i = 0; lf[i]; i++) { int maxsize = 4096; if (lf[i] == LF_RDIST) maxsize *= 4; rec_cache(lf[i]).set_items_limit(maxsize); rec_cache(lf[i]).test_file_changes(FALSE); } _form = new TExplode_distinta_form("db1100a"); TForm_item& fi_cod = _form->find_field('B', odd_page, 1); _default_code_width = fi_cod.width(); _liv_giac = new TCodgiac_livelli; _liv_giac->set_sheetcolumn(sa, F_LIV1, 1); _liv_giac->set_sheetcolumn(sa, F_LIV2, 2); _liv_giac->set_sheetcolumn(sa, F_LIV3, 3); _liv_giac->set_sheetcolumn(sa, F_LIV4, 4); TConfig conf(CONFIG_DITTA, "mg"); const bool depositi = conf.get_bool("GESDEPOSITI"); sa.enable_column(F_DEP-F_CODDIS,depositi); _mask->show(-G_DEPOSITI, depositi); const bool listini = conf.get_bool("GES", "ve", 1); _mask->enable(-G_LISTINO, listini); _mask->enable(F_CATVEN_LIST, listini && conf.get_bool("GESLISCV", "ve")); _mask->set(F_IMPIANTO, conf.get("DEFAULT_CODIMP", "mr")); _mask->set(F_LINEA, conf.get("DEFAULT_CODLIN", "mr")); _doc = new TDocumento; //Compila la lista di codici numerazione validi per la ricerca dell'ordinato fornitori compile_numeration_list(); return TSkeleton_application::create(); } bool TEsplosione_distinta_app::destroy() { delete _liv_giac; delete _form; delete _mask; delete _doc; return TSkeleton_application::destroy(); } void TEsplosione_distinta_app::compile_periods() { TDate oggi(TODAY),dday; _date_array.destroy(); const long ndays = _parameters._obs_date - oggi; const long daysperiod = ndays / _parameters._periods; dday = oggi; for (int i = 0; i < _parameters._periods; i++) { dday += daysperiod; if (i == _parameters._periods -1) dday = _parameters._obs_date; _date_array.add(dday); } } void TEsplosione_distinta_app::compile_list() { _dist_list.destroy(); TDocumento& doc = *_doc; TString key; TRectype from(LF_DOC); from.put(DOC_ANNO, _parameters._year); from.put(DOC_PROVV, "D"); from.put(DOC_CODNUM, _parameters._from_num); from.put(DOC_DATADOC, _parameters._from_date); from.put(DOC_NDOC, _parameters._from_doc); TRectype to(from); to.put(DOC_CODNUM, _parameters._to_num); to.put(DOC_DATADOC, _parameters._to_date); to.put(DOC_NDOC, _parameters._to_doc); TString filter_expr; if (_parameters._selections == by_date && _parameters._from_num.not_empty() && _parameters._to_num.not_empty()) filter_expr.format("(%s>=\"%s\")&&(%s<=\"%s\")", DOC_CODNUM, (const char*) _parameters._from_num, DOC_CODNUM, (const char*) _parameters._to_num); // Filtra i documenti TLocalisamfile dist(LF_DIST); TRelation r(LF_DOC); TCursor c(&r, filter_expr, _parameters._selections == by_num ? 1 : 3); c.setregion(from,to); const bool null_sel = _parameters._from_num.empty() || _parameters._to_num.empty(); const long items = null_sel ? 0L : c.items(); if (items > 0) { TProgind p(items,TR("Estrazione distinte da esplodere da documenti...")); c.freeze(); for (c = 0L; c.pos() < items; ++c) { if (!p.addstatus(1)) break; if (doc.read(c.curr()) == NOERR) { const int rows = doc.rows(); for (int i = 1; i <= rows; i++) { dist.put("CODDIST", doc[i].get(RDOC_CODART)); if (doc[i].is_articolo() && dist.read() == NOERR) // Aggiunge le righe che sono solo effettivamente articoli di magazzino e distinte { TDist2Explode * de = new TDist2Explode; de->set(doc[i], *_mask); key = de->key(); const bool is_key = _dist_list.is_key(key); if (is_key) { TDist2Explode * dd = (TDist2Explode*)_dist_list.objptr(key); // Check whether we've 2 convert in base UM... if (de->acqven()) // Se acquisto sottrae... de->qta() = dd->qta() - de->qta(); else de->qta() += dd->qta(); // altrimenti aggiunge } _dist_list.add(key, de, TRUE); if (de->qta() == ZERO) _dist_list.remove(key); } } } } } if (_mask->get(F_DADIST).full() || _mask->get(F_ADIST).full()) { TISAM_recordset dist("USE DIST\nFROM CODDIST=#DADIST\nTO CODDIST=#ADIST"); dist.set_var("#DADIST", _mask->get(F_DADIST)); dist.set_var("#ADIST", _mask->get(F_ADIST)); TProgind p(dist.items(), TR("Estrazione distinte...")); TToken_string row; for (bool ok = dist.move_first(); ok; ok = dist.move_next()) { if (!p.addstatus(1)) break; row = dist.get(DIST_CODDIST).as_string(); row.add(dist.get(DIST_UM).as_string(), 9); row.add(1); row.add(TDate(TODAY)); TDist2Explode* de = new TDist2Explode; de->set(row, *_mask); key = de->key(); const bool is_key = _dist_list.is_key(key); if (is_key) { TDist2Explode * dd = (TDist2Explode*)_dist_list.objptr(key); // Check 2 see whether we've 2 convert in base UM... if (de->acqven()) // Se acquisto sottrae... de->qta() = dd->qta() - de->qta(); else de->qta() += dd->qta(); // altrimenti aggiunge } _dist_list.add(key, de, TRUE); } } // Aggiunge le righe dallo spreadsheet TSheet_field& sa = _mask->sfield(F_SHEETART); const int righe = sa.items(); if (righe > 0) { TProgind p(righe,TR("Estrazione distinte da esplodere...")); for (int i = 0; i < righe; i++) { if (!p.addstatus(1L)) break; if (!sa.row(i).empty_items()) { TDist2Explode * de = new TDist2Explode; de->set(sa.row(i), *_mask); key = de->key(); const bool is_key = _dist_list.is_key(key); if (is_key) { TDist2Explode * dd = (TDist2Explode*)_dist_list.objptr(key); // Check 2 see whether we've 2 convert in base UM... if (de->acqven()) // Se acquisto sottrae... de->qta() = dd->qta() - de->qta(); else de->qta() += dd->qta(); // altrimenti aggiunge } _dist_list.add(key, de, TRUE); } } } } void TEsplosione_distinta_app::compile_numeration_list() { // Reperisce prima la lista dei tipi documento che siano Ordini fornitore TProgind p(0,TR("Creazione lista numerazioni in corso..."), FALSE, FALSE); TString_array a; TRelation reltip("%TIP"); const TRectype & tip = reltip.curr(); TCursor curtip(&reltip); const TRecnotype items = curtip.items(); for (curtip = 0L; curtip.pos() < items; ++curtip) { TTipo_documento tp(tip); if (tp.is_ordine() && tp.tipocf() == 'F') // Ordine a fornitore a.add(tp.codice()); } // Poi si interseca questa lista con quella delle numerazioni TRelation relnum("%NUM"); TRectype & num = relnum.curr(); TCursor curnum(&relnum); const TRecnotype itemsnum = curnum.items(); TToken_string t; TString s; int r=0; for (curnum = 0L; curnum.pos() = 0; i--) { // Se il tipo documento esiste in questa numerazione... TToken_string& ai = (TToken_string &) a[i]; if (t.find(ai.get(0)) >= 0) // Aggiunge questo tipo documento alla lista per la numerazione corrente riga.add(ai.get(0)); } } } void TEsplosione_distinta_app::print() { TString chiave; TString_array chiavi; _dist_list.get_keys(chiavi); chiavi.sort(); // sort by : period+codart+livgiac+... const int items = chiavi.items(); if (items == 0) return; // Settaggio parametri del form (fincature) TPrinter& pr = printer(); pr.open(); const int hh = 7; const int fl = pr.formlen(); int rows[4]; // Righe orizzontali rows[0] = hh-3; rows[1] = hh; rows[2] = fl-1; rows[3] = 0; // Calcola la larghezza della colonna codice TForm_item& fi_cod = _form->find_field('B', odd_page, 1); int c_width = _default_code_width; if (_parameters._separate_dist) { c_width += 10; if (_parameters._ordering) c_width += 9; } fi_cod.width() = c_width; // Mostra la colonna Livello se necessario TForm_item& fi_liv = _form->find_field('B', odd_page, 4); fi_liv.show(_parameters._separate_dist); // Setta l'intestazione corretta per la colonna del valore distinta TForm_item& fi_val = _form->find_field('B', odd_page, 10); fi_val.set_col_head(_parameters._fabbisogno ? FR("@cValore da ord./prod.") : FR("@cValore")); _form->set_parameters(&_parameters); _form->genera_intestazioni(odd_page, hh-2); _form->genera_fincatura(odd_page, hh-3, fl-1, rows); _form->reset_cache(); // Resetta ad ogni stampa // Ciclo per distinta: tutte quelle dei documenti indicati // E tutte quelle indicate singolarmente nello spreadsheet dell'articolo // Stampa esplosione distinta, nell'ordine specificato: periodo+codice+livello+um+mag __current_period = __last_period = 0L; _form->reset_rows(); for (int i = 0 ; iset_distinta((TDist2Explode*)_dist_list.objptr(chiave)); // Setta la distinta corrente _form->explode_and_print(); // Esplode & Stampa sta distinta #ifdef DBG unsigned long h, m; TFile_cache::stats(h, m); TString80 msg; msg.format("Hits %lu - Misses %lu", h, m); xvtil_statbar_set(msg); #endif } _form->print_explosion_rows(); // Formfeed finale solo in caso non sia stata indicata la // separazione delle esplosioni (altrimenti ne fa 2...) if (!_parameters._newpage) pr.formfeed(); pr.close(); } void TEsplosione_distinta_app::main_loop() { while (_mask->run()!=K_QUIT) { TDate df(1,1,1998); TDate dt(31,12,1998); // Raccolta dati dalla maschera _parameters._selections = (seltype) _mask->get_int(F_TIPOSEL); _parameters._explosion = (expltype) _mask->get_int(F_STAMPA); _parameters._valorization = (valtype) _mask->get_int(F_VALORIZZAZIONE); _parameters._advanced_val = _mask->get_bool(F_ADVANCED_EXPL); _parameters._group_by = (TExplosion_grouping) _mask->get_int(F_GROUPMODE); _parameters._year = _mask->get_int(F_ANNO); _parameters._from_num = _mask->get(F_NUMFROM); _parameters._to_num = _mask->get(F_NUMTO); // Setta le date di default (dal primo all'ultimo dell'anno) df.set_year(_parameters._year); dt.set_year(_parameters._year); _parameters._from_date = _mask->get_date(F_EMISFROM); if (_parameters._from_date.empty()) _parameters._from_date = df; _parameters._to_date = _mask->get_date(F_EMISTO); if (_parameters._to_date.empty()) _parameters._to_date = dt; _parameters._from_doc = _mask->get_long(F_NDOCFROM); _parameters._to_doc = _mask->get_long(F_NDOCTO); _parameters._obs_date = _mask->get_date(F_DATAOBS); _parameters._periods = _mask->get_int(F_PERIODS); _parameters._det_lev = _mask->get_int(F_DETTAGLIO); _parameters._ordering = _mask->get_int(F_SORT); if (_mask->get_bool(F_NOIGNORE)) _parameters._ordering *= -1; _parameters._vis_art = _mask->get_bool(F_ARTICOLI); _parameters._vis_vir = _mask->get_bool(F_VIRTUALI); _parameters._vis_lav = _mask->get_bool(F_LAVORAZIONI); _parameters._vis_gho = _mask->get_bool(F_GHOST); _parameters._fabbisogno= _mask->get_bool(F_FABBISOGNO); _parameters._no_fabbis_fin= _mask->get_bool(F_FABBISOGNO_FIN); _parameters._no_zero_ord = _mask->get_bool(F_NOZEROORD); _parameters._sl_mag = _mask->get(F_SLMAG); _parameters._sl_mag << _mask->get(F_SLDEP); _parameters._mb_mag = _mask->get(F_MBMAG); _parameters._mb_mag << _mask->get(F_MBDEP); _parameters._val_magmb = _mask->get_bool(F_VALMAGMB); _parameters._val_depmb = _mask->get_bool(F_VALDEPMB); _parameters._liv_attenzione = _mask->get(F_LIVATTENZ)[0]; _parameters._newpage = _mask->get_bool(F_NEWPAGE); _parameters._det_ord_for = _mask->get_bool(F_DETORDFOR); _parameters._sort_for = _mask->get_bool(F_SORTFOR); _parameters._separate_dist = _mask->get_bool(F_SEPARATE_DIST); _parameters._separate_giac = _mask->get_bool(F_SEPARATE_GIAC); _parameters._add_orc = _mask->get_bool(F_ORCLI4DISP); _parameters._add_orf = _mask->get_bool(F_ORFOR4DISP); _parameters._add_prf = _mask->get_bool(F_INPRF4DISP); _parameters._add_prc = _mask->get_bool(F_INPRC4DISP); _parameters._add_incl = _mask->get_bool(F_INCLV4DISP); _parameters._add_acl = _mask->get_bool(F_ACLV4DISP); _parameters._normal_disp = _parameters._add_orc && _parameters._add_orf && _parameters._add_prf && _parameters._add_prc && _parameters._add_acl && _parameters._add_acl; // Credo che il seguente anno esercizio sia calcolato // in modo abbastanza schifoso, visto che si e' in possesso del solo anno solare // Da controllare in futuro ... TDate d(TODAY); d.set_year(_parameters._year); TEsercizi_contabili esc; _parameters._anno_es.format("%04d",esc.date2esc(d)); _parameters._catven=_mask->get(F_CATVEN_LIST); _parameters._codlist=_mask->get(F_CODLIST); // Compila la lista di testate termo-nucleare-globale // delle distinte da esplodere nell'universo conosciuto compile_periods(); compile_list(); // Stampa... print(); } } /////////////////////////////////////////////////////////// // db1100 stampa esplosione distinte /////////////////////////////////////////////////////////// int db1100(int argc, char* argv[]) { TEsplosione_distinta_app *a = new TEsplosione_distinta_app; a->run(argc, argv, TR("Stampa esplosione")); delete a; return 0; }