#include #include #include #include #include #include #include "lvlib.h" #include "../mg/clifogiac.h" #include "../ve/velib.h" #include "clifo.h" #include "cfven.h" #include "lvcondv.h" #include "lvrcondv.h" #include "lvrconsplan.h" #include "lv2600a.h" ///////////////////////////// //// TARTICOLI_KEY //// ///////////////////////////// //classe TArticoli_key class TArticoli_key: public TToken_string { public: const long codcf(); const char* codart(); const TDate data(); TArticoli_key& operator=(const char* key) { set(key); return *this; } TArticoli_key(long codcf, const TString& codart, const TDate& data); TArticoli_key(const TArticoli_key& key) : TToken_string(key) {} TArticoli_key(const char* key) : TToken_string(key) {} }; //CODCF: metodo che restituisce il codcf dalla TToken_string chiave degli articoli const long TArticoli_key::codcf() { return get_int(0); } //CODART: metodo che restituisce il codart dalla TToken_string chiave degli articoli const char* TArticoli_key::codart() { return get(1); } //DATA: metodo che restituisce la data dalla TToken_string chiave degli articoli const TDate TArticoli_key::data() { return (TDate)get(2); } //metodi costruttori TArticoli_key::TArticoli_key(long codcf, const TString& codart, const TDate& data) { add(codcf); add(codart); add(data.date2ansi()); strip(" "); } ////////////////////////////// //// TDOCUMENTI_KEY //// ////////////////////////////// //classe TDocumenti_key class TDocumenti_key : public TToken_string { public: const char* codnum(); const int anno(); const long ndoc(); const int idriga(); const long codcf(); const char* codart(); const TDate data(); TDocumenti_key(int anno, long ndoc, int idriga, long codcf, const TString& codart, const TDate& data); TDocumenti_key(const char* key); }; //CODNUM: metodo che restituisce il codnum dalla TToken_string chiave dei documenti const char* TDocumenti_key::codnum() { return get(0); } //ANNO: metodo che restituisce l'anno dalla TToken_string chiave dei documenti const int TDocumenti_key::anno() { return get_int(1); } //NDOC: metodo che restituisce il numero documento dalla TToken_string chiave dei documenti const long TDocumenti_key::ndoc() { return get_long(2); } //IDRIGA: metodo che restituisce l'idriga dalla TToken_string chiave dei documenti const int TDocumenti_key::idriga() { return get_int(3); } //CODCF: metodo che restituisce il codcf dalla TToken_string chiave dei documenti const long TDocumenti_key::codcf() { return get_int(4); } //CODART: metodo che restituisce il codart dalla TToken_string chiave dei documenti const char* TDocumenti_key::codart() { return get(5); } //DATA: metodo che restituisce la data dalla TToken_string chiave dei documenti const TDate TDocumenti_key::data() { return (TDate)get(6); } //metodi costruttori TDocumenti_key::TDocumenti_key(int anno, long ndoc, int idriga, long codcf, const TString& codart, const TDate& data) { add(ini_get_string(CONFIG_DITTA, "lv", "NUM_RIT(0)")); add(anno); add(ndoc); add(idriga); add(codcf); add(codart); add(data.date2ansi()); strip(" "); } TDocumenti_key::TDocumenti_key(const char* key):TToken_string(key) { } ////////////////////////////////// //// TQUANTITA_CONATATE //// ////////////////////////////////// //classe TQuantita_contate class TQuantita_contate: public TObject { real _numpezzi; real _numrotti; public: const real get_pezzi() const; const real get_rotti() const; void set_pezzi(const real qta); void set_rotti(const real qta); void add_pezzi(const real qta); void add_rotti(const real qta); bool is_empty(); TQuantita_contate(real pezzi = ZERO, real = ZERO); }; //GET_PEZZI: metodo che restituisce il numero di pezzi contati const real TQuantita_contate::get_pezzi() const { return _numpezzi; } //GET_ROTTI: metodo che restituisce il numero di pezzi rotti contati const real TQuantita_contate::get_rotti() const { return _numrotti; } //SET_PEZZI: metodo che setta il numero di pezzi contati void TQuantita_contate::set_pezzi(const real qta) { _numpezzi = qta; } //SET_ROTTI: metodo che setta il numero di pezzi rotti contati void TQuantita_contate::set_rotti(const real qta) { _numrotti = qta; } //ADD_PEZZI: metodo che somma i pezzi contati alla quantià che già esisteva void TQuantita_contate::add_pezzi(const real qta) { _numpezzi += qta; } //ADD_PEZZI: metodo che somma i pezzi rotti contati alla quantià che già esisteva void TQuantita_contate::add_rotti(const real qta) { _numrotti += qta; } //IS_EMPTY: metodo che resituisce true se entrambe le quantità sono a zero bool TQuantita_contate::is_empty() { return _numpezzi == 0 && _numrotti == 0; } //metodo costruttore TQuantita_contate::TQuantita_contate(real pezzi, real rotti) { set_pezzi(pezzi); set_rotti(rotti); } ///////////////////////////////// //// TARTICOLI_CONTATI //// ///////////////////////////////// //classe TArticoli_contati class TArticoli_contati: public TAssoc_array { public: TQuantita_contate* quantita(long codcf, const TString& codart, const TDate& data, bool create = false); }; //QUANTITA: metodo che cerca nel TAssoc_array le quantità contate in base ai parametri passati //e lo crea in automatico se il parametro create vale "true" TQuantita_contate* TArticoli_contati::quantita(long codcf, const TString& codart, const TDate& data, bool create) { TArticoli_key key(codcf, codart, data); TQuantita_contate* qc = (TQuantita_contate*)objptr(key); if(qc == NULL && create) { qc = new TQuantita_contate(); add(key, qc); } return qc; } ///////////////////////////////// //// TACQUISIZIONE_MSK //// ///////////////////////////////// //classe TAcquisizione_msk class TAcquisizione_msk: public TAutomask { protected: virtual bool on_field_event(TOperable_field& o,TField_event e,long jolly); public: TAcquisizione_msk(); }; //ON_FIELD_EVENT: metodo che gestisce gli eventi sui campi della maschera bool TAcquisizione_msk::on_field_event(TOperable_field& f,TField_event e,long jolly) { return true; } //metodo costruttore che precarica i campi di interesse sulla maschera TAcquisizione_msk::TAcquisizione_msk():TAutomask("lv2600a") { TConfig configlv(CONFIG_DITTA, "lv"); const TString& path = configlv.get("PathContapezzi"); set(F_PATH, path); TSheet_field& sheet = sfield(F_SHEET_NAME); for (int i = 0; ; i++) { const TString& nomefile = configlv.get("FileName", NULL, i); if (nomefile.blank()) break; TToken_string& row = sheet.row(-1); row = nomefile; } sheet.force_update(); } /////////////////////////////////// //// TACQUISIZIONE_CACHE //// /////////////////////////////////// //classe TAcquisizione_cache class TAcquisizione_cache : public TCache { TString4 _codnum, _tipodoc, _stato; long _ndoc; protected: virtual void discarding(const THash_object* obj); virtual TObject* key2obj(const char* key); public: TDocumento& doc(const TDate& gg, const long cc); TAcquisizione_cache(); }; //DISCARDING: metodo che salva un documento sul disco prima di eliminarlo dalla cache void TAcquisizione_cache::discarding(const THash_object* obj) { TDocumento& doc = (TDocumento&)obj->obj(); doc.sort_rows(RDOC_CODART); int err = doc.rewrite(); if (err != NOERR) error_box(FR("Errore %d di scrittura del documento"), err); } //KEY2OBJ: metodo che sceglie il documento giusto da disco in modo da poterlo continuare, o lo crea se non c'è TObject* TAcquisizione_cache::key2obj(const char* key) { TToken_string chiave(key); const TDate datadoc = chiave.get(0); const long codcf = chiave.get_long(); const TDate datagen(TODAY); TDate dadata = datadoc; TDate adata = datagen; adata.addmonth(1); if(_ndoc == 0) { TString query2; query2 << "USE DOC\n" << "FROM PROVV=\"D\" ANNO=" << datadoc.year() << " CODNUM=\"" << _codnum << "\"\n" << "TO PROVV=\"D\" ANNO=" << datadoc.year() << " CODNUM=\"" << _codnum << "\""; TISAM_recordset sporco(query2); if (sporco.move_last()) _ndoc = sporco.get(DOC_NDOC).as_int(); } TString query = "USE DOC KEY 2\n"; query << "SELECT (TIPODOC=\"" << _tipodoc << "\")&&(STATO=\"" << _stato <<"\")\n"; query << "FROM TIPOCF=C CODCF=" << codcf << " PROVV=D ANNO=" << datadoc.year() << " DATADOC=" << datadoc << " CODNUM=" << _codnum << "\n"; query << "TO TIPOCF=C CODCF=" << codcf << " PROVV=D ANNO=" << datadoc.year() << " DATADOC=" << datadoc << " CODNUM=" << _codnum << "\n"; TISAM_recordset rset(query); TDocumento* doc = NULL; if (rset.move_first()) doc = new TDocumento(rset.cursor()->curr()); else { TToken_string key; key.add('C'); key.add(codcf); const int codindsp = atoi(cache().get(LF_CFVEN, key, CFV_CODINDSP)); TLaundry_contract cont(codcf, codindsp, datadoc); const TString8 codcont = cont.get(LVCONDV_CODCONT); TString query1 = "USE LVRCONSPLAN KEY 3\n"; query1 << "FROM CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=#DADATA\n"; query1 << "TO CODCF=" << codcf << " CODCONT=" << codcont << " DTCONS=#ADATA\n"; TISAM_recordset consegne(query1); consegne.set_var("#DADATA", ++dadata); consegne.set_var("#ADATA", adata); consegne.move_first(); const TDate dataprco = consegne.get(LVRCONSPLAN_DTCONS).as_date(); const int coditi = consegne.get(LVRCONSPLAN_CODITI).as_int(); TString8 codaut = consegne.get(LVRCONSPLAN_CODAUT).as_string().right(5); codaut.trim(); //recupero i dati di interesse dal cliente const TRectype& clifo = cache().get(LF_CLIFO, key); const TString4 codpag = clifo.get(CLI_CODPAG); const long codabi = clifo.get_long(CLI_CODABI); const long codcab = clifo.get_long(CLI_CODCAB); const TString80 iban = clifo.get(CLI_IBAN); //reupero la cuasale di magazzino di testata const TString16 causmag = cache().get("%TIP", _tipodoc, "S9"); //recupero i dati di interesse dal file CFVEN const TRectype& cfven = cache().get(LF_CFVEN, key); const long codabipr = cfven.get_long(CFV_CODABIPR); const long codcabpr = cfven.get_long(CFV_CODCABPR); const bool ragdoc = cfven.get_bool(CFV_RAGGDOC); const TString8 codag1 = cfven.get(CFV_CODAG1); const TString4 codmez = cfven.get(CFV_CODSPMEZZO); const TString4 codporto = cfven.get(CFV_CODPORTO); const TString4 codnote1 = cfven.get(CFV_CODNOTESP1); const TString4 codnote2 = cfven.get(CFV_CODNOTESP2); const TString4 codnote = cfven.get(CFV_CODNOTE); const TString8 codvet1 = cfven.get(CFV_CODVETT1); const TString8 codvet2 = cfven.get(CFV_CODVETT2); const TString8 codvet3 = cfven.get(CFV_CODVETT3); const real speseinc = cfven.get_real(CFV_PERCSPINC); const TString4 catven = cfven.get(CFV_CATVEN); const bool addbolli = cfven.get_bool(CFV_ADDBOLLI); const TString8 codlist = cfven.get(CFV_CODLIST); const TString4 codzona = cfven.get(CFV_CODZONA); if(codaut.empty()) codaut = cfven.get(CFV_CODAG); //gestione sconto TString sconto; const char tpgest = ini_get_string(CONFIG_DITTA, "ve", "GESSCO")[0]; switch(tpgest) { case 'P': sconto = cfven.get(CFV_SCONTO); break; //Percentuale su anagrafica cliente case 'T': sconto = cache().get("%SCC", cfven.get(CFV_CODSCC), "S1"); break; //Gestione tabella sconti case 'A': //Gestione archivio sconti { TConfig ditta(CONFIG_DITTA, "ve"); TLocalisamfile sconti(LF_SCONTI); sconti.put("TIPO", "I"); if(ditta.get_bool("SCOKEY", "ve", 1)) sconti.put("CODCAT", cfven.get(CFV_CATVEN)); TString16 cod; if(ditta.get_bool("SCOKEY", "ve", 2)) cod.format("%-2s", (const char*)cfven.get(CFV_CODSCC)); else cod = " "; if(ditta.get_bool("SCOKEY", "ve", 3)) { TString8 tmp; tmp.format("%-2s", (const char*)cfven.get(CFV_CODZONA)); cod << tmp; } else cod << " "; if(ditta.get_bool("SCOKEY", "ve", 4)) cod << clifo.get(CLI_CODPAG); sconti.put("CODART", cod); if (sconti.read() == NOERR) sconto = sconti.get("SCONTO"); } case 'N': //sconto non gestito default: break; } if (cont.get(LVCONDV_CODNUM).empty()) { doc = new TDocumento('D', datadoc.year(), _codnum, ++_ndoc); doc->put(DOC_TIPODOC, _tipodoc); } else { doc = new TDocumento('D', datadoc.year(), cont.get(LVCONDV_CODNUM), ++_ndoc); doc->put(DOC_TIPODOC, cont.get(LVCONDV_TPDOC)); } doc->put(DOC_STATO, _stato); doc->put(DOC_DATADOC, datadoc); doc->put(DOC_TIPOCF, 'C'); doc->put(DOC_CODCF, codcf); doc->put(DOC_CODCONT, codcont); if(codindsp > 0) doc->put(DOC_CODINDSP, codindsp); doc->put(DOC_CODPAG, codpag); doc->put(DOC_CAUSMAG, causmag); doc->put(DOC_CODABIA, codabi); doc->put(DOC_CODCABA, codcab); doc->put(DOC_IBAN, iban); doc->put(DOC_CODABIP, codabipr); doc->put(DOC_CODCABP, codcabpr); doc->put(DOC_CODAG, codaut); doc->put(DOC_CODAGVIS, codag1); doc->put(DOC_CODSPMEZZO, codmez); doc->put(DOC_ZONA, codzona); doc->put(DOC_CODPORTO, codporto); doc->put(DOC_CODNOTESP1, codnote1); doc->put(DOC_CODNOTESP2, codnote2); doc->put(DOC_CODNOTE, codnote); doc->put(DOC_CODVETT1, codvet1); doc->put(DOC_CODVETT2, codvet2); doc->put(DOC_CODVETT3, codvet3); doc->put(DOC_CATVEN, catven); doc->put(DOC_CODLIST, codlist); doc->put(DOC_CAUSMAG, causmag); doc->put(DOC_PERCSPINC, speseinc); doc->put(DOC_ADDBOLLI, addbolli); doc->put(DOC_SCONTOPERC, sconto); doc->put("DATACON", datadoc); //data conteggio doc->put("DATAGEN", datagen); //data generazione del documento doc->put("DATAPRCO", dataprco); //data prevista consegna doc->put("CODITI", coditi); //codice itinerario } return doc; } //DOC: metodo che restituisce un puntatore ad un documento identificato dalla coppia data - cliente TDocumento& TAcquisizione_cache::doc(const TDate& gg, const long cc) { TString16 key; key << gg.date2ansi() << '|' << cc; return *(TDocumento*)objptr(key); } //metodo costruttore di una cache di 17 elementi TAcquisizione_cache::TAcquisizione_cache() : TCache(17) { _codnum = ini_get_string(CONFIG_DITTA, "lv", "NUM_RIT(0)"); _tipodoc = ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_RIT(0)"); _stato = cache().get("%TIP", _tipodoc, "S2").left(1); _ndoc = 0; } /////////////////////////////////// //// TCONFRONTO_CACHE //// /////////////////////////////////// //classe TConfronto_cache class TConfronto_cache : public TCache { TString4 _codnum, _tipodoc, _stato; protected: virtual void discarding(const THash_object* obj); virtual TObject* key2obj(const char* key); public: TDocumento& doc(const TDate& gg, const long cc); TConfronto_cache(); }; //DISCARDING: metodo che salva un documento sul disco prima di eliminarlo dalla cache void TConfronto_cache::discarding(const THash_object* obj) { TDocumento& doc = (TDocumento&)obj->obj(); if (!doc.empty()) int err = doc.rewrite(); } //KEY2OBJ: metodo che sceglie il documento giusto da disco in modo da poterlo continuare, o lo crea se non c'è TObject* TConfronto_cache::key2obj(const char* key) { TToken_string chiave(key); TDate datadoc = chiave.get(); const TDate datagen(TODAY); TDate adata = datagen; adata.addmonth(); const long codcf = chiave.get_long(); TString query = "USE DOC KEY 2\n"; query << "SELECT (TIPODOC=\"" << _tipodoc << "\")&&(STATO=\"" << _stato <<"\")\n"; query << "FROM TIPOCF=C CODCF=" << codcf << " PROVV=D ANNO=" << datadoc.year() << " DATADOC=" << datadoc << " CODNUM=" << _codnum << "\n"; query << "TO TIPOCF=C CODCF=" << codcf << " PROVV=D ANNO=" << datadoc.year() << " DATADOC=" << datadoc << " CODNUM=" << _codnum << "\n"; TISAM_recordset rset(query); TDocumento* doc = NULL; if (rset.move_first()) doc = new TDocumento(rset.cursor()->curr()); else doc = new TDocumento(); return doc; } //DOC: metodo che restituisce un puntatore ad un documento identificato dalla coppia data - cliente TDocumento& TConfronto_cache::doc(const TDate& gg, const long cc) { TString16 key; key << gg.date2ansi() << '|' << cc; return *(TDocumento*)objptr(key); } //metodo costruttore di una cache di 17 elementi TConfronto_cache::TConfronto_cache() : TCache(17) { _codnum = ini_get_string(CONFIG_DITTA, "lv", "NUM_RIT(0)"); _tipodoc = ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_RIT(0)"); _stato = cache().get("%TIP", _tipodoc, "S2").left(1); } //////////////////////////////////////////// //// TACQUISIZIONE_LAVANDERIE_APP //// //////////////////////////////////////////// //classe TAcquisizione_lavanderie_app class TAcquisizione_lavanderie_app : public TSkeleton_application { TAcquisizione_msk* _msk; TString4 _auto; TString4 _gr; protected: virtual bool create(); virtual bool destroy(); bool elabora_file(const TString& file, TLog_report &rep, TArticoli_contati& articoli, int& nrighe, int& nrsalt); void controlla_documenti(TLog_report& rep, TArticoli_contati& articoli, TAssoc_array& documenti); void genera_documenti(TLog_report& rep, TAssoc_array& documenti); void sposta_file(const TString& file); public: bool transfer(); virtual void main_loop(); }; //CREATE: metodo costruttore bool TAcquisizione_lavanderie_app::create() { _msk = new TAcquisizione_msk(); TSheet_field& sheet = _msk->sfield(F_SHEET_NAME); sheet.set_auto_append(); //se ho più di un parametro, allora lo sto lanciando da linea di comando, e ne devo tenere conto if (argc() > 2) { _auto = argv(2); _auto = _auto.right(1); _gr = argv(3); _gr = _gr.right(1); } else { _auto = "N"; _gr = ""; } if (_gr == "S" || _gr.empty()) _msk->set(F_RICGIRI, "X"); else _msk->reset(F_RICGIRI); open_files(LF_DOC, LF_RIGHEDOC, LF_CLIFO, LF_CFVEN, LF_SCONTI, LF_TAB, LF_TABCOM, LF_ANAMAG, LF_UMART, 0); return TSkeleton_application::create(); } //DESTROY: metodo distruttore bool TAcquisizione_lavanderie_app::destroy() { delete _msk; return TApplication::destroy(); } //ELABORA_FILE: metodo che effettivamente fa l'elaborazione del file bool TAcquisizione_lavanderie_app::elabora_file(const TString& file, TLog_report& rep, TArticoli_contati& articoli, int& nrighe, int& nrsalt) { //fisso l'anno esercizio TEsercizi_contabili& esc = esercizi(); const int last_esc = esc.last(); //scandisco il file solo se esiste TScanner s(file); while (s.ok()) { const TString& riga = s.line(); if (riga.blank()) continue; const int reclen = riga.len(); TDate datadoc; long codcf = 0; TCodice_articolo codart; long qta; long rotti; long ndoc = 0; TString16 tipo_conteggio; TString80 operatore; //controllo quale tracciato record devo seguire if (reclen == 34) // -> MONTANARI { nrighe++; //leggo i campi dalla riga del file const int d = atoi(riga.mid(0,2)); const int m = atoi(riga.mid(2,2)); const int y = atoi(riga.mid(4,4)); if (d > 0 && d <= 31 && m > 0 && m <= 12 && y > 2000) { datadoc = TDate(d, m, y); if (datadoc < _msk->get_date(F_DADATA) || datadoc > _msk->get_date(F_ADATA)) { nrsalt++; continue; } const TString& codcf_str = riga.mid(8,6); codcf = atol(codcf_str); codart = riga.mid(14,8); qta = atol(riga.mid(22,6)); rotti = atol(riga.mid(28,6)); } else continue; } else if (reclen == 81 || reclen == 121) // ->SKEMA { //leggo i campi dalla riga del file const int y = atoi(riga.mid(0,4)); const int m = atoi(riga.mid(4,2)); const int d = atoi(riga.mid(6,2)); if (d > 0 && d <= 31 && m > 0 && m <= 12 && y > 2000) { const TString& codcf_str = riga.mid(28,20); codcf = atol(codcf_str); datadoc = TDate(d, m, y); codart = riga.mid(8,20); qta = atoi(riga.mid(48,11)); ndoc = atoi(riga.mid(59,11)); switch (atoi(riga.mid(70,11))) { case 1: tipo_conteggio = "Automatico"; break; case 2: tipo_conteggio = "Manuale"; break; case 3: tipo_conteggio = "Scarto"; break; default: break; } operatore = riga.mid(81,40); } else continue; } TToken_string key; key.format("C|%ld", codcf); const int codindsp = atoi(cache().get(LF_CFVEN, key, CFV_CODINDSP)); TLaundry_contract cont(codcf, codindsp, datadoc); const TRectype& rcont = cont.row(codart.trim()); if (rcont.empty()) { TString str; str << "L'articolo " << codart << " non è previsto nel contratto del cliente " << codcf; warning_box(str); //ATTENZIONE: DEVE CHIEDERE CHE COSA FARE (Aggiungerlo o Ignorarlo) } TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcf, 0); //estraggo il record corrispondente su LF_CLIFOGIAC const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); //leggo il record corrispondente if(!reclav.empty()) { const real dotod = reclav.get_real(CLIFOGIAC_DOTOD); if (qta > dotod) { TString str; str << "Attenzione! Il cliente " << codcf << " per l'articolo " << codart << " ha una dotazione di " << dotod << " pezzi e ne sono stati ritirati " << qta << " (" << real(qta - dotod) << " in più)."; warning_box(str); } } TQuantita_contate* qc = articoli.quantita(codcf, codart.trim(), datadoc, true); //se la chiave è già presente nel TAssoc_array, chiedi cosa fare delle quantità //altrimenti aggiungila con la rispettiva al TAssoc_array con la quantità appena conteggiata if (!qc->is_empty()) { if(codcf == 1184) int cazzone = 1; TString str; str << "ATTENZIONE: è già presente un conteggio per il cliente " << codcf << " sull'articolo " << codart << "\n" << "Quantità conteggio attuale: " << qta << " Quantità conteggio precedente: " << qc->get_pezzi() << "\n" << "Si desidera sommare le quantità?\n" << "(SI -> Somma NO -> Ignora Conteggio ANNULLA -> Sosituisci il conteggio precedente)\n"; KEY k = yesnocancel_box(str); switch (k) { case K_YES: qc->add_pezzi(qta); qc->add_rotti(rotti); break; //sommo le quantità case K_NO: break; //lascio tutto com'è default: qc->set_pezzi(qta); qc->set_rotti(rotti); break; //sostituisco le quantità } } else { qc->set_pezzi(qta); qc->set_rotti(rotti); } } return true; } //CONTROLLA_DOCUMENTI: metodo che si occupa di controllare se i dati che sto inserendo in questo momento sono //già stati inseriti in documenti precedenti, chiedendo cosa fare di volta in volta void TAcquisizione_lavanderie_app::controlla_documenti(TLog_report& rep, TArticoli_contati& articoli, TAssoc_array& documenti) { TConfronto_cache ca; bool found = false; FOR_EACH_ASSOC_OBJECT(articoli, obj, key, itm) { const TQuantita_contate* qc = (TQuantita_contate*)itm; //recupero i dati dalla chiave del TAssoc_array degli articoli TArticoli_key keyart(key); const long codcf = keyart.codcf(); const TString80 codart = keyart.codart(); const TDate datadoc = keyart.data(); //recupero i dati dal contenuto del TAssoc_array degli articoli TQuantita_contate* quantita = new TQuantita_contate(qc->get_pezzi(), qc->get_rotti()); TDocumento& doc = ca.doc(datadoc, codcf); if (doc.empty()) { //preparo la chiave per il TAssoc_array dei documenti TDocumenti_key keydoc(datadoc.year(), 0, 0, codcf, codart, datadoc); //aggiungo la riga corrispondente documenti.add(keydoc, quantita); } else { int idriga = 0; FOR_EACH_PHYSICAL_RDOC(doc, r, prdoc) { //cerco se esiste già una riga sul documento selezionato per quell'articolo const TRiga_documento& rdoc = *prdoc; const TString& codart_doc = rdoc.get(RDOC_CODART); if (codart_doc == codart) { found = true; idriga = r; TString str; str << "ATTENZIONE: è già presente un buono di ritiro per il cliente " << codcf << " sull'articolo " << codart << "\n" << "Quantità conteggio: " << quantita->get_pezzi() << " Quantità buono di ritiro: " << rdoc.get_int(RDOC_QTAGG1) << "\n" << "Si desidera sommare le quantità?\n" << "(SI -> Somma NO -> Ignora Conteggio ANNULLA -> Modifica Buono)\n"; const KEY k = yesnocancel_box(str); switch (k) { case K_YES: quantita->add_pezzi(rdoc.get_real(RDOC_QTAGG1)); quantita->add_rotti(rdoc.get_real(RDOC_QTAGG2)); break; //sommo le quantità case K_NO: break; //lascio tutto com'è default: quantita->set_pezzi(rdoc.get_real(RDOC_QTAGG1)); quantita->set_rotti(rdoc.get_real(RDOC_QTAGG2)); break; //sostituisco le quantità } break; } } if (!found) idriga = 0; // Mi pare implicito!!! //preparo la chiave per il TAssoc_array dei documenti const TDocumenti_key keydoc(datadoc.year(), doc.get_long(DOC_NDOC), idriga, codcf, codart, datadoc); documenti.add(keydoc, quantita); found = false; } } ca.destroy(); } //metodo che effettivamente genera i buoni di ritiro, se l'utente ha confermato la sua intenzione a crearli void TAcquisizione_lavanderie_app::genera_documenti(TLog_report& rep, TAssoc_array& documenti) { TAcquisizione_cache ca; const bool giri = _msk->get_bool(F_RICGIRI); FOR_EACH_ASSOC_OBJECT(documenti, obj, key, itm) { TDocumenti_key keydoc(key); const TString4 codnum = keydoc.codnum(); const int anno = keydoc.anno(); const int ndoc = keydoc.ndoc(); int idriga = keydoc.idriga(); // May change const int codcf = keydoc.codcf(); const TString80 codart = keydoc.codart(); const TDate datadoc = keydoc.data(); TQuantita_contate* qc = (TQuantita_contate*)itm; const real qtacon = qc->get_pezzi(); const real qtarotti = qc->get_rotti(); TToken_string key; key.add('C'); key.add(codcf); const int codindsp = atoi(cache().get(LF_CFVEN, key, CFV_CODINDSP)); const TLaundry_contract cont(codcf, codindsp, datadoc); const TString8 codcont = cont.get(LVCONDV_CODCONT); const TRectype& rcont = cont.row(codart); TDocumento& doc = ca.doc(datadoc, codcf); if (!giri) { const TDate oggi(TODAY); doc.put("DATAPRCO", oggi); } const TDate dtcons = doc.get_date("DATAPRCO"); TString4 causale = rcont.get(LVRCONDV_CAUSLAV); if (causale.blank()) causale = ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV"); // idriga NON è affidabile, per cui ricerco per codart if (idriga > 0 && doc.body().exist(idriga) && doc[idriga].get(RDOC_CODARTMAG) != codart) { idriga = 0; // Invalidate by now FOR_EACH_PHYSICAL_RDOC(doc, r, row) { if (row->get(RDOC_CODARTMAG) == codart) { idriga = r; break; } } } if (idriga > 0 && doc.body().exist(idriga)) { TRiga_documento& rdoc = doc[idriga]; rdoc.put(RDOC_QTAGG1, qtacon); rdoc.put(RDOC_QTAGG2, qtarotti); } else { const TRectype& anamag = cache().get(LF_ANAMAG, codart); TString descrart; descrart << anamag.get(ANAMAG_DESCR) << anamag.get(ANAMAG_DESCRAGG); TRiga_documento& rdoc = doc.new_row("22"); rdoc.put(RDOC_CODART, codart); if (descrart.len() > 50) { rdoc.put(RDOC_DESCR, descrart.left(50)); rdoc.put(RDOC_DESCLUNGA, true); rdoc.put(RDOC_DESCEST, descrart.sub(50)); } else rdoc.put(RDOC_DESCR, descrart); rdoc.put(RDOC_CODARTMAG, codart); rdoc.put(RDOC_CHECKED, 'X'); rdoc.put(RDOC_CODAGG1, causale); rdoc.put(RDOC_QTAGG1, qtacon); rdoc.put(RDOC_QTAGG2, qtarotti); rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //scrivo il magazzino const TCausale_lavanderie cau(causale); TCausale_magazzino rit(cau.causale_ritiro()); TCausale_magazzino con(cau.causale_consegna()); TString8 magazzino, magazzinoc; if(rit.get("S10").full()) magazzino = rit.get("S10").mid(0,5); else magazzino << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGN"); if(con.get("S10").full()) magazzinoc = con.get("S10").mid(0,5); else magazzinoc << ini_get_string(CONFIG_DITTA, "lv", "CODMAG") << ini_get_string(CONFIG_DITTA, "lv", "CODMAGC"); rdoc.put(RDOC_CODMAG, magazzino); rdoc.put(RDOC_CODMAGC, magazzinoc); //scrivo l'unità di misura TToken_string key; key.add(codart); key.add(1); const TRectype& umart = cache().get(LF_UMART, key); rdoc.put(RDOC_UMQTA, umart.get(UMART_UM)); } if (giri && !doc.get_date("DATAPRCO").ok()) { TString msg; msg << TR("Il documento ") << doc.get(DOC_NDOC) << TR(" del ") << doc.get(DOC_DATADOC) << TR(" del cliente ") << codcf << TR(" non ha data di prevista consegna."); rep.log(1,msg); } } if (ca.empty()) warning_box(TR("ATTENZIONE: il file importato non ha generato nessun documento.\n" "controllare che il tracciato record sia coerente")); else ca.destroy(); } //SPOSTA_FILE: metodo che sposta cambiando nome i file elaborati durante la generazione dei buoni void TAcquisizione_lavanderie_app::sposta_file(const TString& file) { TFilename fileori = file; TFilename path = fileori.path(); path.add("elaborati"); make_dir(path); TString strname; strname.format("%06d_%06d_%s", TDate(TODAY).date2ansi(), daytime(), (const char*)fileori.name()); TFilename filedest = path; filedest.add(strname); //se la copia è andata a buon fine, creo un file .old vuoto e cancello il file .dat if (fcopy(fileori, filedest)) { TFilename fileold; fileold = fileori.path(); TString strn = fileori.name_only(); strn << ".old"; fileold.add(strn); fclose(fopen(fileold, "w")); fileori.fremove(); } } //TRANSFER: metodo che scorre i campi nome e, se sono pieni, richiama il metodo //ELABORA_FILE(), che effettivamente fa l'elaborazione bool TAcquisizione_lavanderie_app::transfer() { //prendo il path dalla maschera const TString& path = _msk->get(F_PATH); TSheet_field& sheet = _msk->sfield(F_SHEET_NAME); TFilename file; TLog_report logrep(TR("Acquisizione da contapezzi")); logrep.kill_duplicates(true); TArticoli_contati articoli; TAssoc_array documenti; int nrighe = 0; int nrsalt = 0; //per ogni riga dello sheet, leggo il suo contenuto, se contiene dei caratteri jolly //preparo la lista dei file che soddisfano la maschera in quella directory e li elaboro //tutti, altrimenti elaboro esattamente il file che è scritto sullo sheet bool elaborato = false; bool esiste = false; FOR_EACH_SHEET_ROW(sheet, r1, row1) if (!row1->empty_items()) { if (row1->find('/') >= 0 || row1->find('\\') >= 0) file = *row1; else { file = path; file.add(*row1); } if (file.find('*') >= 0 || file.find('?') >= 0) { TString_array lista_file; list_files(file, lista_file); FOR_EACH_ARRAY_ROW(lista_file, r2, row2) { const TFilename strname = *row2; if (strname.exist()) { esiste = true; elaborato = elabora_file(strname, logrep, articoli, nrighe, nrsalt); } } } else if (file.exist()) { esiste = true; elaborato = elabora_file(file, logrep, articoli, nrighe, nrsalt); } if (!esiste) warning_box(TR("ATTENZIONE: non è stato trovato nessun file da elaborare")); } if (elaborato) { controlla_documenti(logrep, articoli, documenti); bool genera = true; if (_auto == "A") { if (nrsalt > 0) { TString str; str << "Sono stati ricevuti " << nrighe << " record, di cui " << nrighe - nrsalt << " sono stati elaborati correttamente" << " e " << nrsalt << " ignorati.\nSi desidera procedere con la generazione dei buoni di ritiro?"; if (!yesno_box(str)) genera = false; } } else { TString str; str << "Sono stati ricevuti " << nrighe << " record, di cui " << nrighe - nrsalt << " sono stati elaborati correttamente" << " e " << nrsalt << " ignorati.\nSi desidera procedere con la generazione dei buoni di ritiro?"; if (!yesno_box(str)) genera = false; } if (nrsalt == 0 || genera) { genera_documenti(logrep, documenti); //diagnostica TAssoc_array buoni; FOR_EACH_ASSOC_OBJECT(documenti, obj, key, itm) { TDocumenti_key tmp = key; TDoc_key kdoc(tmp.anno(), tmp.codnum(), tmp.ndoc()); if (!buoni.is_key(kdoc)) buoni.add(kdoc, kdoc); } switch (buoni.items()) { case 0: warning_box(TR("Non è stato generato alcun buono di ritiro.")); break; case 1: message_box(TR("E' stato generato un buono di ritiro.")); break; default: message_box(FR("Sono stati generati %d buoni di ritiro."), buoni.items()); break; } FOR_EACH_SHEET_ROW(sheet, r1, row1) { if(row1->full()) { if (row1->find('/') >= 0 || row1->find('\\') >= 0) file = *row1; else { file = path; file.add(*row1); } if (file.find('*') >= 0 || file.find('?') >= 0) { TString_array lista_file; list_files(file, lista_file); FOR_EACH_ARRAY_ROW(lista_file, r2, row2) { const TFilename strname(*row2); if (strname.exist()) sposta_file(strname); } } else if (file.exist()) sposta_file(file); } } } if (_auto != "A") { TReport_book buc; buc.add(logrep); if (buc.pages() > 0) buc.preview(); if (genera) message_box(TR("Generazione terminata")); else warning_box(TR("Generazione interrotta")); } _msk->send_key(K_SPACE, DLG_QUIT); } return true; } void TAcquisizione_lavanderie_app::main_loop() { //lo lancio in automatico da linea di comando if (_auto == "A") _msk->send_key(K_SPACE, DLG_OK); while (_msk->run() == K_ENTER) transfer(); } int lv2600(int argc, char *argv[]) { TAcquisizione_lavanderie_app a; a.run (argc, argv, TR("Acquisizione da contapezzi")); return 0; }