#include "../ve/velib04.h" #include "../ca/calib01.h" #include "pe1400.h" #include "pe1500.h" #include "../ca/fasi.h" /////////////////////////////////////////////////////////// // Utilities /////////////////////////////////////////////////////////// int pe_numero_fasi(const TRecord_array& preventivo) { static const TString4 strFasi = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaFase", "05"); int level = 0; for (int i = preventivo.last_row(); i > 0; i = preventivo.pred_row(i)) { const TRectype& rdoc = preventivo.row(i); const TString& tr = rdoc.get(RDOC_TIPORIGA); if (tr == strFasi) { const int p = rdoc.get_int(RPRV_LEVEL) + 1; if (p > level) level = p; } } return level; } int pe_numero_fasi(const TDocumento& preventivo) { return pe_numero_fasi(preventivo.body()); } int pe_crea_fasi_preventivo(TDocumento& din) { const TString4 _strFasi = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaFase", "05"); const TString4 _strDist = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaDist", "P1"); const int doc_levels = pe_numero_fasi(din); if (doc_levels <= 0) return 0; // Should never happen TConfig& cfg = ca_config(); TString_array picture_fasi; for (int i = 1; i <= 4; i++) { const TString& pic = cfg.get("Fsc", "ca", i); if (pic.full()) picture_fasi.add(pic); else break; } const int cfg_levels = picture_fasi.items(); if (cfg_levels <= 0) { error_box(TR("Occorre configurare le fasi analitiche")); return 0; } const bool faseart = din.get_bool(DOC_ADDBOLLI); TLocalisamfile fasi(LF_FASI); TString16 fase[4], curfase; // Livelli delle fasi (max 4) int curliv = 0; /* Vedere in futuro come gestire numero di fasi incoerente con la configurazione di CA // Crea gli eventuali livelli iniziali mancanti const int delta_levels = cfg_levels-doc_levels; if (delta_levels > 0) { TString80 descr; for (int lev = 0; lev < delta_levels; lev++) { fase[lev].format("%0*ld", picture_fasi.row(lev).len(), 0); fasi.put(FASI_CODCMSFAS, din.get(DOC_CODCMS)); int tot_len = 0; for (int l = 0; l <= lev; l++) tot_len += picture_fasi.row(lev).len(); descr.format("%0*ld", tot_len, 0); fasi.put(FASI_CODFASE, descr); descr.format(FR("FASE%d"), lev); fasi.put(FASI_DESCRIZ, descr); fasi.write_rewrite(); } } */ const int nrows = din.physical_rows(); FOR_EACH_PHYSICAL_RDOC(din, r, rdoc) { const TString& tr = rdoc->get(RDOC_TIPORIGA); if (tr == _strFasi) { const int level = rdoc->get_int(RPRV_LEVEL); // Livello logico della riga [0,3] if (r >= nrows || (level == (cfg_levels-1) && din[r+1].is_descrizione())) continue; // Salta fasi vuote if (level >= 0 && level < cfg_levels) { const int fase_len = picture_fasi.row(level).len(); TString& cod = fase[level]; cod = rdoc->get(RDOC_CODART).left(10); const int delta_len = fase_len - cod.len(); if (delta_len != 0) { if (delta_len > 0) cod.rpad(fase_len, ' '); else cod.cut(fase_len); } curliv = level; curfase.cut(0); for (int i = 0; i <= level; i++) curfase << fase[i]; fasi.put(FASI_CODCMSFAS, din.get(DOC_CODCMS)); fasi.put(FASI_CODFASE, curfase); fasi.put(FASI_DESCRIZ, rdoc->get(RDOC_DESCR)); fasi.write_rewrite(); } } else if (tr == _strDist) { if (faseart && curliv == cfg_levels-2) { fasi.put(FASI_CODCMSFAS, din.get(DOC_CODCMS)); TString80 fase = curfase; fase << rdoc->get(RDOC_CODART); fasi.put(FASI_CODFASE, fase); fasi.put(FASI_DESCRIZ, rdoc->get(RDOC_DESCR)); fasi.write_rewrite(); } } // Aggiorna codice fase anche nella riga di input const TString& lastfase = fasi.get(FASI_CODFASE); if (lastfase.full() && rdoc->get(RDOC_FASCMS) != lastfase) rdoc->put(RDOC_FASCMS, lastfase); } return cfg_levels; } /////////////////////////////////////////////////////////// // TOrdinazione /////////////////////////////////////////////////////////// class TOrdinazione : public TElaborazione_esterna { TString4 _strFasi, _strDist; public: virtual bool elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo = false); TOrdinazione(const TString& cod); }; const TRectype& find_precedente(const TDocumento& doc, const TString& codnum, bool& bEvaso) { TString query, limit; limit << RDOC_DAPROVV << '=' << doc.get(DOC_PROVV) << ' ' << RDOC_DAANNO << '=' << doc.get_int(DOC_ANNO) << ' ' << RDOC_DACODNUM << '=' << doc.get(DOC_CODNUM) << ' ' << RDOC_DANDOC << '=' << doc.get_long(DOC_NDOC); query << "USE 34 KEY 4" << "\nSELECT CODNUM=\"" << codnum << '"' << "\nFROM " << limit << "\nTO " << limit; bEvaso = false; TISAM_recordset recset(query); const TRectype& rdoc = recset.cursor()->curr(); TToken_string key; for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { key = rdoc.get(RDOC_PROVV); key.add(rdoc.get(RDOC_ANNO)); key.add(rdoc.get(RDOC_CODNUM)); key.add(rdoc.get(RDOC_NDOC)); if (rdoc.get_bool(RDOC_RIGAEVASA)) { bEvaso = true; break; } } return cache().get(LF_DOC, key); } bool TOrdinazione::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo) { const TString80 codart = ini_get_string(CONFIG_DITTA, "ci", "CODARTPR"); for (int i = 0; i < doc_in.items(); i++) { TDocumento& din = doc_in[i]; // Mi assicuro che ad ogni documento in ingresso ne corrisponda uno in uscita if (i >= doc_out.items()) { const TString4 codnum = codice_numerazione_finale(); bool bEvaso = false; const TRectype& ord = find_precedente(din, codnum, bEvaso); if (!ord.empty()) { if (bEvaso) { if (interattivo) error_box("Il preventivo è collegato all'ordine già evaso %s %d/%ld", (const char*)ord.get(DOC_CODNUM), ord.get_int(DOC_ANNO), ord.get_long(DOC_NDOC)); continue; } else { if (interattivo) warning_box("Il preventivo aggiornerà l'ordine %s %d/%ld", (const char*)ord.get(DOC_CODNUM), ord.get_int(DOC_ANNO), ord.get_long(DOC_NDOC)); } } TDocumento* doc = NULL; if (ord.empty()) { doc = new TDocumento('D', data_elab.year(), codnum, 0L); doc->put(DOC_TIPODOC, tipo_finale()); } else { doc = new TDocumento(ord); doc->destroy_rows(); } doc_out.add(doc); } const int cfg_levels = pe_crea_fasi_preventivo(din); if (cfg_levels <= 0) return false; TDocumento& don = doc_out[i]; din.put(DOC_STATO, stato_finale_doc_iniziale()); don.put(DOC_TIPOCF, din.get(DOC_TIPOCF)); don.put(DOC_CODCF, din.get(DOC_CODCF)); don.put(DOC_DATADOC, data_elab); don.put(DOC_NOTE, din.get(DOC_NOTE)); don.put(DOC_CODCMS, din.get(DOC_CODCMS)); don.put(DOC_STATO, stato_finale()); don.put(DOC_NUMDOCRIF, din.get(DOC_NDOC)); don.put(DOC_DATADOCRIF, din.get(DOC_DATADOC)); const int doc_levels = pe_numero_fasi(din); if (doc_levels <= 0) continue; // Should never happen const int nrows = din.physical_rows(); FOR_EACH_PHYSICAL_RDOC(din, r, rdoc) { const TString& tr = rdoc->get(RDOC_TIPORIGA); if (tr == _strFasi) { const int level = rdoc->get_int(RPRV_LEVEL); // Livello logico della riga [0,3] if (r >= nrows || (level == (cfg_levels-1) && din[r+1].is_descrizione())) continue; // Salta fasi vuote TRiga_documento& rout = don.new_row(_strFasi); TDocumento::copy_data(rout, *rdoc); rout.set_original_rdoc_key(*rdoc); rout.put(RDOC_CODCMS, din.get(DOC_CODCMS)); } else if (tr == _strDist) { TRiga_documento& rout = don.new_row(_strDist); TDocumento::copy_data(rout, *rdoc); rout.set_original_rdoc_key(*rdoc); rout.put(RDOC_CODCMS, din.get(DOC_CODCMS)); rout.put(RDOC_CODARTMAG, codart); } } don.write(); // Salva ordine } return true; } TOrdinazione::TOrdinazione(const TString& cod) : TElaborazione_esterna(cod) { _strFasi = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaFase", "05"); _strDist = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaDist", "P1"); } /////////////////////////////////////////////////////////// // Generazione fabbisogno /////////////////////////////////////////////////////////// class TFabbisognazione : public TElaborazione_esterna { TString4 _strFasi, _strDett, _strDist; public: virtual bool elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo = false); TFabbisognazione(const TString& cod); }; bool TFabbisognazione::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo) { for (int i = 0; i < doc_in.items(); i++) { TDocumento& din = doc_in[i]; if (i >= doc_out.items()) { const TString4 codnum = codice_numerazione_finale(); bool bEvaso = false; const TRectype& fabb = find_precedente(din, codnum, bEvaso); if (!fabb.empty()) { if (bEvaso) { if (interattivo) error_box("Il preventivo è collegato al fabbisogno già evaso %s %d/%ld", (const char*)fabb.get(DOC_CODNUM), fabb.get_int(DOC_ANNO), fabb.get_long(DOC_NDOC)); continue; } else { if (interattivo) warning_box("Il preventivo aggiornerà il fabbisogno %s %d/%ld", (const char*)fabb.get(DOC_CODNUM), fabb.get_int(DOC_ANNO), fabb.get_long(DOC_NDOC)); } } TDocumento* doc = new TDocumento('D', data_elab.year(), codnum, 0L); doc->put(DOC_TIPODOC, tipo_finale()); doc_out.add(doc); } const int cfg_levels = pe_crea_fasi_preventivo(din); if (cfg_levels <= 0) continue; TDocumento& don = doc_out[i]; din.put(DOC_STATO, stato_finale_doc_iniziale()); don.zero(DOC_TIPOCF); don.zero(DOC_CODCF); // NO clifo don.put(DOC_DATADOC, data_elab); don.put(DOC_NOTE, din.get(DOC_NOTE)); don.put(DOC_CODCMS, din.get(DOC_CODCMS)); don.put(DOC_STATO, stato_finale()); don.put(DOC_NUMDOCRIF, din.get(DOC_NDOC)); don.put(DOC_DATADOCRIF, din.get(DOC_DATADOC)); const int doc_levels = pe_numero_fasi(din); if (doc_levels <= 0) continue; // Should never happen bool dettagliato = false; real qta = UNO; const int nrows = din.rows(); FOR_EACH_PHYSICAL_RDOC(din, r, rdoc) { const TString& tr = rdoc->get(RDOC_TIPORIGA); if (tr == _strFasi) { // Nothig to do } else if (tr == _strDist) { // Aggiorna quantità qta = rdoc->get_real(RDOC_QTA); if (qta <= ZERO) qta = UNO; } else if (tr == _strDett) { TRiga_documento& rout = don.new_row(_strDett); TDocumento::copy_data(rout, *rdoc); rout.set_original_rdoc_key(*rdoc); rout.put(RDOC_CODCMS, din.get(DOC_CODCMS)); rout.put(RDOC_QTA, real(qta * rdoc->get_real(RDOC_QTA))); rout.put(RDOC_PREZZO, rdoc->get(RDOC_QTAGG5)); dettagliato = true; } } if (dettagliato) don.write(); // Salva nuovo documento else { if (interattivo) error_box(FR("Il preventivo %s %d/%ld non ha articoli: impossibile generare il fabbisogno"), (const char*)din.get(DOC_CODNUM), din.get_int(DOC_ANNO), din.get_long(DOC_NDOC)); } } return true; } TFabbisognazione::TFabbisognazione(const TString& cod) : TElaborazione_esterna(cod) { _strFasi = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaFase", "05"); _strDist = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaDist", "P1"); _strDett = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaDett", "01"); } /////////////////////////////////////////////////////////// // Utility pubbliche /////////////////////////////////////////////////////////// const TString& pe_trova_elaborazione(const TRectype& doc, char tipo) { TString16 cod; const TString& codnum = doc.get(DOC_CODNUM); TString str; if (tipo == 'F') str << "USE %ELD SELECT (STR(I0=\"0\"))&&(S3=\"pe1 -5\")&&(S5=\"" << codnum << "\")"; // Fabbisogni else str << "USE %ELD SELECT (STR(I0=\"0\"))&&(S3=\"pe1 -4\")&&(S5=\"" << codnum << "\")"; // Ordini TRecordset* eld = create_recordset(str); if (eld != NULL) { for (bool ok = eld->move_first(); ok; ok = eld->move_next()) { const TString& c = eld->get("CODTAB").as_string(); const TElaborazione e(c); if (e.is_document_ok(doc)) { cod = c; break; } } delete eld; } return get_tmp_string() = cod; } const TString& pe_trova_elaborazione(const TMask& m, char tipo) { TRectype doc(LF_DOC); doc.put(DOC_PROVV, 'D'); doc.put(DOC_ANNO, m.get(DOC_ANNO)); doc.put(DOC_CODNUM, m.get(DOC_CODNUM)); doc.put(DOC_NDOC, m.get(DOC_NDOC)); doc.put(DOC_TIPODOC, m.get(DOC_TIPODOC)); doc.put(DOC_STATO, m.get(DOC_STATO)); return pe_trova_elaborazione(doc, tipo); } bool pe_genera_documento(TRectype& doc, const TString& cod, char tipo) { TString16 codelab = cod; if (codelab.blank()) codelab = pe_trova_elaborazione(doc, tipo); const TString& app = cache().get("%ELD", codelab, "S3"); tipo = app.find("-5") > 0 ? 'F' : 'O'; TElaborazione* e = NULL; if (tipo == 'F') e = new TFabbisognazione(codelab); else e = new TOrdinazione(codelab); if (e->empty()) { delete e; return error_box(FR("Impossibile trovare l'elaborazione %s"), (const char*)cod); } const TDate oggi(TODAY); TLista_documenti doc_in, doc_out; doc_in.add(new TDocumento(doc)); bool ok = e->elabora(doc_in, doc_out, oggi, true); if (ok) { int err = doc_in.rewrite(); if (err == NOERR) { const TRectype& idoc = doc_in[0]; for (int i = 0; i < idoc.items(); i++) { const char* fld = idoc.fieldname(i); const TString& val = idoc.get(fld); if (val.full()) doc.put(fld, val); } err = doc_out.write(); if (err != NOERR) error_box(TR("Errore %d in scrittura del documento"), err); } } delete e; return ok; } /////////////////////////////////////////////////////////// // TOrdinazione_app /////////////////////////////////////////////////////////// class TOrdinazione_app : public TSkeleton_application { protected: virtual void main_loop(); }; void TOrdinazione_app::main_loop() { TFilename ininame; if (argc() >= 2) { const TFixed_string arg = argv(2); ininame = arg.starts_with("-i", true) ? arg.mid(2) : arg; } TConfig ini(ininame, "Transaction"); const TString8 codelab = ini.get("Action"); ini.set_paragraph("33"); TRectype doc(LF_DOC); doc.put(DOC_PROVV, ini.get(DOC_PROVV)); doc.put(DOC_ANNO, ini.get(DOC_ANNO)); doc.put(DOC_CODNUM, ini.get(DOC_CODNUM)); doc.put(DOC_NDOC, ini.get(DOC_NDOC)); if (pe_genera_documento(doc, codelab, 'O')) { ini.set_paragraph("Transaction"); ini.set("Result", "OK"); ini.set("Error", "0"); ini.set_paragraph("33"); for (int i = 0; i < doc.items(); i++) { const char* fld = doc.fieldname(i); const TString& val = doc.get(fld); if (val.full()) ini.set(fld, val); } } } int pe1500(int argc, char* argv[]) { TOrdinazione_app a; a.run(argc, argv, TR("Generazione ordini")); return 0; }