#include "velib.h" ///////////////////////////////////////////////////////////// // TCodice_numerazione ///////////////////////////////////////////////////////////// TCodice_numerazione::TCodice_numerazione(const char* codnum) : TRectype(LF_TABCOM) { settab("NUM"); if (codnum && *codnum) read(codnum); else setempty(TRUE); } TCodice_numerazione::TCodice_numerazione(const TRectype& rec) : TRectype(rec) { } TCodice_numerazione::~TCodice_numerazione() { } const TString& TCodice_numerazione::tipo_doc(int i) const { CHECK(i < 36, "Impossibbile tipo documento"); const char * field = i < 17 ? "S2" : "S3"; if (i >= 17) i -= 17; TString & tmp = get_tmp_string(); tmp = get(field).mid(i * 4, 4); tmp.trim(); return tmp; } int TCodice_numerazione::ntipi_doc() const { int l = get("S3").len(); if (l > 0) return ((l - 1) / 4) + 18; l = get("S2").len(); return l ? (((l - 1) / 4) + 1) : 0; } void TCodice_numerazione::complete_num(long num, TString& codnum) const { codnum = prefisso(); codnum << num; codnum << postfisso(); } int TCodice_numerazione::read(const char* codnum) { *this = cache().get("%NUM", codnum); int err = empty() ? _iskeynotfound : NOERR; #ifdef DBG if (err != NOERR) NFCHECK("Codice numerazione errato: %s", codnum); #endif return err; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // trova le numerazioni documenti in base ai tipi richiesti (ca3800,ca3900,ps1001) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int numerazioni_documenti(TString_array& num_doc, TString_array& tip_doc, const int tipo) { //cominciamo con i tipi TISAM_recordset tipi_recset("USE %TIP\nSELECT STR(I1=#TIPO)"); tipi_recset.set_var("#TIPO", TVariant(long(tipo))); for (bool ok = tipi_recset.move_first(); ok; ok = tipi_recset.move_next()) //giro sui vari tipi ordine { const TString4 tipo = tipi_recset.get("CODTAB").as_string(); tip_doc.add(tipo); } //e adesso cerca le numerazioni che contengono tipi ordine TISAM_recordset num_recset("USE %NUM"); for (bool ok = num_recset.move_first(); ok; ok = num_recset.move_next()) //giro sui vari tipi numerazione { const TString4 codtab = num_recset.get("CODTAB").as_string(); const TCodice_numerazione numerazione(codtab); for (int t = numerazione.ntipi_doc() - 1; t >= 0; t--) { const TString& tipo_doc = numerazione.tipo_doc(t); if (tip_doc.find(tipo_doc) >= 0) { if (num_doc.find(codtab) < 0) // Evito aggiunta di doppioni num_doc.add(codtab); break; } } //for (int t = codnum.. } //for (bool ok = num_recset... return num_doc.items(); } int numerazioni_ordini(TString_array& num_ordini, TString_array& tip_ordini) { //i documenti che vanno presi in cosiderazione sono quelli che generano un IMPEGNATO secondo le auree regole del.. //..nostro invincibile Adolf! num_ordini.destroy(); tip_ordini.destroy(); numerazioni_documenti(num_ordini, tip_ordini, 3); return num_ordini.items(); } int numerazioni_fatture(TString_array& num_fatture, TString_array& tip_fatture) { //i documenti che vanno presi in cosiderazione sono quelli non ancora contabilizzati di tipo 0=Altro 2=Fattura num_fatture.destroy(); tip_fatture.destroy(); numerazioni_documenti(num_fatture, tip_fatture, 0); numerazioni_documenti(num_fatture, tip_fatture, 2); return num_fatture.items(); } ///////////////////////////////////////////////////////////// // TSpesa_prest ///////////////////////////////////////////////////////////// TSpesa_prest::TSpesa_prest(const char* codice, char tipo) : TRectype(LF_TAB) { switch (tipo) { case RIGA_SPESEDOC : settab("SPP"); break; case RIGA_PRESTAZIONI : settab("PRS"); break; case RIGA_RISORSE : settab("RSS"); break; case RIGA_ATTREZZATURE : settab("ATR"); break; default : settab("SPP"); break; } if (codice && *codice) { const int err = read(codice); #ifdef DBG if (err != NOERR) switch (tipo) { case RIGA_SPESEDOC : error_box("Spesa %s assente", codice); break; case RIGA_PRESTAZIONI : error_box("Prestazione %s assente", codice); break; case RIGA_RISORSE : error_box("Risorsa %s assente", codice); break; case RIGA_ATTREZZATURE : error_box("Attrezzatura %s assente", codice); break; default : error_box("Spesa %s assente", codice); break; } #endif } } TSpesa_prest::TSpesa_prest(const TRectype& rec) : TRectype(rec) { } char TSpesa_prest::genere() const { const TString & tipo = get("COD"); if (tipo == "SPP") return RIGA_SPESEDOC; else if (tipo == "PRS") return RIGA_PRESTAZIONI; else if (tipo == "RSS") return RIGA_RISORSE; else if (tipo == "ATR") return RIGA_ATTREZZATURE; return ' '; } int TSpesa_prest::read(const char* codice) { const TString8 cod = get("COD"); *this = cache().get(cod, codice); return empty() ? _iskeynotfound : NOERR; } const TString& TSpesa_prest::cod_iva() const { // La parte seguente di s3 e' utilizzata dalle atrezzature per altri campi TString& tmp = get_tmp_string(); tmp = get("S3").left(4); tmp.trim(); return tmp; } real TSpesa_prest::prezzo() const { real r = get("R10"); // Prezzo con tanti decimali if (r.is_zero()) r = get_real("R0"); // Prezzo con pochi decimali return r; } bool is_real_discount(const TString& exp) { if (exp.blank()) return false; TString80 good; real perc; return scontoexpr2perc(exp, false , good, perc) && perc != UNO; } bool scontoexpr2perc(const char * exp, bool signal , TString & goodexp, real & val_perc ) { bool valid = true; goodexp.cut(0); // Elimina gli spazi molesti // work.strip_spaces( ); val_perc = 1.0; if (exp && *exp) { TString80 num; bool dec = false; // Flag che indica se si attende l'inizio di un numero bool startnum = true; // Flag che indica se siamo all'inizio di un numero int errorchar = ' '; // Flag che indica se sono nella parte decimale di un numero for (const char * s = exp; *s && errorchar == ' '; s++) { const char c = *s; switch(c) { case '+': case '-': // Se ero in in numero ... if( !startnum ) { // Aggiunge il numero alla sequenza real newval( num ); val_perc *= ( CENTO - newval ) / CENTO; goodexp << num; } // Inizia il nuovo numero num = (c == '-') ? "-" : "+"; startnum = true; dec = false; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': num << c; startnum = false; break; case '.': case ',': if(!dec) { if( startnum ) num << '0'; // Se occorreva un numero ci metto lo 0 num << '.'; // Interpreto la virgola come punto dec = true; startnum = true; } else errorchar = c; // Se siamo gi` nella parte decimale segnala un errore break; case ' ': break; default: errorchar = c; break; } } // Controlla la validita` valid = errorchar == ' '; if (valid) { // Aggiunge l'ultimo numero preso real lastval( num ); val_perc *= ( CENTO - lastval ) / CENTO; goodexp << num; // Assegna la nuova espressione formattata bene } else { if (signal) // Se richiesto segnala l'errore warning_box( "Espressione di sconto non valida. Errore sul carattere %c.", errorchar); val_perc = UNO; // Azzera la sequenza di percentuali goodexp = ""; } } return valid; } real prezzo_scontato(const real& prezzo, const TString& sconto) { if (sconto.full()) { TString80 exp; real val_sconto; if (scontoexpr2perc(sconto, false , exp, val_sconto) && val_sconto != UNO) return prezzo * val_sconto; } return prezzo; }