#include "velib07.h" #include "../cg/cgsaldac.h" #include "../db/dblib.h" /////////////////////////////////////////////////////////// // TMateriali_base_recordset /////////////////////////////////////////////////////////// const TVariant& TMateriali_base_recordset::get(const char* column_name) const { if (column_name[0] != '#') { TVariant& var = get_tmp_var(); int rownum = current_row(); if (reverse()) rownum = items() - 1 - rownum; const TRiga_esplosione* row = (const TRiga_esplosione*)boom().objptr(rownum); if (row != NULL) { const TFixed_string name(column_name); if (name == "LASTQTA") var = row->last_qta(); else if (name == "TOTQTA") var = row->val(); else { if (rownum != _lastrow) { ((TMateriali_base_recordset *) this)->_lastrow = rownum; const TCodice_articolo & comp = row->componente(); const TCodice_articolo & dist = row->distinta(); TLocalisamfile rd(LF_RDIST); rd.setkey(2); rd.put("CODCOMP", comp); rd.put("CODDIST", dist); if (rd.read() == NOERR) *_rdist = rd.curr(); } if (_rdist != NULL) { const TString & v = _rdist->get(column_name); var = v; } } } return var; } return TRecordset::get(column_name); } const TVariant& TMateriali_base_recordset::get(unsigned int column) const { const TRecordset_column_info & ci = column_info(column); return get(ci._name); } void TMateriali_base_recordset::requery() { _boom.destroy(); int pos1 = query_text().find("MATBASE"); if (pos1 > 0) { pos1 += 7; set_reverse(query_text()[pos1] == '-'); if (reverse()) pos1++; int pos = query_text().find("==", pos1); int pos2 = -1; if (pos > 0) { TString val(query_text().mid(pos + 2)); pos2 = val.find("FILTER"); if (pos2 > 0) val.cut(pos2 - 1); if (val.starts_with("\"") || val.starts_with("'")) { val.ltrim(1); val.rtrim(1); } else { TVariant var = get(val); val = var.as_string(); } const TCodice_articolo art(val); TDistinta_tree distinta; if (distinta.set_root(art)) { while (isspace(query_text()[pos1])) pos1++; const int level = atoi(query_text().mid(pos1)); if (level > 0 || query_text()[pos1] =='0') while (isdigit(query_text()[pos1])) pos1++; while (isspace(query_text()[pos1])) pos1++; TString8 filter; if (query_text()[pos1] != 'S') while (isalpha(query_text()[pos1])) filter << query_text()[pos1++]; distinta.explode(_boom, true, RAGGR_EXP_NONE, level, filter); } pos = query_text().find("FILTER", pos); if (pos > 0) { pos = query_text().find("==", pos); if (pos > 0) { TString val(query_text().mid(pos + 2)); if (val.starts_with("\"") || val.starts_with("'")) { val.ltrim(1); val.rtrim(1); } else { TVariant var = get(val); val = var.as_string(); } const int items = _boom.items(); for (int i = 0; i < items; i++) { const TRiga_esplosione * row = (const TRiga_esplosione *)_boom.objptr(i); if ( row != NULL && row->componente() != val) _boom.destroy(i); } _boom.pack(); } } } } } TMateriali_base_recordset::TMateriali_base_recordset(const char* use) : _query(use) { _lastrow = -1; _rdist = new TRectype(LF_RDIST); const int nfields = _rdist->items(); int pos = 1; for ( int i = 0 ; i < nfields; i++) { TRecordset_column_info * ci = new TRecordset_column_info; ci->_name = _rdist->fieldname(i); ci->_pos = pos; ci->_type = _rdist->type(ci->_name); const int len = _rdist->length(ci->_name); pos += len; ci->_width = len; _column.add(ci); } } /////////////////////////////////////////////////////////// // TScalare_recordset /////////////////////////////////////////////////////////// void TScalare_recordset::requery() { boom().destroy(); int pos1 = query_text().find("SCALARE"); if (pos1 > 0) { pos1 += 7; set_reverse(query_text()[pos1] == '-'); if (reverse()) pos1++; int pos = query_text().find("==", pos1); if (pos > 0) { TString val(query_text().mid(pos + 2)); if (val.starts_with("\"") || val.starts_with("'")) { val.ltrim(1); val.rtrim(1); } else { TVariant var = get(val); val = var.as_string(); } const TCodice_articolo art(val); TDistinta_tree distinta; if (distinta.set_root(art)) { while (isspace(query_text()[pos1])) pos1++; const int level = atoi(query_text().mid(pos1)); if (level > 0 || query_text()[pos1] =='0') while (isdigit(query_text()[pos1])) pos1++; while (isspace(query_text()[pos1])) pos1++; TString8 filter; if (query_text()[pos1] != 'S') while (isalpha(query_text()[pos1])) filter << query_text()[pos1++]; distinta.explode(boom(), false, RAGGR_EXP_NONE, level, filter); } pos = query_text().find("FILTER", pos); if (pos > 0) { pos = query_text().find("==", pos); if (pos > 0) { TString val(query_text().mid(pos + 2)); if (val.starts_with("\"") || val.starts_with("'")) { val.ltrim(1); val.rtrim(1); } else { TVariant var = get(val); val = var.as_string(); } const int items = boom().items(); for (int i = 0; i < items; i++) { const TRiga_esplosione * row = (const TRiga_esplosione *)boom().objptr(i); if ( row != NULL && row->componente() != val) boom().destroy(i); } boom().pack(); } } } } } /////////////////////////////////////////////////////////// // TDocument_cache /////////////////////////////////////////////////////////// TObject* TDocument_cache::key2obj(const char* key) { TToken_string k(key); const char provv = *k.get(0); const int anno = k.get_int(); const TString4 codnum= k.get(); const long ndoc = k.get_long(); TDocumento* doc = new TDocumento(provv, anno, codnum, ndoc); doc->get("IMPONIBILI"); // Bastardata per far funzionare la successiva dirty_fields doc->dirty_fields(); return doc; } TDocumento& TDocument_cache::doc(const TRectype& rec) { TToken_string key; key = rec.get(DOC_PROVV); key.add(rec.get(DOC_ANNO)); key.add(rec.get(DOC_CODNUM)); key.add(rec.get(DOC_NDOC)); TDocumento& d = *(TDocumento*)objptr(key); return d; } TDocument_cache:: TDocument_cache() : TCache(3) { } TDocument_cache:: ~TDocument_cache() { } /////////////////////////////////////////////////////////// // TDocument_recordset /////////////////////////////////////////////////////////// const TVariant& TDocument_recordset::get_field(int num, const char* field) const { if (*field != '#') { const int idx = relation()->log2ind(num); if (idx < 0) return NULL_VARIANT; const int logic = num > 0 ? num : relation()->file(idx).num(); if (logic == LF_DOC || logic == LF_RIGHEDOC) { const TRectype& rec = relation()->file(idx).curr(); // Se non e' un campo standard, ma e' calcolato da una formula... if (rec.type(field) == _nullfld && strncmp(field, "G1:", 3) != 0) { const TDocumento& doc = ((TDocument_cache&)_cache).doc(rec); TVariant& var = get_tmp_var(); if (xvt_str_compare_ignoring_case(field, "SEGNO") == 0) { var = doc.is_nota_credito() ? -UNO : UNO; } else if (xvt_str_compare_ignoring_case(field, "IS_COSTO") == 0) { bool costo = (doc.tipo().is_costo()) || (!doc.tipo().is_ricavo() && doc.get_char(DOC_TIPOCF)=='F'); var = costo ? UNO : ZERO; } else if (xvt_str_compare_ignoring_case(field, "IS_RICAVO") == 0) { bool ricavo = (doc.tipo().is_ricavo()) || (!doc.tipo().is_costo() && doc.get_char(DOC_TIPOCF)=='C'); var = ricavo ? UNO : ZERO; } else { const TFieldref ref(field, logic); if (logic == LF_DOC) { var = ref.read(doc); } else { const int nriga = rec.get_int(RDOC_NRIGA); if (nriga > 0 && nriga <= doc.rows()) { const TRiga_documento& rdoc = doc[nriga]; var = ref.read(rdoc); } else var = NULL_VARIANT; } } return var; } } } return TISAM_recordset::get_field(num, field); } /////////////////////////////////////////////////////////// // TDocument_report /////////////////////////////////////////////////////////// bool TDocument_report::set_recordset(const TString& query) { if (query.find("MATBASE") > 0) return TReport::set_recordset(new TMateriali_base_recordset(query)); if (query.find("SCALARE") > 0) return TReport::set_recordset(new TScalare_recordset(query)); return TReport::set_recordset(new TDocument_recordset(query)); } bool TDocument_report::load(const char* name) { const bool ok = TReport::load(name); if (ok) { // Purtroppo il recordset delle sottosezioni deve essere reimpostato a mano for (int i = 11; i <= 999; i++) { TReport_section* sec = find_section('B', i); if (sec != NULL) { TRecordset* recset = sec->recordset(); if (recset != NULL) { const TString use = recset->query_text(); if (use.find("MATBASE") > 0) recset = new TMateriali_base_recordset(use); else if (use.find("SCALARE") > 0) recset = new TScalare_recordset(use); else recset = new TDocument_recordset(use); sec->set_recordset(recset); } } } } return ok; } void TDocument_report::output_values(const TRectype& rec, const TString& output) { TToken_string out(output, '!'); TString curr; for (const char * str = out.get(0); str; str = out.get()) { // scansione sugli elementi dell'output curr = str; int poseq = curr.find('='); // divide la stringa corrente in lvalue e rvalue if (poseq < 0) { curr_field()->set(rec.get(curr)); } else { int posrv = poseq+1; if (poseq >= 0 && curr[posrv] == '=') posrv++; TString16 fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale const TString& dat = rec.get(curr.mid(posrv)); // preleva il nome del campo del file alla destra dell'uguale e lo legge dal record TReport_field* campo = field(fld); if (campo != NULL) campo->set(dat); } } } void TDocument_report::reset_values(const TString& output) { TToken_string out(output, '!'); TString curr; for (const char * str = out.get(0); str; str = out.get()) { // scansione sugli elementi dell'output curr = str; int poseq = curr.find('='); // divide la stringa corrente in lvalue e rvalue if (poseq < 0) { curr_field()->set(""); } else { TString16 fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale TReport_field* campo = field(fld); if (campo != NULL) campo->set(""); } } } bool TDocument_report::msg_parent_doc(TVariant_stack& stack) { TReport_field& cf = *curr_field(); int idx =((TISAM_recordset *)recordset())->cursor()->relation()->log2ind(LF_DOC); if (idx < 0) return false; const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr(); TDocumento & doc = (TDocumento &)((TDocument_recordset*)recordset())->doc(rec); const TRiga_documento * rdoc = NULL; // Se il campo corrente non appartiene al body allora cerco la prima riga documento buona! if (cf.section().type() == 'B') { idx = ((TISAM_recordset*)recordset())->cursor()->relation()->log2ind(LF_RIGHEDOC); if (idx < 0) return false; const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr(); const int n = rec.get_long("NRIGA"); rdoc = &(doc[n]); } else { const TRiga_documento * first_desc = NULL; for (int r = 1; r <= doc.physical_rows(); r++) { const TRiga_documento& row = doc[r]; if (row.get(RDOC_DANDOC).not_empty()) { if (row.is_descrizione()) { if (first_desc == NULL) first_desc = &row; // Non e' una riga buona, ma nemmeno da buttare! } else { rdoc = &row; break; // Ho trovato la riga buona! } } } if (rdoc == NULL && first_desc != NULL) rdoc = first_desc; } int level = stack.pop().as_int(); for (; rdoc != NULL && level > 0; level--) rdoc = (const TRiga_documento *)(rdoc->find_original_rdoc()); const TString& values = stack.pop().as_string(); const bool is_full = stack.peek().as_bool(); if (rdoc != NULL && rdoc->get(RDOC_PROVV).not_empty()) { const char provv = rdoc->get_char(RDOC_PROVV); const int anno = rdoc->get_int(RDOC_ANNO); const TString4 codnum = rdoc->get(RDOC_CODNUM); const long ndoc = rdoc->get_long(RDOC_NDOC); if (is_full) { TDocumento doc(provv, anno, codnum, ndoc); output_values(doc, values); } else { TToken_string key; key.add(provv); key.add(anno); key.add(codnum); key.add(ndoc); const TRectype& doc = cache().get(LF_DOC, key); output_values(doc, values); } } else reset_values(values); return true; } bool TDocument_report::msg_parent_row(TVariant_stack& stack) { int idx = ((TISAM_recordset*)recordset())->cursor()->relation()->log2ind(LF_RIGHEDOC); if (idx < 0) return false; const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr(); const int n = rec.get_long("NRIGA"); idx =((TISAM_recordset *)recordset())->cursor()->relation()->log2ind(LF_DOC); if (idx < 0) return false; TDocumento & doc = (TDocumento &)((TDocument_recordset*)recordset())->doc(rec); const TRiga_documento * rdoc = &(doc[n]); // Se il campo corrente non appartiene al body allora cerco la prima riga documento buona! int level = stack.pop().as_int(); for (; rdoc != NULL && level > 0; level--) rdoc = (const TRiga_documento *)(rdoc->find_original_rdoc()); const TString& values = stack.pop().as_string(); const bool is_full = stack.peek().as_bool(); if (rdoc != NULL && rdoc->get(RDOC_PROVV).not_empty()) { if (is_full) { const char provv = rdoc->get_char(RDOC_PROVV); const int anno = rdoc->get_int(RDOC_ANNO); const TString4 codnum = rdoc->get(RDOC_CODNUM); const long ndoc = rdoc->get_long(RDOC_NDOC); TDocumento doc(provv, anno, codnum, ndoc); output_values(doc[rdoc->get_int(RDOC_NRIGA)], values); } else output_values(*rdoc, values); } return true; } size_t TDocument_report::get_usr_words(TString_array& words) const { TReport::get_usr_words(words); const char* const name[] = { "DOC_PARENT_DOC", "DOC_PARENT_ROW", NULL }; ((TDocument_report*)this)->_first_msg = words.items(); // Calcola il primo numero disponibile for (size_t i = 0; name[i] != NULL; i++) words.add(name[i]); return words.items(); } bool TDocument_report::execute_usr_word(unsigned int opcode, TVariant_stack& stack) { if (opcode < _first_msg) return TReport::execute_usr_word(opcode, stack); opcode -= _first_msg; switch (opcode) { case 0 : msg_parent_doc(stack); break; case 1 : msg_parent_row(stack); break; default: break; } while (!stack.pop().is_null()); // Svuota eventuali parametri variabili inutilizzati return true; } ///////////////////////////////////////// // Metodi non appartenenti a classi ///////////////////////////////////////// static TImporto get_importo(const TISAM_recordset& partite, const char* sezione, const char* valore) { const char sez = partite.get(sezione).as_string()[0]; const real val = partite.get(valore).as_real(); return TImporto(sez, val); } static void calcola_fido_da_saldaconto (const char tipocf, const long codcf, const TDate& datacalc, const int riskdays, real& saldo, real& saldo_sbf) { //estrae le partite aperte del clifo selezionato (no righe 9999) con data <= della data selezionata datacalc TString query; query << "USE PART\nSELECT ((NRIGA!=9999)&&(CHIUSA!=\"X\")&&(BETWEEN(DATAREG,0,#DATACALC)))\n"; query << "FROM TIPOC=#TIPOCF GRUPPO=0 CONTO=0 SOTTOCONTO=#CODCF\n"; query << "TO TIPOC=#TIPOCF GRUPPO=0 CONTO=0 SOTTOCONTO=#CODCF"; TISAM_recordset partite(query); TString4 str_tipocf = tipocf; partite.set_var("#TIPOCF", TVariant(str_tipocf)); partite.set_var("#CODCFCF", codcf); partite.set_var("#DATACALC", datacalc); //importone somma degli importi delle righe del recordset TImporto importone_saldo, importone_sbf; //data considerante i giorni di rischio ammessi dall'utonto TDate data_sbf = datacalc; data_sbf -= riskdays; for (bool ok = partite.move_first(); ok; ok = partite.move_next()) { TImporto importo_riga; //fatture,note di credito,pagamenti TImporto importo_partita = get_importo(partite, PART_SEZ, PART_IMPORTO); importo_riga += importo_partita; //pagamenti (tm=3), insoluti (tm=5), pagamenti insoluti(tm=6) if (partite.get(PART_TIPOMOV).as_int() >= tm_pagamento) { TImporto importo_abbuono = get_importo(partite, PART_SEZABB, PART_ABBUONI); importo_riga += importo_abbuono; //pagamenti in valuta if (!partite.get(PART_CODVAL).is_empty()) { TImporto importo_diff_cambio = get_importo(partite, PART_SEZDIFCAM, PART_DIFFCAM); importo_riga += importo_diff_cambio; } //importo pagamento a rischio (solo pagamenti, mai fatture) const bool is_sbf = partite.get(PART_DATAREG).as_date() >= data_sbf; if (is_sbf) importone_sbf += importo_riga; } //somma importi presenti sulla riga partita (fatture, pagamenti, insoluti, pagamenti insoluti) importone_saldo += importo_riga; } //la normalizzazione del totale delle partite va fatta in base al fatto che si parli di 'C'liente o 'F'ornitore const char sezione_finale = (tipocf == 'C') ? 'A' : 'D'; importone_saldo.normalize(sezione_finale); importone_sbf.normalize(sezione_finale); //primo valore in output saldo += importone_saldo.valore(); saldo_sbf += importone_sbf.valore(); } static void calcola_fido_da_documenti(const char tipocf, const long codcf, const TDate& datacalc, const int riskdays, real& saldo, real& saldo_sbf) { TConfig config(CONFIG_DITTA, "ve"); //scansione delle righe FIDO_XX(j)=.. sul paragrafo di configurazione VE per avere i parametri di numerazione/tipo.. //..da considerare for (int j = 0;;j++) { const TString& num_fido = config.get("FIDO_NUM", NULL, j); //se manca la numerazione si puņ fermare,in quanto non puņ esistere un tipo senza numerazione if (num_fido.blank()) break; const TString& tipo_fido = config.get("FIDO_TIP", NULL, j); const int stato_fido = config.get_int("FIDO_STA", NULL, j); const bool residuo_fido = config.get_bool("FIDO_RES", NULL, j); //per la numerazione scelta queryzza gli archivi alla ricerca dei documenti che rientrano nei parametri TString query; query << "USE DOC KEY 2\n"; query << "SELECT (CODNUM=#CODNUM)&&(TIPODOC=#TIPODOC)&&(STATO=#STATO)\n"; query << "FROM TIPOCF=#TIPOCF CODCF=#CODCF PROVV='D'\n"; query << "TO TIPOCF=#TIPOCF CODCF=#CODCF PROVV='D' ANNO=#ANNO DATADOC=#DATACALC"; TISAM_recordset documenti(query); TString4 str_tipocf = tipocf; documenti.set_var("#TIPOCF", TVariant(str_tipocf)); documenti.set_var("#CODCFCF", codcf); documenti.set_var("#ANNO", TVariant((long)datacalc.year())); documenti.set_var("#DATACALC", datacalc); documenti.set_var("#CODNUM", TVariant(num_fido)); documenti.set_var("#TIPODOC", TVariant(tipo_fido)); documenti.set_var("#STATO", TVariant((long)stato_fido)); const int items = documenti.items(); //adesso che ha i documenti che cercava.. for (bool ok = documenti.move_first(); ok; ok = documenti.move_next()) { const real totdoc = documenti.get("G1:TOTDOC").as_real(); } } } //metodo per il calcolo fido di un cliente ad una data definita void calcola_fido_cliente (const char tipocf, const long codcf, const TDate& datacalc, const int riskdays, real& saldo, real& saldo_sbf) { //PRIMA PARTE: controlla il saldaconto calcola_fido_da_saldaconto(tipocf, codcf, datacalc, riskdays, saldo, saldo_sbf); //SECONDA PARTE: controlla i documenti calcola_fido_da_documenti(tipocf, codcf, datacalc, riskdays, saldo, saldo_sbf); }