#include #include #include #include "velib04.h" /////////////////////////////////////////////////////////// // Lista di documenti /////////////////////////////////////////////////////////// TDate TLista_documenti::num2date(char provv, int anno, const char* codnum, long num) const { TLocalisamfile doc(LF_DOC); CHECK(num > 0, "Numero documento nullo."); TDocumento::set_key(doc.curr(), provv, anno, codnum, num); if (doc.read(_isgteq) != NOERR) // In caso d'errore ... doc.last(); // prendi l'ultimo return doc.get_date(DOC_DATADOC); } bool TLista_documenti::find(char provv, int anno, const char* codnum, long ndoc) const { bool found = false; const int it = items(); if (ndoc > 0 && it > 0) { for (int i = 0; !found && i < it; i++) { const TRectype& head = doc(i).head(); found = (head.get_long(DOC_NDOC) == ndoc) && (head.get_char(DOC_PROVV) == provv) && (head.get_int(DOC_ANNO) == anno) && (head.get(DOC_CODNUM) == codnum); } } return found; } int TLista_documenti::read(char provv, char tipocf, long clifo, int anno, TToken_string& tipidoc, TToken_string& statidoc, const TDate& dd, const TDate& ad, const char* codnum, long dn, long an) { CHECK(provv == 'D' || provv == 'P', "Provvisorio o Definitivo?"); CHECK(tipocf == 'C' || tipocf == 'F', "Il tipo deve essere Cliente o Fornitore"); CHECKD(clifo > 0L, "Codice cliente non valido", clifo); CHECKD(anno > 2000, "Anno non valido: ", anno); CHECK(!tipidoc.empty_items(), "Lista dei tipi documento vuota"); CHECK(!statidoc.empty_items(), "Lista degli stati documento vuota"); TRelation doc(LF_DOC); TRectype start(LF_DOC), stop(LF_DOC); int anno_start, anno_stop; start.put(DOC_TIPOCF, tipocf); stop.put(DOC_TIPOCF, tipocf); start.put(DOC_CODCF, clifo); stop.put(DOC_CODCF, clifo); start.put(DOC_PROVV, provv); stop.put(DOC_PROVV, provv); anno_start = anno_stop = anno; if (dd.ok()) { anno_start = dd.year(); start.put(DOC_ANNO, anno_start); } if (ad.ok()) { anno_stop = ad.year(); stop.put(DOC_ANNO, anno_stop); } if (dn > 0) { const TDate d(num2date(provv, anno_start, codnum, dn)); start.put(DOC_DATADOC, d); start.put(DOC_ANNO, d.year()); start.put(DOC_NDOC, dn); } else { if (dd.ok() && dd > botime) start.put(DOC_DATADOC, dd); if (anno_start <= anno_stop) start.put(DOC_ANNO, anno_start); } if (an > 0) { const TDate d(num2date(provv, anno_stop, codnum, an)); stop.put(DOC_DATADOC, d); stop.put(DOC_ANNO, d.year()); stop.put(DOC_NDOC, an); } else { if (ad.ok() && ad < eotime) stop.put(DOC_DATADOC, ad); stop.put(DOC_ANNO, anno_stop); } TString filter; if (codnum && *codnum > ' ') { if (!start.get(DOC_DATADOC).empty()) start.put(DOC_CODNUM, codnum); if (!stop.get(DOC_DATADOC).empty()) stop.put(DOC_CODNUM, codnum); filter << DOC_CODNUM << "=\"" << codnum << '"'; } TCursor cur(&doc, filter, 2, &start, &stop); const TRectype& head = cur.curr(); _documenti.destroy(); for (cur = 0; cur.ok(); ++cur) { const TString4 tipodoc = head.get(DOC_TIPODOC); const TString4 statodoc = head.get(DOC_STATO); bool match = false; for (int i = tipidoc.items()-1; i>=0; i--) { const TString & tipo = tipidoc.get(i); if (tipo.blank() || tipodoc == tipo) { const TString & stato = statidoc.get(i); if (stato.blank() || statodoc == stato) { match = true; break; } } } if (match) { TDocumento* d = new TDocumento(head); _documenti.add(d); } } return _documenti.items(); } int TLista_documenti::write(bool re) const { const int docs = _documenti.items(); TString msg; if (re) msg.format(FR("Aggiornamento di %d documenti"), docs); else msg.format(FR("Creazione di %d documenti"), docs); TProgress_monitor pi(docs, msg, true); int err = NOERR; for (int i = 0; i < docs && err == NOERR; i++) { TDocumento& d = (TDocumento&)doc(i); err = d.write(re); d.flush_rows(); if (!pi.add_status(1)) break; } return err; } static int doc_cmp(const TSortable& o1, const TSortable& o2, void* jolly) { const TDocumento& d1 = (const TDocumento&)o1; const TDocumento& d2 = (const TDocumento&)o2; TToken_string& order_by = *(TToken_string*)jolly; int cmp = 0; FOR_EACH_TOKEN(order_by, fld) { const TFieldtypes ft = d1.type(fld); switch(ft) { case _intfld : case _longfld : case _intzerofld : case _longzerofld: cmp = d1.get_long(fld) - d2.get_long(fld); break; case _datefld : cmp = d1.get_date(fld) - d2.get_date(fld); break; default : cmp = d1.get(fld).compare(d2.get(fld), -1, true); break; } if (cmp != 0) break; } return cmp; } int TLista_documenti::sort(const char* fields) { TToken_string orderby = fields; _documenti.sort(doc_cmp, &orderby); return items(); } /////////////////////////////////////////////////////////// // TLista_clifo /////////////////////////////////////////////////////////// void TLista_clifo::TClifo::init(const TRectype& rec, const TRectype& ven) { _codice = rec.get_long(CLI_CODCF); CHECK(_codice > 0, "Codice cliente nullo"); if (!ven.empty()) { _agente = ven.get_long(CLI_CODAG); _zona = ven.get_long(CLI_CODZONA); } else _agente = _zona = 0; } bool TLista_clifo::TClifo::read(char tipo, long cod) { TRelation clifo(LF_CLIFO); clifo.add(LF_CFVEN, "TIPOCF=TIPOCF|CODCF=CODCF"); TRectype& curr = clifo.curr(); curr.put(CLI_TIPOCF, tipo); curr.put(CLI_CODCF, cod); if (clifo.read() == NOERR) init(curr, clifo.curr(LF_CFVEN)); else zero(); return ok(); } TLista_clifo::TClifo::TClifo(const TRectype& rec) { CHECK(rec.num() == LF_CLIFO || rec.num() == LF_DOC, "Record senza TIPOCF e CODCF"); const char tipo = rec.get_char(CLI_TIPOCF); const long codice = rec.get_long(CLI_CODCF); read(tipo, codice); } int TLista_clifo::leggi(long dc, long ac, long da, long aa, const char * dz, const char * az) { TRelation clifo(LF_CLIFO); clifo.add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF"); TRectype start(LF_CLIFO), stop(LF_CLIFO); start.put(CLI_TIPOCF, tipo()); if (dc > 0) start.put(CLI_CODCF, dc); stop.put(CLI_TIPOCF, tipo()); if (ac > 0) stop.put(CLI_CODCF, ac); TString filter(32); if (da > 0) filter << '(' << LF_CFVEN << "->" << CLI_CODAG << ">=" << da << ')'; if (aa > 0) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODAG << "<=" << aa << ')'; } if (dz && (*dz !='\0')) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << ">=\"" << dz << "\")"; } if (az && (*az !='\0')) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << "<=\"" << az << "\")"; } TCursor cur(&clifo, "", 1, &start, &stop); if (filter.not_empty()) cur.setfilter(filter, TRUE); const TRectype& cli = cur.curr(); const TRectype& ven = cur.curr(LF_CFVEN); for (cur = 0; cur.ok(); ++cur) { TClifo* c = new TClifo(cli, ven); _clifo.add(c); } if (dc > 0 || ac > 0) ordina_per_codice(); else if (da > 0 || aa > 0) ordina_per_agente(); else if ((dz && (*dz !='\0')) || (az && (*dz !='\0'))) ordina_per_zona(); return _clifo.items(); } static bool add_filter(TString& filter, const char* name, long da, long al) { if (!(da > 0 || al > da)) return false; if (filter.full()) filter << "&&"; TString16 field = name; if (xvt_str_compare_ignoring_case(name, DOC_CODCF) != 0) field.insert("17->"); if (da == al) filter << "(" << field << "==" << da << ")"; else if (da <= 0 && al > 0) filter << "(" << field << "<=" << al << ")"; else if (da > 0 && al < da) filter << "(" << field << ">=" << da << ")"; else filter << "(BETWEEN(" << field << ',' << da << ',' << al << "))"; return true; } int TLista_clifo::leggi_doc(const TElaborazione& eld, const TDate& dd, const TDate& ad, long dc, long ac, long da, long aa, const char* dz, const char* az) { if (!dd.ok()) return leggi(dc, ac, da, aa, dz, az); TRelation doc(LF_DOC); doc.add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF"); const TRectype& rec = doc.curr(); TRectype start(rec), stop(rec); start.put(DOC_DATADOC, dd); stop.put (DOC_DATADOC, ad); TString filter(127); add_filter(filter, DOC_CODCF, dc, ac); add_filter(filter, CLI_CODAG, da, aa); if (dz && (*dz !='\0')) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << ">=\"" << dz << "\")"; } if (az && (*az !='\0')) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << "<=\"" << az << "\")"; } TCursor cur(&doc, filter, 3, &start, &stop); TBit_array buoni; for (cur = 0; cur.ok(); ++cur) { const char tipocf = rec.get_char(DOC_TIPOCF); const long codcf = rec.get_long(DOC_CODCF); if (tipocf == tipo() && !buoni[codcf]) { if (eld.is_document_ok(rec)) { TClifo* c = new TClifo(tipocf, codcf); _clifo.add(c, codcf); buoni.set(codcf); } } } if (da > 0 || aa > 0) ordina_per_agente(); else { if ((dz && (*dz !='\0')) || (az && (*dz !='\0'))) ordina_per_zona(); else ordina_per_codice(); } return _clifo.items(); } int TLista_clifo::leggi_ragsoc(const char *dr, const char * ar, long da, long aa, const char * dz, const char * az) { TRelation clifo(LF_CLIFO); clifo.add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF"); TRectype start(LF_CLIFO), stop(LF_CLIFO); start.put(CLI_TIPOCF, tipo()); if (dr && *dr) start.put(CLI_RAGSOC, dr); stop.put(CLI_TIPOCF, tipo()); if (ar && *ar) stop.put(CLI_RAGSOC, ar); TString filter(32); if (da > 0) filter << '(' << LF_CFVEN << "->" << CLI_CODAG << ">=" << da << ')'; if (aa > 0) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODAG << "<=" << aa << ')'; } if (dz && (*dz !='\0')) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << ">=\"" << dz << "\")"; } if (az && (*az !='\0')) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << "<=\"" << az << "\")"; } TCursor cur(&clifo, "", 2, &start, &stop); if (filter.not_empty()) cur.setfilter(filter, TRUE); const TRectype& cli = cur.curr(); const TRectype& ven = cur.curr(LF_CFVEN); for (cur = 0; cur.ok(); ++cur) { TClifo* c = new TClifo(cli, ven); _clifo.add(c); } return _clifo.items(); } int TLista_clifo::sort_by_code(const TObject** o1, const TObject** o2) { TLista_clifo::TClifo* c1 = (TLista_clifo::TClifo*)*o1; TLista_clifo::TClifo* c2 = (TLista_clifo::TClifo*)*o2; const long d = c1->codice() - c2->codice(); return d == 0L ? 0 : (d > 0 ? +1 : -1); } int TLista_clifo::sort_by_agent(const TObject** o1, const TObject** o2) { TLista_clifo::TClifo* c1 = (TLista_clifo::TClifo*)*o1; TLista_clifo::TClifo* c2 = (TLista_clifo::TClifo*)*o2; const long d = c1->agente() - c2->agente(); return d == 0L ? 0 : (d > 0 ? +1 : -1); } int TLista_clifo::sort_by_zone(const TObject** o1, const TObject** o2) { TLista_clifo::TClifo* c1 = (TLista_clifo::TClifo*)*o1; TLista_clifo::TClifo* c2 = (TLista_clifo::TClifo*)*o2; const long d = c1->zona() - c2->zona(); return d == 0L ? 0 : (d > 0 ? +1 : -1); } int TLista_clifo::ordina_per_codice() { _clifo.sort(sort_by_code); return _clifo.items(); } int TLista_clifo::ordina_per_agente() { _clifo.sort(sort_by_agent); return _clifo.items(); } int TLista_clifo::ordina_per_zona() { _clifo.sort(sort_by_zone); return _clifo.items(); } int TLista_clifo::find(long cod) const { int i; for (i = items()-1; i >= 0; i--) if (clifo(i).codice() == cod) break; return i; } int TLista_clifo::add(long cod) { int pos = find(cod); if (pos < 0) { TClifo* c = new TClifo(tipo(), cod); pos = _clifo.add(c); } return pos; } /////////////////////////////////////////////////////////// // TParametri_elaborazione /////////////////////////////////////////////////////////// void TParametri_elaborazione::set(const char* name, const char* val) { _par.add(name, new TString(val), true); } const TString & TParametri_elaborazione::get(const char * name) const { const TObject* val = _par.objptr(name); return val ? *(const TString*)val : EMPTY_STRING; } /////////////////////////////////////////////////////////// // TElaborazione /////////////////////////////////////////////////////////// const TString& TElaborazione::tipo_iniziale(int i) const { if (i >= 0 && i < 10) { const TString& t = get("S2").mid(i*4, 4); if (t.full()) return ((TString&)t).rtrim(); } return EMPTY_STRING; } bool TElaborazione::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo) { SORRY_BOX(); return false; } TElaborazione::TElaborazione(const char* cod) : TRectype(LF_TABCOM) { settab("ELD"); if (cod && *cod) read(cod); } int TElaborazione::read(const char* cod) { int err = NOERR; TRectype::operator=(cache().get("%ELD", cod)); if (empty()) err = _iskeynotfound; return err; } bool TElaborazione::is_document_ok(const TRectype& doc) const { bool ok = false; const TString4 codnum = doc.get(DOC_CODNUM); const TString& codnumel = codice_numerazione_iniziale(); if (codnumel.blank() || codnum == codnumel) { const TString4 tipodoc = doc.get(DOC_TIPODOC); const char stato = doc.get_char(DOC_STATO); for (int i = 0; !ok && i < TElaborazione::_max_tipi_doc_elab; i++) { const TString& tipel = tipo_iniziale(i); if (tipel.blank()) break; const char stael = stato_iniziale(i); ok = tipodoc == tipel && stato == stael; } } return ok; } void TElaborazione::tipi_stati_iniziali(TToken_string& tipi, TToken_string& stati) const { TString4 t; tipi.cut(0); stati.cut(0); for (int i = 0; i < TElaborazione::_max_tipi_doc_elab; i++) { t = tipo_iniziale(i); const char s = stato_iniziale(i); if (t.blank() && s == '\0') break; else if (t.full() || s > ' ') { tipi.add(t); stati.add(s); } } CHECK(!tipi.empty_items(), "Nessun tipo documento valido"); CHECK(!stati.empty_items(), "Nessuno stato documento valido"); } /////////////////////////////////////////////////////////// // TElaborazione_esterna /////////////////////////////////////////////////////////// TElaborazione_esterna::TElaborazione_esterna(const char* cod) : TElaborazione(cod) { } bool TElaborazione_esterna::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo) { if (applicazione_esterna().blank()) return error_box("Non è stato specificato il nome del'applicazione esterna"); CHECK(doc_in.items() == 1, "Si deve specificare un solo documento in entrata"); CHECK(doc_out.items() <= 1, "Si deve specificare un solo documento in uscita"); TDocumento& d = doc_in[0]; TFilename name; name.temp("ext"); TString16 par; { TConfig c(name, "Transaction"); c.set("Action", codice()); c.set("DataElab", data_elab.string()); c.set("Interattivo", interattivo); if (doc_out.items() == 1) { c.set("ProvvOut", doc_out[0].get(DOC_PROVV)); c.set("AnnoOut", doc_out[0].get(DOC_ANNO)); c.set("CodNumOut", doc_out[0].get(DOC_CODNUM)); c.set("NDocOut", doc_out[0].get(DOC_NDOC)); } else if (codice_numerazione_finale().full()) { c.set("ProvvOut", d.get(DOC_PROVV)); c.set("AnnoOut", d.get(DOC_ANNO)); c.set("CodNumOut", codice_numerazione_finale()); c.set("NDocOut", 0L); } par.format("%d", LF_DOC); const int doc_fields = d.items(); for (int i = 0; i < doc_fields; i++) { const char* fname = d.fieldname(i); const TFieldref f(fname, LF_DOC); f.write(c, par, d.get(fname)); } for (TVariable_field* v = d.first_variable_field(); v ; v = d.succ_variable_field()) c.set(v->name(), v->get(), par); FOR_EACH_PHYSICAL_RDOC(d, r, row) { par.format("%d,%d", LF_RIGHEDOC, r); const int row_fields = row->items(); for (int i = 0; i < row_fields; i++) { const char* fname = row->fieldname(i); const TFieldref f(fname, LF_RIGHEDOC); f.write(c, par, row->get(fname)); } for (TVariable_field * v = row->first_variable_field(); v ; v = row->succ_variable_field()) c.set(v->name(), v->get(), par); } } TString command_line; command_line << applicazione_esterna() << " /i" << name; TExternal_app app(command_line); if (app.run() == 0) { TConfig c(name, "Transaction"); const TString & res = c.get("Result"); if (res == "SUCCESS") { TDocumento& d = doc_in[0]; const int doc_fields = d.items(); par.format("%d", LF_DOC); for (int i = 0; i < doc_fields; i++) { const char* fname = d.fieldname(i); TFieldref f(fname, LF_DOC); d.put(fname, f.read(c, par)); } for (TVariable_field * v = d.first_variable_field(); v ; v = d.succ_variable_field()) v->put(c.get(v->name(), par)); TString_array p; c.list_paragraphs(p); d.destroy_rows(); for (int r = 1; ; r++) { par.format("%d,%d", LF_RIGHEDOC, r); if (p.find(par) < 0) break; const TString& tiporiga = c.get(RDOC_TIPORIGA, par, -1, "01"); TRiga_documento& row = d.new_row(tiporiga); for (int i = row.items()-1; i >= 0; i--) { const char* fname = row.fieldname(i); const TFieldref f(fname, LF_RIGHEDOC); const TString& val = f.read(c, par); if (val.full()) row.put(fname, val); } } const char final = stato_finale_doc_iniziale()[0]; if (final > '0' && d.stato() != final) d.stato(final); return true; } else if (res == "OUTDOC") { if (doc_out.items()) { const TString& ndoc = c.get("NDocOut", "Transaction"); if (ndoc != doc_out[0].get(DOC_NDOC)) doc_out[0].put(DOC_NDOC, ndoc); doc_out[0].read(); return true; } } } return false; } /////////////////////////////////////////////////////////// // TCopia_documento /////////////////////////////////////////////////////////// TCopia_documento::TCopia_documento(const char* cod) : TElaborazione(cod), _preserve_original_rif(false) { } bool TCopia_documento::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool /*interattivo*/) { // CHECK(doc_in.items() == doc_out.items(), "Si deve specificare un numero uguale di documenti in entrata ed in uscita"); pre_process_input(doc_in); for (int d = 0; d < doc_in.items(); d++) { TDocumento& doc_src = doc_in[d]; if (doc_out.items() <= d) { const TString4 codnum = codice_numerazione_finale(); doc_out.add(new TDocumento('D', doc_src.get_int(DOC_ANNO), codnum, 0L)); } TDocumento& doc_dest = doc_out[d]; doc_dest.copy_contents(doc_src); const TString& tipodoc = tipo_finale(); doc_dest.put(DOC_TIPODOC, tipodoc); const TString& stato = stato_finale(); doc_dest.put(DOC_STATO, stato); // Scancello tutti gli inutili riferimenti al documento origine if (!_preserve_original_rif) { FOR_EACH_PHYSICAL_RDOC(doc_dest, r, rdoc) rdoc->reset_original_rdoc_key(); } if (data_elab.ok()) doc_dest.put(DOC_DATADOC, data_elab); doc_src.put(DOC_STATO, stato_finale_doc_iniziale()); } post_process_input(doc_in); post_process(doc_out, doc_in); return true; }