#include "velib.h" #include "vepriv.h" #include #ifndef __APPLICAT_H #include #endif #ifndef __PREFIX_H #include #endif #ifndef __VEUML_H #include "veuml.h" #endif #ifndef __TABUTIL_H #include #endif #ifndef __UTILITY_H #include #endif #ifndef __VEINI_H #include "veini.h" #endif #ifndef __MGLIB_H #include "../mg/mglib.h" #endif #ifndef __SCONTI_H #include "sconti.h" #endif #ifndef __MODAUT_H #include #endif #ifndef __SVLIB01_H #include "../sv/svlib01.h" #endif #include "../mg/movmag.h" /////////////////////////////////////////////////////////// // Movimento di magazzino /////////////////////////////////////////////////////////// class TMov_mag_doc : public TMov_mag { const TDocumento * _doc; protected: virtual const char * codmag_rauto(int r) const; public: TMov_mag_doc(const TDocumento * d) : _doc(d) {} virtual ~TMov_mag_doc() {} }; const char * TMov_mag_doc::codmag_rauto(int r) const { const int rows = _doc->physical_rows(); const long num = get_long(MOVMAG_NUMREG); for (int i = 1; r > 0 && i <= rows; i++) if ((*_doc)[i].is_articolo() && num == (*_doc)[i].get_long("MOVMAG")) r--; i--; if (i > rows) return NULL; const TString & codmag = (*_doc)[i].get("CODMAGC"); return codmag.empty() ? NULL : (const char *) codmag; } /////////////////////////////////////////////////////////// // 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")); _totale = profile.get("TOTALE", "MAIN"); if (_totale.empty()) _totale = "TOTDOC"; TTable frd("%FRD"); frd.put("CODTAB", _totale); if (frd.read() != NOERR) _formule_documento.add(_totale, new TFormula_documento(_documento, _totale, "IMPONIBILI()+IMPOSTE()"), TRUE); if (_formule.find(_totale) < 0) _formule.add(_totale); _totale_netto = "_"; _totale_netto << _totale; _basesconto = profile.get("BASESCONTO", "MAIN"); if (_basesconto.empty()) _basesconto = "BASESCONTO"; frd.put("CODTAB", _basesconto); if (frd.read() != NOERR) _formule_documento.add(_basesconto, new TFormula_documento(_documento, _basesconto, "SOMMA(\"IMPONIBILE()\", \"(TIPO() != 'S') && (TIPO() != 'C')\")"), TRUE); if (_formule.find(_basesconto) < 0) _formule.add(_basesconto); _spese = profile.get("SPESE", "MAIN"); if (_spese.empty()) _spese = "SPESE"; frd.put("CODTAB", _spese); if (frd.read() != NOERR) _formule_documento.add(_spese, new TFormula_documento(_documento, _spese, "SOMMA(\"IMPONIBILE()\", \"TIPO() == 'S'\")"), TRUE); if (_formule.find(_spese) < 0) _formule.add(_spese); if (provvigioni()) { _totprovv = profile.get("TOTPROVV", "MAIN"); if (_totprovv.empty()) _totprovv = "TOTPROVV"; frd.put("CODTAB", _totprovv); if (frd.read() != NOERR) _formule_documento.add(_totprovv, new TFormula_documento(_documento, _totprovv, "SOMMA(\"PROVV()\")"), TRUE); if (_formule.find(_totprovv) < 0) _formule.add(_totprovv); } } 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(); const TString formula(_formule.get()); 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; } else return NULL; } ///////////////////////////////////////////////////////////// // TRiepilogo IVA ///////////////////////////////////////////////////////////// TRiepilogo_iva& TRiepilogo_iva::copy(const TRiepilogo_iva& a) { (TRectype &) _codiva = (TRectype &) a._codiva; _imp = a._imp; _imp_spese = a._imp_spese; _iva = a._iva; _iva_spese = a._iva_spese; _tipo = a._tipo; return *this; } TRiepilogo_iva::TRiepilogo_iva(const TIVA & codiva) : _codiva(codiva) { const TString & t =_codiva.tipo(); if (t == "VE") _tipo = 2; else if (t == "ES") _tipo = 4; else if (t == "NI") _tipo = 8; else if (t == "NS") _tipo = 16; else _tipo = 1; } /////////////////////////////////////////////////////////// // Documento per vendite /////////////////////////////////////////////////////////// long TDocumento::_firm = -1; TAssoc_array TDocumento::_tipi; TAssoc_array TDocumento::_numerazioni; TString16 TDocumento::_codiva_spese; TString16 TDocumento::_codiva_bolli; HIDDEN TStats_agg _st_agg; HIDDEN TAssoc_array _docs_to_agg; bool TDocumento::_has_mag = 3; bool TDocumento::_has_stat_ven = 3; bool TDocumento::_has_provv = 3; TDocumento::TDocumento() : TMultiple_rectype(LF_DOC), _condv(NULL), _sconto(NULL), _esenzione(NULL), _stato_originale(' ') { add_file(LF_RIGHEDOC, "NRIGA"); _tipocf = new TRecfield(*this, "TIPOCF"); _codcf = new TRecfield(*this, "CODCF"); _cod_occas = new TRecfield(*this, "OCFPI"); _provv_agente = new TProvvigioni_agente; set_memo_fld("G1"); for (int i = 3 ; i >= 0; i--) _liv_len[i] = 0; check_modules(); } TDocumento::TDocumento(const TDocumento & d) : TMultiple_rectype(LF_DOC), _condv(NULL), _sconto(NULL), _esenzione(NULL), _stato_originale(' ') { add_file(LF_RIGHEDOC, "NRIGA"); copy(d); check_modules(); } TDocumento::TDocumento(char provv, int anno, const char* codnum, long numdoc, TCond_vendita * condv) : TMultiple_rectype(LF_DOC), _condv(condv), _sconto(NULL), _esenzione(NULL), _stato_originale(' ') { add_file(LF_RIGHEDOC, "NRIGA"); _tipocf = new TRecfield(*this, "TIPOCF"); _codcf = new TRecfield(*this, "CODCF"); _cod_occas = new TRecfield(*this, "OCFPI"); _provv_agente = new TProvvigioni_agente; set_memo_fld("G1"); check_modules(); if (numdoc <= 0) { numdoc = 0; set_key(*this, provv, anno, codnum, numdoc); } else read(provv, anno, codnum, numdoc); for (int i = 3 ; i >= 0; i--) _liv_len[i] = 0; } TDocumento::TDocumento(const TRectype& rec, TCond_vendita * condv) : TMultiple_rectype(LF_DOC), _condv(condv), _sconto(NULL), _provv_agente(NULL), _esenzione(NULL), _stato_originale(' ') { add_file(LF_RIGHEDOC, "NRIGA"); _tipocf = new TRecfield(*this, "TIPOCF"); _codcf = new TRecfield(*this, "CODCF"); _cod_occas = new TRecfield(*this, "OCFPI"); _provv_agente = new TProvvigioni_agente; set_memo_fld("G1"); read(rec); for (int i = 3 ; i >= 0; i--) _liv_len[i] = 0; check_modules(); } TDocumento::~TDocumento() { delete _tipocf; delete _codcf; delete _cod_occas; delete _provv_agente; if (_sconto != NULL) delete _sconto; if (_esenzione != NULL) delete _esenzione; } void TDocumento::check_modules() { if (_has_mag == 3) { _has_mag = main_app().has_module(MGAUT, CHK_DONGLE); _has_stat_ven = main_app().has_module(SVAUT, CHK_DONGLE); _has_provv = main_app().has_module(PRAUT, CHK_DONGLE); } } void TDocumento::test_firm() { const long new_firm = prefix().get_codditta(); if (_firm != new_firm) { TConfig conf(CONFIG_DITTA); _codiva_spese = conf.get("SPINCODIVA", "ve"); _codiva_bolli = conf.get("SPBOCODIVA", "ve"); _firm = new_firm; } } real TDocumento::spese_incasso(real & imp, int ndec, TTipo_importo t) const { real imp_spese; real percentuale = get_real("PERCSPINC"); static TArray spese_inc; if (percentuale > ZERO) { if (ndec == AUTO_DECIMALS) ndec = in_valuta() ? 3 : 0; 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("IMPSPINC", "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; real iva_spese(iva(imp_spese, TRiga_documento::iva(codiva_spese()), ndec)); if (t == _lordo) imp_spese += iva_spese; else if (t == _imposta) imp_spese = iva_spese; imp_spese /= cambio; imp_spese.round(ndec); } return imp_spese; } real TDocumento::bolli(real & imp, int ndec, TTipo_importo t) 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")) { if (ndec == AUTO_DECIMALS) ndec = in_valuta() ? 3 : 0; 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; real imp_orig = imposta(); real sp_orig = spese(); for (int j = 0; j < 5 && tot_bolli != old_bolli; j++) { old_bolli = tot_bolli + iva_bolli; const real imposte = imp_orig * cambio + iva_bolli; const real imp_spese = sp_orig * 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; if (imp_bolli.items() > 0) 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; } } iva_bolli = iva(tot_bolli, TRiga_documento::iva(codiva_bolli()), ndec); importo += (tot_bolli + iva_bolli - old_bolli); } if (t == _lordo) tot_bolli += iva_bolli; else if (t == _imposta) tot_bolli = iva_bolli; tot_bolli /= cambio; tot_bolli.round(ndec); } return tot_bolli; } bool TDocumento::modificabile() const { const char stato_attuale = stato(); if (stato_attuale <= ' ') return TRUE; TString80 stati_modifica = tipo().stati_iniziali_modifica(); return stati_modifica.trim().empty() || stati_modifica.find(stato_attuale) >= 0; } bool TDocumento::cancellabile() const { const char stato_attuale = stato(); if (stato_attuale <= ' ') return TRUE; TString80 stati_cancellazione = tipo().stati_iniziali_cancellazione(); return stati_cancellazione.trim().empty() || stati_cancellazione.find(stato_attuale) >= 0; } bool TDocumento::stampabile() const { const char stato_attuale = stato(); if (stato_attuale <= ' ') return TRUE; TString80 stati_stampa = tipo().stati_iniziali_stampa(); return stati_stampa.trim().empty() || stati_stampa.find(stato_attuale) >= 0; } // 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); } void TDocumento::copy_contents(const TDocumento & src) { copy_data(head(), src.head()); destroy_rows(); const int rows = src.physical_rows(); for (int i = 0; i < rows ; i++) { const TRiga_documento & s = src[i]; TRiga_documento & r = new_row(s.tipo().codice()); copy_data(r, s); } } TRiga_documento& TDocumento::insert_row(int row, const char *tipo) { TRiga_documento & r = (TRiga_documento &) TMultiple_rectype::insert_row(row); // ok if (tipo) r.set_tipo(tipo); return r; } TRiga_documento& TDocumento::new_row(const char *tipo) { TRiga_documento & r = (TRiga_documento&)TMultiple_rectype::new_row(); // ok if (tipo) r.set_tipo(tipo); return r; } int TDocumento::read(TBaseisamfile& f, word op, word lockop) { int err = TMultiple_rectype::read(f, op ,lockop); _cli_for.zero(); _occas.zero(); set_riga_sconto(); if (is_fattura()) set_riga_esenzione(); _stato_originale = stato(); if (err == NOERR && tipo().statistiche() && _has_stat_ven) { TString80 key(get(DOC_PROVV)); key << get(DOC_ANNO); key << get(DOC_CODNUM); key << get(DOC_NDOC); TObject * o = _docs_to_agg.objptr(key); if ( lockop >= _lock && o == NULL) { _docs_to_agg.add(key, key); for (int i = physical_rows(); i > 0; i--) _st_agg.sub(row(i)); } else if (lockop == _unlock && o != NULL) { _docs_to_agg.remove(key); for (int i = physical_rows(); i > 0; i--) _st_agg.add(row(i)); } if (_docs_to_agg.items() == 0) _st_agg.update(); } return err; } int TDocumento::read(char provv, int anno, const char* codnum, long numdoc, word op, word lockop) { CHECK(numdoc > 0, "Numero documento nullo."); zero(); set_key(*this, provv, anno, codnum, numdoc); return read(op, lockop); } long TDocumento::renum_ndoc(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); } put(DOC_NDOC, numdoc); // Aggiorna testata TMultiple_rectype::renum_key(); // Aggiorna righe ok return numdoc; } void TDocumento::set_riga_sconto() { const TString80 sconto(get("SCONTOPERC")); if (sconto.empty()) { if(_sconto != NULL) delete _sconto; _sconto = NULL; } else { if (_sconto == NULL) { static TString _tipo_riga_sc; if (_tipo_riga_sc.empty()) { TConfig conf(CONFIG_STUDIO); _tipo_riga_sc = conf.get("TRSCONTI", "ve"); } _sconto = new TRiga_documento(this, _tipo_riga_sc); _sconto->put("DESCR","Sconto"); } _sconto->put("SCONTO", sconto); } } void TDocumento::set_riga_esenzione() { TCli_for & c = clifor(); const TIVA codes(c.vendite().get(CFV_ASSFIS)); const TString16 v_esenzione(c.vendite().get(CFV_VSPROT)); const TString16 v_data_esenzione(c.vendite().get(CFV_VSDATAREG)); // const TString16 ufficio_IVA; ?? const TString16 n_registrazione(c.vendite().get(CFV_NSPROT)); const TString16 n_data_registrazione(c.vendite().get(CFV_NSDATAREG)); bool esente = codes.tipo().not_empty() && v_esenzione.not_empty() && v_data_esenzione.not_empty() && n_registrazione.not_empty() && n_data_registrazione.not_empty(); if (esente) { esente = FALSE; const TString16 codiva(codes.codice()); for (int i = physical_rows(); !esente && i > 0; i--) esente = codiva == row(i).get("CODIVA"); } if (!esente) { if(_esenzione != NULL) delete _esenzione; _esenzione = NULL; } else { static TString _tipo_riga_es; static real _bollo_es; if (_tipo_riga_es.empty()) { TConfig conf(CONFIG_STUDIO); _tipo_riga_es = conf.get("TRESENZ", "ve"); _bollo_es = (real)conf.get("BOLLIES", "ve"); } if (_esenzione == NULL) _esenzione = new TRiga_documento(this, _tipo_riga_es); TString d(256); d.format("Fattura non imponibile come da vostra dichiarazion"); _esenzione->put( "DESCR", d); /* rilasciata dall' ufficio IVA di %s*/ d.format("e n. %s del %s da noi annotata al n. %s il %s. Marca da bollo da Lit. %s sull' originale.", (const char *) v_esenzione, (const char *) v_data_esenzione, /*(const char *) ufficio_IVA, */(const char *) n_registrazione, (const char *) n_data_registrazione, _bollo_es.string(".")); _esenzione->put("DESCLUNGA", "X"); _esenzione->put("DESCEST", d); } } 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(); dirty_tabella_iva(); for (int i = loaded_rows(); i > 0; i--) { TRiga_documento & r = (TRiga_documento &) row(i); if (r.doc_dependent()) r.dirty_fields(FALSE); } } int TDocumento::write_rewrite(TBaseisamfile & f, bool re) const { TDocumento & myself = *((TDocumento *)this); const bool new_doc = nuovo() || numero() <= 0; // E' nuovo di zecca! if (new_doc) { char stato_finale = tipo().stato_finale_inserimento(); if (stato_finale > ' ') myself.stato(stato_finale); } else { if (_stato_originale == stato()) if (!modificabile() && !yesno_box("Documento non modificabile,\n vuoi continuare ugualmente")) return NOERR; myself._stato_originale = stato(); } const bool check_movmag = main_app().has_module(MGAUT, CHK_DONGLE) && tipo().mov_mag(); const char stato_doc(stato()); const bool do_movmag = tipo().stato_with_mov_mag(stato_doc); if (tipo().spese_aut() && !get_bool("SPESEUPD")) { TString16 name("CODSP0"); TString_array spese; TRectype & ven_rec = clifor().vendite(); for (int i = 1; i <= 4; i++) { name.rtrim(1); name << i; const TString16 s(ven_rec.get(name)); if (s.not_empty()) spese.add(s); } myself.update_spese_aut(spese); } int err = NOERR; long num = get_long("MOVMAG"); const int rows = physical_rows(); if (check_movmag) { TMov_mag_doc mov(this); TLocalisamfile m(LF_MOVMAG); mov.zero(); if (num == 0 && do_movmag) { num = atol(mov.get_next_key()); mov.put(MOVMAG_NUMREG, num); while (mov.write(m) == _isreinsert) { num++; mov.put(MOVMAG_NUMREG, num); } myself.put("MOVMAG", num); } if (num > 0) { mov.put(MOVMAG_NUMREG, num); while (mov.read(m, _isequal, _testandlock) == _islocked) message_box("Movimento di magazzino in uso da parte di un'altro utente"); if (do_movmag) { TRecord_array & b = mov.body(); const int mag_rows = mov.rows(); for (int i = mag_rows; i > 0; i--) { TRectype & r = b[i]; if (r.get_char(RMOVMAG_TIPORIGA) == riga_dadocumento) { b.destroy_row(i); if (b.exist(i + 1) && b[i + 1].get_char(RMOVMAG_TIPORIGA) == riga_automatica) b.destroy_row(i + 1); } } b.pack(); TDate d(get("DATADOC")); mov.put(MOVMAG_ANNOES, mov.codice_esercizio(d)); mov.put(MOVMAG_DATAREG, d); mov.put(MOVMAG_DATACOMP, d); mov.put(MOVMAG_DOCPROVV, get("PROVV")); mov.put(MOVMAG_ANNODOC, get("ANNO"));; mov.put(MOVMAG_CODNUM, get("CODNUM")); const long numdoc = get_long("NDOC"); mov.put(MOVMAG_NUMDOC, numdoc); mov.put(MOVMAG_CATVEN, get("CATVEN")); mov.put(MOVMAG_CODLIST, get("CODLIST")); mov.put(MOVMAG_CODCONT, get("CODCONT")); mov.put(MOVMAG_CODCAMP, get("CODCAMP")); mov.put(MOVMAG_CODCAUS, get("CAUSMAG")); mov.put(MOVMAG_DESCR, format("%s n.ro %ld del %s", (const char *) tipo().get("S1"), numdoc, (const char *) d.string())); mov.put(MOVMAG_TIPOCF, get("TIPOCF")); mov.put(MOVMAG_CODCF, get("CODCF")); int j = 1; for (i = 1; i <= rows; i++) { TRiga_documento & r = myself.row(i); if (r.is_articolo()) { long r_num = r.get_long("MOVMAG"); if (r_num == 0) { r_num = num; r.put("MOVMAG", r_num); } if (r_num == num) { TRectype & rm = mov.insert_row(j++); rm.put(RMOVMAG_CODMAG, r.get("CODMAG")); rm.put(RMOVMAG_CODART, r.get("CODARTMAG")); rm.put(RMOVMAG_LIVGIAC, r.get("LIVELLO")); rm.put(RMOVMAG_UM, r.get("UMQTA")); rm.put(RMOVMAG_QUANT, r.get("QTA")); rm.put(RMOVMAG_PREZZO, r.get("PREZZO")); rm.put(RMOVMAG_CODCAUS, r.get("CAUSMAG")); rm.put(RMOVMAG_TIPORIGA, (char) riga_dadocumento); } } } mov.rewrite(m); } else { mov.remove(m); for (int i = rows; i > 0; i--) { TRiga_documento & r = myself.row(i); long r_num = r.get_long("MOVMAG"); if (r_num == num) r.zero("MOVMAG"); } ((TDocumento *)this)->zero("MOVMAG"); } } } { TLocalisamfile anamag(LF_ANAMAG); TLocalisamfile codalt(LF_CODCORR); codalt.setkey(2); for (int i = rows; i > 0; i--) { TRiga_documento & r = myself.row(i); if ((r.is_merce() || r.is_omaggio()) && !r.is_checked()) { const TString & codart = r.get("CODART"); anamag.put("CODART", codart); if (anamag.read() == NOERR) r.put("CODARTMAG", codart); else { codalt.put("CODARTALT", codart); if (codalt.read() == NOERR) r.put("CODARTMAG", codalt.get("CODART")); } r.checked(); } } } err = TMultiple_rectype::write_rewrite(f, re); if (err == NOERR && clifor().occasionale()) { if (get("OCFPI").not_empty()) { TLocalisamfile o(LF_OCCAS); TOccasionale & occ = occas(); err = occ.write(o); if (err == _isreinsert) err = occ.rewrite(o); } } if (tipo().statistiche() && _has_stat_ven) { TString80 key(get(DOC_PROVV)); key << get(DOC_ANNO); key << get(DOC_CODNUM); key << get(DOC_NDOC); TObject * o = _docs_to_agg.objptr(key); if (o != NULL) _docs_to_agg.remove(key); for (int i = physical_rows(); i > 0; i--) _st_agg.add(myself.row(i)); if (_docs_to_agg.items() == 0) _st_agg.update(); } return err; } // eliminare anche il mov di mag. ?????? int TDocumento::remove(TBaseisamfile& f) const { if (!cancellabile() && !yesno_box("Documento non cancellabile,\n vuoi continuare ugualmente")) return NOERR; const bool check_movmag = main_app().has_module(MGAUT, CHK_DONGLE) && tipo().mov_mag(); if (check_movmag) { const long num = get_long("MOVMAG"); if (num > 0) { TMov_mag_doc mov(this); TLocalisamfile m(LF_MOVMAG); mov.put(MOVMAG_NUMREG, num); while (mov.read(m, _isequal, _testandlock) == _islocked) message_box("Movimento di magazzino in uso da parte di un'altro utente"); mov.remove(m); } } if (tipo().statistiche() && _has_stat_ven) { TString80 key(get(DOC_PROVV)); key << get(DOC_ANNO); key << get(DOC_CODNUM); key << get(DOC_NDOC); TObject * o = _docs_to_agg.objptr(key); if (o != NULL) _docs_to_agg.remove(key); if (_docs_to_agg.items() == 0) _st_agg.update(); } return TMultiple_rectype::remove(f); } TProvvigioni_agente& TDocumento::calc_provvigioni(const bool generata) { CHECK (_provv_agente, "Bad TProvvigione_agente object"); TString agente(get(DOC_CODAG)); const int anno = TDocumento::anno(); TString codnum(numerazione()); const long ndoc = numero(); TDate datadoc(data()); _provv_agente->read(agente, anno,codnum,ndoc); // Legge le provvigioni per questo documento const real perc = _provv_agente->perc_fatt(); const real tot_provv = provvigione(); real provv_fat = (tot_provv / 100.0) * perc; // Provvigione sul fatturato (rata 0) provv_fat.round(); real provv_pag = tot_provv - provv_fat; // Provvigione sul pagato (da suddivere secondo il pagamento) const real change(cambio()); // Calcolo rate per provvigioni e documento TPagamento& pag1 = pagamento(); // Per rate documento TPagamento* pag2 = new TPagamento(pag1.code(), datadoc.string()); // Per rate documento real totspese = spese(); real totimposte = imposta(); real totimponibili = totale_doc() - totimposte - totspese; const bool valuta = in_valuta(); if (valuta) { real val1 = totimponibili * change; real val2 = totimposte * change; real val3 = totspese * change; pag1.set_total_valuta(totimponibili, totimposte, totspese, change, val1, val2, val3); pag2->set_total_valuta(provv_pag, ZERO, ZERO, change, provv_pag*change, ZERO, ZERO); } else { pag1.set_total(totimponibili, totimposte, totspese); pag2->set_total(provv_pag, ZERO, ZERO); } pag1.set_rate_auto(); pag2->set_rate_auto(); // Crea le nuove rate provvigionali const bool isnew = _provv_agente->items() == 0; // Il documento non ha righe provvigionali TRate_doc& rd = _provv_agente->rate(anno, codnum, ndoc, isnew ? TRUE : FALSE); // A questo punto rd e' vuoto: settiamo i dati del documento: TToken_string t; t.add(anno); t.add(codnum);t.add(ndoc); t.add(datadoc.string()); t.add(totale_doc().string()); t.add(tot_provv.string());t.add(totale_netto().string()); t.add(codcf()); t.add(TDocumento::valuta());t.add(change.string()); t.add(get(DOC_DATACAMBIO)); rd.set(t); // Adesso si possono aggiungere le rate (per quelle gia' esistenti sostituisce solo alcuni valori) // - Rata 0 : importo rata = 0; importo provvigione = provvigione all'atto della fattura (percentuale sugli agenti) // data scadenza viene settata uguale alla data documento // la provvigione rimanente va suddivisa in rate a seconda del codice pagamento const int nrate = pag1.n_rate(); for (int i = 0; i < nrate+1; i++) { TRata& rt = rd.row(i, isnew); rt.set_rata(i); rt.set_datascad(i == 0 ? datadoc : pag1.data_rata(i-1)); rt.set_tipopag(i == 0 ? 1 : pag1.tipo_rata(i-1)); rt.set_imprata(i == 0 ? ZERO : pag1.importo_rata(i-1,valuta ? TRUE : FALSE)); rt.set_impprovv(i == 0 ? provv_fat : pag2->importo_rata(i-1,valuta ? TRUE : FALSE)); if (generata) rt.set_generata(); } // Rimuove eventuali righe in eccesso for (i = nrate; i < _provv_agente->items(); i++) rd.remove_rata(i); delete pag2; return *_provv_agente; } bool TDocumento::in_valuta() const { const TString& val = valuta(); return (val.not_empty() && val != "LIT"); } TRiga_documento & TDocumento::row(int index) { TRecord_array & b = body(); const int nrows = b.rows(); TRiga_documento * r = NULL; if (index <= nrows) { r = &((TRiga_documento &) b.row(index, FALSE)); CHECKD(r, "Riga documento non esistente ", index); } else { CHECKD((index == nrows + 1 && (_sconto != NULL || _esenzione != NULL)) || (index == nrows + 2 && _sconto != NULL && _esenzione != NULL), "Riga documento non esistente ", index); if (index == nrows + 1) { r = _sconto != NULL ? _sconto : _esenzione; } if (index == nrows + 2) r = _esenzione; } return *r; } 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 char * tipodoc) { CHECK(tipodoc && *tipodoc, "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; } const TTipo_documento& TDocumento::tipo() const { const TString16 tipodoc(get("TIPODOC")); return tipo(tipodoc); } const TCodice_numerazione& TDocumento::codice_numerazione() const { const TString16 key(numerazione()); TCodice_numerazione* o = (TCodice_numerazione*)_numerazioni.objptr(key); if (o == NULL) { o = new TCodice_numerazione(key); _numerazioni.add(key, 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 (tipo_valido()) { 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("_"); TString netto_def(exp->string()); if (netto_def.find("IMPONIBILI") == -1) { if (netto_def.not_empty()) netto_def << "+"; netto_def << "IMPONIBILI()"; } if (netto_def.find("IMPOSTE") == -1) { if (netto_def.not_empty()) netto_def << "+"; netto_def << "IMPOSTE()"; } TExpr_documento netto_exp(netto_def, _numexpr, this); add_field(new TDocumento_variable_field(work_tot_doc, netto_exp)); TExpr_documento tot_exp(format("%s + _BOLLI(%s)", (const char *) work_tot_doc, (const char *) work_tot_doc), _numexpr, this); add_field(new TDocumento_variable_field(f->name(), tot_exp)); } else if (exp) { exp->set_doc(this); add_field(new TDocumento_variable_field(f->name(), *exp)); } } } } real TDocumento::imponibile(bool spese, int ndec) const { real val; if (ndec == AUTO_DECIMALS) ndec = in_valuta() ? 3 : 0; for (int i = rows(); i > 0; i--) val += ((TRiga_documento &) ((TDocumento *)this)->row(i)).imponibile(); if (spese) { real tot_doc = val + imposta(FALSE, ndec); val += spese_incasso(tot_doc, ndec, _netto); tot_doc += spese_incasso(tot_doc, ndec); val += bolli(tot_doc, ndec, _netto); } val.round(ndec); return val; } void TDocumento::update_tabella_iva() { const int items = rows(); TAssoc_array & table = _tabella_iva; if (table.items() > 0 || items == 0) { if (items == 0) table.destroy(); return; } real tot_doc; real tot_sconti; real tot_sconti_perc; for (int i = items; i > 0; i--) { const TRiga_documento& r = row(i); const real imponibile = r.imponibile(); tot_doc += imponibile; if (r.is_sconto()) { tot_sconti += imponibile; if (r.is_sconto_perc()) tot_sconti_perc += imponibile; } else if (!r.is_descrizione()) { const real imposta = r.imposta(FALSE); // Aggiorna o aggiunge l'elemento se non esiste const TIVA & iva = r.iva(); const TString16 cod(iva.codice()); TRiepilogo_iva * aliquota = (TRiepilogo_iva *) table.objptr(cod); if (aliquota == NULL) { aliquota = new TRiepilogo_iva(iva); table.add(cod, aliquota); } aliquota->imp() += imponibile; aliquota->iva() += imposta; tot_doc += imposta; } } if (tot_sconti != ZERO) { TGeneric_distrib d(tot_sconti); real tot_sconti_imp = tot_sconti - tot_sconti_perc; const int ndec = in_valuta() ? 3 : 0; table.restart(); for (TRiepilogo_iva * ri = (TRiepilogo_iva *) table.get(); ri != NULL; ri = (TRiepilogo_iva *) table.get()) d.add(ri->imp()); table.restart(); for (ri = (TRiepilogo_iva *) table.get(); ri != NULL; ri = (TRiepilogo_iva *) table.get()) { const char * codiva = ri->cod_iva().codice(); const real i(d.get()); real & imponibile = ri->imp(); imponibile += i; TGeneric_distrib s(i); s.add(tot_sconti_imp); s.add(tot_sconti_perc); ri->sconto_imp() = s.get(); ri->sconto_perc() = s.get(); real & iva = ri->iva(); const TIVA & ci = row(1).iva(codiva); const real imposta(::iva(i, ci, ALL_DECIMALS)); iva += imposta; ri->iva_sconto() = ::iva(i, ci, ndec); tot_doc += imposta; } } TRiepilogo_iva * ri = (TRiepilogo_iva *) table.objptr(codiva_spese()); if (ri == NULL) ri = new TRiepilogo_iva(TIVA(codiva_spese())); real val = spese_incasso(tot_doc, ALL_DECIMALS, _netto); ri->imp_spese() += val; tot_doc += val; val = spese_incasso(tot_doc, ALL_DECIMALS, _imposta); ri->iva_spese() += val; tot_doc += val; ri = (TRiepilogo_iva *) table.objptr(codiva_bolli()); if (ri == NULL) ri = new TRiepilogo_iva(TIVA(codiva_bolli())); val = bolli(tot_doc, ALL_DECIMALS, _netto); ri->imp_spese() += val; tot_doc += val; val = bolli(tot_doc, ALL_DECIMALS, _imposta); ri->iva_spese() += val; tot_doc += val; } real TDocumento::imposta(bool spese, int ndec) const { TAssoc_array & table = ((TDocumento *)this)->tabella_iva(); real val; if (ndec == AUTO_DECIMALS) ndec = in_valuta() ? 3 : 0; for (TRiepilogo_iva * ri = (TRiepilogo_iva *) table.get(); ri != NULL; ri = (TRiepilogo_iva *) table.get()) { real iva = ri->imposta(spese); if (iva < ZERO) iva.floor(ndec); else iva.ceil(ndec); val += iva; } return val; } real TDocumento::totale_doc() const { const TString16 field(tipo().totale_doc()); if (field.not_empty()) return get_real(field); else { real r = imponibile() + imposta(); r += spese_incasso(r, in_valuta() ? 3 : 0); r += bolli(r, in_valuta() ? 3 : 0); return r; } } real TDocumento::totale_netto() const { const TString16 field(tipo().totale_netto()); 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; } real TDocumento::provvigione(int ndec) const { real val; if (ndec == AUTO_DECIMALS) ndec = in_valuta() ? 3 : 0; // update for agente ??? const TString16 & field = tipo().totprovv(); if (field.not_empty()) return get_real(field); else for (int i = rows(); i > 0; i--) val += ((TRiga_documento &) ((TDocumento *)this)->row(i)).provvigione(ndec); return val; } void TDocumento::put_str(const char* fieldname, const char* val) { if (strcmp(fieldname, "TIPODOC") == 0) { const TString v(val); if (TRectype::get("TIPODOC") != v) { TAuto_variable_rectype::put_str(fieldname, v); reset_fields(*this); set_fields(*this); } else dirty_fields(); } else if (strcmp(fieldname, "CODCF") == 0) { const TString v(val); put("SPESEUPD", TRectype::get("CODCF") == v); TAuto_variable_rectype::put_str(fieldname, v); dirty_fields(); } else { TAuto_variable_rectype::put_str(fieldname, val); dirty_fields(); if (strcmp(fieldname, "SCONTOPERC") == 0) set_riga_sconto(); } } void TDocumento::zero(const char * fieldname) { if (strcmp(fieldname, "TIPODOC") == 0) reset_fields(*this); TRectype::zero(fieldname); dirty_fields(); } TCli_for & TDocumento::clifor() const { const char tipo = tipocf(); const long codice = codcf(); if (_cli_for.empty() || _cli_for.tipo() != tipo || _cli_for.codice() != codice) ((TDocumento *) this)->_cli_for.read(tipo, codice); return (TCli_for &)_cli_for; } TOccasionale & TDocumento::occas() const { const TString80 occ_code(cod_occas()); if (_occas.empty() || strcmp(_occas.codice(), occ_code) != 0) { TLocalisamfile o(LF_OCCAS); ((TDocumento *) this)->_occas.zero(); ((TDocumento *) this)->_occas.put(OCC_CFPI, occ_code); TRectype oc(_occas); if (((TDocumento *) this)->_occas.read(o) != NOERR) ((TDocumento *) this)->_occas = oc; } return (TOccasionale &) _occas; } TDocumento & TDocumento::copy(const TDocumento & d) { TMultiple_rectype::operator=((TMultiple_rectype &)d); reset_fields(*this); set_fields(*this); for (int i = physical_rows(); i > 0; i--) { TRiga_documento & r = row(i); r.set_doc(this); } for (i = 0; i < 3; i++) _liv_len[i] = d._liv_len[i]; set_riga_sconto(); if (is_fattura()) set_riga_esenzione(); set_condv(d._condv); return *this; } TRectype & TDocumento::operator =(const TRectype & r) { return TMultiple_rectype::operator=(r); } TRectype & TDocumento::operator =(const char * r) { return TMultiple_rectype::operator=(r); } void TDocumento::update_spese_aut(TString_array & spese_aut, bool preserve_old, TSheet_field * sh) { const bool updated = get_bool("SPESEUPD"); if (updated) return; const bool interactive = sh != NULL; if (tipo().spese_aut()) { const int nrows = physical_rows(); for (int i = nrows; i > 0; i--) { TRiga_documento & r = row(i); if (r.tipo().tipo() == RIGA_SPESEDOC && r.is_generata()) { if (preserve_old) return; destroy_row(i, TRUE); if (interactive) sh->destroy(i - 1); } } TString16 cod_iva_cli; const int nspese = spese_aut.items(); if (nspese > 0) { TLocalisamfile cfven(LF_CFVEN); cfven.put("TIPOCF", get("TIPOCF")); cfven.put("CODCF", get("CODCF")); if (cfven.read() == NOERR) cod_iva_cli = cfven.get("ASSFIS"); for (i = 0; i < nspese; i++) { const TString & s = spese_aut.row(i); TSpesa_prest sp(s); TString16 tipo(sp.tipo_riga()); TRiga_documento & riga = new_row(tipo); riga.put("CODART", s); riga.generata(); riga.put("DESCR", sp.descrizione()); switch (sp.tipo()) { case 'Q': { real qta = sp.qta(); if (qta == ZERO) qta = 1.0; riga.put("QTA", qta); } case 'V': { const real cambio = get_real("CAMBIO"); const TString16 valuta = get("CODVAL"); real prezzo = sp.prezzo(); sppr_calc(sp, valuta, cambio, prezzo); riga.put("PREZZO", prezzo); riga.put("UMQTA", sp.um()); } break; case 'P': default: break; } if (cod_iva_cli.empty()) riga.put("CODIVA", sp.cod_iva()); else riga.put("CODIVA", cod_iva_cli); if (interactive) { const int nrow = sh->insert(-1, FALSE); riga.autoload(*sh); sh->check_row(nrow); } } } } put("SPESEUPD", TRUE); }