Files correlati : ve0.exe ve6.exe Ricompilazione Demo : [ ] Commento : GF20114 Il paragrafo [DEFAULTS] dei profili dei documenti contiene la lista dei valori di default da assegnare a certi campi della maschera di immissione. Tale paragrafo nella versione a 32 bit viene completamente ignorato, mentre nella precedente versione funzionava "quasi" sempre. GF20115 Se si cerca di contabilizzare una fattura di vendita con calcolo al lordo e con sconti "di testa", la procedura tenta di generare un movimento sbilanciato e quindi fallisce. Il problema sembra essere nel fatto che il totale documento e' corretto, mentre imponibile e iva non tengono conto dello sconto. Se si utilizzano gli sconti "di riga" o si toglie il calcolo al lordo, tutto funziona bene. GF20116 Nell'eventualità avessimo una causale contabile definita sull'anagrafica di un nostro cliente/fornit bisogna fare in modo che se stiamo contabilizzando una nota di credito la causale utilizzata non sia quella prevista in anagrafica, ma bensì quella prevista nella tipologia del documento sul quale naturalmente ci sarà la spunta di nota di credito/debito (questa appunto può essere la discriminante) git-svn-id: svn://10.65.10.50/trunk@11704 c028cbd2-c16b-5b4b-a496-9718f37d4682
540 lines
14 KiB
C++
Executable File
540 lines
14 KiB
C++
Executable File
#include <execp.h>
|
|
#include <defmask.h>
|
|
#include <tabutil.h>
|
|
#include <utility.h>
|
|
#include <urldefid.h>
|
|
|
|
#include "ve0100.h"
|
|
#include "veini.h"
|
|
|
|
#include "veuml.h"
|
|
#include "veuml1.h"
|
|
#include "verig.h"
|
|
|
|
#include "sconti.h"
|
|
#include "..\mg\mglib.h"
|
|
|
|
void TMotore_application::init_query_mode( TMask& m )
|
|
{
|
|
disable_menu_item(M_FILE_PRINT);
|
|
|
|
TEdit_field& cn = _msk->efield(F_CODNUM);
|
|
if (cn.empty())
|
|
{
|
|
cn.set(_codnum);
|
|
if (_msk->field(F_TIPODOC).empty())
|
|
{
|
|
cn.set_focusdirty(TRUE);
|
|
cn.on_key(K_TAB);
|
|
cn.set_dirty(FALSE);
|
|
_msk->set(F_TIPODOC, _tipodoc, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TMotore_application::init_insert_mode( TMask& m )
|
|
{
|
|
const TString4 codnum(m.get(F_CODNUM));
|
|
const int anno = m.get_int(F_ANNO);
|
|
const char provv = m.get(F_PROVV)[0];
|
|
const long numdoc = m.get_long(F_NDOC);
|
|
|
|
TDocumento_mask& dm = (TDocumento_mask&)m;
|
|
TDocumento& curdo = dm.doc();
|
|
const TTipo_documento& tp = (const TTipo_documento&)curdo.tipo();
|
|
|
|
curdo.read(provv, anno, codnum, numdoc);
|
|
curdo.set_tipo(m.get(F_TIPODOC));
|
|
|
|
const char stato = tp.stato_finale_inserimento();
|
|
curdo.stato(stato);
|
|
|
|
_codnum = codnum;
|
|
_tipodoc = m.get(F_TIPODOC);
|
|
|
|
m.field(F_CODNUM).set_focusdirty(TRUE);
|
|
m.field(F_CODNUM).on_key(K_TAB);
|
|
m.field(F_TIPODOC).set_focusdirty(TRUE);
|
|
m.field(F_TIPODOC).on_key(K_TAB);
|
|
|
|
// Giro per supplire alla mancanza di una TMask::set(short id, char c);
|
|
char str_stato[2] = { stato, '\0' };
|
|
m.set(F_STATO, str_stato);
|
|
|
|
TLocalisamfile doc(LF_DOC);
|
|
TDate data_doc(TODAY);
|
|
|
|
doc.curr() = curdo.head();
|
|
doc.read(_isgteq);
|
|
if (doc.eof() || doc.prev() == NOERR)
|
|
{
|
|
if (doc.curr().same_key(curdo.head(), 1, 1))
|
|
data_doc = doc.get_date(DOC_DATADOC);
|
|
}
|
|
m.set(F_DATADOC, data_doc);
|
|
|
|
int pos = m.id2pos( F_DATACAMBIO1);
|
|
if (pos >= 0 && m.fld(pos).active() && !m.get(F_CODVAL).empty())
|
|
{
|
|
m.fld(pos).set(data_doc);
|
|
m.fld(pos).dirty();
|
|
}
|
|
m.disable(DLG_PRINT);
|
|
|
|
pos = m.id2pos(F_CAUSMAG);
|
|
if (pos >= 0)
|
|
{
|
|
m.fld(pos).set(tp.caus_mov());
|
|
m.fld(pos).dirty();
|
|
}
|
|
|
|
tp.set_defaults(m);
|
|
|
|
m.disable(DLG_ELABORA);
|
|
}
|
|
|
|
void TMotore_application::init_modify_mode( TMask& m )
|
|
{
|
|
enable_menu_item(M_FILE_PRINT);
|
|
m.enable(DLG_PRINT);
|
|
m.enable(DLG_ELABORA);
|
|
m.disable(F_STATO);
|
|
TString80 key;
|
|
key << m.get(F_CODNUM);
|
|
key << m.get_int(F_ANNO);
|
|
key << m.get(F_PROVV)[0];
|
|
key << m.get_long(F_NDOC);
|
|
|
|
// Non dare messaggi inutili durante la cancellazione automatica
|
|
if (autodeleting() != 0x3)
|
|
{
|
|
const bool transaction = is_transaction();
|
|
const bool no_mod = !transaction && !doc().modificabile();
|
|
const bool no_del = !doc().cancellabile();
|
|
if (no_del || no_mod)
|
|
{
|
|
if (key != __last_key)
|
|
{
|
|
TString msg;
|
|
msg.format("Documento non %s%s%s.", (no_mod ? "modificabile":""),
|
|
(no_mod && no_del ? " ne' ":""), (no_del ? "cancellabile":""));
|
|
if (transaction)
|
|
{
|
|
TTimed_box box("Attenzione", msg, 5, DLG_OK, 32, 5);
|
|
|
|
box.add_button(DLG_OK, 0, "", -11, -1, 10, 2);
|
|
box.run();
|
|
}
|
|
else
|
|
warning_box(msg);
|
|
}
|
|
}
|
|
if (no_mod)
|
|
m.disable(DLG_SAVEREC);
|
|
if (no_del)
|
|
m.disable(DLG_DELREC);
|
|
|
|
if (m.id2pos(F_IBAN_STATO) > 0)
|
|
m.efield(F_IBAN_STATO).validate(K_TAB); // Decodifica IBAN
|
|
}
|
|
__last_key = key;
|
|
}
|
|
|
|
int TMotore_application::user_function(int index)
|
|
{
|
|
switch(index)
|
|
{
|
|
case 1:
|
|
break;
|
|
default:
|
|
yesnofatal_box("Chiamata ad una procedura utente non definita: %d", index);
|
|
return NOERR;
|
|
break;
|
|
}
|
|
return NOERR;
|
|
}
|
|
|
|
bool TMotore_application::changing_mask( int mode )
|
|
{
|
|
static int lastmode = NO_MODE;
|
|
|
|
const bool change = ( mode != lastmode );
|
|
lastmode = mode;
|
|
return change;
|
|
}
|
|
|
|
TMask* TMotore_application::get_mask( int mode )
|
|
{
|
|
switch ( mode )
|
|
{
|
|
case MODE_INS:
|
|
case MODE_MOD:
|
|
{
|
|
const TString4 tipodoc(_msk->get(F_TIPODOC));
|
|
_docmsk = (TDocumento_mask*)_doc_masks.objptr(tipodoc);
|
|
|
|
if (_docmsk == NULL)
|
|
{
|
|
_docmsk = new TDocumento_mask(tipodoc);
|
|
_doc_masks.add(tipodoc, _docmsk);
|
|
}
|
|
}
|
|
return _docmsk;
|
|
break;
|
|
default:
|
|
return _msk;
|
|
break;
|
|
}
|
|
}
|
|
|
|
const char* TMotore_application::get_next_key( )
|
|
{
|
|
TMask& m = curr_mask( );
|
|
TCodice_numerazione cod_num(m.get(F_CODNUM));
|
|
|
|
// Se per questa numerazione h abilitata le numerazione automatica
|
|
if( cod_num.auto_num())
|
|
{
|
|
TLocalisamfile doc(LF_DOC);
|
|
doc.zero();
|
|
doc.put("CODNUM", cod_num.codice());
|
|
doc.put("ANNO", m.get(F_ANNO));
|
|
doc.put("PROVV", m.get(F_PROVV));
|
|
|
|
TRectype cmp_rec(doc.curr()); // record campione
|
|
|
|
doc.put( "NDOC", 9999999L );
|
|
if (doc.read(_isgreat) == NOERR)
|
|
doc.prev();
|
|
else
|
|
doc.last();
|
|
|
|
const long num = ((doc.curr() == cmp_rec) ? doc.get_long( "NDOC" ) : 0) + 1;
|
|
|
|
return (format( "%d|%ld", F_NDOC, num));
|
|
}
|
|
return "";
|
|
}
|
|
|
|
int TMotore_application::read( TMask& m )
|
|
{
|
|
// m.autoload(*_rel);
|
|
TRelation_application::read(m);
|
|
doc() = (TDocumento &)_rel->curr();
|
|
_codnum = m.get(F_CODNUM);
|
|
_tipodoc = m.get(F_TIPODOC);
|
|
|
|
((TDocumento_mask &)m).doc2mask();
|
|
COLOR high_back_color = _sel_color->get_back_color(_link_pos);
|
|
COLOR high_color = _sel_color->get_fore_color(_link_pos);
|
|
|
|
((TDocumento_mask &)m).highlight(high_back_color, high_color);
|
|
|
|
return NOERR;
|
|
}
|
|
|
|
bool TMotore_application::menu(MENU_TAG mt)
|
|
{
|
|
bool ok = TRUE;
|
|
if (mt == MENU_ITEM(1))
|
|
{
|
|
_sel_color->run();
|
|
COLOR high_back_color = _sel_color->get_back_color(_link_pos);
|
|
COLOR high_color = _sel_color->get_fore_color(_link_pos);
|
|
|
|
if (!query_mask().is_running())
|
|
{
|
|
TDocumento_mask * m = (TDocumento_mask * ) &edit_mask();
|
|
|
|
if (m != NULL)
|
|
m->highlight(high_back_color, high_color);
|
|
}
|
|
}
|
|
else
|
|
ok = TRelation_application::menu(mt);
|
|
return ok;
|
|
}
|
|
|
|
int TMotore_application::write( const TMask& m ) // C 90
|
|
{
|
|
TDocumento& d = (TDocumento&) _rel->curr();
|
|
d = ((TDocumento_mask&)m).doc();
|
|
return TRelation_application::write(m);
|
|
}
|
|
|
|
int TMotore_application::rewrite( const TMask& m ) // C 90
|
|
{
|
|
TDocumento& d = (TDocumento &) _rel->curr();
|
|
if (d.bloccato())
|
|
return 0;
|
|
d = ((TDocumento_mask&)m).doc();
|
|
return TRelation_application::rewrite(m);
|
|
}
|
|
|
|
void TMotore_application::on_firm_change()
|
|
{
|
|
if (_config_ditta != NULL)
|
|
delete _config_ditta;
|
|
_config_ditta = new TConfig(CONFIG_DITTA);
|
|
// condv().set_config(_config_ditta);
|
|
_doc_masks.destroy();
|
|
TApplication::on_firm_change();
|
|
}
|
|
|
|
bool TMotore_application::user_create( )
|
|
{
|
|
open_files(LF_DOC, LF_RIGHEDOC, LF_CONDV, LF_RCONDV, LF_ANAMAG, LF_SCONTI, LF_UMART, LF_DESLIN, LF_CODCORR,
|
|
LF_TAB, LF_TABCOM, LF_CLIFO, LF_CFVEN, LF_INDSP, LF_OCCAS, LF_PCON, LF_MOV, LF_STOMAG,
|
|
LF_MOVMAG, LF_RMOVMAG, LF_MAG, LF_SVRIEP, LF_AGENTI, LF_PERCPROV, LF_ATTIV, LF_CAUSALI, 0);
|
|
|
|
|
|
_config_ditta = new TConfig(CONFIG_DITTA);
|
|
|
|
// Metto in relazione testata e righe
|
|
_rel = new TRelation( LF_DOC );
|
|
_rel->lfile().set_curr(new TDocumento);
|
|
|
|
_msk = new TMask("ve0100a");
|
|
_sel_color = new TSelect_color_mask("ve0100a", "0");
|
|
set_search_field(F_NDOC);
|
|
_link_pos =_sel_color->add_color_def("LINKED", "Righe collegate a documento", COLOR_YELLOW, COLOR_BLACK);
|
|
|
|
_msk->set_handler( F_ANNO, TDocumento_mask::anno_handler );
|
|
_msk->set_handler( F_CODNUM, TDocumento_mask::num_handler );
|
|
_msk->set_handler( F_TIPODOC, TDocumento_mask::tip_handler );
|
|
_msk->set_handler( F_NUMDOCRIF, TDocumento_mask::numdocrif_search_handler );
|
|
|
|
TConfig utente( CONFIG_USER );
|
|
_codnum = utente.get("CODNUM");
|
|
_tipodoc = utente.get("TIPODOC");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool TMotore_application::user_destroy( )
|
|
{
|
|
// Registro l'ultimo tipo documento e l'ultima numerazione
|
|
TConfig utente( CONFIG_USER );
|
|
utente.set( "CODNUM", _codnum, "ve" );
|
|
utente.set( "TIPODOC", _tipodoc, "ve" );
|
|
|
|
if (_config_ditta != NULL)
|
|
delete _config_ditta;
|
|
// Distruggo la maschera di modifica
|
|
if ( _msk != NULL )
|
|
delete _msk;
|
|
|
|
if ( _sel_color != NULL )
|
|
delete _sel_color;
|
|
|
|
// Distruggo la relazione
|
|
delete _rel;
|
|
// delete _condv;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int TMotore_application::stato_corrente( )
|
|
{
|
|
return edit_mask().get_int(F_STATO);
|
|
}
|
|
|
|
void TMotore_application::sheet2ini(TSheet_field &sheet,TConfig& ini)
|
|
{
|
|
// scrive le righe degli sheet associati
|
|
TString16 defpar;
|
|
TString str(80);
|
|
TDocumento_mask &m = (TDocumento_mask &)sheet.mask();
|
|
for (int r = 1; r <= sheet.items(); r++)
|
|
{
|
|
defpar.format("%d,%d",LF_RIGHEDOC,r);
|
|
const TMask * sm = m.riga_mask(r-1);
|
|
const TToken_string rigar = sheet.row(r-1);
|
|
for (int sf = 0; sf < sm->fields(); sf++)
|
|
{
|
|
TMask_field& campo = sm->fld(sf);
|
|
if (campo.shown() && campo.field())
|
|
{
|
|
// str = sheet.row(r-1).get(sheet.cid2index(campo.dlg()));
|
|
const short id = campo.dlg();
|
|
rigar.get(sheet.cid2index(id), str);
|
|
if (str.empty())
|
|
str = " ";
|
|
const word field_class = campo.class_id();
|
|
if (field_class == CLASS_MEMO_FIELD ||
|
|
field_class == CLASS_ZOOM_FIELD)
|
|
{
|
|
int p;
|
|
while ((p = str.find('\n', 0)) >= 0)
|
|
{
|
|
str.overwrite("\\", p);
|
|
str.insert("n", p+1);
|
|
}
|
|
}
|
|
campo.field()->write(ini, defpar, str);
|
|
}
|
|
}
|
|
}
|
|
for ( ; ; r++)
|
|
{
|
|
defpar.format("%d,%d",LF_RIGHEDOC,r);
|
|
if (ini.set_paragraph(defpar))
|
|
ini.remove_all();
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TMotore_application::ini2mask(TConfig& ini, TMask& msk, bool query)
|
|
{
|
|
TRelation_application::ini2mask(ini, msk, query); // Default processing
|
|
|
|
if (query)
|
|
{
|
|
// Dobbiamo riempire il tipo documento per determinare il profilo corretto!
|
|
TMask_field& campo = msk.field(F_TIPODOC);
|
|
TString16 str = campo.field()->read(ini, format("%d", LF_DOC));
|
|
if (str.empty())
|
|
{
|
|
TToken_string key;
|
|
key.add(msk.get(F_PROVV));
|
|
key.add(msk.get(F_ANNO));
|
|
key.add(msk.get(F_CODNUM));
|
|
key.add(msk.get(F_NDOC));
|
|
str = cache().get(LF_DOC, key, DOC_TIPODOC);
|
|
}
|
|
campo.set(str);
|
|
|
|
}
|
|
else
|
|
{
|
|
TSheet_field& f = msk.sfield(F_SHEET);
|
|
|
|
TTipo_riga_documento tr;
|
|
|
|
// Scorre tutti i paragrafi delle righe documento
|
|
const TMaskmode oldmode= (TMaskmode)msk.mode();
|
|
|
|
msk.set_mode(MODE_MOD);
|
|
for (int i = 1; ini.set_paragraph(format("%d,%d", LF_RIGHEDOC, i)); i++)
|
|
{
|
|
if (i == 1) // Se trovo almeno una riga allora cancello tutto, poi aggiungo le righe
|
|
{
|
|
f.destroy();
|
|
doc().destroy_rows();
|
|
}
|
|
|
|
// Considera solo i tipi riga validi
|
|
const TString16 tipo = ini.get(RDOC_TIPORIGA);
|
|
if (tr.read(tipo) == NOERR)
|
|
{
|
|
// Crea una nuova riga documento
|
|
TRiga_documento& rec = doc().new_row(tipo);
|
|
// Riempie i campi della nuova riga
|
|
TAssoc_array& var = ini.list_variables();
|
|
FOR_EACH_ASSOC_STRING(var, obj, key, val)
|
|
{
|
|
if (*val == '"' || *val == '\'')
|
|
{
|
|
const int len = strlen(val);
|
|
*(char*)(val+len-1) = '\0';
|
|
val++;
|
|
}
|
|
|
|
if (stricmp(key, RDOC_DESCR) == 0) // Trattamento speciale per la descrizione
|
|
{
|
|
TString s = esc(val); s.rtrim();
|
|
int split_pos = s.find('\n');
|
|
const int descr_len = rec.length(RDOC_DESCR);
|
|
if (split_pos < 0 && s.len() > descr_len)
|
|
split_pos = descr_len;
|
|
if (split_pos > descr_len)
|
|
split_pos = descr_len;
|
|
if (split_pos > 0)
|
|
{
|
|
rec.put(RDOC_DESCR, s.left(split_pos));
|
|
rec.put(RDOC_DESCLUNGA, "X");
|
|
rec.put(RDOC_DESCEST, s.mid(split_pos));
|
|
}
|
|
else
|
|
{
|
|
rec.put(RDOC_DESCR, s);
|
|
rec.zero(RDOC_DESCLUNGA);
|
|
rec.zero(RDOC_DESCEST);
|
|
}
|
|
|
|
}
|
|
else
|
|
if (stricmp(key, RDOC_NRIGA) != 0) // Ignora il numero riga ..
|
|
if (stricmp(key, RDOC_TIPORIGA) != 0) // ... ed il tipo riga
|
|
rec.put(key, val);
|
|
}
|
|
// solo la insert chiama la post_insert necessaria alla disabilitazione verifichiamo
|
|
// l'autoload ??
|
|
f.insert(-1, FALSE);
|
|
// Aggiunge la riga allo sheet
|
|
|
|
const bool checked = rec.get_bool(RDOC_CHECKED);
|
|
|
|
if (checked)
|
|
{
|
|
const TString& codart = rec.get(RDOC_CODARTMAG);
|
|
if (!codart.blank())
|
|
{
|
|
const TRectype& art = cache().get(LF_ANAMAG, codart);
|
|
if (art.empty())
|
|
{
|
|
error_box(FR("Articolo non valido sulla riga %d: %s"), i, (const char*)codart);
|
|
rec.zero(RDOC_CODARTMAG);
|
|
}
|
|
}
|
|
}
|
|
|
|
rec.autoload(f);
|
|
f.check_row(f.items()-1, 0x2);
|
|
|
|
if (!checked) //se non e' checked, il record viene autosalvato (in modo che sia salvato completamente)
|
|
rec.autosave(f);
|
|
}
|
|
}
|
|
msk.set_mode(oldmode);
|
|
}
|
|
}
|
|
|
|
void TMotore_application::print()
|
|
{
|
|
if (save(TRUE)) // Registra il record corrente
|
|
{
|
|
const TDocumento& doc = (const TDocumento&)get_relation()->curr();
|
|
const bool da_stampare = doc.stampabile();
|
|
|
|
TString commandline("ve1 -0 ");
|
|
commandline << doc.get(DOC_CODNUM) << ' ' << doc.get(DOC_ANNO) << ' ';
|
|
commandline << doc.get(DOC_PROVV) << ' ' << doc.get(DOC_NDOC) << ' ' << doc.get(DOC_NDOC);
|
|
commandline << ' ' << (da_stampare ? 'D' : 'P');
|
|
|
|
const TTipo_documento& tipo = doc.tipo();
|
|
const int ncopie = tipo.ncopie();
|
|
if (ncopie > 0)
|
|
commandline << ' ' << ncopie;
|
|
|
|
TExternal_app interattivo( commandline );
|
|
if (interattivo.run() == NOERR)
|
|
{
|
|
if (da_stampare) // Aggiorna stato documento se necessario
|
|
{
|
|
const char s[2] = { tipo.stato_finale_stampa(), '\0'};
|
|
edit_mask().set(F_STATO, s, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int ve0100( int argc, char* argv[])
|
|
{
|
|
TMotore_application a;
|
|
|
|
a.run( argc, argv, TR("Gestione documenti"));
|
|
return 0;
|
|
}
|