#include #include #include #include "lvlib.h" #include "lv3700a.h" /////////////////////////////////// //// TDOC_INVENTARIO_ROW //// /////////////////////////////////// //Classe TDoc_inventario_row class TDoc_inventario_row: public TObject { TRiga_documento& _rinv; public: const TString& codart() const; const TString& desart() const; const real qta() const; const TString& um() const; const int num_pacchi() const; const TToken_string& cod_pacchi() const; const TString& magazzino() const; const TString& magazzinoc() const; void set_codart(const char* codart); void set_desart(const TString& desart); void set_qta(const real qta); void set_um(const char* um); void set_num_pacchi(const int numpacchi); void set_cod_pacchi(const char* codpacchi); void set_magazzino(const char* mag); void set_magazzinoc(const char* magc); TDoc_inventario_row(TRiga_documento& rinv):_rinv(rinv){} }; //CODART: metodo che restituisce il codice articolo della riga documento const TString& TDoc_inventario_row::codart() const { return _rinv.get(RDOC_CODART); } //DESART: metodo che restiruisce la descrizione dell'articolo const TString& TDoc_inventario_row::desart() const { TString& str = get_tmp_string(); str = _rinv.get(RDOC_DESCR); if (_rinv.get_bool(RDOC_DESCLUNGA)) str << _rinv.get(RDOC_DESCEST); return str; } //QTA: metodo che restiruisce la quantità salvata sulla riga const real TDoc_inventario_row::qta() const { return _rinv.get_real(RDOC_QTA); } //UM: metodo che restiruisce l'unità di misura utilizzata sulla riga documento const TString& TDoc_inventario_row::um() const { return _rinv.get(RDOC_UMQTA); } //NUM_PACCHI: metodo che resituisce il numero dei pacchi presenti per quell'articolo const int TDoc_inventario_row::num_pacchi() const { return _rinv.get_int(RDOC_NCOLLI); } //COD_PACCHI: metodo che restiuisce l'elenco dei pacchi salvati su quella riga const TToken_string& TDoc_inventario_row::cod_pacchi() const { TToken_string& tmp = get_tmp_string(); tmp = _rinv.get("CODPACCHI"); return tmp; } //MAGAZZINO: metodo che restituisce il codice del magazzino/deposito const TString& TDoc_inventario_row::magazzino() const { return _rinv.get(RDOC_CODMAG); } //MAGAZZINOC: metodo che restituisce il codice del magazzino/deposito collegato const TString& TDoc_inventario_row::magazzinoc() const { return _rinv.get(RDOC_CODMAGC); } //SET_CODART: metodo che setta il codice articolo void TDoc_inventario_row::set_codart(const char* codart) { _rinv.put(RDOC_CODART, codart); _rinv.put(RDOC_CODARTMAG, codart); } //SET_DESART: metodo che setta la descrizione void TDoc_inventario_row::set_desart(const TString& desart) { if (desart.len() > 50) { _rinv.put(RDOC_DESCR, desart.left(50)); _rinv.put(RDOC_DESCLUNGA, true); _rinv.put(RDOC_DESCEST, desart.mid(50)); } else _rinv.put(RDOC_DESCR, desart); } //SET_QTA_RITIRATA: metodo che setta la quantità ritirata sulla riga void TDoc_inventario_row::set_qta(const real qta) { _rinv.put(RDOC_QTA, qta); } //SET_UM: metodo che setta l'unità di misura void TDoc_inventario_row::set_um(const char* um) { _rinv.put(RDOC_UMQTA, um); } //SET_NUM_PACCHI: metodo che setta il numero dei pacchi void TDoc_inventario_row::set_num_pacchi(const int numpacchi) { _rinv.put(RDOC_NCOLLI, numpacchi); } //SET_COD_PACCHI: metodo che setta l'elenco dei pacchi salvati su quella riga void TDoc_inventario_row::set_cod_pacchi(const char* codpacchi) { _rinv.put("CODPACCHI", codpacchi); } //SET_MAGAZZINO: metodo che setta il codice del magazzino/deposito void TDoc_inventario_row::set_magazzino(const char* mag) { _rinv.put(RDOC_CODMAG, mag); } //SET_MAGAZZINOC: metodo che setta il codice del magazzino/deposito collegato void TDoc_inventario_row::set_magazzinoc(const char* magc) { _rinv.put(RDOC_CODMAGC, magc); } /////////////////////////////// //// TDOC_INVENTARIO //// /////////////////////////////// //Classe TDoc_inventario class TDoc_inventario: public TDocumento { public: const TToken_string& chiave() const; const TDate datadoc() const; TDoc_inventario_row find_or_create_row(const char* codart); void set_difinv(const bool difinv = true); TDoc_inventario& operator= (const TDoc_inventario dinv){dinv;} TDoc_inventario(TDoc_key& key): TDocumento(key.provv(), key.anno(), key.codnum(), key.ndoc()){}; TDoc_inventario(TDoc_inventario& dinv): TDocumento(dinv){}; }; //CHIAVE: metodo che restituisce la chiave del documento const TToken_string& TDoc_inventario::chiave() const { TToken_string& k = get_tmp_string(); k.add(get(DOC_PROVV)); k.add(get(DOC_ANNO)); k.add(get(DOC_CODNUM)); k.add(get(DOC_NDOC)); return k; } //DATADOC: metodo che restiruisce la data documento const TDate TDoc_inventario::datadoc() const { return get_date(DOC_DATADOC); } //FIND_OR_CREATE_ROW: metodo che cerca una riga con un certo codart e se non esiste la crea TDoc_inventario_row TDoc_inventario::find_or_create_row(const char* codart) { //scorro tutte le righe documento; se ne trovo una con quel codart //allora la restituisco for(int i = 1; i <= rows(); i++) { TRiga_documento& row = (*(TDocumento*)this)[i]; const TString& cod = row.get(RDOC_CODART); if(cod == codart) { TDoc_inventario_row rinv(row); return rinv; } } //se sono arrivato qui non ho trovato neanche una riga con quel codart; //in queto caso ne aggiungo una TRiga_documento& row = (*(TDocumento*)this).new_row("21"); TDoc_inventario_row rinv(row); return rinv; } void TDoc_inventario::set_difinv(const bool difinv) { put("DIFINV", difinv); } /////////////////////////////// //// TPACCHI_CONTATI //// /////////////////////////////// //Classe TPacchi_contati class TPacchi_contati: public TObject { real _qta; TString4 _um; int _npacchi; TToken_string _codpacchi; public: const real qta() const; const TString& um() const; const int npacchi() const; const TToken_string& codpacchi() const; void set_qta(const real& qta); void set_um(const char* um); void set_npacchi(const int npacchi = 1); void set_codpacchi(const TToken_string& codpacchi); void add_qta(const real& qta); void add_pacchi(const int pacchi = 1); void add_codpacco(const TString& codpacco); void sub_codpacco(const TString& codpacco); TPacchi_contati(const real& qta = ZERO, const char* um = "", const int npacchi = 0, const char* codpacco = ""); }; //QTA: metodo che restituisce la quantita const real TPacchi_contati::qta() const { return _qta; } //UM: metodo che restituisce l'unità di misura const TString& TPacchi_contati::um() const { return _um; } //NPACCHI: metodo che restituisce il numero dei pacchi pistolati const int TPacchi_contati::npacchi() const { return _npacchi; } //CODPACCHI: metodo che restituisce i codici dei pacchi pistolati const TToken_string& TPacchi_contati::codpacchi() const { return _codpacchi; } //SET_QTA: metodo che setta la quantità void TPacchi_contati::set_qta(const real& qta) { _qta = qta; } //SET_UM: metodo che setta l'unità di misura void TPacchi_contati::set_um(const char* um) { _um = um; } //SET_NPACCHI: metodo che setta il numero di pacchi void TPacchi_contati::set_npacchi(const int npacchi) { _npacchi = npacchi; } //SET_CODPACCHI: metodo che setta i codici dei pacchi void TPacchi_contati::set_codpacchi(const TToken_string& codpacchi) { TToken_string tmp(codpacchi, '-'); _codpacchi = tmp; } //ADD_QTA_CON: metodo che aggiunge un quantitativo di roba alla quantità consegnata void TPacchi_contati::add_qta(const real& qta) { _qta += qta; } //ADD_PACCHI: metodo che aggiunge un certo numero di pacchi a quelli consegnati (default = 1) void TPacchi_contati::add_pacchi(const int pacchi) { _npacchi += pacchi; } //ADD_CODPACCO: metodo che aggiunge un codice di un pacco alla TToken_string che li contiene void TPacchi_contati::add_codpacco(const TString& codpacco) { _codpacchi.add(codpacco); } //SUB_CODPACCO: metodo che toglie un codice di un pacco alla TToken_string che li contiene void TPacchi_contati::sub_codpacco(const TString& codpacco) { int pos = _codpacchi.get_pos(codpacco); _codpacchi.destroy(pos); } //metodo costruttore TPacchi_contati::TPacchi_contati(const real& qta, const char* um, const int npacchi, const char* codpacco) { set_qta(qta); set_um(um); set_npacchi(npacchi); TToken_string tmp(codpacco, '-'); set_codpacchi(tmp); } //////////////////////////////// //// TRIGHE_INV_ARRAY //// //////////////////////////////// //Classe TRighe_inv_array class TRighe_inv_array: public TAssoc_array { public: TPacchi_contati* quantita(TString& codart, bool create); }; //QUANTITA: metodo che cerca nel TAssoc_array le quantità della riga interessata in base ai parametri passati //e lo crea in automatico se il parametro create vale "true" TPacchi_contati* TRighe_inv_array::quantita(TString& codart, bool create) { TPacchi_contati* pc = (TPacchi_contati*)objptr(codart); if(pc == NULL && create) { pc = new TPacchi_contati(); add(codart, pc); } return pc; } /////////////////////////////////// //// TINVENTARIO_TER_MSK //// /////////////////////////////////// //Classe TInventario_ter_msk class TInventario_ter_msk: public TAutomask { TRighe_inv_array _ria; bool _nuovo; int _autoselect; protected: bool precarica_righe(); void registra(); void aggiorna_campi(const char* codart, const TPacchi_contati& pc, const real& qtapacco); void inventario_da_terminale(); virtual void on_idle(); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TInventario_ter_msk(); }; //PRECARICA_RIGHE: metodo che carica in un TAssoc_array le righe fisiche del documento bool TInventario_ter_msk::precarica_righe() { //instanzio il documento inventario TDoc_key kinv(get_int(F_ANNO), ini_get_string(CONFIG_DITTA, "lv", "NUM_INV", NULL), get_long(F_NINV)); TDoc_inventario inv(kinv); if (inv.empty()) { warning_box(TR("L'inventario cercato è inesistente")); return false; } //controllo lo stato del documento const TString4 stato = cache().get("%TIP", ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_INV", NULL), "S2").mid(2,1); if (inv.get(DOC_STATO) == stato) { TString str; str << "L'inventario " << get_long(F_NINV) << " è già stato stampato e non può essere aggiornato"; warning_box(str); reset(F_CHIAVE); return false; } TDate oggi(TODAY); //metto ogni riga del documento nel TAssoc_array che contiene gli oggetti TPacchi_contati //e che ha per chiave il codice articolo FOR_EACH_PHYSICAL_RDOC(inv, i, row) { TDoc_inventario_row rinv(*row); TString80 codart = rinv.codart(); if (codart.blank()) continue; TPacchi_contati* pc = _ria.quantita(codart, true); pc->set_qta(rinv.qta()); pc->set_um(rinv.um()); pc->set_npacchi(rinv.num_pacchi()); pc->set_codpacchi(rinv.cod_pacchi()); } return true; } //REGISTRA: metodo che salva il buono di prelievo così com'è void TInventario_ter_msk::registra() { //se sto salvando un documento nuovo, allora lo genero, //altrimenti aggiorno quello esiete già TDoc_key kinv(get_date(F_DATAINV).year(), get(F_CODNUM), get_long(F_NINV)); if (_nuovo) kinv.set_ndoc(0); //instanzio il documento e salvo i dati di interesse sulle testate //se necessario TDoc_inventario inv(kinv); if(_nuovo) { inv.put(DOC_TIPODOC, get(F_TPDOC)); inv.put(DOC_DATADOC, get_date(F_DATAINV)); inv.set_difinv(); } //per ogni oggetto dell'array cerco o creo una riga merce del documento FOR_EACH_ASSOC_OBJECT(_ria, obj, key, itm) { const TPacchi_contati& pc = *(TPacchi_contati*)itm; const TString80 codart(key); const TString& desart = cache().get(LF_ANAMAG, codart, "DESCR"); TString8 magazzino; magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGP"); TDoc_inventario_row& rinv = inv.find_or_create_row(codart); rinv.set_codart(codart); rinv.set_desart(desart); rinv.set_qta(pc.qta()); rinv.set_um(pc.um()); rinv.set_num_pacchi(pc.npacchi()); rinv.set_cod_pacchi(pc.codpacchi()); rinv.set_magazzino(magazzino); //DA CONTROLLARE rinv.set_magazzinoc(magazzino); //DA CONTROLLARE } inv.write(); if(_nuovo) { //aggiorno il numero documento con quello sicuramente corretto TToken_string tmp = inv.chiave(); TDoc_key chiave(tmp); set(F_NINV, chiave.ndoc()); _nuovo = false; } } //AGGIORNA_CAMPI: metodo che aggiorna i campi della maschera void TInventario_ter_msk::aggiorna_campi(const char* codart, const TPacchi_contati& pc, const real& qtapacco) { set(F_CODART, codart); set(F_PACCHI, pc.npacchi()); set(F_QTACON, pc.qta()); set(F_QTAPACCO, qtapacco); } //INVENTARIO_DA_TERMINALE: metodo che somma alla riga corretta un pacco (quello pistolato) e lo assegna a un cliente, //sottraendolo dal magazzino del pulito void TInventario_ter_msk::inventario_da_terminale() { //leggo il codice del pacco pistolato const TString80 codpacco = get(F_BARCODE); if (codpacco.full()) { //se posso instanzio la riga pacco TRiga_pacco rp(codpacco); if (rp.empty()) { warning_box(TR("Il pacco non esiste a magazzino")); warning_box(TR("Non è stato possibile sommare il pacco a nessuna riga del buono")); } else { //leggo i dati di interesse dal pacco TString80 codart = rp.articolo(); const real qtapacco = rp.quantita(); //se è la prima volta, creo il nuovo TPacchi_contati, //altrimenti aggiorno quello che già esiste if(!_ria.is_key(codart)) { TPacchi_contati& pc = *(_ria.quantita(codart, true)); pc.set_qta(qtapacco); //recupero l'unità di misura principale di quest'articolo TToken_string key; key.add(codart); key.add(1); const TString4 um = cache().get(LF_UMART, key, UMART_UM); pc.set_um(um); pc.set_npacchi(); key.cut(0); key.add(codpacco); pc.set_codpacchi(key); aggiorna_campi(codart, pc, qtapacco); } else { TPacchi_contati& pc = *(TPacchi_contati*)_ria.objptr(codart); TToken_string codpacchi(pc.codpacchi()); int pos = codpacchi.get_pos(codpacco); if(pos >= 0) { if(yesno_box(TR("Il pacco risulta già nell'inventario; si desidera annullarlo?"))) { pc.add_qta(-qtapacco); pc.add_pacchi(-1); pc.sub_codpacco(codpacco); } else return; } pc.add_qta(qtapacco); pc.add_pacchi(); pc.add_codpacco(codpacco); aggiorna_campi(codart, pc, qtapacco); } } } } //ON_FIELD_EVENT: metodo che gestisce gli eventi sui campi della maschera bool TInventario_ter_msk::on_field_event(TOperable_field& f, TField_event e, long jolly) { //a seconda del bottone premuto esegui un metodo diverso switch (f.dlg()) { case DLG_NEWREC: //se viene premuto nuovo, cerco il prossimo numero di inventario //e mostro/nascondo i campi corretti if (e == fe_button) { _nuovo = true; int ninv = 0; TString query; query << "USE DOC\n" << "FROM PROVV=\"D\" ANNO=" << get_int(F_ANNO) << " CODNUM=\"" << get(F_CODNUM) << "\"\n" << "TO PROVV=\"D\" ANNO=" << get_int(F_ANNO) << " CODNUM=\"" << get(F_CODNUM) << "\""; TISAM_recordset inventari(query); if (inventari.move_last()) ninv = inventari.get(DOC_NDOC).as_int(); ninv++; set(F_NINV, ninv); disable(F_NINV); show(F_BARCODE); show(F_CODART); show(F_PACCHI); show(F_QTAPACCO); show(F_QTACON); hide(F_CHIAVE); hide(F_ANNO); hide(F_DATAINV); enable(DLG_SAVEREC); enable(DLG_DELREC); enable(DLG_CANCEL); field(F_BARCODE).set_focus(); _autoselect = 1; return false; } break; case DLG_SAVEREC: //se viene premuto salva, registro l'inventario if (e == fe_button) { registra(); return false; } break; case DLG_DELREC: //se viene premutop cancella, elimino l'inventario corrente, poi mostro/nascondo i campi corretti if (e == fe_button && yesno_box(TR("Si vuole veramente cancellare l'inventario corrente?"))) { //se non è nuovo, lo rimuovo anche dagli archivi if (!_nuovo) { TLocalisamfile doc(LF_DOC); TDoc_key kinv(get_int(F_ANNO), get(F_CODNUM), get_long(F_NINV)); TDoc_inventario inv(kinv); inv.destroy_rows(); inv.remove(doc); } _ria.destroy(); reset(F_BARCODE); hide(F_BARCODE); reset(F_CODART); hide(F_CODART); reset(F_PACCHI); hide(F_PACCHI); reset(F_QTAPACCO); hide(F_QTAPACCO); reset(F_QTACON); hide(F_QTACON); enable(F_NINV); reset(F_NINV); show(F_CHIAVE); reset(F_CHIAVE); show(F_ANNO); show(F_DATAINV); reset(F_DATAINV); disable(DLG_SAVEREC); disable(DLG_DELREC); disable(DLG_CANCEL); } break; case DLG_CANCEL: //se viene premuto annulla, lascio perdere quello che stavo facendo //e torno alla situazione iniziale if (e == fe_button) { reset(F_BARCODE); hide(F_BARCODE); reset(F_CODART); hide(F_CODART); reset(F_PACCHI); hide(F_PACCHI); reset(F_QTAPACCO); hide(F_QTAPACCO); reset(F_QTACON); hide(F_QTACON); enable(F_NINV); reset(F_NINV); show(F_CHIAVE); reset(F_CHIAVE); show(F_ANNO); show(F_DATAINV); reset(F_DATAINV); disable(DLG_SAVEREC); disable(DLG_DELREC); disable(DLG_CANCEL); _ria.destroy(); return false; } break; case F_CHIAVE: { //se viene riempito il campo chiave, cerca di caricare un documento if (e == fe_modify) { TString kinv = f.get(); if (kinv.full()) { set(F_ANNO, atol(kinv.left(4))); set(F_NINV, atol(kinv.mid(4))); field(F_NINV).check(); if(!precarica_righe()) return false; hide(F_ANNO); hide(F_DATAINV); show(F_BARCODE); show(F_CODART); show(F_PACCHI); show(F_QTAPACCO); show(F_QTACON); enable(DLG_SAVEREC); enable(DLG_DELREC); enable(DLG_CANCEL); disable(F_NINV); _autoselect = 1; field(F_BARCODE).set_focus(); f.hide(); } } } break; case F_NINV: { //se viene riempito il campo NINV, cerca di caricare un documento if (e == fe_modify && f.get_long() != 0 && get(F_CHIAVE).empty()) { field(F_NINV).check(); _nuovo = false; if(!precarica_righe()) return false; hide(F_ANNO); hide(F_DATAINV); show(F_BARCODE); show(F_CODART); show(F_PACCHI); show(F_QTAPACCO); show(F_QTACON); enable(DLG_SAVEREC); enable(DLG_DELREC); enable(DLG_CANCEL); f.disable(); _autoselect = 1; field(F_BARCODE).set_focus(); } } break; case F_BARCODE: { //se viene riempito il campo barcode, lanco la procedura dell'inventario if (e == fe_modify && f.get().full()) { _autoselect = 1; inventario_da_terminale(); } } break; default:break; } return true; } void TInventario_ter_msk:: on_idle() { TMask::on_idle(); if (_autoselect >= 0 && get(F_BARCODE).full()) { reset(F_BARCODE); field(F_BARCODE).set_focus(); _autoselect = -1; } } TInventario_ter_msk::TInventario_ter_msk():TAutomask("lv3700a") { //precarico i campi fissi set(F_CODNUM, ini_get_string(CONFIG_DITTA, "lv", "NUM_INV", NULL)); set(F_TPDOC, ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_INV", NULL)); const TRectype& tpdoc = cache().get("%NUM", ini_get_string(CONFIG_DITTA, "lv", "NUM_INV", NULL)); set(F_DESCR, tpdoc.get("S0")); TDate data(TODAY); TEsercizi_contabili es; int annoes = es.date2esc(data); set(F_ANNO, annoes); hide(F_CODCF); hide(F_RAGSOC); hide(F_BARCODE); hide(F_CODART); hide(F_PACCHI); hide(F_QTAPACCO); hide(F_QTACON); disable(DLG_SAVEREC); disable(DLG_DELREC); disable(DLG_CANCEL); } /////////////////////////////////// //// TINVENTARIO_TER_APP //// /////////////////////////////////// //classe TInventario_ter_app class TInventario_ter_app : public TSkeleton_application { TInventario_ter_msk* _msk; protected: virtual bool create(); virtual bool destroy(); public: bool transfer(); virtual void main_loop(); }; //CREATE: metodo costruttore bool TInventario_ter_app::create() { _msk = new TInventario_ter_msk(); open_files(LF_DOC, LF_RIGHEDOC); return TSkeleton_application::create(); } //DESTROY: metodo distruttore bool TInventario_ter_app::destroy() { delete _msk; return TApplication::destroy(); } //TRANSFER: metodo che scorre i campi nome e, se sono pieni, richiama il metodo //ELABORA_FILE(), che effettivamente fa l'elaborazione bool TInventario_ter_app::transfer() { return true; } void TInventario_ter_app::main_loop() { while (_msk->run() == K_ENTER) transfer(); } int lv3700(int argc, char *argv[]) { TInventario_ter_app a; a.run (argc, argv, "Evasione Buoni di Prelievo"); return TRUE; }