Files correlati : ve0.exe ve0300a.ini ve0100a.msk ve0200g.msk ve1300.alx ve1.exe ve17001.rep ve17002.rep ve1700a.msk ve1700a.msk ve2.exe ve6.exe ve61000a.msk ve17001.rep ve17002.rep ve17002.rep ve17001.rep ve1700a.msk ve6b00a.msk MODIFICHE CRPA Se si mette il flag P sulla data documento della maschera di un tipo documento viene proposta l’ultima data inserita. Possibilità di impostare il numero di copie nell’inserimento/modifica di un documento. Righe documento massime 10000 Aggiunta ricerca per riferimento cliente (ricerca alternativa). Aggiunto indirizzo cliente/fornitore sulla ricerca documenti. Lista documenti avanzata (report). Aggiunte le regolarizzazioni nella contabilizzazione documenti Sistema abilitazione della data registrazione in contabilizzazione documenti Aggiunta la possibilità di usare campi del documento nella dicitura del riferimento. Gestiti i movimenti di sola iva in contabilizzazione. Riferimento per mese nelle partite. Ordinamento per documento nell’evasione ordini con un flag in configurazione Impostato il tipo CF in base al tipo documento Aggiunto il messaggio cliente alla stampa report delle vendite git-svn-id: svn://10.65.10.50/branches/R_10_00@24024 c028cbd2-c16b-5b4b-a496-9718f37d4682
986 lines
27 KiB
C++
Executable File
986 lines
27 KiB
C++
Executable File
#include "velib07.h"
|
||
|
||
#include "../cg/cgsaldac.h"
|
||
#include "../cg/cglib02.h"
|
||
#include "../db/dblib.h"
|
||
|
||
#include <pconti.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;
|
||
}
|
||
|
||
void TDocument_cache::set_firmval(bool firmval)
|
||
{
|
||
_firmval = firmval;
|
||
destroy();
|
||
}
|
||
|
||
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(bool firmval) : TCache(3), _firmval(firmval)
|
||
{
|
||
}
|
||
|
||
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_cliente(TVariant_stack& stack)
|
||
{
|
||
TReport_field& cf = *curr_field();
|
||
const 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 TCli_for& cli_for = doc.clifor();
|
||
const TOccasionale& cli_occ = doc.occas();
|
||
const bool occasionale = cli_for.occasionale();
|
||
|
||
TString in = stack.pop().as_string(); // prende la macro o il fieldref
|
||
TString valore;
|
||
|
||
if (in[0] != '!')
|
||
{
|
||
// Controlla l'esistenza dei campi...
|
||
if (occasionale && cli_occ.exist(in))
|
||
valore = cli_occ.get(in);
|
||
|
||
if (!occasionale && cli_for.exist(in))
|
||
valore = cli_for.get(in);
|
||
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
in.ltrim(1);
|
||
if (in=="INDNUM")
|
||
{
|
||
valore = occasionale ? cli_occ.get(OCC_INDIR) : cli_for.get(CLI_INDCF);
|
||
valore << ' ';
|
||
valore << (occasionale ? cli_occ.get(OCC_CIV) : cli_for.get(CLI_CIVCF));
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in.find("COM") == 0)
|
||
{
|
||
const bool nascita = in[3] == 'N';
|
||
const int p = in.find("->");
|
||
if (p > 0)
|
||
in.ltrim(p + 2);
|
||
|
||
TString8 key;
|
||
if (nascita)
|
||
{
|
||
key = occasionale ? cli_occ.get(OCC_STATONASC) : cli_for.get(CLI_STATONASC);
|
||
key << '|' << (occasionale ? cli_occ.get(OCC_COMNASC) : cli_for.get(CLI_COMNASC));
|
||
}
|
||
else
|
||
{
|
||
key = occasionale ? cli_occ.get(OCC_STATO): cli_for.get(CLI_STATOCF);
|
||
key << '|' << (occasionale ? cli_occ.get(OCC_COM): cli_for.get(CLI_COMCF));
|
||
}
|
||
valore = cache().get(LF_COMUNI, key, in);
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in.find("CAP") == 0)
|
||
{
|
||
valore = occasionale ? cli_occ.get(OCC_CAP) : cli_for.get(CLI_CAPCF);
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in.find("TEL") == 0)
|
||
{
|
||
if (!occasionale)
|
||
{
|
||
if (in.len() == 3)
|
||
in << "1";
|
||
const TString num(cli_for.get(in));
|
||
in.insert("P");
|
||
valore = cli_for.get(in);
|
||
valore << "/" << num;
|
||
}
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in=="FAX")
|
||
{
|
||
if (!occasionale)
|
||
{
|
||
valore = cli_for.get("PFAX");
|
||
valore << "/" << cli_for.get("FAX");
|
||
}
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
if (in=="RAGSOC")
|
||
{
|
||
valore = occasionale ? cli_occ.get(in) : cli_for.get(in);
|
||
valore.strip_double_spaces();
|
||
cf.set(valore);
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
bool TDocument_report::msg_riepilogo_iva(TVariant_stack& stack)
|
||
{
|
||
// tabella riepilogo aliquote iva e relative imposte
|
||
// sintassi: _RIEPILOGOIVA,<indice>,<macro>
|
||
// dove: <indice> parte da zero se ' e minore di zero vengono scritti tutti
|
||
// dove: <macro> <20> uno dei seguenti:
|
||
// COD colonna dei codici
|
||
// IMP colonna degli imponibili
|
||
// IVA colonna delle imposte
|
||
// ALI colonna delle aliquote
|
||
// DES colonna delle descrizioni (stampata solo se il regime IVA non e' normale)
|
||
|
||
int index = stack.pop().as_int();
|
||
const 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);
|
||
TAssoc_array & IVA = doc.tabella_iva(); // serve per aggiornare la tebella
|
||
TRiepilogo_iva * r = (TRiepilogo_iva *) doc.riepilogo_iva(index);
|
||
TString value;
|
||
if (r != NULL)
|
||
{
|
||
const TString& what = stack.pop().as_string(); // cosa deve stampare ?
|
||
|
||
if (what == "COD") // Ritorna il codice IVA
|
||
value = r->cod_iva().codice();
|
||
else
|
||
if (what == "IMP") // Ritorna l'imponibile
|
||
value = r->imp().string();
|
||
else
|
||
if (what == "IVA") // Ritorna l'imposta
|
||
value = r->iva().string();
|
||
else
|
||
if (what == "ALI") // Ritorna l'aliquota %
|
||
value << r->cod_iva().percentuale().string();
|
||
else
|
||
if (what == "DES" && r->cod_iva().tipo().not_empty())
|
||
value == r->cod_iva().descrizione();
|
||
}
|
||
|
||
const bool full = value.full();
|
||
|
||
curr_field()->show(full);
|
||
curr_field()->set(TVariant(full ? value : ""));
|
||
return true;
|
||
}
|
||
|
||
size_t TDocument_report::get_usr_words(TString_array& words) const
|
||
{
|
||
TReport::get_usr_words(words);
|
||
const char* const name[] = { "DOC_CLIENTE", "DOC_PARENT_DOC", "DOC_PARENT_ROW",
|
||
"DOC_TABELLA_IVA", 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_cliente(stack); break;
|
||
case 1: msg_parent_doc(stack); break;
|
||
case 2: msg_parent_row(stack); break;
|
||
case 3: msg_riepilogo_iva(stack); break;
|
||
default: break;
|
||
}
|
||
|
||
while (stack.items() > 0)
|
||
stack.pop(); // Svuota eventuali parametri variabili inutilizzati
|
||
|
||
return true;
|
||
}
|
||
|
||
/////////////////////////////////////////
|
||
// Metodi non appartenenti a classi
|
||
/////////////////////////////////////////
|
||
|
||
// METODI PER IL CALCOLO DEL FIDO
|
||
|
||
//estrazioni mastri clienti e/o fornitori
|
||
static const TString_array& mastro(char tipocf)
|
||
{
|
||
static TString_array m[2];
|
||
const TString_array& a = m[tipocf == 'C' ? 0 : 1];
|
||
|
||
if (a.empty())
|
||
{
|
||
TISAM_recordset mastri("USE PCON SELECT (CONTO!=\"\")&&(SOTTOCONTO=\"\")");
|
||
for (bool ok = mastri.move_first(); ok; ok = mastri.move_next())
|
||
{
|
||
const int gruppo = mastri.get(PCN_GRUPPO).as_int();
|
||
const int conto = mastri.get(PCN_CONTO).as_int();
|
||
const int indbil = mastri.get(PCN_INDBIL).as_int();
|
||
const char tipocf = mastri.get(PCN_TMCF).as_string()[0];
|
||
if (tipocf > ' ')
|
||
{
|
||
TToken_string info;
|
||
info.add(gruppo);
|
||
info.add(conto);
|
||
info.add(indbil);
|
||
m[tipocf == 'C' ? 0 : 1].add(info);
|
||
}
|
||
}
|
||
}
|
||
return a;
|
||
}
|
||
|
||
static real calcola_saldo_contabile(const char tipocf, const long codcf, const TDate& datacalc)
|
||
{
|
||
real saldone;
|
||
|
||
TEsercizi_contabili esc;
|
||
TDate datainies, datafines;
|
||
const int codes = esc.date2esc(datacalc);
|
||
if (codes > 0)
|
||
esc.code2range(codes, datainies, datafines);
|
||
else
|
||
{
|
||
datainies = datacalc;
|
||
datainies.set_day(1);
|
||
datainies.set_month(1);
|
||
}
|
||
|
||
const TString_array& a = mastro(tipocf);
|
||
|
||
//per tutti i mastri selezionati va a calcolare il saldo del cliente/fornitore in input
|
||
FOR_EACH_ARRAY_ROW(a, i, row)
|
||
{
|
||
const int gruppo = row->get_int(0);
|
||
const int conto = row->get_int(1);
|
||
const int indbil = row->get_int(2);
|
||
|
||
TSaldo saldo;
|
||
real saldo_periodo = saldo.saldo_periodo(gruppo, conto, codcf, datainies, datacalc, indbil, false);
|
||
|
||
saldone += saldo_periodo;
|
||
}
|
||
return saldone;
|
||
}
|
||
|
||
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 real calcola_esposto_da_saldaconto (const char tipocf, const long codcf, const TDate& datacalc, const int riskdays)
|
||
{
|
||
//estrae le righe partita relative a pagamenti successivi alla data di rischio (e con tipopag >2,<7)
|
||
TString query;
|
||
query << "USE PART\nSELECT BETWEEN(DATAPAG,#DATASBF,0)&&BETWEEN(TIPOPAG,2,7)\n";
|
||
query << "FROM TIPOC=#TIPOCF GRUPPO=0 CONTO=0 SOTTOCONTO=#CODCF ANNO=#ANNO\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("#CODCF", codcf);
|
||
partite.set_var("#DATACALC", datacalc);
|
||
//data considerante i giorni di rischio ammessi dall'utonto
|
||
TDate data_sbf = datacalc;
|
||
data_sbf -= riskdays;
|
||
partite.set_var("#DATASBF", data_sbf); //data salvo buon fine
|
||
partite.set_var("#ANNO", TVariant((long)data_sbf.year()));
|
||
|
||
|
||
//importone somma degli importi delle righe del recordset
|
||
TImporto importone_esposto;
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
//somma importi presenti sulla riga partita (fatture, pagamenti, insoluti, pagamenti insoluti)
|
||
importone_esposto += 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_esposto.normalize(sezione_finale);
|
||
|
||
//valore in output
|
||
real esposto;
|
||
esposto += importone_esposto.valore();
|
||
|
||
return esposto;
|
||
}
|
||
|
||
|
||
static real calcola_fido_da_documenti(const char tipocf, const long codcf, const TDate& datacalc, const TDoc_key& ignore)
|
||
{
|
||
real totalone;
|
||
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<70> fermare,in quanto non pu<70> esistere un tipo senza numerazione
|
||
if (num_fido.blank())
|
||
break;
|
||
const TString& tipo_fido = config.get("FIDO_TIP", NULL, j);
|
||
const TString4 da_stato_fido = config.get("FIDO_DASTA", NULL, j);
|
||
const TString4 a_stato_fido = config.get("FIDO_ASTA", 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)&&(BETWEEN(STATO,#DASTATO,#ASTATO))\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);
|
||
|
||
const char str_tipocf[2] = { tipocf, 0 };
|
||
documenti.set_var("#TIPOCF", TVariant(str_tipocf));
|
||
documenti.set_var("#CODCF", 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("#DASTATO", TVariant(da_stato_fido));
|
||
documenti.set_var("#ASTATO", TVariant(a_stato_fido));
|
||
|
||
const int items = documenti.items();
|
||
if (items > 0)
|
||
{
|
||
const TRectype& curr = documenti.cursor()->curr();
|
||
//adesso che ha i documenti che cercava..
|
||
for (bool ok = documenti.move_first(); ok; ok = documenti.move_next())
|
||
{
|
||
if (ignore.full())
|
||
{
|
||
const TDoc_key k(curr);
|
||
if (k == ignore)
|
||
continue;
|
||
}
|
||
|
||
const TDocumento doc(curr);
|
||
//deve tener conto di eventuali docs in valuta
|
||
TCurrency_documento totdoc(ZERO, doc);
|
||
|
||
//documento a residuo (tipo ordini)
|
||
if (residuo_fido)
|
||
totdoc.set_num(doc.valore(false, true));
|
||
else //documento normale (tipo fattura)
|
||
totdoc.set_num(doc.totale_doc());
|
||
|
||
totdoc.change_to_firm_val();
|
||
|
||
//le nac vanno con segno rovesciato
|
||
if (doc.is_nota_credito())
|
||
totdoc = -totdoc;
|
||
|
||
totalone += totdoc.get_num();
|
||
}
|
||
}
|
||
}
|
||
|
||
return totalone;
|
||
}
|
||
|
||
|
||
//metodo per il calcolo fido di un cliente ad una data definita
|
||
real calcola_fido_cliente (long codcf, const TDate& datacalc, const TDoc_key& ignore)
|
||
{
|
||
//PRIMA PARTE: controlla i movimenti
|
||
real saldo_contabile = calcola_saldo_contabile('C', codcf, datacalc);
|
||
//SECONDA PARTE: controlla il saldaconto
|
||
real esposto_saldaconto = calcola_esposto_da_saldaconto('C', codcf, datacalc, 10); // 10 giorni ?
|
||
//TERZA PARTE: controlla i documenti
|
||
real tot_documenti = calcola_fido_da_documenti('C',codcf, datacalc, ignore);
|
||
|
||
return saldo_contabile + esposto_saldaconto + tot_documenti;
|
||
}
|
||
|
||
// FINE METODI PER IL CALCOLO DEL FIDO
|