#include #include #include "velib.h" #include "vepriv.h" #include "verig.h" #include "../db/dblib.h" #include "../mg/mglib.h" ///////////////// ////////////////////////////////////////// // Tipo documento /////////////////////////////////////////////////////////// TAssoc_array TTipo_documento::_formule_documento; TTipo_documento::TTipo_documento(const char* tipodoc) : TRectype(LF_TABCOM), _tipocf('\0') { settab("TIP"); if (tipodoc && *tipodoc) read(tipodoc); } TTipo_documento::TTipo_documento(const TRectype& rec) : TRectype(rec), _tipocf('\0') { read_formule(); } TTipo_documento::~TTipo_documento() { } int TTipo_documento::read(const char* tipodoc) { *this = cache().get("%TIP", tipodoc); int err = empty() ? _iskeynotfound : NOERR; _formule.cut(0); if (err == NOERR) read_formule(); else yesnofatal_box("Tipo documento errato: %s", tipodoc); return err; } const TString& TTipo_documento::mask_name() const { TString& name = get_tmp_string(); name = get("S4"); name.cut(8); name.trim(); return name; } const TFilename& TTipo_documento::profile_name(TFilename& profile) const { profile = get("S4"); profile.cut(8); profile.trim(); profile.ext("ini"); return profile; } bool TTipo_documento::main_print_profile(TFilename& report, int filter) const { TString8 base = get("S5").left(8); base.trim(); bool ok = base.full(); if (ok) { ok = false; if (filter != 1) { report = base; report.ext("rep"); ok = report.custom_path(); } if (!ok && filter != 2) { report = base; report.ext("frm"); ok = report.custom_path(); } } return ok; } bool TTipo_documento::additional_print_profile(TFilename& report, int filter) const { TString8 base = get("S5").mid(8, 8); base.trim(); bool ok = base.full(); if (ok) { ok = false; if (filter != 1) // Non voglio i soli frm { report = base; report.ext("rep"); ok = report.custom_path(); } if (!ok && filter != 2) // Non voglio i soli rep { report = base; report.ext("frm"); ok = report.custom_path(); } } return ok; } bool TTipo_documento::mail_print_profile(TFilename& report) const { report = get("S5").mid(16, 8); bool ok = report.full(); if (ok) { report.trim(); report.ext("rep"); ok = report.custom_path(); } if (!ok) ok = main_print_profile(report, 2); // Solo rep return ok; } bool TTipo_documento::is_costo() const { return _tipocr == 'C' || tipocf() == 'F'; } bool TTipo_documento::is_ricavo() const { return _tipocr == 'R' || tipocf() == 'C'; } const char TTipo_documento::tipocf() const { if (_tipocf < ' ') { TFilename pn; profile_name(pn); TConfig prof(pn); (char&)_tipocf = prof.get_char("TIPOCF", "MAIN"); } return _tipocf; } const TString& TTipo_documento::riferimento(const TDocumento & doc, TString& rif) const { rif = get("S1"); int p = rif.find('{'); while (p >= 0) { const int last = rif.find('}'); const TString16 field_name(rif.sub(p + 1, last)); const TFieldref field(field_name, LF_DOC); if (last < 0) rif.cut(p); else { const int len = rif.len() - last; for (int i = 0; i <= len; i++) rif[p + i] = rif[last + i + 1]; } if (field.file() == LF_DOC) rif.insert(field.read(doc), p); else { TString16 key(doc.get(DOC_TIPOCF)); key << "|" << doc.get(DOC_CODCF); const TRectype& rec = cache().get(field.file(), key); rif.insert(field.read(rec), p); } p = rif.find('{'); } return rif; } const TString_array& TTipo_documento::keys_descrs() const { if (_keys_descrs.empty()) { TFilename pn; profile_name(pn); TConfig prof(pn, "RIGHE"); TTipo_riga_documento tr; TToken_string k, d; for (int i = 0; ; i++) { const TString& tiporiga = prof.get("Tipo", NULL, i); if (tiporiga.full()) { tr.read(tiporiga); k.add(tr.codice()); d.add(tr.descrizione()); } else break; //esce da un eventuale ciclo infinito } if (k.blank()) { TTable tri("%TRI"); TFilename name; for (int err = tri.first(); err == NOERR; err = tri.next()) { name.format("verig%s.msk", (const char *) tri.get("CODTAB")); name.custom_path(); if (fexist(name)) { k.add(tri.get("CODTAB")); d.add(tri.get("S0")); } } } // Fool const ((TString_array&)_keys_descrs).add(k); ((TString_array&)_keys_descrs).add(d); } return _keys_descrs; } const TString_array& TTipo_documento::sheet_columns() const { if (_sheet_columns.empty()) { TFilename pn; profile_name(pn); TConfig prof(pn, "SHEET"); for (int i = 0; i < MAX_COLUMNS; i++) { const TString& id = prof.get("Col", NULL, i); if (atoi(id) <= 0) break; ((TString_array&)_sheet_columns).add(id); } } return _sheet_columns; } const TString_array& TTipo_documento::handlers() const { if (_handlers.empty()) { TString16 chiave; TFilename pn; profile_name(pn); TConfig prof(pn, "HANDLERS"); for (int i = 0; ; i++) { const TString & h = prof.get("Handler", NULL, i); if (h.empty()) break; ((TString_array &)_handlers).add(h); } } return _handlers; } void TTipo_documento::set_defaults(TMask& m) const { if (_defaults.empty()) // Carica lo string_array con i defaults { TFilename pn; profile_name(pn); TConfig prof(pn, "DEFAULT"); for(int i = 0; ; i++) { TToken_string s(prof.get("Default", NULL, i)); if (s.empty()) break; const int field = s.get_int(); ((TTipo_documento*)this)->_defaults.add(s.get(), field); } } // Setta i campi della maschera FOR_EACH_ARRAY_ROW(_defaults, i, tt) { m.set(i, *tt, TRUE); } } void TTipo_documento::add_formula_if_needed(TConfig& profile, TString& variable, const char* varname, const char* formula) { variable = profile.get(varname, "MAIN"); if (variable.blank()) variable = varname; const TRectype& trr = cache().get("%FRD", variable); if (trr.empty() || trr.get("S1").empty()) _formule_documento.add(variable, new TFormula_documento(_documento, variable, formula), TRUE); if (_formule.find(variable) < 0) _formule.add(variable); } void TTipo_documento::read_formule() { TFilename profile; profile_name(profile); TConfig prof(profile, "MAIN"); prof.write_protect(); // Altrimenti non si distrugge!!! _tipocr = prof.get_char("TIPOCR", NULL, -1, ' '); _formule = prof.get("CAMPICALC"); const TString& calcoli = prof.get("CALCOLI"); if (calcoli == "*") { TTable frd("%FRD"); for (int err = frd.first(); err == NOERR; err = frd.next()) { const TString & formula = frd.get("CODTAB"); if (_formule.find(formula) < 0) _formule.add(formula); } } else _formule.add(calcoli); add_formula_if_needed(prof, _totale, "TOTALE", "IMPONIBILI()+IMPOSTE()"); if (_totale == "TOTALE") _totale = "TOTDOC"; _totale_netto = "_"; _totale_netto << _totale; add_formula_if_needed(prof, _basesconto, "BASESCONTO", "SOMMA(\"IMPONIBILE()\", \"(TIPO()!='S') && (TIPO()!='C')\")"); add_formula_if_needed(prof, _spese, "SPESE", "SOMMA(\"IMPONIBILE()\", \"TIPO() == 'S'\")"); add_formula_if_needed(prof, _totvalres, "TOTVALRES", "VALDOC(0)"); add_formula_if_needed(prof, _totvalore, "TOTVALORE", "VALDOC(1)"); if (provvigioni()) { TString80 campo(prof.get("TOTPROVV")); if (campo.empty()) campo = "TOTPROVV"; const TRectype& frd = cache().get("%FRD", campo); _totprovv = "_"; _totprovv << campo; TString80 expr(frd.get("S1")); if (expr.empty()) expr = "SOMMA(\"PROVV()\")"; _formule_documento.add(_totprovv, new TFormula_documento(_documento, _totprovv, expr, TRUE)); if (_formule.find(campo) < 0) _formule.add(campo); _formule.add(_totprovv); _formule_documento.add(campo, new TFormula_documento(_documento, campo, "TOTPROVV()"), TRUE); campo = prof.get("TOTPROVV1"); if (campo.empty()) campo = "TOTPROVV1"; const TRectype& frd1 = cache().get("%FRD", campo); _totprovv1 = "_"; _totprovv1 << campo; expr = frd1.get("S1"); if (expr.empty()) expr = "SOMMA(\"PROVV(-883,0)\")"; _formule_documento.add(_totprovv1, new TFormula_documento(_documento, _totprovv1, expr)); if (_formule.find(campo) < 0) _formule.add(campo); _formule.add(_totprovv1); _formule_documento.add(campo, new TFormula_documento(_documento, campo, "TOTPROVV(-883,0)")); } _totale_cont = prof.get("TOTALECONT"); _cnt_prezzi = prof.get_bool("CONTROLLO_PREZZI"); _field_prezzo = prof.get(RDOC_PREZZO); _field_qta = prof.get(RDOC_QTA, NULL, -1, RDOC_QTA); _field_qtaevasa = prof.get(RDOC_QTAEVASA, NULL, -1, RDOC_QTAEVASA); _field_qta_mag = prof.get("QTA_MAG"); if(_field_qta_mag.blank()) _field_qta_mag = _field_qta; _field_qtaevasa_mag = prof.get("QTAEVASA_MAG"); if(_field_qtaevasa_mag.blank()) _field_qtaevasa_mag = _field_qtaevasa; _check_qta = prof.get_char("CHECK_QTA", "MAIN"); _load_cont = prof.get_bool("LOAD_CONT", "MAIN"); _raee_cod = prof.get("RAEE_COD", "MAIN"); _raee_fld = prof.get("RAEE_FLD", "MAIN"); _str_desc_doc = prof.get("DESCRIZIONE_DOC"); _str_desc_rdoc = prof.get("DESCRIZIONE_RDOC"); _show_evaded_lines = !prof.get_bool("NASCONDI_RIGHE_EVASE"); // Normalmente mostra anche evase _non_evadere = prof.get_bool("NON_EVADERE"); // Normalmente mostra anche evase _module = prof.get("MODULE", NULL, -1, "ve").left(2); } bool TTipo_documento::stato_with_mov_mag(const char stato) const { if (!mov_mag()) return FALSE; const char stato_finale(stato_mov_finale()); if (stato_finale > ' ' && stato > stato_finale) return FALSE; const char stato_iniziale(stato_mov_iniziale()); return stato >= stato_iniziale; } TFormula_documento* TTipo_documento::succ_formula(bool restart) { if (restart) _formule.restart(); TString formula = _formule.get(); while (formula.not_empty()) { if (formula.blank()) formula = _formule.get(); else break; } if (formula.not_empty()) { char *expr = NULL; const int p = formula.find('='); if (p > 0) { expr = (char *) (const char *) formula + p; *expr = '\0'; expr++; } TFormula_documento* o = (TFormula_documento*)_formule_documento.objptr(formula); if (o == NULL) { o = new TFormula_documento(_documento, formula, expr); _formule_documento.add(formula, o); } return o; } return NULL; } bool TTipo_documento::scarica_residuo() const { if (is_ordine() && !riporta_ordinato()) return true; return get_bool("B4"); } /////////////////////////////////////////////////////////// // Espressione documento /////////////////////////////////////////////////////////// TExpr_documento::TExpr_documento(const char* expression, TTypeexp type, TDocumento* doc, TRiga_documento * row) : TExpression(type), _doc(doc), _row(row) { if (!set(expression, type)) error_box("Wrong expression : '%s'", expression); } int TExpr_documento::parse_user_func(const char * name, int nparms) const { if (strcmp(name, "SOMMA") == 0) return nparms > 0 || nparms < 3 ? _somma : -1; if (strcmp(name, "BOLLI") == 0) return nparms > 0 || nparms < 4 ? _bolli : -1; if (strcmp(name, "_BOLLI") == 0) return nparms > 0 || nparms < 3 ? _bolli_int : -1; if (strcmp(name, "SPESEINC") == 0) return nparms > 0 || nparms < 4 ? _spinc : -1; if (strcmp(name, "PREZZO") == 0) return nparms < 4 ? _prezzo : -1; if (strcmp(name, "IMPORTO") == 0) return nparms < 4 ? _importo : -1; if (strcmp(name, "SCONTO") == 0) return nparms < 2 ? _sconto : -1; if (strcmp(name, "IMPONIBILE") == 0) return nparms == 0 ? _imponibile : -1; if (strcmp(name, "IVA") == 0) return nparms == 0 ? _iva : -1; if (strcmp(name, "PROVV") == 0) return nparms < 3 ? _provv : -1; if (strcmp(name, "QUANT") == 0) return nparms < 2 ? _quant : -1; if (strcmp(name, "QUANTEVASA") == 0) return nparms < 2 ? _quantevasa : -1; if (strcmp(name, "QTARES") == 0) return nparms < 2 ? _qtares : -1; if (strcmp(name, "VALDOC") == 0) return nparms < 3 ? _valdoc : -1; if (strcmp(name, "TIPO") == 0) return nparms == 0 ? _tipo : -1; if (strcmp(name, "IMPONIBILI") == 0) return nparms < 3 ? _imponibili : -1; if (strcmp(name, "IMPOSTE") == 0) return nparms < 3 ? _imposte : -1; if (strcmp(name, "TOTPROVV") == 0) return nparms < 3 ? _totprovv : -1; if (strcmp(name, "PSCONTOT") == 0) return nparms < 1 ? _pscontot : -1; if (strcmp(name, "RITENUTA") == 0) return nparms < 3 ? _ritenuta : -1; if (strcmp(name, "TIPORIT") == 0) return nparms < 1 ? _tipo_ritenuta : -1; if (strcmp(name, "COMP") == 0) return nparms == 2 ? _componente : -1; if (strcmp(name, "COMPQTA") == 0) return nparms == 2 ? _comp_qta : -1; if (strcmp(name, "NRATE") == 0) return nparms == 0 ? _nrate : -1; return -1; } void TExpr_documento::evaluate_user_func(int index, int nparms, TEval_stack & stack, TTypeexp type) const { if (index >= _componente) int i = 0; switch (index) { case _somma: { const TString cond(nparms == 2 ? stack.pop_string() : "STR(1)"); const TString & field = stack.pop_string(); real somma; if (_doc != NULL) { TExpr_documento cond_expr(cond, _strexpr, _doc); const int cond_nvars = cond_expr.numvar(); TExpr_documento expr(field, _numexpr, _doc); const int nvars = expr.numvar(); const int nrows = _doc->rows(); for (int i = nrows; i > 0; i--) { TRiga_documento & riga = (TRiga_documento &) (*_doc)[i]; int j; for (j = cond_nvars - 1; j >= 0; j--) { const char* s = cond_expr.varname(j); TFieldref f(s,0); cond_expr.setvar(j, f.read(riga)); } cond_expr.set_row(&riga); if ((bool)cond_expr) { for (j = nvars - 1; j >= 0; j--) { const char* s = expr.varname(j); TFieldref f(s,0); expr.setvar(j, f.read(riga)); } expr.set_row(&riga); somma += expr.as_real(); } } } stack.push(somma); } break; case _spinc: { int ndec = AUTO_DECIMALS; bool netto = FALSE; if (nparms > 2) ndec = (int) stack.pop_real().integer(); if (nparms > 1) netto = !stack.pop_real().is_zero(); real & r = stack.peek_real(); if (_doc) r = _doc->spese_incasso(real(r - _doc->ritenute()), ndec, netto ? _netto : _lordo); else r = ZERO; } break; case _bolli: { int ndec = AUTO_DECIMALS; bool netto = FALSE; if (nparms > 2) ndec = (int) stack.pop_real().integer(); if (nparms > 1) netto = !stack.pop_real().is_zero(); real & r = stack.peek_real(); if (_doc) { r += _doc->spese_incasso(real(r - _doc->ritenute()), ndec); r = _doc->bolli(real(r - _doc->ritenute()), ndec, netto ? _netto : _lordo); } else r = ZERO; } break; case _bolli_int: { int ndec = AUTO_DECIMALS; if (nparms > 2) ndec = (int) stack.pop_real().integer(); real & r = stack.peek_real(); if (_doc) { real r1 = _doc->spese_incasso(real(r - _doc->ritenute()), ndec); r += r1; r1 += _doc->bolli(real(r - _doc->ritenute()), ndec); r = r1; } else r = ZERO; } break; case _prezzo: { int ndec = AUTO_DECIMALS; bool lordo = FALSE; bool scontato = FALSE; if (nparms > 2) ndec = (int) stack.pop_real().integer(); if (nparms > 1) lordo = !stack.pop_real().is_zero(); if (nparms > 0) scontato = !stack.peek_real().is_zero(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) val = _row->prezzo(scontato, lordo, ndec); else val = ZERO; } break; case _importo: { int ndec = AUTO_DECIMALS; bool lordo = FALSE; bool scontato = FALSE; if (nparms > 2) ndec = (int) stack.pop_real().integer(); if (nparms > 1) lordo = !stack.pop_real().is_zero(); if (nparms > 0) scontato = !stack.peek_real().is_zero(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) val = _row->importo(scontato, lordo, ndec); else val = ZERO; } break; case _imponibile: { real r; if (_row) r = _row->imponibile(); stack.push(r); } break; case _sconto: { int ndec = AUTO_DECIMALS; if (nparms > 0) ndec = (int) stack.peek_real().integer(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) { val = _row->importo(false, false, ndec); if (_row->is_sconto()) val = -val; else val -= _row->importo(true, false, ndec); } else val = ZERO; } break; case _iva: { real r; if (_row) r = _row->imposta(); stack.push(r); } break; case _provv: { int ndec = AUTO_DECIMALS; bool first = true; if (nparms > 1) first = !stack.peek_real().is_zero(); if (nparms > 0) ndec = (int) stack.peek_real().integer(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) val = _row->provvigione(first, ndec); else val = ZERO; } break; case _quant: { int ndec = AUTO_DECIMALS; if (nparms > 0) ndec = (int)stack.peek_real().integer(); else stack.push(ZERO); real& val = stack.peek_real(); if (_row) val = _row->quantita(); else val = ZERO; } break; case _quantevasa: { int ndec = AUTO_DECIMALS; if (nparms > 0) ndec = (int)stack.peek_real().integer(); else stack.push(ZERO); real& val = stack.peek_real(); if (_row) val = _row->qtaevasa(); else val = ZERO; } break; case _qtares: { int ndec = AUTO_DECIMALS; if (nparms > 0) ndec = (int) stack.peek_real().integer(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) val = _row->qtaresidua(); else val = ZERO; } break; case _valdoc: { int ndec = AUTO_DECIMALS; bool totale = TRUE; // Totale o residuo per documento if (nparms > 1) ndec = (int)stack.pop_real().integer(); if (nparms > 0) totale = !stack.peek_real().is_zero(); else stack.push(ZERO); real & r = stack.peek_real(); if (_doc) r = _doc->valore(totale, false, ndec); else r = ZERO; } break; case _tipo: { TString s; if (_row) s << _row->tipo().tipo(); stack.push(s); } break; case _imponibili: { int ndec = AUTO_DECIMALS; bool spese = FALSE; if (nparms > 1) ndec = (int) stack.pop_real().integer(); if (nparms > 0) spese = !stack.peek_real().is_zero(); else stack.push(ZERO); real & val = stack.peek_real(); val = _doc->imponibile(spese, ndec); } break; case _imposte: { int ndec = AUTO_DECIMALS; bool spese = FALSE; if (nparms > 1) ndec = (int) stack.pop_real().integer(); if (nparms > 0) spese = !stack.peek_real().is_zero(); else stack.push(ZERO); real & val = stack.peek_real(); val = _doc->imposta(spese, ndec); } break; case _totprovv: { int ndec = AUTO_DECIMALS; bool first = true; if (nparms > 1) first = !stack.peek_real().is_zero(); if (nparms > 0) ndec = (int) stack.peek_real().integer(); else stack.push(ZERO); real & val = stack.peek_real(); val = _doc->provvigione(first, ndec); } break; case _pscontot: { real val; TString80 s; if (_doc && scontoexpr2perc(_doc->get(DOC_SCONTOPERC), FALSE, s, val) && val != ZERO) val = 1 - val; stack.push(val); } break; case _ritenuta: { int ndec = AUTO_DECIMALS; bool lordo = FALSE; if (nparms > 1) ndec = (int) stack.pop_real().integer(); if (nparms > 0) lordo = !stack.peek_real().is_zero(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row && _row->tipo().tipo() == 'S') { const char tipo = _row->spesa().tipo_ritenuta(); val = _row->ritenuta(tipo, lordo, ndec); } else val = ZERO; } break; case _tipo_ritenuta: { TString s; if (_row && _row->tipo().tipo() == 'S') s << _row->spesa().tipo_ritenuta(); stack.push(s); } break; case _componente: case _comp_qta: { static TAssoc_array comps; static TAssoc_array qtas; const TString substr = stack.pop_string(); const int pos = atoi(stack.pop_real().string()); const TString codart = _row->get(RDOC_CODARTMAG); TString * val = (TString *) comps.objptr(codart); if (val != NULL) { if (index == _componente) stack.push(*val); else { const real &val = *(real *) qtas.objptr(codart); stack.push(val); } } else { TDistinta_tree db; TArray comp; bool found = false; db.set_root(codart); const int items = db.explode(comp, true, RAGGR_EXP_UMBASE, 0, "A", false); if (items > 0) { for (int i = comp.first(); !found && i < items; i = comp.succ(i)) { TRiga_esplosione & r = (TRiga_esplosione &) comp[i]; const TString c(r.articolo()); if (c.find(substr, pos) > 0) { if (index == _componente) stack.push(c); else stack.push(r.val()); comps.add(codart, c); qtas.add(codart, r.val()); found = true; } } } if (!found) { if (index == _componente) stack.push(EMPTY_STRING); else stack.push(ZERO); comps.add(codart, EMPTY_STRING); qtas.add(codart, ZERO); } } } break; case _nrate: { const TPagamento & p = _doc->pagamento(); const real r = p.n_rate(); stack.push(r); } break; default: TExpression::evaluate_user_func(index, nparms, stack, type); break; } } TObject* TExpr_documento::dup() const { TExpr_documento* o = new TExpr_documento(*this); return o; } /////////////////////////////////////////////////////////// // Formula documento /////////////////////////////////////////////////////////// TFormula_documento::TFormula_documento(TTipo_formula tipo, const char* codice, const char * expr, bool numexpr) : TRectype(LF_TABCOM), _expr(NULL) { settab(tipo == _documento ? "FRD" : "FRR"); if (codice && *codice) read(codice, expr, numexpr); } TFormula_documento::TFormula_documento(const TRectype& rec) : TRectype(rec), _expr(NULL) { const TTypeexp et = expr_type(); _expr = new TExpr_documento(expr_string(), et); } TFormula_documento::~TFormula_documento() { if (_expr) delete _expr; } int TFormula_documento::read(const char* codice, const char * expr, bool numexpr) { if (_expr != NULL) { delete _expr; _expr = NULL; } put("CODTAB", codice); int err = NOERR; if (expr && *expr) { put("S1", expr); put("B0", numexpr ? "X" : ""); } else { TString4 cod; cod << '%' << get("COD"); TTable t(cod); err = TRectype::read(t); } if (err == NOERR) { const TTypeexp et = expr_type(); const TString& e = expr_string(); // Copio espressione proveniente da record _expr = new TExpr_documento(e, et); } else { zero(); put("CODTAB", codice); } return err; }