#include #include #ifndef __APPLICAT_H #include #endif #ifndef __EXPR_H #include #endif #ifndef __STACK_H #include #endif #ifndef __UTILITY_H #include #endif #include "velib01.h" #include "sconti.h" #ifndef __VE0100C_H #include "ve0100c.h" #endif #ifndef __VERIG_H #include "verig.h" #endif #ifndef __VEUML_H #include "veuml.h" #endif #ifndef __VEUML1_H #include "veuml1.h" #endif #ifndef __VEINI_H #include "veini.h" #endif #ifndef __PAGAMENT_H #include "..\cg\pagament.h" #endif #ifndef __SCONTI_H #include "sconti.h" #endif TSpesa_prest::TSpesa_prest(const char* codice, char tipo) : TRectype(LF_TAB) { settab(tipo == 'S' ? "SPP" : "PRS"); if (codice && *codice) read(codice); } TSpesa_prest::TSpesa_prest(const TRectype& rec) : TRectype(rec) { } int TSpesa_prest::read(const char* codice) { TTable t(get("COD")); put("CODTAB", codice); int err = TRectype::read(t); if (err != NOERR) yesnofatal_box("Tipo spesa assente : %s", codice); return err; } TIVA::TIVA(const char* codice) : TRectype(LF_TABCOM) { settab("IVA"); if (codice && *codice) read(codice); } TIVA::TIVA(const TRectype& rec) : TRectype(rec) { } int TIVA::read(const char* codice) { TTable t("%IVA"); put("CODTAB", codice); int err = TRectype::read(t); if (err != NOERR) yesnofatal_box("Codice IVA assente : %s", codice); return err; } bool ora_hndl( TMask_field& field, KEY key ) { if (field.to_check(key)) { TFixed_string ora( field.get( ), 6 ); ora.trim( ); if (ora.not_empty() || field.required() ) { if ( isdigit( ora[ 0 ] ) ) { if ( ora[ 2 ] != ':') { if ( ora.len( ) > 4 ) ora.overwrite( ":", 2 ); else ora.insert( ":", 2 ); } } const bool ok = ((isdigit(ora[0]))&&(isdigit(ora[1]))&&(isdigit(ora[3]))&&(isdigit(ora[4]))) && ((atoi(&(ora[0]))<24)&&(atoi(&(ora[3]))<60)); if (ok ) field.set((ora)); else return error_box("Ora errata o formato non valido"); } } return TRUE; } bool dummy_hndl(TMask_field& field, KEY key) { warning_box( "Al campo %d è arrivato un KEY %d", field.dlg( ), key ); return TRUE; } // Handler per il calcolo delle date di pagamento bool condpag_hndl( TMask_field& field, KEY key ) { if ( field.to_check(key)) { TDocumento_mask& m = (TDocumento_mask &) field.mask( ); TString16 condpag( m.get( F_CODPAG ) ); TString16 data( m.get( F_DATAINSC ) ); if ( condpag.not_empty() && data.not_empty()) { TPagamento pag(condpag, data); pag.set_total( 100, 10, 10 ); pag.set_rate_auto( ); int numrate = pag.n_rate( ); if (numrate > 5) numrate = 5; for( int i = 0; i < numrate; i ++ ) m.set( F_DATASCAD1 + i, pag.data_rata(i).string()); for( ; i < 5; i ++ ) m.hide( F_DATASCAD1 + i ); } } return TRUE; } // handler delle righe HIDDEN void row_set_handler( TMask& m, const int field, const int index ) { switch ( index ) { case 1: m.set_handler( field, dummy_hndl ); break; default: yesnofatal_box( FALSE, "Funzione di handler sulla riga non definita( %d ).", index ); } } HIDDEN TString16 curr_um; HIDDEN real curr_fc(1.0); HIDDEN bool codart_handler( TMask_field& f, KEY key ) { // Se qualcuno cerca di modificare la maschera if ( key == K_TAB && f.focusdirty()) { TMask& row_mask = f.mask(); TDocumento_mask & mask = (TDocumento_mask &) row_mask.get_sheet()->mask(); TCond_vendita & condv = mask.condv(); condv.set_testa(&mask); condv.set_riga(&row_mask); TLocalisamfile & anamag = ((TEdit_field &) f).browse()->cursor()->file(); TLocalisamfile & umart = ((TEdit_field &) row_mask.field(FR_UMQTA)).browse()->cursor()->file(); condv.set_anamag(anamag); condv.set_umart(umart); TString80 codart(f.get()); anamag.setkey(1); anamag.put("CODART", codart); if (anamag.read() != NOERR) { TLocalisamfile codalt(LF_CODCORR); codalt.setkey(2); codalt.put("CODARTALT", codart); if (codalt.read() == NOERR) { codart = codalt.get("CODART"); anamag.zero(); anamag.put("CODART", codart); if (anamag.read() == NOERR) f.set(codart); } } if (anamag.good()) { const TString16 lingua = mask.get(F_CODLIN); const TString codart(row_mask.get(FR_CODART)); TString desc(anamag.get("DESCR")); if (lingua.not_empty()) { TLocalisamfile deslin(LF_DESLIN); deslin.setkey(2); deslin.put("CODART", codart); deslin.put("CODLIN", lingua); if (deslin.read() == NOERR) desc = deslin.get("DESCR"); } row_mask.set(FR_DESCR, desc); umart.setkey(1); umart.zero(); umart.put("CODART", codart); if (umart.read(_isgteq) == NOERR && codart == umart.get("CODART")) { curr_um = umart.get("UM"); curr_fc = umart.get_real("FC"); } else { curr_um.cut(0); curr_fc = 1.0; } row_mask.set(FR_UMQTA, curr_um); } condv.ricerca(); } return TRUE; } HIDDEN bool umart_handler( TMask_field& f, KEY key ) { // Se qualcuno cerca di modificare la maschera if ( key == K_TAB && f.focusdirty()) { TMask& row_mask = f.mask( ); TDocumento_mask & mask = (TDocumento_mask &) row_mask.get_sheet()->mask(); TLocalisamfile & anamag = ((TEdit_field &) row_mask.field(FR_CODART)).browse()->cursor()->file(); TLocalisamfile & umart = ((TEdit_field &) f).browse()->cursor()->file(); TCond_vendita & condv = mask.condv(); condv.set_testa(&mask); condv.set_riga(&row_mask); condv.set_anamag(anamag); condv.set_umart(umart); condv.ricerca(TRUE); const TString16 um(f.get()); real fc(1.0); if (um.not_empty() && curr_um.not_empty() && um != curr_um) { umart.setkey(2); umart.put("CODART", row_mask.get(FR_CODART)); umart.put("UM", um); if (umart.read() == NOERR) { real qta(row_mask.get_real(FR_QTA)); qta *= curr_fc; fc = umart.get_real("FC"); qta /= fc; row_mask.set(FR_QTA, qta); } } curr_um = um; curr_fc = fc; } return TRUE; } HIDDEN bool descr_handler( TMask_field& f, KEY key ) { if (key == K_TAB && f.focusdirty()) { const TString s(f.get()); if (s.find('\n') < 0) { TLocalisamfile & anamag = ((TEdit_field &) f).browse()->cursor()->file(); anamag.zero(); anamag.setkey(2); anamag.put("DESCR", ((TZoom_field &) f).get_first_line()); if (anamag.read() == NOERR) { f.mask().set(FR_CODART, anamag.get("CODART")); f.mask().field(FR_CODART).set_dirty(); f.mask().check_field(FR_CODART); } } } return TRUE; } HIDDEN bool qta_handler( TMask_field& f, KEY key ) { // Se qualcuno cerca di modificare la maschera if ( key == K_TAB && f.focusdirty()) { TMask& row_mask = f.mask( ); TDocumento_mask & mask = (TDocumento_mask &) row_mask.get_sheet()->mask(); TLocalisamfile & anamag = ((TEdit_field &) row_mask.field(FR_CODART)).browse()->cursor()->file(); TLocalisamfile & umart = ((TEdit_field &) row_mask.field(FR_UMQTA)).browse()->cursor()->file(); TCond_vendita & condv = mask.condv(); condv.set_testa(&mask); condv.set_riga(&row_mask); condv.set_anamag(anamag); condv.set_umart(umart); condv.ricerca(FALSE, TRUE); } return TRUE; } HIDDEN bool sppr_handler( TMask_field& f, KEY key ) { if (key == K_TAB && f.focusdirty()) { TMask& row_mask = f.mask( ); const int pos = row_mask.id2pos(FR_PREZZO); if (pos >= 0) { TMask & mask = row_mask.get_sheet()->mask(); TRectype & spprrec = ((TEdit_field &) row_mask.field(FR_CODART)).browse()->cursor()->file().curr(); if (spprrec.get("CODTAB") == row_mask.get(FR_CODART) && spprrec.get_char("S6") != 'P') { real cambio = mask.get(F_CAMBIO); real prezzo = row_mask.get(FR_PREZZO); const TString16 doc_valuta(mask.get(F_CODVAL)); const TString16 sppr_valuta(spprrec.get("S4")); if (sppr_valuta != doc_valuta && cambio != 0.0) { TTable val("%VAL"); val.put("CODTAB", sppr_valuta); if (val.read() == NOERR) { const real sppr_cambio = val.get_real("R10"); if (sppr_cambio != ZERO) prezzo *= sppr_cambio; } prezzo /= mask.get_real(F_CAMBIO); } row_mask.set(FR_PREZZO, prezzo); } } } return TRUE; } /////////////////////////////////////////////////////////// // Funzioni per il calcolo dei prezzi netti/lordi /////////////////////////////////////////////////////////// real lordo2netto(real& lordo, const TString& codiva, int ndec) { TTable tabiva("%IVA"); real aliquota = 0.0; tabiva.put("CODTAB", codiva); if (tabiva.read() == NOERR) aliquota = tabiva.get_real("R0"); return lordo2netto(lordo,aliquota, ndec); } real netto2lordo(const real& netto, const TString& codiva, int ndec) { TTable tabiva("%IVA"); real aliquota = 0.0; tabiva.put("CODTAB", codiva); if (tabiva.read() == NOERR) aliquota = tabiva.get_real("R0"); return netto2lordo(netto,aliquota, ndec); } real lordo2netto(real& lordo, const real& iva, int ndec) { real netto; real imposta = 0.0; real imposta_rec = 0.0; if (!iva.is_zero()) { imposta = (lordo * iva) / (iva + 100.0); // Calcola l'imposta... imposta.ceil(ndec); } netto = lordo - imposta; // Questo e' l'importo netto imposta_rec = (netto * iva) / 100.0; // Ricalcola l'imposta con il nuovo imponibile imposta_rec.ceil(ndec); if (imposta != imposta_rec) // In questo caso corregge l'importo lordo lordo = netto + imposta_rec; return netto; } real netto2lordo(const real& netto, const real& iva, int ndec) { real lordo; real imposta = 0.0; if (!iva.is_zero()) { imposta = (netto * iva) / 100.0; // Calcola l'imposta imposta.ceil(ndec); } lordo = imposta + netto; // prezzo lordo return lordo; } real prezzo_scontato(const real& prezzo, const char * sconto) { real scontato = prezzo; if (sconto && *sconto) { TCond_vendita cv; cv.set_sconto(sconto); scontato = cv.sconto_val() * prezzo; } return scontato; } enum TTipo_calcolo { _nessun_calcolo, _qtaprezzo, _valore, _percentuale, _scontoimp, _scontoperc}; real iva(real imponibile, const TIVA & iva,int ndec) { real val = imponibile * iva.aliquota() / 100.0; val.ceil(ndec); return val; } real TDocumento::spese_incasso(real & imp, int ndec, bool netto) const { real imp_spese; real percentuale = get_real("PERCSPINC"); static TArray spese_inc; if (percentuale > ZERO) { if (spese_inc.objptr(_rim_dir) == NULL) { TConfig conf(CONFIG_STUDIO); for (TTipo_pag p = _rim_dir; p < _nessun_pag; p = (TTipo_pag) ((int)p + 1)) { real r(conf.get("IMPSPIN", "ve", p)); spese_inc.add(r, p); } } TPagamento & pag = ((TDocumento *)this)->pagamento(); const int nrate = pag.n_rate(); for (int i = 0; i < nrate; i++) { const TTipo_pag p = (TTipo_pag) pag.tipo_rata(i); imp_spese += (real &) spese_inc[p]; } imp_spese *= percentuale / 100.0; real cambio = get_real("CAMBIO"); if (cambio == ZERO) cambio = 1.0; imp_spese /= cambio; imp_spese.round(ndec); if (netto == FALSE) { static TString16 codiva; static long firm = -1; long new_firm = main_app().get_firm(); if (firm != new_firm) { TConfig conf(CONFIG_DITTA); codiva = conf.get("SPINCODIVA", "ve"); firm = new_firm; } imp_spese += iva(imp_spese, TRiga_documento::iva(codiva), ndec); } } return imp_spese; } real TDocumento::bolli(real & imp, int ndec, bool netto) const { real tot_bolli; static TArray sca_bolli; static TArray imp_bolli; static int nscagl; TLocalisamfile clifo(LF_CLIFO); bool estero = 2; if (get_bool("ADDBOLLI")) { real cambio = get_real("CAMBIO"); if (cambio == ZERO) cambio = 1.0; real importo = imp*cambio; TPagamento & pag = ((TDocumento*)this)->pagamento(); const int nrate = pag.n_rate(); real old_bolli = -1.00; real iva_bolli; for (int j = 0; j < 5 && tot_bolli != old_bolli; j++) { old_bolli = tot_bolli; const real imposte = imposta() * cambio + iva_bolli; const real imp_spese = spese() * cambio + tot_bolli - iva_bolli; const real imponibile = importo - imposte - imp_spese; tot_bolli = ZERO; pag.set_total(imponibile, imposte, imp_spese); pag.set_rate_auto(); for (int i = 0; i < nrate; i++) { const TTipo_pag p = (TTipo_pag) pag.tipo_rata(i); real imp = pag.importo_rata(i); switch (p) { case _ric_ban: { if (sca_bolli.objptr(0) == NULL) { TConfig conf(CONFIG_STUDIO); for (nscagl = 0; nscagl < 7; nscagl++) { real s(conf.get("SPBOSCA", "ve", nscagl + 1)); real i(conf.get("SPBOIMP", "ve", nscagl + 1)); if (s == ZERO && i == ZERO) break; sca_bolli.add(s, nscagl); imp_bolli.add(i, nscagl); } } for (int i = 0; i < nscagl - 1; i++) if ((real &) sca_bolli[i] >= imp) break; tot_bolli += (real &) imp_bolli[i]; } break; case _tratta: case _tratta_acc: { if (estero == 2) { clifo.put("TIPOCF", get("TIPOCF")); clifo.put("CODCF", get("CODCF")); if (clifo.read() != NOERR) clifo.zero(); const TString16 stato(clifo.get("STATOPAIV")); estero = stato.not_empty() && stato != "IT"; if (!estero) estero = clifo.get("STATOCF").not_empty() || clifo.get("COMCF")[0] == 'Z'; } real r(imp); r.ceil(-3); if (estero) r *= 0.009; else r *= 0.012; r.round(-2); tot_bolli += r; } break; case _cessione: case _paghero: case _let_cred: case _rim_dir: case _rid: case _bonfico: default: break; } } if (netto == FALSE) { static TString16 codiva; static long firm = -1; long new_firm = main_app().get_firm(); if (firm != new_firm) { TConfig conf(CONFIG_DITTA); codiva = conf.get("SPBOCODIVA", "ve"); firm = new_firm; } iva_bolli = iva(tot_bolli, TRiga_documento::iva(codiva), ndec); tot_bolli += iva_bolli; } importo += (tot_bolli - old_bolli); } tot_bolli /= cambio; tot_bolli.round(ndec); } return tot_bolli; } /////////////////////////////////////////////////////////// // Formula generica /////////////////////////////////////////////////////////// HIDDEN enum _formula {_somma, _bolli, _bolli_int, _spinc, _prezzo, _importo, _sconto, _iva, _provv, _tipo}; 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; else if (strcmp(name, "BOLLI") == 0) return nparms > 0 || nparms < 4 ? _bolli : -1; else if (strcmp(name, "_BOLLI") == 0) return nparms > 0 || nparms < 3 ? _bolli_int : -1; else if (strcmp(name, "SPESEINC") == 0) return nparms > 0 || nparms < 4 ? _spinc : -1; else if (strcmp(name, "PREZZO") == 0) return nparms < 4 ? _prezzo : -1; else if (strcmp(name, "IMPORTO") == 0) return nparms < 4 ? _importo : -1; else if (strcmp(name, "SCONTO") == 0) return nparms < 2 ? _sconto : -1; else if (strcmp(name, "IVA") == 0) return nparms < 2 ? _iva : -1; else if (strcmp(name, "PROVV") == 0) return nparms < 2 ? _provv : -1; else if (strcmp(name, "TIPO") == 0) return nparms == 0 ? _tipo : -1; else return -1; } void TExpr_documento::evaluate_user_func(int index, int nparms, TEval_stack & stack, TTypeexp type) const { switch (index) { case _somma: { const TString cond(nparms == 2 ? stack.pop_string() : "STR(1)"); const TString & fieldname = stack.pop_string(); real somma; if (_doc != NULL) { TExpr_documento cond_expr(cond, _strexpr, _doc); const int nrows = _doc->rows(); const int nvars = cond_expr.numvar(); for (int i = nrows; i > 0 ; i--) { TRiga_documento & riga = (TRiga_documento &) (*_doc)[i]; for (int j = 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) somma += riga.get_real(fieldname); } } stack.push(somma); } break; case _spinc: { int ndec = _doc && _doc->in_valuta() ? 3 : 0; 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(r, ndec, netto); else r = ZERO; } break; case _bolli: { int ndec = _doc && _doc->in_valuta() ? 3 : 0; 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(r, ndec); r = _doc->bolli(r, ndec, netto); } else r = ZERO; } break; case _bolli_int: { int ndec = _doc && _doc->in_valuta() ? 3 : 0; if (nparms > 2) ndec = (int) stack.pop_real().integer(); real & r = stack.peek_real(); if (_doc) { real r1 = _doc->spese_incasso(r, ndec); r += r1; r1 += _doc->bolli(r, ndec); r = r1; } else r = ZERO; } break; case _prezzo: { int ndec = _doc && _doc->in_valuta() ? 3 : 0; 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 = _doc && _doc->in_valuta() ? 3 : 0; 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 _sconto: { int ndec = _doc && _doc->in_valuta() ? 3 : 0; if (nparms > 0) ndec = (int) stack.peek_real().integer(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) { if (_row->tipo().tipo() == 'C') val = -_row->importo(FALSE, FALSE, ndec); else val = _row->importo(FALSE, FALSE, ndec) - _row->importo(TRUE, FALSE, ndec); } else val = ZERO; } break; case _iva: { int ndec = _doc && _doc->in_valuta() ? 3 : 0; if (nparms > 0) ndec = (int) stack.peek_real().integer(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) val = _row->iva(ndec); else val = ZERO; } break; case _provv: { int ndec = _doc && _doc->in_valuta() ? 3 : 0; if (nparms > 0) ndec = (int) stack.peek_real().integer(); else stack.push(ZERO); real & val = stack.peek_real(); if (_row) { val = _row->importo(TRUE, FALSE, ndec) * _row->get_real("PERCPROV") / 100.0; val.round(ndec); } else val = ZERO; } break; case _tipo: { TString s; if (_row) s << _row->tipo().tipo(); stack.push(s); } 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 generica /////////////////////////////////////////////////////////// TFormula_documento::TFormula_documento(TTipo_formula tipo, const char* codice) : TRectype(LF_TABCOM), _expr(NULL) { _tab = tipo == _documento ? "FRD" : "FRR"; settab(_tab); _tab.insert("%"); if (codice && *codice) read(codice); } TFormula_documento::TFormula_documento(const TRectype& rec) : TRectype(rec), _expr(NULL) { _tab = "%"; _tab << rec.get("COD"); _expr = new TExpr_documento(expr_string(), expr_type()); } TFormula_documento::~TFormula_documento() { if (_expr) delete _expr; } int TFormula_documento::read(const char* codice) { if (_expr != NULL) { delete _expr; _expr = NULL; } TTable t(_tab); put("CODTAB", codice); int err = TRectype::read(t); if (err == NOERR) { const TString e(expr_string()); _expr = new TExpr_documento(e, expr_type()); } else { zero(); put("CODTAB", codice); } return err; } /////////////////////////////////////////////////////////// // Tipo documento /////////////////////////////////////////////////////////// TAssoc_array TTipo_documento::_formule_documento; TTipo_documento::TTipo_documento(const char* tipodoc) : TRectype(LF_TABCOM) { settab("TIP"); if (tipodoc && *tipodoc) read(tipodoc); } TTipo_documento::TTipo_documento(const TRectype& rec) : TRectype(rec) { read_formule(); } TTipo_documento::~TTipo_documento() { } int TTipo_documento::read(const char* tipodoc) { TTable t("%TIP"); put("CODTAB", tipodoc); int err = TRectype::read(t); _formule = ""; if (err == NOERR) read_formule(); else yesnofatal_box("Tipo documento errato: %s", tipodoc); return err; } void TTipo_documento::read_formule() { TFilename prof(profile_name()); prof.ext("ini"); TConfig profile(prof); _formule = profile.get("CAMPICALC", "MAIN"); _formule.add(profile.get("CALCOLI", "MAIN")); _imponibile = profile.get("IMPONIBILE", "MAIN"); if (_imponibile.not_empty() && _formule.find(_imponibile) < 0) { error_box("Campo imponibile (%s) sconosciuto nel tipo documento %s", (const char *) _imponibile, (const char *) codice()); _imponibile.cut(0); } _imposta = profile.get("IMPOSTA", "MAIN"); if (_imposta.not_empty() && _formule.find(_imposta) < 0) { error_box("Campo imposta (%s) sconosciuto nel tipo documento %s", (const char *) _imposta, (const char *) codice()); _imposta.cut(0); } _totale = profile.get("TOTALE", "MAIN"); if (_totale.not_empty() && _formule.find(_totale) < 0) { error_box("Campo totale documento (%s) sconosciuto nel tipo documento %s", (const char *) _totale, (const char *) codice()); _totale.cut(0); } _basesconto = profile.get("BASESCONTO", "MAIN"); if (_basesconto.not_empty() && _formule.find(_basesconto) < 0) { error_box("Campo sconto documento (%s) sconosciuto nel tipo documento %s", (const char *) _basesconto, (const char *) codice()); _basesconto.cut(0); } _spese = profile.get("SPESE", "MAIN"); if (_spese.not_empty() && _formule.find(_spese) < 0) { error_box("Campo spese (%s) sconosciuto nel tipo documento %s", (const char *) _spese, (const char *) codice()); _spese.cut(0); } } TFormula_documento * TTipo_documento::succ_formula(bool restart) { if (restart) _formule.restart(); const TString16 formula(_formule.get()); if (formula.not_empty()) { TFormula_documento * o = (TFormula_documento*)_formule_documento.objptr(formula); if (o == NULL) { o = new TFormula_documento(_documento, formula); _formule_documento.add(formula, o); } return o; } else return NULL; } /////////////////////////////////////////////////////////// // Tipo riga di un documento /////////////////////////////////////////////////////////// TAssoc_array TTipo_riga_documento::_formule_riga; TTipo_riga_documento::TTipo_riga_documento(const char* tiporig) : TRectype(LF_TABCOM), _mask(NULL) { settab("TRI"); _name = "verig"; _name << codice(); if (tiporig && *tiporig) read(tiporig); } TTipo_riga_documento::TTipo_riga_documento(const TRectype& rec) : TRectype(rec), _mask(NULL) { _name = "verig"; _name << codice(); read_formule(); } TTipo_riga_documento::~TTipo_riga_documento() { if (_mask) delete _mask; } int TTipo_riga_documento::read(const char* tiporig) { TTable t("%TRI"); put("CODTAB", tiporig); int err = TRectype::read(t); if (err == NOERR) read_formule(); else yesnofatal_box("Tipo riga documento errato: %s", tiporig); return err; } void TTipo_riga_documento::read_formule() { TFilename prof(profile_name()); prof.ext("ini"); TConfig profile(prof); _formule = profile.get("CAMPICALC", "MAIN"); _formule.add(profile.get("CALCOLI", "MAIN")); _imponibile = profile.get("IMPONIBILE", "MAIN"); if (_imponibile.not_empty() && _formule.find(_imponibile) < 0) { error_box("Campo imponibile (%s) sconosciuto nel tipo riga %s", (const char *) _imponibile, (const char *) codice()); _imponibile.cut(0); } _imposta = profile.get("IMPOSTA", "MAIN"); if (_imposta.not_empty() && _formule.find(_imposta) < 0) { error_box("Campo imposta (%s) sconosciuto nel tipo riga %s", (const char *) _imposta, (const char *) codice()); _imposta.cut(0); } } TFormula_documento * TTipo_riga_documento::succ_formula(bool restart) { if (restart) _formule.restart(); const TString16 formula(_formule.get()); if (formula.not_empty()) { TFormula_documento * o = (TFormula_documento*)_formule_riga.objptr(formula); if (o == NULL) { o = new TFormula_documento(_riga, formula); _formule_riga.add(formula, o); } return o; } else return NULL; } TVariable_mask * TTipo_riga_documento::mask() { if (mask_loaded()) return _mask; _mask = new TVariable_mask(mask_name()); TFilename proname(profile_name()); proname.ext( "ini" ); TConfig pro( proname ); int numhandler = pro.get_int( "NHANDLER", "HANDLERS" ); for( int i = 1; i <= numhandler; i ++ ) { TString chiave; chiave.format( "%d", i ); TToken_string riga = pro.get( chiave, "HANDLERS" ); row_set_handler( *_mask, riga.get_int( 0 ), riga.get_int( 1 ) ); } const int pos = _mask->id2pos(FR_CODART); if (pos >= 0) { const TMask_field & f = _mask->field(FR_CODART); if (f.is_edit()) { TBrowse * browse = ((TEdit_field &) f).browse(); const char tipo_r = tipo(); if (browse ) { const TCursor * cur = browse->cursor(); if (cur) { const int num = cur->file().num(); if (num == LF_ANAMAG) { _mask->set_handler( FR_CODART, codart_handler ); _mask->set_handler( FR_UMQTA, umart_handler ); _mask->set_handler( FR_DESCR, descr_handler ); _mask->set_handler( FR_QTA, qta_handler ); } else if (tipo_r == 'S' || tipo_r == 'P') _mask->set_handler( FR_CODART, sppr_handler ); } } } } return _mask; } /////////////////////////////////////////////////////////// // Riga documento per vendite /////////////////////////////////////////////////////////// TAssoc_array TRiga_documento::_tipi; TAssoc_array TRiga_documento::_spese; TAssoc_array TRiga_documento::_ive; TRiga_documento::TRiga_documento(TDocumento* doc, const char * tipo) : TAuto_variable_rectype(LF_RIGHEDOC), _doc(doc) { if (tipo) set_tipo(tipo); } TRiga_documento::TRiga_documento(const TRiga_documento& rec, TDocumento* doc, const char * tipo) : TAuto_variable_rectype(rec), _doc(doc) { if (tipo) set_tipo(tipo); } const TTipo_riga_documento& TRiga_documento::tipo() const { const TString16 tiporig(get("TIPORIGA")); CHECK(tiporig.not_empty(), "Tipo riga documento nullo"); TTipo_riga_documento* o = (TTipo_riga_documento*)_tipi.objptr(tiporig); if (o == NULL) { if (_tipi.items() == 0) { TTable tri("%TRI"); // Tabella dei tipi riga for (tri.first(); !tri.eof(); tri.next()) { const TString16 codice = tri.get("CODTAB"); _tipi.add(codice, new TTipo_riga_documento(tri.curr())); } } o = (TTipo_riga_documento*)_tipi.objptr(tiporig); if (o == NULL) { o = new TTipo_riga_documento(tiporig); _tipi.add(tiporig, o); } } return *o; } const TSpesa_prest & TRiga_documento::spesa() const { const char tipor = tipo().tipo(); CHECK(tipor == 'S' || tipor == 'P', "Tipo riga incompatibile con le spese"); static long firm = -1; long new_firm = main_app().get_firm(); if (firm != new_firm) { _spese.destroy(); firm = new_firm; } const TString16 codice(get("CODART")); TString16 index; index << tipor << codice; TSpesa_prest * s = (TSpesa_prest *) _spese.objptr(index); if (s == NULL) { s = new TSpesa_prest(codice, tipor); _spese.add(index, s); } return *s; } const TIVA & TRiga_documento::iva(const char *codice) { TIVA * v = (TIVA *) _ive.objptr(codice); if (v == NULL) { v = new TIVA(codice); _ive.add(codice, v); } return *v; } bool TRiga_documento::sola_descrizione() const { char t = tipo().tipo(); if (t <= ' ' && get("QTA").empty() && get("PREZZO").empty()) t = 'D'; return t == 'D'; } void TRiga_documento::forza_sola_descrizione() { // In realta' il test serve anche a caricare la lista dei tipi riga! if (tipo().tipo() != 'D') { _tipi.restart(); for (const TObject* o = _tipi.get(); o; o = _tipi.get()) { const TTipo_riga_documento* trd = (const TTipo_riga_documento*)o; if (trd->tipo() == 'D') { put("TIPORIGA", trd->codice()); break; } } zero("QTA"); zero("PREZZO"); } } TRectype & TRiga_documento::operator =(const TRectype & r) { TRectype::operator=(r); reset_fields(*this); set_fields(*this); return *this; } TRectype & TRiga_documento::operator =(const char * r) { TRectype::operator=(r); reset_fields(*this); set_fields(*this); return *this; } // Ritorna TRUE se le due righe del documento possono essere sommate bool TRiga_documento::raggruppabile(const TRiga_documento& r, TToken_string& campi) const { bool ok = TRUE; TString campo; for (const char* c = campi.get(0); c && ok; c = campi.get()) { campo = get(c); // Separare le due get! ok &= campo == r.get(c); } return ok; } TRiga_documento& TRiga_documento::operator +=(const TRiga_documento& r) { TToken_string campi("QTA|NCOLLI|QTAEVASA"); for (const char* c = campi.get(0); c && ok; c = campi.get()) { real num(r.get_real(c)); if (!num.is_zero()) { num += get_real(c); put(c, num); } } if (!get_bool("RIGAEVASA")) { const real qta = get_real("QTA"); const real qtaeva = get_real("QTAEVASA"); if (qtaeva >= qta) put("RIGAEVASA", "X"); } return *this; } void TRiga_documento::set_fields(TAuto_variable_rectype & rec) { if (get("TIPORIGA").not_empty()) { TTipo_riga_documento & tipo_riga = (TTipo_riga_documento &) tipo(); for (const TFormula_documento * f = tipo_riga.first_formula(); f; f = tipo_riga.succ_formula()) { TExpr_documento * exp = f->expr(); add_field(new TDocumento_variable_field(f->name(), exp)); if (exp) { exp->set_doc(_doc); exp->set_row(this); } } } } real TRiga_documento::prezzo(bool scontato, bool lordo, int ndec) const { real prezzo = get_real("PREZZO"); if (scontato) prezzo = prezzo_scontato(prezzo, get("SCONTO")); prezzo.round(ndec); if (lordo) prezzo = netto2lordo(prezzo, get("CODIVA"), ndec); prezzo.round(ndec); return prezzo; } real TRiga_documento::importo(bool scontato, bool lordo, int ndec, bool iva_calc) const { real importo; TTipo_calcolo c = _nessun_calcolo; const char tipor = tipo().tipo(); const real qta = get_real("QTA"); TString16 field_perc; TCond_vendita cv; switch (tipor) { case 'M': c = _qtaprezzo; break; case 'P': case 'S': { const TSpesa_prest & s = spesa(); switch (s.tipo()) { case 'Q': c = _qtaprezzo; break; case 'V': c = _valore; break; case 'P': c = _percentuale; field_perc = s.field_perc(); break; default: break; } } break; case 'C': cv.set_sconto(get("SCONTO")); if (cv.get_sconto().not_empty()) c = _scontoperc; else c = _scontoimp; break; case 'O': if (iva_calc) c = _qtaprezzo; default: break; } switch (c) { case _qtaprezzo: importo = prezzo(scontato, lordo, ndec) * qta; break; case _valore: importo = prezzo(scontato, lordo, ndec); break; case _percentuale: importo = doc().get_real(field_perc) * get_real("PSPESA") / 100; break; case _scontoimp: importo = -prezzo(FALSE, lordo, ndec); break; case _scontoperc: importo = doc().basesconto() * (cv.sconto_val() - 1.0); break; default: break; } importo.round(ndec); return importo; } real TRiga_documento::imponibile() const { const TString16 field(tipo().imponibile()); if (field.not_empty()) return get_real(field); else return importo(TRUE, FALSE, doc().in_valuta() ? 3 : 0); } real TRiga_documento::imposta() const { const TString16 field(tipo().imposta()); if (field.not_empty()) return get_real(field); else return iva(doc().in_valuta() ? 3 : 0); } void TRiga_documento::dirty_fields(bool dirty_document) { for (TDocumento_variable_field * f = (TDocumento_variable_field *) first_variable_field(); f != NULL; f = (TDocumento_variable_field *) succ_variable_field()) f->set_dirty(); if (dirty_document) ((TDocumento &)doc()).dirty_fields(); } bool TRiga_documento::doc_dependent() const { const char tipor = tipo().tipo(); if (tipor == 'S') return spesa().tipo() == 'P'; else if (tipor == 'C') return get("SCONTO").not_empty(); return FALSE; } void TRiga_documento::put_str(const char* fieldname, const char* val) { if (strcmp(fieldname, "TIPORIGA") == 0 && TRectype::get("TIPORIGA") != val) { TAuto_variable_rectype::put_str(fieldname, val); reset_fields(*this); set_fields(*this); } else { TAuto_variable_rectype::put_str(fieldname, val); dirty_fields(); } } void TRiga_documento::zero(const char * fieldname) { if (strcmp(fieldname, "TIPORIGA") == 0) reset_fields(*this); TAuto_variable_rectype::zero(fieldname); dirty_fields(); } void TRiga_documento::zero(char c) { reset_fields(*this); TAuto_variable_rectype::zero(c); } void TRiga_documento::autosave(TSheet_field & f) { const int num = numero() - 1; if (num >= 0 && num < f.items()) { TToken_string & row = f.row(num); put( "STATORIGA", row.get( f.cid2index(FR_STATORIGA) ) ); put( "TIPORIGA", row.get( f.cid2index(FR_TIPORIGA )) ); TString16 codmag(row.get(f.cid2index(FR_CODMAG))); codmag.left_just(3); codmag << row.get( f.cid2index(FR_CODDEP )); put( "CODMAG", codmag); put( "CODART", row.get( f.cid2index(FR_CODART )) ); TString s(row.get(f.cid2index(FR_DESCR))); int split_pos = s.find('\n'); if (split_pos > 0) { put( "DESCR", s.left(split_pos)); put("DESCLUNGA", "X"); s.ltrim(split_pos); put("DESCEST", s); } else { put("DESCR", s); put("DESCLUNGA", ""); zero("DESCEST"); } put( "PREZZO", row.get( f.cid2index(FR_PREZZO )) ); put( "UMQTA", row.get( f.cid2index(FR_UMQTA )) ); TMask * m = ((TTipo_riga_documento &)tipo()).mask(); const int pos = m->id2pos(FR_QTA); if (pos >= 0 && m->fld(pos).field()->name() == "PSPESA") put( "PSPESA", row.get( f.cid2index(FR_QTA )) ); else put( "QTA", row.get( f.cid2index(FR_QTA )) ); put( "QTAEVASA", row.get( f.cid2index(FR_QTAEVASA )) ); put( "RIGAEVASA", row.get( f.cid2index(FR_RIGAEVASA )) ); put( "TARA", row.get( f.cid2index(FR_TARA )) ); put( "PNETTO", row.get( f.cid2index(FR_PNETTO )) ); put( "NCOLLI", row.get( f.cid2index(FR_NCOLLI )) ); put( "DAEVADERE", row.get( f.cid2index(FR_DAEVADERE )) ); put( "SCONTO", row.get( f.cid2index(FR_SCONTO )) ); put( "PERCPROV", row.get( f.cid2index(FR_PERCPROV )) ); put( "IMPFISSO", row.get( f.cid2index(FR_IMPFISSO )) ); put( "CODIVA", row.get( f.cid2index(FR_CODIVA )) ); put( "ADDIVA", row.get( f.cid2index(FR_ADDIVA )) ); put( "ASPBENI", row.get( f.cid2index(FR_ASPBENI )) ); } } void TRiga_documento::autoload(TSheet_field & f) { const int num = numero() - 1; if (num >= 0 && num < f.items()) { TToken_string & row = f.row(num); row.add( get( "STATORIGA" ), f.cid2index(FR_STATORIGA )); row.add( get( "TIPORIGA" ), f.cid2index(FR_TIPORIGA )); const TString codmag(get("CODMAG")); row.add( codmag.left(3), f.cid2index(FR_CODMAG )); row.add( codmag.mid(3), f.cid2index(FR_CODDEP )); row.add( get( "CODART" ), f.cid2index(FR_CODART )); TString s(get("DESCR")); if (get_bool("DESCLUNGA")) s << get("DESCEST"); row.add(s, f.cid2index(FR_DESCR )); row.add( get( "UMQTA" ), f.cid2index(FR_UMQTA )); row.add( get( "PREZZO" ), f.cid2index(FR_PREZZO )); TMask * m = ((TTipo_riga_documento &)tipo()).mask(); const int pos = m->id2pos(FR_QTA); if (pos >= 0 && m->fld(pos).field()->name() == "PSPESA") row.add( get( "PSPESA" ), f.cid2index(FR_QTA )); else row.add( get( "QTA" ), f.cid2index(FR_QTA )); row.add( get( "QTAEVASA" ), f.cid2index(FR_QTAEVASA )); row.add( get( "RIGAEVASA" ), f.cid2index(FR_RIGAEVASA )); row.add( get( "TARA" ), f.cid2index(FR_TARA )); row.add( get( "PNETTO" ), f.cid2index(FR_PNETTO )); row.add( get( "NCOLLI" ), f.cid2index(FR_NCOLLI )); row.add( get( "DAEVADERE" ), f.cid2index(FR_DAEVADERE )); row.add( get( "SCONTO" ), f.cid2index(FR_SCONTO )); row.add( get( "PERCPROV" ), f.cid2index(FR_PERCPROV )); row.add( get( "IMPFISSO" ), f.cid2index(FR_IMPFISSO )); row.add( get( "CODIVA" ), f.cid2index(FR_CODIVA )); row.add( get( "ADDIVA" ), f.cid2index(FR_ADDIVA )); row.add( get( "ASPBENI" ), f.cid2index(FR_ASPBENI )); } } TDocumento_mask::TDocumento_mask(const char* name, TDocumento * doc, int num, int max) : TVariable_mask(name, num, max), _progs_page(-1), _last_prog(-1), _doc(doc) { const int pos = id2pos(BASE_PIEDE + 1); if (pos >= 0) { _progs_page = find_parent_page(fld(pos)); _last_prog = 0; while (id2pos(BASE_PIEDE + _last_prog + 1) >= 0) _last_prog++; } } void TDocumento_mask::next_page(int p) { TMask::next_page(p); if (curr_page() == _progs_page) { begin_wait(); autosave(get_relation()); for (int i = _last_prog; i > 0; i--) { const short id = BASE_PIEDE + i; const TString16 name(field(id).field()->name()); set(id , doc().get(name)); } end_wait(); } } bool TDocumento_mask::on_key(KEY key) { if (key == K_SHIFT + K_F12) { field(F_STATO).enable(!field(F_STATO).enabled()); return TRUE; } return TVariable_mask::on_key(key); } /////////////////////////////////////////////////////////// // Documento per vendite /////////////////////////////////////////////////////////// TAssoc_array TDocumento::_tipi; TDocumento::TDocumento() : TAuto_variable_rectype(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA"), _nuovo(TRUE), _condv(NULL), _rel(NULL) { set_memo_fld("G1"); } TDocumento::TDocumento(char provv, int anno, const char* codnum, long numdoc, TCond_vendita * condv, TRelation * rel) : TAuto_variable_rectype(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA"), _nuovo(TRUE), _condv(condv), _rel(rel) { set_memo_fld("G1"); if (numdoc <= 0) { numdoc = 0; set_key(*this, provv, anno, codnum, numdoc); TRiga_documento* key = new TRiga_documento(this); set_key(*key, provv, anno, codnum, numdoc); _rows.set_key(key); } else read(provv, anno, codnum, numdoc); } // Funzione statica utile a tutti gli utenti di LF_DOC e LF_RIGHEDOC void TDocumento::set_key(TRectype& rec, char provv, int anno, const char* codnum, long numdoc) { CHECK(provv == 'D' || provv == 'P', "Provvisorio o Definitivo?"); CHECKD(anno > 1900, "Anno non valido: ", anno); CHECK(codnum && *codnum, "Codice numerazione nullo"); CHECKD(numdoc >= 0, "Numero documento non valido ", numdoc); rec.put("PROVV", provv); rec.put("ANNO", anno); rec.put("CODNUM", codnum); rec.put("NDOC", numdoc); } // Funzione statica utile a tutti gli utenti di LF_DOC e LF_RIGHEDOC void TDocumento::copy_data(TRectype& dst, const TRectype& src) { // Memorizza tutti i campi chiave const char provv = dst.get_char("PROVV"); const int anno = dst.get_int("ANNO"); const TString16 codnum = dst.get("CODNUM"); const long numdoc = dst.get_long("NDOC"); const int nriga = dst.num() == LF_RIGHEDOC ? dst.get_int("NRIGA") : 0; // Copia tutto il record dst = src; // Ripristina tutti i campi chiave set_key(dst, provv, anno, codnum, numdoc); if (nriga > 0) dst.put("NRIGA", nriga); } TDocumento::TDocumento(const TRectype& rec, TCond_vendita * condv, TRelation * rel) : TAuto_variable_rectype(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA"), _nuovo(FALSE), _condv(condv), _rel(rel) { set_memo_fld("G1"); read(rec); } TRiga_documento& TDocumento::insert_row(int row, const char *tipo) { TRiga_documento * r = new TRiga_documento((const TRiga_documento &) _rows.key(), this); r->set_numero(row); if (tipo) r->set_tipo(tipo); _rows.insert_row(r); return *r; } TRiga_documento& TDocumento::new_row(const char *tipo) { TRiga_documento & r = (TRiga_documento&)_rows.row(-1, TRUE); if (tipo) r.set_tipo(tipo); return r; } int TDocumento::read(const TRectype& rec) { head() = rec; TRiga_documento* key = new TRiga_documento(this); const char pr = tipo_numerazione(); const int an = anno(); const TString16 cn = numerazione(); const long nu = numero(); CHECK(nu > 0, "Numero documento nullo."); set_key(*key, pr, an, cn, nu); TLocalisamfile doc(LF_DOC); int err = TRectype::read(doc); if (err == NOERR) { _nuovo = FALSE; _rows.read(key); } else { _nuovo = TRUE; head() = rec; destroy_rows(); _rows.set_key(key); } return err; } int TDocumento::read(char provv, int anno, const char* codnum, long numdoc) { TRectype rec(LF_DOC); CHECK(numdoc > 0, "Numero documento nullo."); set_key(rec, provv, anno, codnum, numdoc); return read(rec); } long TDocumento::renum(long numdoc) { if (numdoc <= 0) { const char tn = tipo_numerazione(); const int an = anno(); const TString16 nu = numerazione(); numdoc = get_next_key(tn, an, nu); } char num[16]; sprintf(num, "%ld", numdoc); renum_key("NDOC", num); // Aggiorna testata _rows.renum_key("NDOC", num); // Aggiorna righe return numdoc; } void TDocumento::dirty_fields() { for (TDocumento_variable_field * f = (TDocumento_variable_field *) first_variable_field(); f != NULL; f = (TDocumento_variable_field *) succ_variable_field()) f->set_dirty(); for (int i = rows(); i > 0; i--) { TRiga_documento & r = (TRiga_documento &) _rows.row(i, FALSE); if (r.doc_dependent()) r.dirty_fields(FALSE); } } int TDocumento::write(bool re) const { const bool nuovo = _nuovo || numero() <= 0; // E' nuovo di zecca! if (nuovo && re) // quindi ... re = FALSE; // ... non fare la rewrite TLocalisamfile doc(LF_DOC); int err = NOERR; if (re) { err = _rows.write(re); if (err == NOERR) { err = TRectype::rewrite(doc); if (err != NOERR) err = TRectype::write(doc); } } else { if (nuovo) { TDocumento& myself = *(TDocumento*)this; if (numero() <= 0) myself.renum(); do { err = TRectype::write(doc); if (err == _isreinsert) myself.renum(); } while (err == _isreinsert); myself._nuovo = FALSE; } else { err = TRectype::write(doc); if (err != NOERR) err = TRectype::rewrite(doc); } if (err == NOERR) err = _rows.write(re); } return err; } int TDocumento::remove() const { TLocalisamfile doc(LF_DOC); int err = _rows.remove(); if (err == NOERR) err = TRectype::remove(doc); return err; } const bool TDocumento::in_valuta() const { const TString& val = valuta(); return (val.not_empty() && val != "LIT"); } long TDocumento::get_next_key(char provv, int anno, const char* codnum) const { static long n = 0; if (n == 0) { TLocalisamfile doc(LF_DOC); TRectype& curr = doc.curr(); set_key(curr, provv, anno, codnum, 9999999L); const int err = doc.read(_isgreat); if (err != _isemptyfile) { if (err == NOERR) doc.prev(); if (curr.get_char("PROVV") == provv && curr.get_int("ANNO") == anno && curr.get("CODNUM") == codnum) n = curr.get_long("NDOC"); } } n++; return n; } const TTipo_documento& TDocumento::tipo() const { const TString16 tipodoc(get("TIPODOC")); CHECK(tipodoc.not_empty(), "Tipo documento nullo"); TTipo_documento * o = (TTipo_documento*)_tipi.objptr(tipodoc); if (o == NULL) { o = new TTipo_documento(tipodoc); _tipi.add(tipodoc, o); } return *o; } bool TDocumento::raggruppabile(const TDocumento& doc, TToken_string& campi) const { bool ok = raggruppabile() && doc.raggruppabile(); if (ok) { TString campo; for (const char* c = campi.get(0); c && ok; c = campi.get()) { campo = get(c); ok &= campo == doc.get(c); } } return ok; } void TDocumento::set_fields(TAuto_variable_rectype & rec) { if (get("TIPODOC").not_empty()) { TTipo_documento & tipo_doc = (TTipo_documento &) tipo(); const TString16 tot_doc(tipo_doc.totale_doc()); for (const TFormula_documento * f = tipo_doc.first_formula(); f; f = tipo_doc.succ_formula()) { TExpr_documento * exp = f->expr(); if (tot_doc == f->name()) { TString work_tot_doc(tot_doc); work_tot_doc.insert("_"); add_field(new TDocumento_variable_field(work_tot_doc, exp)); TExpr_documento * new_exp = new TExpr_documento( format("%s + _BOLLI(%s)", (const char *) work_tot_doc, (const char *) work_tot_doc), _numexpr, this); add_field(new TDocumento_variable_field(f->name(), new_exp)); } else add_field(new TDocumento_variable_field(f->name(), exp)); if (exp) exp->set_doc(this); } } } real TDocumento::imponibile() const { const TString16 field(tipo().imponibile()); if (field.not_empty()) return get_real(field); else { real val; for (int i = rows(); i > 0; i--) val += ((TRiga_documento &) ((TDocumento *)this)->row(i)).imponibile(); return val; } } real TDocumento::imposta() const { const TString16 field(tipo().imposta()); if (field.not_empty()) return get_real(field); else { real val; for (int i = rows(); i > 0; i--) val += ((TRiga_documento &) ((TDocumento *)this)->row(i)).imposta(); return val; } } real TDocumento::totale_doc() const { const TString16 field(tipo().totale_doc()); if (field.not_empty()) return get_real(field); else return imponibile() + imposta(); } real TDocumento::basesconto() const { const TString16 field(tipo().basesconto()); if (field.not_empty()) return get_real(field); else return ZERO; } real TDocumento::spese() const { const TString16 field(tipo().spese()); if (field.not_empty()) return get_real(field); else return ZERO; } TPagamento & TDocumento::pagamento() { const TString16 codpag(get("CODPAG")); if (codpag != _pag.code()) { _pag.set_code(codpag); _pag.read(); } return _pag; } void TDocumento::put_str(const char* fieldname, const char* val) { if (strcmp(fieldname, "TIPODOC") == 0 && TRectype::get("TIPODOC") != val) { TAuto_variable_rectype::put_str(fieldname, val); reset_fields(*this); set_fields(*this); } else { TAuto_variable_rectype::put_str(fieldname, val); dirty_fields(); } } void TDocumento::zero(const char * fieldname) { if (strcmp(fieldname, "TIPODOC") == 0) reset_fields(*this); TAuto_variable_rectype::zero(fieldname); dirty_fields(); } void TDocumento::zero(char c) { reset_fields(*this); TAuto_variable_rectype::zero(c); } TRectype & TDocumento::operator =(const TRectype & r) { TRectype::operator=(r); reset_fields(*this); set_fields(*this); return *this; } TRectype & TDocumento::operator =(const char * r) { TRectype::operator=(r); reset_fields(*this); set_fields(*this); return *this; } /////////////////////////////////////////////////////////// // 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("DATADOC"); } 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 > 1900, "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); start.put("TIPOCF", tipocf); stop.put("TIPOCF", tipocf); start.put("CODCF", clifo); stop.put("CODCF", clifo); start.put("PROVV", provv); stop.put("PROVV", provv); start.put("ANNO", anno); stop.put("ANNO", anno); if (dn > 0) { start.put("DATADOC", num2date(provv, anno, codnum, dn)); start.put("NDOC", dn); } else { if (dd.ok() && dd > botime) start.put("DATADOC", dd); } if (an > 0) { stop.put("DATADOC", num2date(provv, anno, codnum, an)); stop.put("NDOC", an); } else { if (ad.ok() && ad < eotime) stop.put("DATADOC", ad); } TString filter(16); if (codnum && *codnum) { bool numfilter = FALSE; if (start.get("DATADOC").empty()) numfilter = TRUE; else start.put("CODNUM", codnum); if (stop.get("DATADOC").empty()) numfilter = TRUE; else stop.put("CODNUM", codnum); if (numfilter) filter << "CODNUM=\"" << codnum << '"'; } TCursor cur(&doc, filter, 2, &start, &stop); const TRectype& head = cur.curr(); _documenti.destroy(); for (cur = 0; cur.ok(); ++cur) { const TString16 tipodoc = head.get("TIPODOC"); const TString16 statodoc = head.get("STATO"); if (tipidoc.get_pos(tipodoc) >= 0 && statidoc.get_pos(statodoc) >= 0) { TDocumento* d = new TDocumento(head); _documenti.add(d); } } return _documenti.items(); } int TLista_documenti::write(bool re) const { int err = NOERR; for (int i = 0; i < _documenti.items() && err == NOERR; i++) err = doc(i).write(re); return err; } /////////////////////////////////////////////////////////// // Cliente/Fornitore per vendite /////////////////////////////////////////////////////////// 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, "Record non clienti"); 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, long dz, long 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 > 0) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << ">=" << dz << ')'; } if (az > 0) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_CFVEN << "->" << CLI_CODZONA << "<=" << az << ')'; } TCursor cur(&clifo, filter, 1, &start, &stop); 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 > 0 || az > 0) ordina_per_zona(); 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 { for (int 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; } /////////////////////////////////////////////////////////// // TElaborazione /////////////////////////////////////////////////////////// TElaborazione::TElaborazione(const char* cod) : TRectype(LF_TABCOM) { settab("ELD"); if (cod && *cod) read(cod); } int TElaborazione::read(const char* cod) { CHECK(cod && *cod, "Codice elaborazione nullo"); TTable eld("%ELD"); put("CODTAB", cod); const int err = TRectype::read(eld); if (err != NOERR) yesnofatal_box("Codice elaborazione non valido: %s", cod); return err; } /////////////////////////////////////////////////////////// // TFatturazione bolle /////////////////////////////////////////////////////////// TFatturazione_bolle::TFatturazione_bolle(const char* cod) : TElaborazione(cod) { } void TFatturazione_bolle::tipi_validi(TToken_string& tipi) const { const TString& s2 = get("S2"); tipi.cut(0); TString16 t; for (int i = 0; i < 5; i++) { t = s2.mid(i*4, 4); t.trim(); if (t.not_empty()) tipi.add(t); } CHECK(!tipi.empty_items(), "Nessun tipo documento valido"); } void TFatturazione_bolle::stati_validi(TToken_string& stati) const { const TString& s7 = get("S7"); stati.cut(0); TString16 s; for (int i = 0; i < 5; i++) { s = s7.mid(i*4, 1); s.trim(); if (s.not_empty()) stati.add(s); } CHECK(!stati.empty_items(), "Nessuno stato documento valido"); } bool TFatturazione_bolle::raggruppa(TDocumento& doc_in, TDocumento& doc_out) { #ifdef DBG const TString tipi = get("S2"); const TString& tipodoc = doc_in.tipo().codice(); for (int i = 0; i < 5; i++) { if (tipodoc == tipi.mid(i*4, 4)) break; } if (i >= 5) { NFCHECK("Tipo documento non valido: '%s'", (const char*)tipodoc); return FALSE; } #endif const char stato_finale_in = get_char("S4"); doc_in.stato(stato_finale_in); const TString& tipo_out = get("S8"); doc_out.put("TIPODOC", tipo_out); const char stato_finale_out = get_char("S9"); doc_out.stato(stato_finale_out); if (gestione_riferimenti()) { // Determina ed eventualmente crea la riga di riferimento const int riga_rif = riferimenti_in_testa() ? 1 : doc_out.rows()+1; if (riga_rif > doc_out.rows()) { TRiga_documento& rout = doc_out.new_row(); rout.forza_sola_descrizione(); } TRiga_documento& rout = doc_out[riga_rif]; // Costruisce la stringa di riferimento TString riferimento(80); riferimento = doc_in.tipo().riferimento(); if (riferimento.empty()) riferimento = doc_in.tipo().descrizione(); riferimento << " n. " << doc_in.numero(); riferimento << " del " << doc_in.data().string(); // Setta la descrizione se vuota if (rout.get("DESCR").empty()) rout.put("DESCR", riferimento); else { // Altrimenti aggiungi il riferimento al memo TString memo(1024); memo = rout.get("DESCEST"); if (memo.empty()) rout.put("DESCLUNGA", "X"); else memo << '\n'; memo << riferimento; rout.put("DESCEST", memo); } } const bool ignora_desc = ignora_descrizioni(); TToken_string campi_riga(80); const bool ragg_rig = raggruppa_righe(); if (ragg_rig) { campi_riga = "CODART|UMQTA"; // Uguali sempre // Uguali opzionalmente if (riga_uguale(0)) campi_riga.add("CODMAG"); if (riga_uguale(1)) campi_riga.add("CODIVA"); if (riga_uguale(2)) campi_riga.add("PREZZO|SCONTO"); } for (int r = 1; r <= doc_in.rows(); r++) { const TRiga_documento& rin = doc_in[r]; const bool rindesc = rin.sola_descrizione(); // La riga di input e' descrittiva if (ignora_desc && rindesc) continue; bool elaborata = FALSE; // Raggruppo le righe se e' settato il falg di raggruppamento e // se la riga non contiene solo una descrizione if (ragg_rig && !rindesc) // Se devo raggruppare le righe ... { const int last = doc_out.rows(); for (int o = 1; o <= last; o++) // ... cerca una riga compatibile { TRiga_documento& rout = doc_out[o]; if (rout.sola_descrizione()) // Ignora le righe descrittive continue; if (rin.raggruppabile(rout, campi_riga)) // Se esiste una riga compatibile ... { rout += rin; // ... sommaci la quantita' ecc. elaborata = TRUE; // Ricorda di averla gia' elaborata break; } } } if (!elaborata) // Se la riga non e' stata gia' sommata ... { TRiga_documento& rout = doc_out.new_row(); // ... crea una riga nuova e ... doc_out.copy_data(rout, rin); // ... copiaci tutti i campi della riga sorgente. } } return TRUE; } bool TFatturazione_bolle::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab) { bool ok = TRUE; TToken_string campi_doc(128); // Lista di campi che devono essere uguali campi_doc = "TIPOCF|CODCF|CODVAL|CODLIN"; // Uguali sempre // Uguali opzionalmente const char* cond[] = { "CAMBIO", "SCONTO", "TIPODOC", "CODNUM", "CODPAG", "CODABIA|CODCABA", "CODLIST", "CODAG", "CODSPMEZZO", "CODPORTO", "CAUSTRASP", "CODVETT1|CODVETT2|CODVETT3", NULL }; for (int u = 0; cond[u]; u++) if (doc_uguale(u)) campi_doc.add(cond[u]); for (int id = 0; id < doc_in.items() && ok; id++) { TDocumento& campione = doc_in[id]; const int tot = doc_out.items(); int od = tot; if (campione.raggruppabile()) // Se il documento ha il flag di raggruppabilita' ... { for (od = 0; od < tot; od++) // ... cerca un documento compatibile. { if (campione.raggruppabile(doc_out[od], campi_doc)) break; } } if (od >= tot) // Se non ho trovato un documento compatibile ... { // ... creane uno nuovo (certamente compatibile) const char provv = tipo_numerazione(); const int anno = campione.anno(); const TString codnum = codice_numerazione_finale(); TDocumento* new_doc = new TDocumento(provv, anno, codnum, -1); // Copia i dati della testata TDocumento::copy_data(new_doc->head(), campione.head()); new_doc->put("DATADOC", data_elab); // Aggiungilo alla lista dei documenti in uscita od = doc_out.add(new_doc); } ok = raggruppa(campione, doc_out[od]); } return ok; }