#include #include #include #include "lvlib.h" #include "lv3700a.h" /////////////////////////////// //// 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); TLocalisamfile fdoc(LF_DOC); int err = inv.read(fdoc, _isequal, _testandlock); if(err != NOERR) { warning_box(TR("L'inventario già in uso")); return false; } 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) { TString8 codcau = cache().get("%TIP", ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_INV", NULL), "S9"); inv.put(DOC_TIPODOC, get(F_TPDOC)); inv.put(DOC_DATADOC, get_date(F_DATAINV)); inv.put(DOC_CAUSMAG, codcau); 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 if(rp.is_associato()) { warning_box(TR("Il pacco pistolato è un pacco a cliente")); return; } TToken_string tmp = rp.rigabolla(); if(tmp.get_long(3) > 0) { warning_box(TR("Il pacco pistolato è già associato a un buono")); return; } if(tmp.get_long(3) < 0) { warning_box(TR("Il pacco pistolato non è disponibile per l'inventario")); return; } 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) { TDoc_key kinv(get_int(F_ANNO), ini_get_string(CONFIG_DITTA, "lv", "NUM_INV", NULL), get_long(F_NINV)); TDoc_inventario inv(kinv); TLocalisamfile fdoc(LF_DOC); inv.read(fdoc); 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; }