#include #include #include #include #include #include #include "lvlib.h" #include "../mg/anamag.h" #include "../mg/clifogiac.h" #include "../ve/velib.h" #include "../ve/rcondv.h" #include "doc.h" #include "lvcondv.h" #include "lvrcondv.h" #include "lvrconsplan.h" #include "rdoc.h" #include "lv2400a.h" ///////////////////////////////////// //// TGENERA_DOCUMENTI_MSK //// ///////////////////////////////////// //classe TGenera_documenti_msk class TGenera_documenti_msk : public TAutomask { public: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); TGenera_documenti_msk (const char* name) : TAutomask(name) {set(F_STAMPA, 'X');} }; //ON_FIELD_EVENT: questo metodo gestisce i vari eventi che si verificano sui campi della maschera bool TGenera_documenti_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_DTDOC: if (e == fe_modify) { const TDate oggi(TODAY); if (get_date(F_DTDOC) <= oggi) { warning_box(TR("Attenzione: la data documento non può essere nel passato")); o.reset(); } } break; default: break; } return true; } ////////////////////////////////////// //// TGENERA_DOCUMENTI_APP //// ////////////////////////////////////// //classe TGenera_documenti_app class TGenera_documenti_app : public TSkeleton_application { TGenera_documenti_msk* _msk; TAssoc_array _quantita; TAssoc_array _quantita_ritirata; TConfig* _configlv; char _buono; long _ndoc; private: //Metodi per la generazione dei documenti bool crea_documento_ritiro(const TISAM_recordset& ritiro, TLog_report& rep, int& numdocgen, TAssoc_array& documenti); bool crea_documento_plan(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen, TAssoc_array& documenti); void crea_riga(TToken_string& chiave, const char modpas, const int tplis, const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep); //Metodi per il recupero di codnum, tpdoc, stato bool numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; bool numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; bool numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const; //Metodi per l'eliminazione dei documenti void cambia_stato(const char ritoant, const TString_array& docarr); void elimina_bolle(const long codcli, const long codind, TString_array& docarr); //Metodi per la scansione dei documenti int scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen); void scansione_consegne(const long codcli, const long codind, const TDocumento& docgen); //Metodo per il calcolo delle quantità in bolla void calcolo_quantita(const TDocumento& doc, const char ritoant); //Metodi aggiornare il conguaglio sui contratti void aggiorna_conguaglio(TRectype& rcondv, const real arr) const; protected: virtual bool create(); virtual void on_config_change(); virtual bool destroy(); public: bool transfer(); virtual void main_loop(); }; //////////////////////////////// //// Metodi Protected //// //////////////////////////////// //CREATE: metodo costruttore bool TGenera_documenti_app::create() { open_files(LF_DOC, LF_RIGHEDOC, 0); _msk = new TGenera_documenti_msk("lv2400a"); _ndoc = 0; _configlv = new TConfig(CONFIG_DITTA,"lv"); _buono = *TApplication::argv(2); return TSkeleton_application::create(); } //ON_CONFIG_CHANGE: metodo che aggiorna la variabile TConfig ogni volta //che faccio un cambiamento al file fisico void TGenera_documenti_app::on_config_change() { if (_configlv != NULL) delete _configlv; _configlv = new TConfig(CONFIG_DITTA,"lv"); } //DESTROY: metodo distruttore bool TGenera_documenti_app::destroy() { delete _configlv; delete _msk; return TApplication::destroy(); } /////////////////////////////////////////////////////// //// Metodi per la generazione dei documenti //// /////////////////////////////////////////////////////// //CREA_DOCUMENTO_RITIRO: metodo che crea un nuovo documento di trasporto dai dati salvati bool TGenera_documenti_app::crea_documento_ritiro(const TISAM_recordset& ritiro, TLog_report& rep, int& numdocgen, TAssoc_array& documenti) { //recupero i dati di interesse dalla maschera const TDate datagen(TODAY); //per ogni planning recupero i dati di interesse dal planning const long codcli = ritiro.get(DOC_CODCF).as_int(); const long codcont = ritiro.get(DOC_CODCONT).as_int(); const TDate dtcons = ritiro.get("G1:DATAPRCO").as_date(); //che è anche la data documento const int coditi = int(ritiro.get("CODITI").as_int()); TString8 codaut = ritiro.get(DOC_CODAG).as_string().right(5); codaut.trim(); const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons; const int anno = datadoc.year(); const long ag_selected = _msk->get_long(F_CODAUT); if (ag_selected > 0L && atol(codaut) != ag_selected) return true; //preparo la chiave per la tabella contratti TToken_string keycont; keycont.add(codcli); keycont.add(codcont); //instanzio una cache sulla tabella dei contratti const TRectype& tcont = cache().get(LF_LVCONDV,keycont); //estraggo i dati di interesse dalla cache const long codind = tcont.get_long(LVCONDV_CODINDSP); //codice dell'indirizzo di spedizione const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino //const bool prinbo = tcont.get_bool(LVCONDV_STPRZBOL); //prezzo in bolla const bool prinbo = true; //sempre a true; verrà gestita a video in futuro (27/10/2009) //variabili che conterranno i parametri dei documenti che devo generare... //...settati dalla funzione numerazione_ddt() TString4 codnum, tpdoc, statoi, statof; //Cerco il tipo documento da generare sul contratto; se non lo trovo lo cerco in configurazione. //Se non trovo quale documento generare, evito il resto dell'elaborazione if (tcont.get(LVCONDV_CODNUM).full() && _buono == 'C') { codnum = tcont.get(LVCONDV_CODNUM); tpdoc = tcont.get(LVCONDV_TPDOC); //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) const TString& s2 = cache().get("%TIP",tpdoc,"S2"); statoi = s2.left(1); statof = s2.mid(1,1); } else if (!numerazione_ddt(codnum, tpdoc, statoi, statof)) return NOERR; //recupero i dati di interesse dal cliente TToken_string key; key.add('C'); key.add(codcli); 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 TString8 causmag = cache().get("%TIP", tpdoc, "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 int codindsp = cfven.get_int(CFV_CODINDSP); 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"); } break; case 'N': //sconto non gestito default: break; } //creo il documento corretto riempiendo i campi che già conosco TDocumento doc('D', anno, codnum, 0L); doc.put(DOC_TIPODOC, tpdoc); doc.put(DOC_DATADOC, datadoc); doc.put(DOC_TIPOCF, 'C'); doc.put(DOC_CODCF, codcli); doc.put(DOC_CODCONT, codcont); if(codindsp > 0) doc.put(DOC_CODINDSP, codindsp); doc.put(DOC_RAGGR, ragdoc); doc.put(DOC_CODPAG, codpag); 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(DOC_DATAPART, TDate(TODAY)); doc.put("DATAGEN", datagen); //data generazione del documento doc.put("DATAPRCO", dtcons); //data prevista consegna doc.put("CODITI", coditi); //codice itinerario //calcola tutte le quantità riportate sui documenti di ritiro, sui documenti di anticipo int numerodoc = scansione_ritiri_anticipi(codcli, dtcons, 'R', doc); scansione_ritiri_anticipi(codcli, dtcons, 'A', doc); int err = 1; if(numerodoc > 0) { FOR_EACH_ASSOC_OBJECT(_quantita,h,key,obj) { TToken_string chiave(key); const TCodice_articolo codart = chiave.get(0); //preparo la chiave per la tabella righe contratti TToken_string keyrcont; keyrcont.add(codcli); keyrcont.add(codcont); keyrcont.add(codart); const TRectype& rcont = cache().get(LF_LVRCONDV, keyrcont); const TDate dadata = rcont.get_date(LVRCONDV_INDTTMP); const TDate adata = rcont.get_date(LVRCONDV_FIDTTMP); if (dadata.ok() && dtcons >= adata) crea_riga(chiave, ' ', tplis, true, prinbo, doc, rep); else crea_riga(chiave, ' ', tplis, false, prinbo, doc, rep); } if (doc.rows() > 0) { TToken_string orderkey; orderkey.add(RDOC_CODART); doc.sort_rows(orderkey); while (err = doc.write() == _isreinsert) { const long old_ndoc = doc.get_long(DOC_NDOC); doc.renum_ndoc(); const long new_ndoc = doc.get_long(DOC_NDOC); message_box("Attenzione documento numero %ld rinumerato in %ld", old_ndoc, new_ndoc); } ++numdocgen; } else doc.remove(); //scrivo sul planning il riferimento alla bolla che lo accompagna if (err == NOERR) { //tengo traccia dei documenti che sto generando, per poterli stampare dopo TDoc_key kdoc(doc.get_int(DOC_ANNO), doc.get(DOC_CODNUM), doc.get_int(DOC_NDOC)); if (!documenti.is_key(kdoc)) documenti.add(kdoc, kdoc); } } return err == NOERR; } //CREA_DOCUMENTO_PLAN: metodo che crea un nuovo documento di trasporto dai dati salvati bool TGenera_documenti_app::crea_documento_plan(const TISAM_recordset& plan, TLog_report& rep, int& numdocgen, TAssoc_array& documenti) { //recupero i dati di interesse dalla maschera const TDate datagen(TODAY); //per ogni planning recupero i dati di interesse dal planning const long codcli = plan.get(LVRCONSPLAN_CODCF).as_int(); const long codcont = plan.get(LVRCONSPLAN_CODCONT).as_int(); const TDate dtcons = plan.get(LVRCONSPLAN_DTCONS).as_date(); //che è anche la data documento const char modpas = plan.get(LVRCONSPLAN_MODPASS).as_string()[0]; const int coditi = plan.get(LVRCONSPLAN_CODITI).as_int(); TString8 codaut = plan.get(LVRCONSPLAN_CODAUT).as_string().right(5); codaut.trim(); const TDate datadoc = _msk->get_bool(F_DTEMIS) ? _msk->get_date(F_DTDOC) : dtcons; const int anno = datadoc.year(); //preparo la chiave per la tabella contratti TToken_string keycont; keycont.add(codcli); keycont.add(codcont); //instanzio una cache sulla tabella dei contratti const TRectype& tcont = cache().get(LF_LVCONDV,keycont); //estraggo i dati di interesse dalla cache const long codind = tcont.get_long(LVCONDV_CODINDSP); //codice dell'indirizzo di spedizione const int tplis = tcont.get_int(LVCONDV_TIPOLIS); //tipo listino //const bool prinbo = tcont.get_bool(LVCONDV_STPRZBOL); //prezzo in bolla const bool prinbo = true; //sempre a true; verrà gestita a video in futuro (27/10/2009) //variabili che conterranno i parametri dei documenti che devo generare... //...settati dalla funzione numerazione_ddt() TString4 codnum, tpdoc, statoi, statof; //Cerco il tipo documento da generare sul contratto; se non lo trovo lo cerco in configurazione. //Se non trovo quale documento generare, evito il resto dell'elaborazione if (tcont.get(LVCONDV_CODNUM).full() && _buono == 'C') { codnum = tcont.get(LVCONDV_CODNUM); tpdoc = tcont.get(LVCONDV_TPDOC); //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) const TString& s2 = cache().get("%TIP",tpdoc,"S2"); statoi = s2.left(1); statof = s2.mid(1,1); } else if (!numerazione_ddt(codnum, tpdoc, statoi, statof)) return NOERR; if(_ndoc == 0) { TString query2; query2 << "USE DOC\n" << "FROM PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\"\n" << "TO PROVV=\"D\" ANNO=" << anno << " CODNUM=\"" << codnum << "\""; TISAM_recordset bolle(query2); if (bolle.move_last()) _ndoc = bolle.get(DOC_NDOC).as_int(); } //recupero i dati di interesse dal cliente TToken_string key; key.add('C'); key.add(codcli); 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 TString8 causmag = cache().get("%TIP", tpdoc, "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 int codindsp = cfven.get_int(CFV_CODINDSP); 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"); } break; case 'N': //sconto non gestito default : break; } //creo il documento corretto riempiendo i campi che già conosco TDocumento doc('D', anno, codnum, ++_ndoc); doc.put(DOC_TIPODOC, tpdoc); if(_msk->get_bool(F_DTEMIS)) doc.put(DOC_DATADOC, _msk->get_date(F_DTDOC)); else doc.put(DOC_DATADOC, dtcons); doc.put(DOC_TIPOCF, 'C'); doc.put(DOC_CODCF, codcli); doc.put(DOC_CODCONT, codcont); if(codindsp > 0) doc.put(DOC_CODINDSP, codindsp); doc.put(DOC_RAGGR, ragdoc); doc.put(DOC_CODPAG, codpag); 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("DATAGEN", datagen); //data generazione del documento doc.put("DATAPRCO", dtcons); //data prevista consegna doc.put("CODITI", coditi); //codice itinerario //calcola tutte le quantità riportate sui documenti di ritiro, sui documenti di anticipo int numerodoc = scansione_ritiri_anticipi(codcli, dtcons, 'R', doc); scansione_ritiri_anticipi(codcli, dtcons, 'A', doc); int err = 1; if(numerodoc > 0) { FOR_EACH_ASSOC_OBJECT(_quantita,h,key,obj) { TToken_string chiave(key); const TString80 codart = chiave.get(0); //preparo la chiave per la tabella righe contratti TToken_string keyrcont; keyrcont.add(codcli); keyrcont.add(codcont); keyrcont.add(codart); const TRectype& rcont = cache().get(LF_LVRCONDV, keyrcont); const TDate dadata = rcont.get_date(LVRCONDV_INDTTMP); const TDate adata = rcont.get_date(LVRCONDV_FIDTTMP); if (dadata.ok() && dtcons >= adata) crea_riga(chiave, modpas, tplis, true, prinbo, doc, rep); else crea_riga(chiave, modpas, tplis, false, prinbo, doc, rep); } if (doc.rows() > 0) { TToken_string orderkey; orderkey.add(RDOC_CODART); doc.sort_rows(orderkey); err = doc.rewrite(); ++numdocgen; } else doc.remove(); //scrivo sul planning il riferimento alla bolla che lo accompagna if (err == NOERR) { TLocalisamfile& f = plan.cursor()->file(); f.put(LVRCONSPLAN_ANNO, anno); f.put(LVRCONSPLAN_CODNUM, codnum); f.put(LVRCONSPLAN_NDOC, _ndoc); f.rewrite(); //tengo traccia dei documenti che sto generando, per poterli stampare dopo TDoc_key kdoc(doc.get_int(DOC_ANNO), doc.get(DOC_CODNUM), doc.get_int(DOC_NDOC)); if (!documenti.is_key(kdoc)) documenti.add(kdoc, kdoc); } } return err == NOERR; } //CREA_RIGA: questa funzione crea una riga merce per una bolla di consegna void TGenera_documenti_app::crea_riga(TToken_string& chiave, const char modpas, const int tplis, const bool tmp, const bool prinbo, TDocumento& doc, TLog_report& rep) { const int perarr = ini_get_int(CONFIG_DITTA, "lv", "Perarr"); //creo la nuova riga TString4 tiporiga; switch (_buono) { case 'P': tiporiga = "24"; break; case 'C': tiporiga = "21"; break; default: break; } const long codcli = doc.get_long(DOC_CODCF); const long codcont = doc.get_long(DOC_CODCONT); const TString80 codart = chiave.get(0); const TString4 causale = chiave.get(1); //calcolo della quantità che va sulla bolla //preparo la chiave per la tabella righe contratti TLaundry_contract cont(codcli, codcont); const TRectype& rcont = cont.row(codart); const bool artbloc = rcont.get_int(LVRCONDV_ARTBLOC) > 0; if (artbloc) return; //recupero i dati di interesse dalla riga del contratto const bool arrot = rcont.get_int(LVRCONDV_CALCCONS) == 1; const real conguaglio = rcont.get_real(LVRCONDV_QTACONG); real& qta = *(real*)_quantita.objptr(chiave); const real& qta1 = *(real*)_quantita_ritirata.objptr(chiave); const real przdttmp = rcont.get_real(LVRCONDV_PRZDTTMP); //instanzio una cache sulla tabella del magazzino const TRectype& anamag = cache().get(LF_ANAMAG,codart); //recupero i dati di interesse dall'anagrafica di magazzino, ma devo evitare divisioni per 0 const real ppconf = anamag.get_real(ANAMAG_PPCONF) != 0 ? anamag.get_real(ANAMAG_PPCONF) : 1; TString descrart; descrart << anamag.get(ANAMAG_DESCR) << anamag.get(ANAMAG_DESCRAGG); //recupero i valori delle dotazione temporanea dal magazzino del cliente TArticolo_lavanderie& artrec = cached_article_laundry(codart, 'C', codcli, 0); //fisso l'anno esercizio TEsercizi_contabili& esc = esercizi(); const int last_esc = esc.last(); //estraggo il record corrispondente su LF_CLIFOGIAC const TRecmag_lavanderie& reclav = artrec.find_rec(last_esc); real dotod = reclav.get_real(CLIFOGIAC_DOTOD); real dottmp = reclav.get_real(CLIFOGIAC_DOTTM); //GESTIONE DOTAZIONE TEMPOARANEA if (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && dottmp > 0) { TRiga_documento& rdoc = doc.new_row(tiporiga); 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'); if (prinbo) rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); //prezzo rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva const TCausale_lavanderie caudt(ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT")); //se ho ritirato un quantitativo di roba maggiore o uguale alla dotazione temporanea //allora creo la nuova riga documento e azzero la dottmp; altrimenti preparo la riga //per la quantità che ho ritirato e tengo traccia della cosa if (qta >= dottmp) { qta -= dottmp; rdoc.put(RDOC_QTAGG1, dottmp); //quantità ritirata rdoc.put(RDOC_GENERATA, true); rdoc.put(RDOC_CODAGG1, caudt.caucol().empty() ? caudt.codice() : caudt.caucol()); dottmp = 0; dotod -= dottmp; TString str; str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) << " numero " << doc.get(DOC_NDOC) << " in dotazione è stato ritirato completamente."; rep.log(1, str); } else { dottmp -= qta; dotod -= qta; rdoc.put(RDOC_QTAGG1, qta); //quantità ritirata rdoc.put(RDOC_GENERATA, true); rdoc.put(RDOC_CODAGG1, caudt.caucol().empty() ? caudt.codice() : caudt.caucol()); TString str; str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) << " numero " << doc.get(DOC_NDOC) << " in dotazione temporanea non è stato ritirato completamente." << " Mancano " << dottmp << "unità"; rep.log(1, str); qta = ZERO; } //scrivo il magazzino const TCausale_magazzino rit(caudt.causale_ritiro()); const TCausale_magazzino con(caudt.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); //recupero l'unità di misura principale di quest'articolo TToken_string key; key.add(codart); key.add(1); const TRectype& umart = cache().get(LF_UMART, key); TString4 um = umart.get(UMART_UM); rdoc.put(RDOC_UMQTA, um); //scrivo gli estremi della dotazione temporanea rdoc.put("DADATATMP", rcont.get_date(LVRCONDV_INDTTMP)); rdoc.put("ADATATMP", rcont.get_date(LVRCONDV_FIDTTMP)); rdoc.dirty_fields(); } if (qta > ZERO || (tmp && rcont.get_bool(LVRCONDV_RITAUDTTMP) && qta == ZERO)) { TRiga_documento& rdoc = doc.new_row(tiporiga); //causale da mettere sulle righe documento const TCausale_lavanderie cau(causale); const TString4 codcau = cau.caucol().empty() ? cau.codice() : cau.caucol(); rdoc.put(RDOC_CODAGG1, codcau); if (cau.is_consegna()) { const real quantita_noarr = qta - conguaglio; real quantita_arr = quantita_noarr > ZERO ? quantita_noarr : ZERO; //se devo arrotondare if (quantita_arr > ZERO && arrot) { //calcolo di quanti pezzi sforo long arr = quantita_arr.integer() % ppconf.integer(); //se sforo (arr > 0) allora calcolo quanti pezzi in più gli devo dare e aggiorno la quantità if (arr > 0) { if (arr > ppconf.integer() * perarr / 100) //arr <= ppconf*perarr/100 -> formula calcolo congualgio di Tassan { arr = ppconf.integer() - arr; quantita_arr += arr; } else quantita_arr -= arr; } } //scrivo le quantità rdoc.put(RDOC_QTA, quantita_arr); //quantità consegnata eventualmente arrotondata rdoc.put(RDOC_QTAGG2, conguaglio); //conguaglio rdoc.put(RDOC_QTAGG3, quantita_arr); //copia della quantità consegnata rdoc.put(RDOC_QTAGG4, quantita_noarr); //quantità che avrei consegnato se non arrotondavo (qta ritirata) rdoc.put(RDOC_GENERATA, true); //aggiorno il conguaglio sulla riga del contratto //altrimenti se il record di riga contratto è vuoto aggiorno il log if (!rcont.empty()) { aggiorna_conguaglio((TRectype&)rcont, quantita_arr - quantita_noarr); } else { TString str; str << "L'articolo " << codart << " inserito nel documento " << doc.get(DOC_CODNUM) << "-" << doc.get(DOC_TIPODOC) << " numero " << doc.get(DOC_NDOC) << " per la quantità di " << quantita_arr << " unità" << " non è presente sul contratto del cliente " << codcli; rep.log(1, str); } } //essendo la dot tmp un di cui la quantità ritirata è sempre quella if(cau.is_ritiro()) rdoc.put(RDOC_QTAGG1, qta1); //quantità ritirata //elaborazione sul prezzo da utilizzare real prezzo; if (rcont.empty()) { //PROPONI PREZZO TToken_string key; key.add('C'); key.add(codcli); const TRectype& cfven = cache().get(LF_CFVEN, key); bool trvlst = false; if (!cfven.empty()) { //se è settata la categoria merceologica, leggo sia il listino che la cat merc, altrimenti solo il listino TString8 codlis = cfven.get(CFV_CODLIST); TString8 catven; TConfig* configve = new TConfig(CONFIG_DITTA,"ve"); const char gesliscv = configve->get_char("GESLISCV"); if (gesliscv != 'X') catven = ""; else catven = cfven.get(CFV_CATVEN); //cerco il prezzo sul listino key.cut(0); key.add('L'); //tipo key.add(catven); //catven key.add(""); //tipocf key.add(""); //codcf key.add(codlis); //codlis key.add('A'); //tiporiga key.add(codart); //codriga key.add(""); //um key.add(""); //nscagl const TRectype& rcondv = cache().get(LF_RCONDV, key); if (!rcondv.empty()) { prezzo = rcondv.get_real(RCONDV_PREZZO); trvlst = true; } } //se non ho trovato un listino, o se non c'è un listino impostato //propongo come prezzo il valore convenzionale if (!trvlst) { key.cut(0); key.add(codart); key.add(1); const TRectype& umart = cache().get(LF_UMART, key); prezzo = umart.get_real(UMART_PREZZO); if (umart.get(UMART_PREZZO).full()) trvlst = true; } } else { //elaborazione per il prezzo: o lo prendo dalle righe contratto, o dall'anagrafica magazzino if (tplis == 0) prezzo = rcont.get_real(LVRCONDV_PREZZO); else prezzo = anamag.get_real(ANAMAG_COSTSTD); } rdoc.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); //codiva 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'); if (prinbo) { if (!tmp) rdoc.put(RDOC_PREZZO, prezzo); else rdoc.put(RDOC_PREZZO,rcont.get_real(LVRCONDV_PRZDTTMP)); rdoc.put(RDOC_SCONTO,rcont.get(LVRCONDV_SCONTPERC)); //sconto } //recupero l'unità di misura principale di quest'articolo TToken_string key; key.add(codart); key.add(1); const TRectype& umart = cache().get(LF_UMART, key); TString4 um = umart.get(UMART_UM); rdoc.put(RDOC_UMQTA, um); //scrivo il magazzino TCausale_magazzino rit(cau.causale_ritiro()); TCausale_magazzino con(cau.causale_consegna()); TString8 magazzino; TString8 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); rdoc.dirty_fields(); } if (dottmp == 0) { cont.update_row(codart, LVRCONDV_INDTTMP, NULLDATE); cont.update_row(codart, LVRCONDV_FIDTTMP, NULLDATE); } } ////////////////////////////////////////////////////////////// //// Metodi per il recupero di codnum, tpdoc, stato //// ////////////////////////////////////////////////////////////// //NUMERAZIONE_DDT: questa funzione cerca quali sono i codnum e i tpdoc che devo generare bool TGenera_documenti_app::numerazione_ddt(TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const { //questo switc mi permette di generare con lo stesso programma sia i buoni di prelievo (P) //che i buoni di consegna (C); la variabile globale _buono viene inizializzata con il valore //passato come parametro al programma al momento della chiamata da menù switch (_buono) { case 'P': { codnum = _configlv->get("NUM_PRE(0)"); tpdoc = _configlv->get("TIPODOC_PRE(0)"); } break; case 'C': { codnum = _configlv->get("NUM_GEN"); tpdoc = _configlv->get("TIPODOC_GEN"); } break; default: break; } //instanzio una cache sulla tabella dei tipi documento (cerco lo stato iniziale) const TString& s2 = cache().get("%TIP",tpdoc,"S2"); statoi = s2.left(1); statof = s2.mid(1,1); return codnum.full() && tpdoc.full(); } //NUMERAZIONE_DRIT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di ritiro bool TGenera_documenti_app::numerazione_drit(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const { codnum = _configlv->get("NUM_RIT", NULL, cod); tpdoc = _configlv->get("TIPODOC_RIT", NULL, cod); //instanzio una cache sulla tabella tipi documento (cerco lo stato iniziale) const TString& s2 = cache().get("%TIP",tpdoc,"S2"); statoi = s2.left(1); statof = s2.mid(1,1); return codnum.full() && tpdoc.full(); } //NUMERAZIONE_DANT: questa funzione cerca quali sono i codnum e i tpdoc dei documenti di anticipo bool TGenera_documenti_app::numerazione_dant(const int cod, TString& codnum, TString& tpdoc, TString& statoi, TString& statof) const { codnum = _configlv->get("NUM_ANT", NULL, cod); tpdoc = _configlv->get("TIPODOC_ANT", NULL, cod); //instanzio una cache sulla tabella delle righe contratti (cerco lo stato iniziale) const TString& s2 = cache().get("%TIP",tpdoc,"S2"); statoi = s2.left(1); statof = s2.mid(1,1); return codnum.full() && tpdoc.full(); } ////////////////////////////////////////////////////////////// //// Metodi per la scansione dei documenti //// ////////////////////////////////////////////////////////////// //SCANSIONE_RITIRI_ANTICIPI: questa funzione cerca tutte le bolle di ritiro relative a un certo cliente non ancora evase... //e, dopo l'elaborazione, gli cambia stato int TGenera_documenti_app::scansione_ritiri_anticipi(const long codcli, const TDate& data, const char ritoant, const TDocumento& docgen) { const long aanno = data.year(); TDate dadata = data; dadata.addmonth(-1); const long daanno = dadata.year(); TString4 codnum; TString4 tpdoc; TString4 statoi; TString4 statof; bool err = NOERR; //distinguo se sto scandendo i documenti di ritiro o i documenti di anticipo switch (ritoant) { case 'R': err = numerazione_drit(0, codnum, tpdoc, statoi, statof); break; case 'A': err = numerazione_dant(0, codnum, tpdoc, statoi, statof); break; default: break; } if (!err) return err; //instanzio un recordset che contiene tutti i documenti di interesse TString query; query << "USE DOC " << "SELECT (TIPOCF=\"C\")&&(BETWEEN(CODCF," << codcli << ',' << codcli << "))&&" << "(ANSI(G1:DATAPRCO)<=#ADATA)&&" << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" << "(STATO=\"" << statoi <<"\")\n" << "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n" << "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n"; //instanzio un recordset che contiene tutti i documenti di interesse TISAM_recordset docritiri(query); docritiri.set_var("#ADATA", data); //per ogni documento che trovo, aggiorno la quantità, e poi cambio stato al documento for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) { TDocumento doc(docritiri.cursor()->curr()); //instanzio il documento calcolo_quantita(doc, ritoant); doc.put(DOC_STATO,statof); //stato di elaborato //salvo i riferimenti del documento che sto andando a generare doc.put("PROVVDG", docgen.get(DOC_PROVV)); doc.put("ANNODG", docgen.get(DOC_ANNO)); doc.put("CODNUMDG", docgen.get(DOC_CODNUM)); doc.put("NDCODG", docgen.get(DOC_NDOC)); doc.rewrite(); } return docritiri.items(); } ////////////////////////////////////////////////////////////// //// Metodo per il calcolo delle quantità in bolla //// ////////////////////////////////////////////////////////////// //CALCOLO_QUANTITA: questa funzione scorre tutte le righe documento di una bolla di ritiro, riempiendo un... //TAssoc_array con le quantità ritirate per ogni articolo, sommando le diverse righe con lo stesso articolo... //Questa funzione viene richiamata per ogni documento valido individuato dalla SCANSIONE_RITIRI void TGenera_documenti_app::calcolo_quantita(const TDocumento& doc, const char ritoant) { //scorro le righe documento for (long i = 1; i <= doc.rows(); i++) { //instanzio la riga corrente const TRiga_documento& rdoc = doc[i]; //estraggo i dati di interesse const TString80 codart = rdoc.get(RDOC_CODARTMAG); const TString4 codcau = rdoc.get(RDOC_CODAGG1); TToken_string key; key.add(codart); key.add(codcau); const real qtardoc = rdoc.get_real(RDOC_QTAGG1); //se è una riga che riguarda un articolo e se la quantità su questa riga non è nulla, allora la elaboro if (codart.full() && !qtardoc.is_zero()) { TArticolo& art = rdoc.articolo(); //leggo se esiste già nel TAssoc_array real *qta = (real*)_quantita.objptr(key); real *qta1 = (real*)_quantita_ritirata.objptr(key); //se non esiste if (qta == NULL) { //per ora memorizzo zero qta = new real; _quantita.add(key,qta); } if (qta1 == NULL) { //per ora memorizzo zero qta1 = new real; _quantita_ritirata.add(key,qta1); } //aggiorno la quantità convertendola all'unità di misura di base, aggiungendola o sottraendola //...se si tratta di un ritiro o di un anticipo rispettivamente; nel caso della scansione delle //...bolle di consegna modificate a mano (caso 'B'), devo modificare la quantità da consegnare //...tenendo conto delle modifiche manuali switch (ritoant) { case 'R': *qta += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); *qta1 += art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); break; case 'A': *qta -= art.convert_to_um(qtardoc, NULL, rdoc.get(RDOC_UMQTA)); break; default: break; } } } return; } ////////////////////////////////////////////////////////////// //// Metodi aggiornare il conguaglio sui contratti //// ////////////////////////////////////////////////////////////// //AGGIORNA_CONGUAGLIO: questa funzione aggiorna il parametro conguaglio sulla riga del contratto void TGenera_documenti_app::aggiorna_conguaglio(TRectype& rcondv, const real arr) const { TLocalisamfile rcont(LF_LVRCONDV); rcondv.put(LVRCONDV_QTACONG,arr); rcondv.rewrite(rcont); } //////////////////////////////// //// Metodi Pubblic //// //////////////////////////////// bool TGenera_documenti_app::transfer() { //leggo i dati dalla maschera const TDate adata = _msk->get_date(F_DTCONS); TDate dadata(TODAY); if (_msk->get_int(F_TPGEN) == 1) dadata = adata; else ++dadata; const int daanno = dadata.year() - 1; const int aanno = adata.year(); const long coditi = _msk->get_long(F_CODITI); const long codaut = _msk->get_long(F_CODAUT); long codcli = _msk->get_long(F_CODCF); TLog_report rep("Riepilogo associazioni"); rep.kill_duplicates(true); //preparo un recordset che contiene tutti planning per cui voglio creare i documenti relativi TString4 codnum, tpdoc, statoi, statof; numerazione_drit(0, codnum, tpdoc, statoi, statof); int numdocgen = 0; TAssoc_array documenti; if (_msk->get_bool(F_NOTPLAN)) { if (_msk->get_int(F_TPGEN) != 1) dadata.addmonth(-1); //per ogni data cerco i documenti e per ogni documento cerco i dati del passaggio TString query; query << "USE DOC " << "SELECT (ANSI(G1:DATAPRCO)<=#ADATA)&&" << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" << "(STATO=\"" << statoi <<"\")&&"; query << "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\n" << "FROM PROVV=\"D\" ANNO=" << dadata.year() << " CODNUM=\"" << codnum << "\"\n" << "TO PROVV=\"D\" ANNO=" << adata.year() << " CODNUM=\"" << codnum << "\"\n"; TISAM_recordset docritiri(query); docritiri.set_var("#ADATA", adata); docritiri.set_var("#CODCF", codcli); TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso...")); for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) { _quantita.destroy(); _quantita_ritirata.destroy(); crea_documento_ritiro(docritiri, rep, numdocgen, documenti); if (!pi.add_status()) break; } } else { //TDate d(adata); d.addmonth(-1); for (dadata; dadata <= adata; ++dadata) { //per ogni data cerco i documenti e per ogni documento cerco i dati del passaggio TString query; query << "USE DOC " << "SELECT (ANSI(G1:DATAPRCO)<=#ADATA)&&" << "(CODNUM=\"" << codnum << "\")&&(TIPODOC=\"" << tpdoc << "\")&&" << "(STATO=\"" << statoi <<"\")&&" << "(TIPOCF=\"C\")&&(BETWEEN(CODCF,#CODCF,#CODCF))\n" << "FROM PROVV=\"D\" ANNO=" << daanno << " CODNUM=\"" << codnum << "\"\n" << "TO PROVV=\"D\" ANNO=" << aanno << " CODNUM=\"" << codnum << "\"\n"; TISAM_recordset docritiri(query); docritiri.set_var("#ADATA", adata); docritiri.set_var("#CODCF", codcli); TProgress_monitor pi(docritiri.items(), TR("Generazione documenti in corso...")); for (bool ok = docritiri.move_first(); ok; ok = docritiri.move_next()) { if (!pi.add_status()) break; if (_msk->field(F_CODCF).empty()) codcli = docritiri.get(DOC_CODCF).as_int(); // instanzio un recordset che contiene tutti i documenti di interesse TString query = "USE LVRCONSPLAN KEY 2"; query << " SELECT (CODCF=" << codcli << ")"; if (coditi || codaut) { if (coditi > 0) query << "&&(CODITI=" << coditi << ")"; if (codaut > 0) query << "&&(CODAUT=" << codaut << ")"; } query << "\nFROM DTCONS=#DADATA"; query << "\nTO DTCONS=#ADATA"; TISAM_recordset plan(query); plan.set_var("#DADATA", dadata); if (_msk->get_int(F_TPGEN) == 0) plan.set_var("#ADATA", adata); else plan.set_var("#ADATA", dadata); if (plan.move_first()) { _quantita.destroy(); _quantita_ritirata.destroy(); crea_documento_plan(plan, rep, numdocgen, documenti); } codcli = _msk->get_long(F_CODCF); } } } if (_msk->get_bool(F_STAMPA) && documenti.items() > 0) { TFilename tmp; tmp.temp("", "ini"); // Ensure that the ofstream is well closed before ve1 call if (tmp.full()) // dummy test { TDoc_key kd(documenti.get_hashobj()->key()); TString16 chiavedoc; // Parte della chiave comune a tutti i documenti chiavedoc << kd.provv() << '|' << kd.anno() << '|' << kd.codnum() << '|'; ofstream outf(tmp); outf << "[Transaction]" << endl; // Transaction header outf << "Action=S" << endl; // 'S'tampa o 'A'nteprima outf << "Mode=D" << endl; // Definitive (always?) outf << "NoPrintDlg=X" << endl; // Dont' prompt the user with the print dialog outf << endl; outf << "[33]" << endl; // Transaction body long nx = 0; // Document counter FOR_EACH_ASSOC_OBJECT(documenti, obj, r, riga) { TDoc_key& kdoc = *(TDoc_key*)riga; outf << "Doc(" << (nx++) << ")="; outf << chiavedoc << kdoc.ndoc() << endl; } } if (tmp.exist()) { { TString cmdline; cmdline << "ve1 -2 -i" << tmp; TExternal_app app(cmdline); app.run(); } { TString cmdline; cmdline << "lv1 -3 -i" << tmp; TExternal_app app(cmdline); app.run(); } tmp.fremove(); } } if (documenti.items() == 0) warning_box(TR("Non è stato possibile generare nessun documento; probabilmente i documenti richiesti esistono già")); else { if (adata < TODAY && _msk->get_int(F_TPGEN) == 0) warning_box(TR("Non è stato possibile generare documenti con data prevista consegna nel passato")); else { TReport_book buc; buc.add(rep); if (buc.pages() > 0) buc.preview(); else { TString str; if (numdocgen > 1) str << TR("Sono stati generati ") << numdocgen << TR(" buoni."); else str << TR("E' stato generato ") << numdocgen << TR(" buono."); message_box(str); message_box(TR("Generazione terminata")); } } } return true; } void TGenera_documenti_app::main_loop() { _msk->set(F_NOTPLAN, "X"); while (_msk->run() == K_ENTER) { transfer(); _msk->set(F_NOTPLAN, "X"); } } int lv2400(int argc, char* argv[]) { TGenera_documenti_app app; app.run(argc, argv, TR("Generazione documenti")); return 0; }