#include #include #include "velib01.h" /////////////////////////////////////////////////////////// // Funzioni per il calcolo dei prezzi netti/lordi /////////////////////////////////////////////////////////// real lordo2netto(real& lordo, const TString& codiva, bool is_valuta) { TTable tabiva("%IVA"); real aliquota = 0.0; tabiva.put("CODTAB", codiva); if (tabiva.read() == NOERR) aliquota = tabiva.get_real("R0"); return lordo2netto(lordo,aliquota,is_valuta); } real netto2lordo(const real& netto, const TString& codiva, bool is_valuta) { TTable tabiva("%IVA"); real aliquota = 0.0; tabiva.put("CODTAB", codiva); if (tabiva.read() == NOERR) aliquota = tabiva.get_real("R0"); return netto2lordo(netto,aliquota,is_valuta); } real lordo2netto(real& lordo, const real& iva, bool is_valuta) { 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(is_valuta ? 3 : 0); } netto = lordo - imposta; // Questo e' l'importo netto imposta_rec = (netto * iva) / 100.0; // Ricalcola l'imposta con il nuovo imponibile imposta_rec.ceil(is_valuta ? 3 : 0); 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, bool is_valuta) { real lordo; real imposta = 0.0; if (!iva.is_zero()) { imposta = (netto * iva) / 100.0; // Calcola l'imposta imposta.ceil(is_valuta ? 3 : 0); } lordo = imposta + netto; // prezzo lordo return lordo; } /////////////////////////////////////////////////////////// // Tipo documento /////////////////////////////////////////////////////////// TTipo_documento::TTipo_documento(const char* tipodoc) : _rec(LF_TABCOM) { if (tipodoc && *tipodoc) read(tipodoc); } TTipo_documento::TTipo_documento(const TRectype& rec) : _rec(rec) { } TTipo_documento::~TTipo_documento() { } int TTipo_documento::read(const char* tipodoc) { TTable t("%TIP"); t.put("CODTAB", tipodoc); int err = t.read(); if (err == NOERR) _rec = t.curr(); return err; } /////////////////////////////////////////////////////////// // Documento per vendite /////////////////////////////////////////////////////////// TAssoc_array TDocumento::_tipi; TDocumento::TDocumento() : _head(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA") { } TDocumento::TDocumento(char provv, int anno, const char* codnum, long numdoc) : _head(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA") { if (numdoc <= 0) { numdoc = get_next_key(provv, anno, codnum); set_key(_head, provv, anno, codnum, numdoc); TRectype* key = new TRectype(LF_RIGHEDOC); set_key(*key, provv, anno, codnum, numdoc); _rows.set_key(key); #ifdef DBG TLocalisamfile doc(LF_DOC); TRectype test(_head); if (test.read(doc) != NOERR) yesnofatal_box("Documento gia' esistente: %c %d %s %l", provv, anno, codnum, numdoc); #endif } 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, "Codice numerazione nullo"); CHECK(numdoc > 0, "Numero documento nullo"); 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) { 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"); dst = src; set_key(dst, provv, anno, codnum, numdoc); } TDocumento::TDocumento(const TRectype& rec) : _head(LF_DOC), _rows(LF_RIGHEDOC, "NRIGA") { read(rec); } int TDocumento::read(const TRectype& rec) { _head = rec; TRectype* key = new TRectype(LF_RIGHEDOC); const char pr = tipo_numerazione(); const int an = anno(); const TString16 cn = numerazione(); const long nu = numero(); set_key(*key, pr, an, cn, nu); TLocalisamfile doc(LF_DOC); int err = _head.read(doc); if (err == NOERR) _rows.read(key); else { _head = rec; _rows.set_key(key); } return err; } int TDocumento::read(char provv, int anno, const char* codnum, long numdoc) { TRectype rec(LF_DOC); set_key(rec, provv, anno, codnum, numdoc); return read(rec); } int TDocumento::write(bool re) const { TLocalisamfile doc(LF_DOC); int err = NOERR; if (re) { err = _rows.write(re); if (err == NOERR) { err = _head.rewrite(doc); if (err != NOERR) err = _head.write(doc); } } else { err = _head.write(doc); if (err != NOERR) err = _head.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 = _head.remove(doc); return err; } long TDocumento::get_next_key(char provv, int anno, const char* codnum) const { TLocalisamfile doc(LF_DOC); TRectype& curr = doc.curr(); set_key(curr, provv, anno, codnum, 9999999L); const int err = doc.read(_isgreat); long n = 1; 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") + 1; } return n; } const TTipo_documento& TDocumento::tipo() const { const TString16 tipodoc(_head.get("TIPODOC")); CHECK(*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; } bool TDocumento::raggruppabile(const TDocumento& doc) const { if (!raggruppabile() || !doc.raggruppabile()) return FALSE; TToken_string campi(128); campi = "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 }; const TTipo_documento& tipodoc = tipo(); for (int u = 0; cond[u]; u++) { if (tipodoc.uguale(u)) campi.add(cond[u]); } const TRectype& other = doc.head(); bool ok = TRUE; for (const char* c = campi.get(0); c && ok; c = campi.get()) ok &= _head.get(c) == other.get(c); return ok; } /////////////////////////////////////////////////////////// // Lista di documenti /////////////////////////////////////////////////////////// TDate TLista_documenti::num2date(char provv, int anno, const char* codnum, long num) const { TLocalisamfile doc(LF_DOC); TRectype& curr = doc.curr(); TDocumento::set_key(curr, provv, anno, codnum, num); TDate d; if (doc.read() == NOERR) d = curr.get("DATADOC"); return d; } int TLista_documenti::read(char tipo, long clifo, int anno, const TDate& dd, const TDate& ad, const char* codnum, long dn, long an, char provv) { CHECK(tipo == 'C' || tipo == 'F', "Il tipo deve essere Cliente o Fornitore"); CHECK(clifo > 0L, "Codice cliente non valido"); CHECK(provv == 'D' || provv == 'P', "Provvisorio o Definitivo?"); CHECKD(anno > 1900, "Anno non valido: ", anno); TRelation doc(LF_DOC); TRectype start(LF_DOC), stop(LF_DOC); start.put("TIPOCF", tipo); stop.put("TIPOCF", tipo); 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); _documenti.destroy(); for (cur = 0; cur.ok(); ++cur) { TDocumento* d = new TDocumento(cur.curr()); _documenti.add(d); } return _documenti.items(); } int TLista_documenti::write(bool re) const { int err = NOERR; for (int i = _documenti.items()-1; i >= 0 && 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, const TRectype& ven) { if (!ven.empty()) init(rec, ven); else { 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); for (cur = 0; cur.ok(); ++cur) { TClifo* c = new TClifo(cur.curr(), cur.curr(LF_CFVEN)); _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) : _rec(LF_TAB) { if (cod && *cod) read(cod); } int TElaborazione::read(const char* cod) { CHECK(cod && *cod, "Codice elaborazione nullo"); TTable eld("%ELD"); eld.put("CODTAB", cod); const int err = eld.read(); if (err == NOERR) _rec = eld.curr(); else yesnofatal_box("Codice elaborazione non valido: %s", cod); return err; } /////////////////////////////////////////////////////////// // TFatturazione bolle /////////////////////////////////////////////////////////// bool TFatturazione_bolle::raggruppa(TDocumento& doc_in, TDocumento& doc_out) { const TString tipi = _rec.get("S2"); for (int i = 0; i < 5; i++) { if (doc_in.tipo() == tipi.mid(i*4, 4)) break; } CHECK(i < 5, "Tipo documento non valido"); const char stato_finale_in = _rec.get("S7")[i]; doc_in.stato(stato_finale_in); const char stato_finale_out = _rec.get_char("S9"); doc_out.stato(stato_finale_out); for (i = 1; i <= doc_in.rows(); i++) { TRectype& nr = doc_out.new_row(); doc_out.copy_data(nr, doc_in[i]); } return TRUE; } bool TFatturazione_bolle::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out) { bool ok = TRUE; 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()) { for (od = 0; od < tot; od++) { if (campione.raggruppabile(doc_out[od])) break; } } if (od >= tot) { const char provv = _rec.get_char("S3"); const int anno = campione.anno(); const TString codnum = _rec.get("S5"); TDocumento* new_doc = new TDocumento(provv, anno, codnum, -1); new_doc->copy_data(new_doc->head(), campione.head()); od = doc_out.add(new_doc); } ok = raggruppa(campione, doc_out[od]); } return ok; }