09708f3513
git-svn-id: svn://10.65.10.50/trunk@2849 c028cbd2-c16b-5b4b-a496-9718f37d4682
2533 lines
72 KiB
C++
Executable File
2533 lines
72 KiB
C++
Executable File
#include <progind.h>
|
|
#include <tabutil.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
|
|
#include "cg2100.h"
|
|
#include "cg2102.h"
|
|
#include "cg21sld.h"
|
|
|
|
#include <mov.h>
|
|
#include <rmov.h>
|
|
#include <clifo.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Funzioni di decodifica/calcolo
|
|
///////////////////////////////////////////////////////////
|
|
|
|
char TPrimanota_application::row_type(const TToken_string& s)
|
|
{
|
|
const int l = s.len()-1;
|
|
return l > 0 ? s[l] : ' ';
|
|
}
|
|
|
|
// Determina il tipo IVA da causale+anno
|
|
// Certified 100%
|
|
TipoIVA TPrimanota_application::cau2IVA(const char* cod, int annoiva)
|
|
{
|
|
if (!read_caus(cod, annoiva))
|
|
error_box("Causale errata: '%s'", cod);
|
|
return causale().iva();
|
|
}
|
|
|
|
// Calcolo della percentuale di un dato codice IVA
|
|
// Certified 99%
|
|
const real& TPrimanota_application::cod2IVA(const TMask& m)
|
|
{
|
|
static TString16 _codiva; // Ultimo codice iva decodificato
|
|
static real _percent; // Percentuale dell'ultimo codice iva
|
|
// Tipo Costo Ricavo
|
|
if (app().iva() == iva_acquisti && m.get_int(103) == 3)
|
|
return ZERO;
|
|
|
|
const TString& codiva = m.get(102);
|
|
if (_codiva != codiva)
|
|
{
|
|
_codiva = codiva;
|
|
TCodiceIVA c(_codiva);
|
|
_percent = c.percentuale();
|
|
}
|
|
|
|
return _percent;
|
|
}
|
|
|
|
|
|
// Scorpora dall'imponibile la percentuale d'imposta(0.0%-100.0%) e ritorna l'imposta stessa
|
|
// Certified 99% Non sono sicurissimo degli imponibili negativi
|
|
real TPrimanota_application::scorpora(real& imponibile, const real& percent)
|
|
{
|
|
real imposta = abs(imponibile) * percent / (percent + 100.0); imposta.ceil();
|
|
if (imponibile.sign() < 0) imposta = -imposta;
|
|
imponibile -= imposta;
|
|
return imposta;
|
|
}
|
|
|
|
|
|
// Calcola il totale del documento tenendo conto del segno della prima riga e di quella delle
|
|
// ritenute sociali sulla causale
|
|
real TPrimanota_application::totale_documento()
|
|
{
|
|
const TMask& m = curr_mask();
|
|
|
|
const bool swapt = test_swap(FALSE); // Totale invertito ?
|
|
const bool swaps = test_swap(TRUE); // Ritenute sociali invertite ?
|
|
|
|
real tot(m.get(F_TOTALE)); // Legge totale
|
|
const real ritfis(m.get(F_RITFIS));
|
|
tot += ritfis; // Somma ritenute fiscali
|
|
|
|
real ritsoc(m.get(F_RITSOC));
|
|
if (swapt ^ swaps)
|
|
ritsoc = -ritsoc;
|
|
tot += ritsoc; // Somma ritenute sociali con segno
|
|
|
|
return tot;
|
|
}
|
|
|
|
|
|
// Determina se un codice sospeso o no
|
|
// Certified 99%
|
|
bool TPrimanota_application::suspended_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (f.to_check(k))
|
|
{
|
|
const TEdit_field& c = (const TEdit_field&)f;
|
|
const TBrowse* b = c.browse();
|
|
CHECKD(b, "Can't check suspension of a edit-field without a USE ", f.dlg());
|
|
const TLocalisamfile& i = b->cursor()->file();
|
|
// Tabella File
|
|
const char* sf = i.tab() ? "B2" : "SOSPESO";
|
|
const bool suspended = i.get_bool(sf);
|
|
if (suspended)
|
|
{
|
|
sf = f.get();
|
|
return f.error_box("Il codice '%s' e' sospeso e non puo' essere utilizzato", sf);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Determina se un codice detrazione e' di tipo detraibile o no
|
|
// Certified 70%
|
|
bool TPrimanota_application::detraibile(TToken_string& row)
|
|
{
|
|
if (app().iva() == iva_vendite) // Vendite sempre detraibili
|
|
return TRUE;
|
|
|
|
const int tipo_det = row.get_int(2); // Leggi tipo detraibilita
|
|
if (tipo_det != 0)
|
|
return FALSE;
|
|
|
|
const real& prorata = app().causale().reg().prorata();
|
|
return prorata < 100.0; // Se prorata = 100% e' indetraibile
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Funzioni di ricerca
|
|
///////////////////////////////////////////////////////////
|
|
|
|
int TPrimanota_application::type2pos(char tipo)
|
|
{
|
|
TString_array& cg = app().cgs().rows_array();
|
|
for (int i = 0; i < cg.items(); i++)
|
|
{
|
|
const TToken_string& s = cg.row(i);
|
|
const char t = row_type(s);
|
|
if (t == tipo)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
// Trova nelle righe contabili un conto nelle righe di tipo prescelto
|
|
int TPrimanota_application::bill2pos(const TBill& conto, char tipo)
|
|
{
|
|
TString_array& cg = app().cgs().rows_array();
|
|
for (int i = 0; i < cg.items(); i++)
|
|
{
|
|
TToken_string& s = cg.row(i);
|
|
const char t = row_type(s);
|
|
if (t == tipo)
|
|
{
|
|
const TBill c(s, 3, 0x0);
|
|
if (c == conto)
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
// Trova nelle righe contabili un conto di contropartita per il conto dato
|
|
int TPrimanota_application::bill2contr(const TBill& conto, char sezione) const
|
|
{
|
|
TString_array& rows = cgs().rows_array();
|
|
for (int i = 0; i < rows.items(); i++)
|
|
{
|
|
TToken_string& r = rows.row(i);
|
|
const real dare(r.get(0));
|
|
const char sez = dare.is_zero() ? 'A' : 'D';
|
|
if (sez == sezione) // Devo cercare sezione contraria
|
|
continue;
|
|
const TBill c(r, 3, 0x0);
|
|
if (conto == c)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
// Controlla se un conto e' usato nelle righe IVA
|
|
int TPrimanota_application::bill_used(const TBill& conto) const
|
|
{
|
|
int users = 0;
|
|
|
|
const TArray& rows = ivas().rows_array();
|
|
for (int i = 0; i < rows.items(); i++)
|
|
{
|
|
TToken_string& row = (TToken_string&)rows[i];
|
|
if (!row.empty_items())
|
|
{
|
|
const TBill c(row, 6, 0x0);
|
|
if (conto == c) users++;
|
|
}
|
|
}
|
|
|
|
return users;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Gestione sheet CG
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TSheet_field& TPrimanota_application::cgs() const
|
|
{
|
|
TSheet_field& s = (TSheet_field&)curr_mask().field(F_SHEETCG);
|
|
return s;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
// Scrive l'importo imp nella opportuna colonna della riga n
|
|
void TPrimanota_application::set_cgs_imp(int n, const TImporto& imp)
|
|
{
|
|
TSheet_field& s = cgs();
|
|
imp.add_to(s.row(n), 0);
|
|
s.force_update(n);
|
|
}
|
|
|
|
// Legge l'importo della riga n e lo ritorna col segno dovuto
|
|
// Certified 100%
|
|
TImporto TPrimanota_application::get_cgs_imp(int n)
|
|
{
|
|
TSheet_field& s = cgs();
|
|
|
|
TImporto importo;
|
|
|
|
const TMask& m = s.sheet_mask();
|
|
if (m.is_running() && s.selected() == n)
|
|
{
|
|
const TString& imp = m.get(CG_DARE);
|
|
if (imp.not_empty())
|
|
importo.set('D', real(imp));
|
|
else
|
|
importo.set('A', real(m.get(CG_AVERE)));
|
|
}
|
|
else
|
|
importo = s.row(n);
|
|
|
|
return importo;
|
|
}
|
|
|
|
// Certified 90%
|
|
bool TPrimanota_application::add_cgs_imp(int n, const TImporto& imp)
|
|
{
|
|
TImporto tot(get_cgs_imp(n));
|
|
tot += imp;
|
|
tot.normalize();
|
|
set_cgs_imp(n, tot);
|
|
return tot.is_zero();
|
|
}
|
|
|
|
// Certified 90%
|
|
bool TPrimanota_application::sub_cgs_imp(int n, const TImporto& imp)
|
|
{
|
|
TImporto tot(get_cgs_imp(n));
|
|
tot -= imp;
|
|
tot.normalize();
|
|
set_cgs_imp(n, tot);
|
|
return tot.is_zero();
|
|
}
|
|
|
|
TImporto TPrimanota_application::real2imp(const real& r, char row_type)
|
|
{
|
|
bool dare;
|
|
if (row_type == 'S')
|
|
{
|
|
dare = causale().sezione_ritsoc() == 'D';
|
|
}
|
|
else
|
|
{
|
|
dare = causale().sezione_clifo() == 'D';
|
|
if (row_type != 'T' && row_type != 'F')
|
|
dare = !dare;
|
|
}
|
|
|
|
TImporto importo(dare ? 'D' : 'A', r);
|
|
return importo;
|
|
}
|
|
|
|
// Disabilita le celle della riga contabile n in base al suo tipo
|
|
void TPrimanota_application::disable_cgs_cells(int n, char tipo)
|
|
{
|
|
TSheet_field& cg = cgs();
|
|
|
|
int first = 0, last = 0;
|
|
switch(tipo)
|
|
{
|
|
case 'T': // Totale documento
|
|
if (causale().corrispettivi())
|
|
{
|
|
last = 2;
|
|
}
|
|
else
|
|
{
|
|
last = 3;
|
|
cg.disable_cell(n, 5);
|
|
cg.disable_cell(n, 6);
|
|
}
|
|
break;
|
|
case 'A': // Abbuoni attivi
|
|
case 'C': // Differenza cambio
|
|
case 'D': // IVA Detraibile
|
|
case 'F': // Ritenute Fiscali
|
|
case 'L': // Contropartita delle spese
|
|
case 'N': // IVA Non detraibile
|
|
case 'P': // Abbuoni passivi
|
|
case 'R': // Ritenute professionali
|
|
case 'S': // Ritenute Sociali
|
|
last = 3;
|
|
break;
|
|
case 'K': // Riga cliente/fornitore per saldaconto
|
|
if (curr_mask().is_running() && n == cg.items()-1) // Sono in inserimento di una riga nuova
|
|
break;
|
|
first = 2;
|
|
case 'I':
|
|
last = 7; // Imponibile
|
|
break;
|
|
default:
|
|
last = 0; // Solo contabile
|
|
break;
|
|
}
|
|
|
|
for (int i = first; i < last; i++)
|
|
cg.disable_cell(n, i);
|
|
}
|
|
|
|
void TPrimanota_application::reset_sheet_row(TSheet_field& s, int n)
|
|
{
|
|
s.row(s.items()); // Append a new line
|
|
s.destroy(n); // Remove line n
|
|
}
|
|
|
|
int TPrimanota_application::set_cgs_row(int n, const TImporto& imp,
|
|
TBill& conto, const char* desc,
|
|
char tipo)
|
|
{
|
|
TSheet_field& cg = cgs();
|
|
if (n < 0) n = cg.first_empty();
|
|
TToken_string& row = cg.row(n);
|
|
row = "";
|
|
imp.add_to(row, 0);
|
|
row.add(conto.string(0x3));
|
|
row.add(""); // Codice decrizione
|
|
row.add(desc); // Descrizione aggiuntiva
|
|
|
|
if (tipo == 'T') // Calcolo contropartita
|
|
{
|
|
TToken_string& irow = ivas().row(0);
|
|
for (int i = 5; i < 10; i++)
|
|
row.add(irow.get(i == 5 ? 5 : -1));
|
|
}
|
|
else
|
|
{
|
|
const int pos = type2pos('T');
|
|
if (pos >= 0)
|
|
{
|
|
TBill contro(cg.row(pos), 2, 0x3);
|
|
row.add(contro.string(0x3));
|
|
}
|
|
else row.add(" | | | | ");
|
|
}
|
|
|
|
row << "| |" << tipo;
|
|
|
|
disable_cgs_cells(n, tipo);
|
|
cg.force_update(n);
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
HIDDEN int compare_rows(const TObject** o1, const TObject** o2)
|
|
{
|
|
// Totale, Rit.Fisc., Rit.Soc., da riga IVA, riga contabile, IVA detr., IVA non detr.
|
|
const char* const sort_order = "TFSI DNAPRC";
|
|
|
|
const TToken_string* r1 = (const TToken_string*)*o1;
|
|
const TToken_string* r2 = (const TToken_string*)*o2;
|
|
const char c1 = app().row_type(*r1);
|
|
const char c2 = app().row_type(*r2);
|
|
return int(strchr(sort_order, c1) - strchr(sort_order, c2));
|
|
}
|
|
|
|
HIDDEN bool can_remove(TToken_string& s)
|
|
{
|
|
const char* dare = s.get(0);
|
|
bool yes = dare == NULL ;
|
|
if (!yes)
|
|
{
|
|
if (*dare == '\0' || *dare == ' ' || strcmp(dare,"0") == 0)
|
|
{
|
|
const char* avere = s.get();
|
|
yes = (avere == NULL || *avere == '\0' || *avere == ' ' || strcmp(avere,"0") == 0);
|
|
}
|
|
}
|
|
return yes;
|
|
}
|
|
|
|
|
|
void TPrimanota_application::cgs_pack()
|
|
{
|
|
TString_array& rows = cgs().rows_array();
|
|
const bool pagamento = is_pagamento();
|
|
const long numreg = curr_mask().get_long(F_NUMREG);
|
|
|
|
for (int i = rows.items()-1; i >= 0; i--)
|
|
{
|
|
TToken_string& r = rows.row(i);
|
|
if (can_remove(r))
|
|
{
|
|
bool ok = TRUE;
|
|
if (pagamento && row_type(r) == 'K')
|
|
{
|
|
ok = !partite().utilizzata(numreg, i+1);
|
|
if (ok)
|
|
cg_notify(cgs(), i, K_DEL);
|
|
}
|
|
if (ok)
|
|
rows.destroy(i, TRUE);
|
|
}
|
|
}
|
|
if (!pagamento) // Il pagamento e' gia' ordinato
|
|
rows.TArray::sort(compare_rows); // Pack and sort array
|
|
}
|
|
|
|
|
|
bool TPrimanota_application::ci_sono_importi() const
|
|
{
|
|
TString_array& rows = cgs().rows_array();
|
|
for (int i = 0; i < rows.items(); i++)
|
|
{
|
|
TToken_string& r = rows.row(i);
|
|
const real dare(r.get(0));
|
|
if (dare != ZERO) return TRUE;
|
|
const real avere(r.get());
|
|
if (avere != ZERO) return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
real TPrimanota_application::calcola_saldo() const
|
|
{
|
|
real tdare, tavere;
|
|
TImporto saldaconto;
|
|
const bool pag = is_pagamento() && !_as400;
|
|
|
|
TString_array& rows = cgs().rows_array();
|
|
const int max = rows.items();
|
|
for (int i = 0; i < max; i++)
|
|
{
|
|
TToken_string& r = rows.row(i);
|
|
const real dare(r.get(0));
|
|
const real avere(r.get());
|
|
|
|
tdare += dare;
|
|
tavere += avere;
|
|
|
|
if (pag)
|
|
{
|
|
const char tipo = row_type(r);
|
|
if (strchr("ACGKP", tipo) != NULL) // Abbuoni attivi, differenze cambio,
|
|
{ // spese, clienti/fornitori, abbuoni passivi
|
|
const char sez = dare.is_zero() ? 'A' : 'D';
|
|
const TImporto importo(sez, sez == 'A' ? avere : dare);
|
|
saldaconto += importo;
|
|
}
|
|
}
|
|
}
|
|
|
|
TMask& m = curr_mask();
|
|
const real sbilancio = abs(tdare)-abs(tavere);
|
|
const real absbilancio = abs(tdare - tavere);
|
|
switch (sbilancio.sign())
|
|
{
|
|
case +1: // Il dare supera l'avere in valore assoluto
|
|
m.set(F_DARE, absbilancio);
|
|
m.reset(F_AVERE);
|
|
break;
|
|
case -1: // L'avere supera il dare in valore assoluto
|
|
m.reset(F_DARE);
|
|
m.set(F_AVERE, absbilancio);
|
|
break;
|
|
default: // Sbilancio nullo
|
|
m.reset(F_DARE);
|
|
m.reset(F_AVERE);
|
|
break;
|
|
}
|
|
|
|
if (pag)
|
|
{
|
|
const char s(causale().sezione(2)); // Conto della cassa
|
|
const real t(m.get(F_TOTALE));
|
|
TImporto totdoc(s, t);
|
|
totdoc += saldaconto;
|
|
totdoc.normalize(s);
|
|
m.set(K_RESIDUO, totdoc.valore().string());
|
|
}
|
|
|
|
return sbilancio;
|
|
}
|
|
|
|
HIDDEN bool imptot_error(const TImporto& imptot, const TImporto& impsal, bool val)
|
|
{
|
|
bool ok = TRUE;
|
|
TImporto cassa(impsal); cassa.swap_section();
|
|
TImporto residuo(imptot); residuo -= cassa; residuo.normalize(imptot.sezione());
|
|
|
|
if (!residuo.is_zero())
|
|
{
|
|
const char* const pic = val ? ".3" : ".";
|
|
TPrimanota_application& a = app();
|
|
const TMask& m = a.curr_mask();
|
|
|
|
TString msg(255);
|
|
msg << "Il totale documento ";
|
|
if (val)
|
|
msg << "in valuta " << m.get(SK_VALUTA);
|
|
else
|
|
msg << "inserito";
|
|
msg << " e' " << imptot.valore().string(pic) << ' ' << imptot.sezione() << ",\n";
|
|
msg << "i pagamenti e le spese ammontano a "
|
|
<< cassa.valore().string(pic) << ' ' << cassa.sezione() << ",\n";
|
|
msg << "per cui il residuo e' " << residuo.valore().string(pic) << '.';
|
|
|
|
if (m.edit_mode() && impsal.is_zero())
|
|
{
|
|
msg << "\nSi desidera registrare ugualmente?";
|
|
ok = a.cgs().yesno_box(msg);
|
|
}
|
|
else
|
|
ok = a.cgs().error_box(msg);
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
// Handler dello sheet di contabilita'
|
|
// Certified 90%
|
|
bool TPrimanota_application::cg_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_ENTER)
|
|
{
|
|
TPrimanota_application& a = app();
|
|
const real saldo = a.calcola_saldo();
|
|
|
|
if (saldo != ZERO)
|
|
{
|
|
const char* ss = saldo.string(".");
|
|
if (*ss == '-') ss++;
|
|
return f.error_box("Il movimento e' sbilanciato di %s lire.", ss);
|
|
}
|
|
|
|
TMask& m = f.mask();
|
|
const bool paga = a.is_pagamento();
|
|
const bool nota = a.is_nota_credito() && m.field(F_NUMRIF).active();
|
|
const bool fatt = a.is_fattura() && m.page_enabled(2);
|
|
|
|
const long numreg = m.get_long(F_NUMREG);
|
|
|
|
const bool in_valuta = m.get(SK_VALUTA).not_empty();
|
|
TImporto saldaconto, saldaconto_val;
|
|
|
|
TSheet_field& cg = a.cgs();
|
|
bool empty = TRUE;
|
|
for (int i = 0; i < cg.items(); i++)
|
|
{
|
|
TToken_string& r = cg.row(i);
|
|
TImporto importo; importo = r;
|
|
|
|
if (!importo.is_zero())
|
|
{
|
|
const TBill c(r, 3, 0x0);
|
|
if (!c.ok())
|
|
return f.error_box("Il conto della riga %d non e' completo", i+1);
|
|
const TBill co(r, 10, 0x0);
|
|
if (!co.empty() && !co.ok())
|
|
f.error_box("La contropartita della riga %d non e' completa", i+1);
|
|
|
|
empty = FALSE;
|
|
if (paga || nota)
|
|
{
|
|
const char tipo = row_type(r);
|
|
if (tipo == 'K' || tipo == 'T' || a._as400)
|
|
{
|
|
const int currig = i+1;
|
|
const TImporto speso = a.partite().importo_speso(numreg, currig);
|
|
|
|
bool errato = importo != speso;
|
|
if (errato && a._as400 && speso.is_zero())
|
|
errato = FALSE;
|
|
|
|
if (errato)
|
|
{
|
|
TString msg(128);
|
|
msg << "L'importo sul saldaconto della riga " << currig << " e' "
|
|
<< speso.valore().string(".");
|
|
if (!speso.is_zero())
|
|
msg << (speso.sezione() == 'A' ? " Avere" : " Dare");
|
|
|
|
bool ok = FALSE;
|
|
if (m.edit_mode() && speso.is_zero())
|
|
{
|
|
msg << "\nSi desidera registrare ugualmente?";
|
|
ok = f.yesno_box(msg);
|
|
}
|
|
else
|
|
ok = f.error_box(msg);
|
|
if (!ok)
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (strchr("ACGKPT", tipo) != NULL)
|
|
{
|
|
saldaconto += importo;
|
|
if (in_valuta)
|
|
saldaconto_val += a.partite().importo_speso(numreg, i+1, TRUE, 0x1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (empty)
|
|
return f.error_box("Il movimento non ha nessuna riga contabile con un importo");
|
|
|
|
if ((paga || nota) && !a._as400)
|
|
{
|
|
const char sez(a.causale().sezione(2));
|
|
const TImporto totdoc(sez, m.get_real(F_TOTALE));
|
|
bool ok = imptot_error(totdoc, saldaconto, FALSE);
|
|
|
|
if (ok && in_valuta && !saldaconto.is_zero())
|
|
{
|
|
const TImporto totdoc_val(sez, m.get_real(SK_TOTDOCVAL));
|
|
ok = imptot_error(totdoc_val, saldaconto_val, TRUE);
|
|
}
|
|
|
|
if (!ok)
|
|
return FALSE;
|
|
}
|
|
|
|
if (fatt || nota)
|
|
{
|
|
TBill contocf;
|
|
if (a.cerca_conto_cf(contocf) < 0)
|
|
{
|
|
TString msg(80); msg = "Non esiste una riga contabile riferita al ";
|
|
msg << (contocf.tipo() == 'C' ? "cliente" : "fornitore") << ' ';
|
|
msg << contocf.codclifo() << ":\n";
|
|
if (m.edit_mode())
|
|
{
|
|
msg << "Si desidera eliminare il saldaconto?";
|
|
const bool kill = f.yesno_box(msg);
|
|
if (kill)
|
|
{
|
|
if (fatt) // Se e' una fattura elimina il numero partita
|
|
{
|
|
m.reset(F_ANNORIF);
|
|
m.reset(F_NUMRIF);
|
|
}
|
|
else
|
|
{ // Se e' una nota credito elimina il saldaconto
|
|
a.notify_cgline_deletion(-1);
|
|
}
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
msg << "Impossibile registrare il saldaconto!";
|
|
return f.error_box(msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void TPrimanota_application::generazione_righe_cg(int r)
|
|
{
|
|
TSheet_field& cg = cgs();
|
|
TToken_string& row = cg.row(r);
|
|
|
|
if (can_remove(row)) // Ignora righe senza importo
|
|
return;
|
|
|
|
begin_wait();
|
|
|
|
TImporto importo; importo = row;
|
|
const bool causale_ok = causale().codice()[0] > ' ';
|
|
|
|
if (r == 0 && cg.row(1).empty_items())
|
|
{
|
|
TBill contro(row, 9, 0x3); // Contropartita della prima riga
|
|
if (causale_ok && !contro.ok())
|
|
{
|
|
causale().bill(2, contro); // Prendi contropartita dalla causale
|
|
if (contro.ok())
|
|
{
|
|
contro.add_to(row, 9, 0x3);
|
|
cg.force_update(r);
|
|
}
|
|
}
|
|
if (contro.ok())
|
|
{
|
|
importo.swap_section();
|
|
set_cgs_row(1, importo, contro, "", ' ');
|
|
TBill conto(row, 2, 0x3);
|
|
conto.add_to(cg.row(1), 9, 0x3);
|
|
cg.force_update(1);
|
|
}
|
|
}
|
|
|
|
if (causale_ok)
|
|
{
|
|
int first_not_empty = 0;
|
|
for (int i = 0; i < r; i++)
|
|
{
|
|
TToken_string& row = cg.row(i);
|
|
if (!can_remove(row))
|
|
{
|
|
first_not_empty = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
TBill conto(row, 2, 0x3);
|
|
if (first_not_empty == r) // Sono la prima riga con importo ?
|
|
{
|
|
int last = -1;
|
|
for (i = r+1; i < cg.items(); i++) // Aggiorna tutte le altre contropartite
|
|
{
|
|
TToken_string& rowi = cg.row(i);
|
|
int gruppo = rowi.get_int(3);
|
|
if (gruppo != 0) // Considera righe con conto ...
|
|
{
|
|
gruppo = rowi.get_int(10);
|
|
if (gruppo == 0) // ... e senza contropartita
|
|
{
|
|
char sez = ' '; // Calcola sezione D/A della riga i
|
|
if (cg.cell_disabled(i,0)) sez = 'A'; else
|
|
if (cg.cell_disabled(i,1)) sez = 'D';
|
|
|
|
if (sez != ' ' && importo.sezione() != sez) // Considera solo le sezioni opposte
|
|
{
|
|
conto.add_to(rowi, 9, 0x3);
|
|
cg.force_update(i);
|
|
if (last < 0) last = i;
|
|
else last = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (last > r)
|
|
{
|
|
importo.swap_section();
|
|
set_cgs_imp(last, importo);
|
|
|
|
const int gruppo = row.get_int(10);
|
|
if (gruppo == 0) // Se non ho contropartita ...
|
|
{
|
|
TBill contro(cg.row(last), 2, 0x3); // ... copiala dalla riga corrispondente
|
|
contro.add_to(row, 9, 0x3);
|
|
cg.force_update(r);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TToken_string& first = cg.row(first_not_empty);
|
|
int gruppo = first.get_int(10);
|
|
if (gruppo == 0) // Se la prima riga non ha contropartita ...
|
|
{
|
|
conto.add_to(first, 9, 0x3); // ... copiaci la mia partita
|
|
cg.force_update(first_not_empty);
|
|
}
|
|
gruppo = row.get_int(10);
|
|
if (gruppo == 0) // Se non ho contropartita ...
|
|
{
|
|
TBill contro(first, 2, 0x3); // ... copiala dalla prima riga
|
|
contro.add_to(row, 9, 0x3);
|
|
cg.force_update(r);
|
|
}
|
|
}
|
|
}
|
|
|
|
end_wait();
|
|
}
|
|
|
|
|
|
int TPrimanota_application::crea_somma_spese(TImporto& imp)
|
|
{
|
|
TConto cassa; causale().bill(2, cassa);
|
|
const TString80 desc(causale().desc_agg(2));
|
|
imp.swap_section(); imp.normalize();
|
|
const int r = set_cgs_row(-1, imp, cassa, desc, 'L');
|
|
cgs().force_update();
|
|
return r;
|
|
}
|
|
|
|
bool TPrimanota_application::cg_notify(TSheet_field& cg, int r, KEY k)
|
|
{
|
|
static TImporto old_spesa;
|
|
static bool delete_l = FALSE;
|
|
|
|
CHECKD(r >= 0, "Chi e' quel ca$$one che notifica la riga ", r);
|
|
|
|
TPrimanota_application& a = app();
|
|
|
|
if (k == K_CTRL + K_DEL)
|
|
{
|
|
if (delete_l)
|
|
{
|
|
const int l = type2pos('L');
|
|
CHECK(l >= 0, "Impossibile cancellare riga di tipo L");
|
|
cg.destroy(l);
|
|
delete_l = FALSE;
|
|
}
|
|
a.calcola_saldo(); // Ricalcola saldo dopo cancellazione
|
|
return TRUE; // Ritorna subito, altrimenti crea riga vuota
|
|
}
|
|
|
|
TToken_string& row = cg.row(r);
|
|
const char tipo = row_type(row); // Tipo della riga in esame
|
|
|
|
switch(k)
|
|
{
|
|
case K_SPACE:
|
|
if (tipo == 'G')
|
|
old_spesa = row;
|
|
break;
|
|
case K_TAB:
|
|
cg.sheet_mask().enable(DLG_DELREC, tipo <= ' ' || tipo == 'K' || tipo == 'G');
|
|
break;
|
|
case K_DEL:
|
|
if (tipo == 'G')
|
|
{
|
|
row.add("", 0);
|
|
row.add("", 1);
|
|
}
|
|
else
|
|
{
|
|
if (tipo == 'K')
|
|
{
|
|
a.notify_cgline_deletion(r+1);
|
|
}
|
|
break;
|
|
}
|
|
case K_ENTER:
|
|
if (tipo == 'G')
|
|
{
|
|
TImporto growth; growth = row; growth -= old_spesa;
|
|
if (!growth.is_zero())
|
|
{
|
|
const int s = type2pos('L');
|
|
if (s < 0)
|
|
a.crea_somma_spese(growth);
|
|
else
|
|
delete_l = a.sub_cgs_imp(s, growth);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (a.iva() == nessuna_iva && !a.is_saldaconto())
|
|
a.generazione_righe_cg(r);
|
|
}
|
|
if (k == K_ENTER)
|
|
a.calcola_saldo(); // Altrimenti ci pensa CTRL-DEL
|
|
break;
|
|
case K_CTRL+K_INS: // Post inserimento
|
|
if (a.is_pagamento())
|
|
{
|
|
const char tipo = cg.mask().get(SK_TIPORIGA)[0];
|
|
if (tipo == 'K' || tipo == 'G')
|
|
{
|
|
const int k = tipo == 'K' ? 1 : RIGA_SPESE;
|
|
TBill conto; a.causale().bill(k, conto);
|
|
const TString80 desc(a.causale().desc_agg(k));
|
|
const char sez = a.causale().sezione(k);
|
|
const real imp(cg.mask().get(K_RESIDUO));
|
|
TImporto importo(sez, imp);
|
|
a.set_cgs_row(r, importo, conto, desc, tipo);
|
|
|
|
if (tipo == 'K')
|
|
{
|
|
for (int i = 0; i < r; i++)
|
|
{
|
|
const TToken_string& row = cg.row(i);
|
|
if (row_type(row) != 'K')
|
|
{
|
|
cg.swap_rows(r, i);
|
|
cg.force_update();
|
|
cg.select(i, FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!importo.is_zero())
|
|
{
|
|
const int s = type2pos('L');
|
|
if (s < 0)
|
|
a.crea_somma_spese(importo);
|
|
else
|
|
a.sub_cgs_imp(s, importo);
|
|
}
|
|
}
|
|
a.calcola_saldo();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TPrimanota_application::descr_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_TAB && f.focusdirty())
|
|
{
|
|
if (app().iva() != nessuna_iva)
|
|
{
|
|
const int first = type2pos('T');
|
|
if (first >= 0)
|
|
{
|
|
TSheet_field& cg = app().cgs();
|
|
cg.row(first).add(f.get(), 8);
|
|
cg.force_update(first);
|
|
}
|
|
}
|
|
}
|
|
if (k == K_ENTER && f.get().empty())
|
|
{
|
|
if (f.mask().get(F_CODCAUS).empty())
|
|
return f.error_box("La descrizione del documento e' necessaria in mancanza della causale");
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Handler per le colonne 'Dare' e 'Avere' dello sheet contabile.
|
|
// Scrivendo qualcosa in dare (101) cancella l'importo in avere (102) e viceversa
|
|
bool TPrimanota_application::dareavere_handler(TMask_field& f, KEY k)
|
|
{
|
|
TPrimanota_application& a = app();
|
|
TSheet_field& cgs = a.cgs();
|
|
const int currig = cgs.selected();
|
|
|
|
if (k == K_F8 && a.is_pagamento())
|
|
{
|
|
const long numreg = a.curr_mask().get_long(F_NUMREG);
|
|
const TImporto speso = a.partite().importo_speso(numreg, currig+1);
|
|
|
|
const char* ss = speso.valore().string();
|
|
TMask& m = f.mask();
|
|
m.set(CG_DARE, speso.sezione() == 'D' ? ss : "");
|
|
m.set(CG_AVERE, speso.sezione() == 'A' ? ss : "");
|
|
|
|
if (!m.is_running())
|
|
{
|
|
speso.add_to(cgs.row(currig), 0); // Aggiorna riga sheet
|
|
a.calcola_saldo(); // Aggiorna saldo e residuo
|
|
}
|
|
}
|
|
|
|
if (k == K_TAB && f.focusdirty())
|
|
{
|
|
const TString& val = f.get();
|
|
TToken_string& row = cgs.row(currig);
|
|
row.add(val, f.dlg() - CG_DARE); // Aggiorno stringa sheet
|
|
|
|
if (val.not_empty())
|
|
{
|
|
// Calcola id del campo da resettare
|
|
const int id = f.dlg() == CG_DARE ? CG_AVERE : CG_DARE;
|
|
f.mask().reset(id); // Aggiorna maschera e ...
|
|
row.add("", id - CG_DARE); // ... riga dello sheet
|
|
}
|
|
|
|
if (!f.mask().is_running())
|
|
a.calcola_saldo(); // Aggiorna saldo e residuo
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
TSheet_field& TPrimanota_application::pags() const
|
|
{
|
|
CHECK(is_fattura(), "Can't use rate sheet without a fattura");
|
|
const int pos = _msk[2]->id2pos(FS_RATESHEET);
|
|
CHECK(pos > 0, "Can't find rate sheet");
|
|
TSheet_field& s = (TSheet_field&)_msk[2]->fld(pos);
|
|
return s;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Gestione sheet IVA
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Ritorna lo sheet delle righe IVA
|
|
// Certified 100%
|
|
TSheet_field& TPrimanota_application::ivas() const
|
|
{
|
|
TSheet_field& s = (TSheet_field&)_msk[2]->field(F_SHEETIVA);
|
|
return s;
|
|
}
|
|
|
|
|
|
TBill& TPrimanota_application::ivas_bill(TBill& c)
|
|
{
|
|
const int spric = c.tipo_cr();
|
|
if (spric == 2 || spric == 3)
|
|
{
|
|
const TString& td = causale().tipo_doc();
|
|
if (td == "FV" || td == "NC")
|
|
c.tipo_cr(4);
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// Gestione del campo imponibile sullo sheet iva
|
|
// Certified 90%
|
|
bool TPrimanota_application::imponibile_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.dirty())
|
|
{
|
|
TMask& m = f.mask();
|
|
TString16 iva(m.get(102));
|
|
if (iva.empty())
|
|
{
|
|
iva = app().curr_mask().get(F_CODIVA);
|
|
m.set(102, iva);
|
|
}
|
|
if (iva.not_empty() && !app().causale().corrispettivi())
|
|
{
|
|
const real& percent = cod2IVA(m);
|
|
const real imponibile(f.get());
|
|
real imposta = abs(imponibile) * percent / 100.0; imposta.ceil();
|
|
if (imponibile.sign() < 0) imposta = -imposta;
|
|
m.set(104, imposta);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Gestione del codice IVA sullo sheet iva
|
|
// Certified 90%
|
|
bool TPrimanota_application::codiva_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (!suspended_handler(f, key))
|
|
return FALSE;
|
|
|
|
if (key == K_TAB && f.dirty())
|
|
{
|
|
TMask& m = f.mask();
|
|
|
|
if (m.get_int(107) == 0)
|
|
{
|
|
TCodiceIVA iva(f.get());
|
|
TBill b; app().IVA2bill(iva, b);
|
|
|
|
char cr[2] = { b.tipo_cr() + '0', '\0' };
|
|
m.set(105, *cr > '0' ? cr : "");
|
|
|
|
const char tipo[2] = { b.tipo(), '\0' };
|
|
m.set(106, tipo);
|
|
m.set(107, b.gruppo());
|
|
m.set(108, b.conto());
|
|
const short id = b.tipo() == 'C' ? 209 : (b.tipo() == 'F' ? 309 : 109);
|
|
m.set(id, b.sottoconto());
|
|
m.set(id+1, b.descrizione());
|
|
}
|
|
|
|
TMask_field& im = m.field(101);
|
|
im.set_dirty();
|
|
im.on_hit();
|
|
} else
|
|
if (key == K_ENTER)
|
|
{
|
|
if (f.get().empty() && f.mask().get(101).not_empty())
|
|
return f.error_box("Codice IVA obbligatorio");
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// Gestione del codice detrazione sullo sheet iva
|
|
// Certified 90%
|
|
bool TPrimanota_application::detrazione_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.dirty() && app().iva() == iva_acquisti)
|
|
{
|
|
TMask_field& ci = f.mask().field(101);
|
|
ci.set_dirty();
|
|
ci.on_hit();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// Gestione del campo imposta sullo sheet iva
|
|
// Certified 90%
|
|
bool TPrimanota_application::imposta_handler(TMask_field& f, KEY key)
|
|
{
|
|
if ((key == K_ENTER || key == K_TAB) && f.dirty())
|
|
{
|
|
const real imponibile(f.mask().get(101));
|
|
const real percent = app().causale().corrispettivi() ? ZERO : cod2IVA(f.mask());
|
|
real imposta = abs(imponibile) * percent / 100.0;
|
|
imposta.ceil();
|
|
if (imponibile.sign() < 0) imposta = -imposta;
|
|
|
|
const real val(f.get());
|
|
if (val != imposta)
|
|
{
|
|
f.warning_box("L'imposta dovrebbe essere %s", (const char*)imposta.string("."));
|
|
}
|
|
} else
|
|
if (key == K_F8)
|
|
{
|
|
real imposta(f.get());
|
|
if (imposta.is_zero())
|
|
{
|
|
real imponibile(f.mask().get(101));
|
|
const real& percent = cod2IVA(f.mask());
|
|
imposta = scorpora(imponibile, percent);
|
|
f.mask().set(101, imponibile.string());
|
|
f.set(imposta.string());
|
|
}
|
|
else
|
|
f.warning_box("Cancellare l'imposta (tasto F2) prima di effettuare lo scorporo");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Calcola il totale degli imponibili e delle imposte e aggiorna
|
|
// i corrispondenti campi della maschera
|
|
// Certified 99%
|
|
real TPrimanota_application::calcola_imp() const
|
|
{
|
|
TArray& rows = ivas().rows_array();
|
|
|
|
real imponibili, imposte;
|
|
for (int r = rows.items()-1; r >= 0; r--)
|
|
{
|
|
TToken_string& row = (TToken_string&)rows[r];
|
|
imponibili += real(row.get(0));
|
|
imposte += real(row.get(3));
|
|
}
|
|
|
|
TMask& m = curr_mask();
|
|
m.set(F_IMPONIBILI, imponibili);
|
|
m.set(F_IMPOSTE, imposte);
|
|
|
|
// Se e' attiva la terza pagina allora riporta i totali in testata
|
|
if (is_fattura())
|
|
{
|
|
real tot(m.get(F_TOTALE)); tot -= imposte;
|
|
m.set(FS_IMPONIBILI, tot);
|
|
m.set(FS_IMPOSTE, imposte);
|
|
}
|
|
|
|
return imponibili+imposte;
|
|
}
|
|
|
|
// Elimina dallo sheet le righr iva senza importi (imponibile e imposta)
|
|
// Certified 99%
|
|
void TPrimanota_application::ivas_pack()
|
|
{
|
|
TString_array& rows = ivas().rows_array();
|
|
|
|
const int max = rows.items();
|
|
for (int i = 0; i < max; i++)
|
|
{
|
|
TToken_string& r = rows.row(i);
|
|
const real imponibile(r.get(0));
|
|
if (imponibile != ZERO) continue;
|
|
const real imposta(r.get(3));
|
|
if (imposta != ZERO) continue;
|
|
rows.destroy(i, FALSE);
|
|
}
|
|
|
|
rows.pack(); // Pack array
|
|
}
|
|
|
|
// Certified 50%
|
|
bool TPrimanota_application::iva_notify(TSheet_field& iva, int r, KEY k)
|
|
{
|
|
static int oldpos,oldposiva;
|
|
static real oldimp, oldiva;
|
|
|
|
TPrimanota_application& a = app();
|
|
if (a._as400)
|
|
return TRUE;
|
|
|
|
TToken_string& row = iva.row(r);
|
|
const TCausale& cau = a.causale();
|
|
|
|
if (k == K_SPACE)
|
|
{
|
|
oldimp = real(row.get(0)); // Imponibile
|
|
oldiva = real(row.get(3)); // Imposta
|
|
|
|
if (oldiva.is_zero() && cau.corrispettivi()) // In caso di corrispettivi ...
|
|
{
|
|
const TString zanicchi(row.get(1)); // Codice IVA
|
|
const TCodiceIVA i(zanicchi);
|
|
oldiva = i.scorpora(oldimp); // ... scorpora imposta dall'imponibile
|
|
}
|
|
|
|
const char tipod = detraibile(row) ? 'D' : 'N';
|
|
oldposiva = type2pos(tipod);
|
|
|
|
if (oldposiva < 0 && !oldiva.is_zero())
|
|
{
|
|
const int ri = tipod == 'D' ? 3 : 4; // Calcola riga causale per l'IVA
|
|
TBill c; cau.bill(ri, c);
|
|
if (c.ok())
|
|
{
|
|
const TString80 d(cau.desc_agg(ri));
|
|
oldposiva = a.set_cgs_row(-1, app().real2imp(ZERO, 'I'), c, d, tipod);
|
|
}
|
|
else
|
|
if (ri == 4) // Se non esiste il conto IVA indetraibile ...
|
|
{ // ... somma imponibile e imposta
|
|
oldimp += oldiva;
|
|
oldiva = 0.0;
|
|
}
|
|
}
|
|
|
|
TBill oldconto(row, 6, 0x0); // g/c/s 6 7 8
|
|
if (oldconto.ok())
|
|
{
|
|
oldpos = bill2pos(oldconto, 'I');
|
|
if (oldpos < 0)
|
|
{
|
|
const TString d(cau.desc_agg(2));
|
|
oldpos = a.set_cgs_row(-1, a.real2imp(ZERO, 'I'), oldconto, d, 'I');
|
|
}
|
|
}
|
|
else
|
|
oldpos = -1; // Se il conto e' incompleto ignoralo
|
|
}
|
|
if (k == K_DEL) // Cancellazione di una riga
|
|
{
|
|
row.add("0", 0); // Azzera imponibile
|
|
row.add("0", 3); // Azzera imposta
|
|
k = K_ENTER; // Elegante o Sporco trucco (dipende dai gusti!)
|
|
}
|
|
if (k == K_ENTER)
|
|
{
|
|
int delimp = -1, deliva = -1; // Eventuali righe contabili da cancellare
|
|
if (oldpos >= 0) // Se il conto esisteva anche prima ...
|
|
{ // sottrai il vecchio imponibile
|
|
TImporto i(a.get_cgs_imp(oldpos));
|
|
i.valore() -= oldimp;
|
|
a.set_cgs_imp(oldpos, i);
|
|
if (i.is_zero()) delimp = oldpos;
|
|
}
|
|
if (oldposiva >= 0) // Se conto IVA esisteva anche prima ...
|
|
{ // sottrai la vecchia imposta
|
|
TImporto i(a.get_cgs_imp(oldposiva));
|
|
i.valore() -= oldiva;
|
|
a.set_cgs_imp(oldposiva, i);
|
|
if (i.is_zero()) deliva = oldposiva;
|
|
}
|
|
|
|
real imponibile(row.get(0)); // Nuovo imponibile
|
|
real imposta(row.get(3)); // Nuova imposta
|
|
|
|
if (imposta.is_zero() && cau.corrispettivi()) // In caso di corrispettivi ...
|
|
{
|
|
const TString zanicchi(row.get(1));
|
|
const TCodiceIVA i(zanicchi);
|
|
imposta = i.scorpora(imponibile); // ... scorpora imposta dall'imponibile
|
|
}
|
|
|
|
TBill conto(row, 5, 0x3);
|
|
int newpos = bill2pos(conto, 'I'); // Riga in cui andra' l'imponibile
|
|
|
|
const bool detrarre = detraibile(row); // Determina se IVA detraibile
|
|
|
|
// Calcola riga causale col conto opportuno
|
|
const int ri = detrarre ? RIGA_IVA_DETRAIBILE : RIGA_IVA_NON_DETRAIBILE;
|
|
TBill contoiva; cau.bill(ri, contoiva);
|
|
|
|
if (ri == 4 && !contoiva.ok()) // Se non c'e' il conto IVA indetraibile ...
|
|
{ // ... somma imponibile e imposta
|
|
imponibile += imposta;
|
|
imposta = 0.0;
|
|
}
|
|
|
|
// Aggiorna conto sulla riga contabile
|
|
if (newpos < 0)
|
|
{
|
|
if (delimp >= 0)
|
|
{
|
|
a.reset_cgs_row(delimp); // Cancella vecchia riga
|
|
if (deliva > delimp) deliva--;
|
|
}
|
|
|
|
const TImporto val(a.real2imp(imponibile, 'I'));
|
|
if (conto.ok() && !val.is_zero()) // Se c'e' imponibile ...
|
|
{ // crea una nuova riga contabile
|
|
const TString d(cau.desc_agg(2));
|
|
a.set_cgs_row(-1, val, conto, d, 'I');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TImporto val(a.real2imp(imponibile, 'I'));
|
|
const bool empty = a.add_cgs_imp(newpos, val);
|
|
if (empty) // Se la riga si e' azzerata ...
|
|
{ // ... cancellala
|
|
a.reset_cgs_row(newpos);
|
|
newpos = -1;
|
|
}
|
|
}
|
|
oldimp = imponibile;
|
|
oldpos = newpos;
|
|
|
|
// Aggiorna conto IVA sulla riga contabile
|
|
|
|
const char tipod = detrarre ? 'D' : 'N';
|
|
int newposiva = type2pos(tipod);
|
|
|
|
if (deliva >= 0 && newposiva != deliva) // E' cambiato il tipo d'imposta
|
|
a.reset_cgs_row(deliva); // Azzera il vecchio tipo se necessario
|
|
|
|
if (newposiva < 0)
|
|
{
|
|
if (!imposta.is_zero()) // Se c'e' imposta ...
|
|
{ // ... crea nuova riga per l'IVA
|
|
const TImporto val(a.real2imp(imposta, 'I'));
|
|
const TString d(cau.desc_agg(ri));
|
|
newposiva = a.set_cgs_row(-1, val, contoiva, d, tipod);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const TImporto val(a.real2imp(imposta, 'I'));
|
|
const bool empty = a.add_cgs_imp(newposiva, val);
|
|
if (empty) // Se l'imposta si e' azzerata ...
|
|
{
|
|
a.reset_cgs_row(newposiva); // ... cancellala
|
|
newposiva = -1;
|
|
}
|
|
}
|
|
|
|
oldiva = imposta;
|
|
oldposiva = newposiva;
|
|
|
|
TMask& m = a.curr_mask();
|
|
if (r == 0) // Se cambio la prima riga ...
|
|
{
|
|
a.add_cgs_tot(m); // ... ricalcola conti e imponibili
|
|
}
|
|
else
|
|
{
|
|
a.calcola_saldo(); // Calcola sbilancio
|
|
a.calcola_imp(); // Calcola imponibili
|
|
}
|
|
|
|
if (a.is_fattura() && m.insert_mode())
|
|
{
|
|
TPagamento& pag = a.pagamento();
|
|
const TValuta cambio(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
|
|
const bool inv = cambio.in_valuta();
|
|
real imposta, imponibile;
|
|
if (inv)
|
|
{
|
|
const real il(m.get(F_IMPOSTE));
|
|
imposta = cambio.lit2val(il);
|
|
imponibile = m.get_real(SK_TOTDOCVAL) - imposta;
|
|
}
|
|
else
|
|
{
|
|
imposta = m.get_real(F_IMPOSTE);
|
|
imponibile = m.get_real(F_TOTALE) - imposta;
|
|
}
|
|
imposta.round(pag.round(inv)); imponibile.round(pag.round(inv));
|
|
real pimposta(pag.imposta(inv)); real pimponibile(pag.imponibile(inv));
|
|
pimposta.round(pag.round(inv)); pimponibile.round(pag.round(inv));
|
|
|
|
if (pimposta != imposta || pimponibile != imponibile)
|
|
a.set_scadenze(m); // Ricalcola rate
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Handler dello sheet
|
|
// Certified 90%
|
|
bool TPrimanota_application::iva_handler(TMask_field& f, KEY k)
|
|
{
|
|
if ((k == K_TAB && !f.mask().is_running()) || k == K_ENTER)
|
|
{
|
|
const real imp = app().calcola_imp();
|
|
if (k == K_ENTER)
|
|
{
|
|
const real tot = app().totale_documento();
|
|
if (imp != tot)
|
|
{
|
|
const TString t(tot.string("."));
|
|
const TString i(imp.string("."));
|
|
return error_box("La somma del totale documento e delle ritenute (%s) e' diverso dalla "
|
|
"somma degli imponibili e delle imposte (%s)", (const char*)t, (const char*)i);
|
|
}
|
|
|
|
TSheet_field& iva = app().ivas();
|
|
for (int i = 0; i < iva.items(); i++)
|
|
{
|
|
TToken_string& row = iva.row(i);
|
|
const real im(row.get(0));
|
|
if (!im.is_zero())
|
|
{
|
|
TBill c(row, 5, 0x1);
|
|
if (!c.ok() || !c.find())
|
|
return error_box("Il conto della riga iva %d e' errato o incompleto", i+1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// Il gruppo non possiede una ricerca propria per cui se viene variato richiama
|
|
// quella del conto.
|
|
bool TPrimanota_application::cg_gruppo_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.focusdirty())
|
|
{
|
|
TEdit_field& conto = f.mask().efield(f.dlg()+1);
|
|
const TRectype& curr = conto.browse()->cursor()->curr();
|
|
if (curr.get(RMV_GRUPPO) != f.get()) // Se non e' gia' posizionato ...
|
|
conto.check(RUNNING_CHECK); // ... forza ricerca sul conto
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TPrimanota_application::cg_conto_handler(TMask_field& f, KEY key)
|
|
{
|
|
bool ok = TRUE;
|
|
|
|
if (key == K_ENTER)
|
|
{
|
|
TMask& m = f.mask();
|
|
if (m.get(CG_ROWTYPE)[0] == 'T' && !app().causale().corrispettivi())
|
|
{
|
|
const char tipo = app().clifo(); // Tipo conto richiesto dal movimento
|
|
char cf = m.get(f.dlg()-2)[0];
|
|
if (cf < ' ') cf = ' '; // Tipo conto della riga
|
|
if (cf != tipo) // Incongruenza!
|
|
{
|
|
const char* d = tipo == 'C' ? "clienti" : "fornitori";
|
|
ok = f.error_box("La riga totale richiede un conto %s.", d);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
// Gestore del sottoconto dello sheet IVA
|
|
// Attenzione questo handler e' agganciato anche alla descrizione del sottoconto
|
|
bool TPrimanota_application::iva_sottoconto_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (!suspended_handler(f, key))
|
|
return FALSE;
|
|
|
|
if (key == K_TAB && f.dirty())
|
|
{
|
|
TMask& m = f.mask();
|
|
const TEdit_field& sotto = m.efield(109);
|
|
const TRectype& piano = sotto.browse()->cursor()->curr();
|
|
const TCausale& caus = app().causale();
|
|
int spric = piano.get_int("TIPOSPRIC");
|
|
if ((spric == 2 || spric == 3) && !caus.corrispettivi())
|
|
{
|
|
const TString& td = caus.tipo_doc();
|
|
if (td == "FV" || td == "NC") spric = 4;
|
|
}
|
|
|
|
TString s; if (spric > 0) s << spric;
|
|
m.set(105, s, TRUE); // Setta il campo spesa-ricavo della riga IVA
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
bool TPrimanota_application::sheet_clifo_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (!suspended_handler(f, k))
|
|
return FALSE;
|
|
|
|
if (k == K_TAB || k == K_ENTER)
|
|
{
|
|
const long codice = atol(f.get());
|
|
if (codice > 0L)
|
|
{
|
|
TMask& m = f.mask();
|
|
const short cid = 100 + (f.dlg() % 100) -1;
|
|
const short gid = cid-1;
|
|
const int conto = m.get_int(cid);
|
|
const int gruppo = m.get_int(gid);
|
|
if (gruppo == 0 && conto == 0)
|
|
{
|
|
TBill c(0, 0, codice, f.dlg() > 300 ? 'F' : 'C');
|
|
m.set(f.dlg()+1, c.descrizione()); // Carica gruppo e conto
|
|
if (c.ok())
|
|
{
|
|
m.set(gid-1, c.tipo() == 'C' ? "C" : "F");
|
|
m.set(gid, c.gruppo());
|
|
m.set(cid, c.conto());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Handlers dei campi della testata
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Handler of the F_NUMREG field on the query mask
|
|
// Certified 99%
|
|
bool TPrimanota_application::num_handler(TMask_field& f, KEY key)
|
|
{
|
|
TMask& m = f.mask();
|
|
const long num = atol(f.get());
|
|
if (key == K_TAB && m.is_running() && num > 0)
|
|
{
|
|
TPrimanota_application& a = app();
|
|
const long max = a._lastreg+1;
|
|
|
|
a._skip_giornale_check = FALSE;
|
|
a._skip_bollato_check = FALSE;
|
|
|
|
if (num < max)
|
|
{
|
|
if (a.find(1))
|
|
{
|
|
const TLocalisamfile& mov = a._rel->lfile();
|
|
bool ok = TRUE;
|
|
|
|
if (mov.get_bool("STAMPATO"))
|
|
{
|
|
ok = yesno_box("Il movimento e' gia' stato stampato sul libro giornale:\n"
|
|
"si desidera continuare ugualmente");
|
|
a._skip_giornale_check = ok;
|
|
}
|
|
|
|
if (ok && mov.get_bool("REGST"))
|
|
{
|
|
ok = yesno_box("Il movimento e' gia' stato stampato sul bollato:\n"
|
|
"si desidera continuare ugualmente");
|
|
a._skip_bollato_check = ok;
|
|
}
|
|
|
|
if (ok && mov.get_bool("INVIATO"))
|
|
{
|
|
ok = yesno_box("Il movimento e' stato inviato ad un'altra contabilita':\n"
|
|
"si desidera continuare ugualmente");
|
|
}
|
|
|
|
if (ok) // Riempie a mano i campi necessari nel caso non sia stato usata la ricerca F9
|
|
{
|
|
m.set(F_DATAREG, mov.get("DATAREG"), TRUE);
|
|
m.set(F_DATACOMP, mov.get("DATACOMP"), TRUE);
|
|
m.set(F_CODCAUS, mov.get("CODCAUS"));
|
|
f.set_focusdirty(FALSE);
|
|
m.stop_run(K_AUTO_ENTER);
|
|
}
|
|
}
|
|
}
|
|
else if (num > max)
|
|
{
|
|
f.set(format("%ld", max));
|
|
return f.error_box("Non e' possibile inserire movimenti superiori al %ld", max);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Handler of the F_CODCAUS field on the query mask
|
|
// Certified 99%
|
|
bool TPrimanota_application::caus_query_handler(TMask_field& f, KEY key)
|
|
{
|
|
const TMask& m = f.mask();
|
|
if (!m.is_running()) return TRUE;
|
|
|
|
if (f.to_check(key))
|
|
{
|
|
const TString cau = f.get();
|
|
const int ann = m.get_int(F_ANNOIVA);
|
|
|
|
const TipoIVA i = app().cau2IVA(cau, ann); // Cerca causale e suo tipo
|
|
if (i != iva_errata)
|
|
{
|
|
const bool ok = suspended_handler(f, key); // Controlla sospensione
|
|
if (ok && key == K_TAB)
|
|
{
|
|
f.set_focusdirty(FALSE);
|
|
f.mask().stop_run(K_INS); // Entra in modo inserimento
|
|
}
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Handler of the F_CODCAUS field on the modify mask
|
|
// Certified 99%
|
|
bool TPrimanota_application::caus_modify_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (f.to_check(key))
|
|
{
|
|
bool ok = suspended_handler(f, key);
|
|
if (!ok) return FALSE;
|
|
|
|
const int ann = f.mask().get_int(F_ANNOIVA);
|
|
const TString cau(f.get());
|
|
const TCausale c(cau, ann);
|
|
if (!c.ok()) return FALSE;
|
|
|
|
ok = app().causale().similar(c);
|
|
if (!ok)
|
|
return FALSE; // L'errore viene gia' segnalato dalla similar
|
|
if (key == K_TAB)
|
|
{
|
|
app().read_caus(cau, ann);
|
|
app().cgs().force_update();
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Handler of the F_DATAREG field
|
|
// Certified 70%
|
|
bool TPrimanota_application::datareg_handler(TMask_field& f, KEY key)
|
|
{
|
|
bool ok = TRUE;
|
|
TMask& m = f.mask();
|
|
|
|
if ((key == K_TAB && m.is_running()) || key == K_ENTER)
|
|
{
|
|
const TDate dr(f.get()); // Data dell'operazione
|
|
if (dr > TDate(TODAY))
|
|
return f.error_box("La data dell'operazione e' superiore quella di sistema");
|
|
|
|
TPrimanota_application& a = app();
|
|
TLibro_giornale& gio = a.giornale();
|
|
|
|
const int ae = a._esercizi.date2esc(dr); // Anno esercizio
|
|
if (ae <= 0)
|
|
return f.error_box("La data dell'operazione non appartiene a nessun esercizio");
|
|
|
|
if (m.query_mode() || gio.year() != ae)
|
|
ok = gio.read(ae);
|
|
else
|
|
ok = TRUE;
|
|
|
|
if (!ok)
|
|
return f.error_box("Non esiste il libro giornale dell'esercizio %d", ae);
|
|
|
|
if (key == K_ENTER || f.focusdirty())
|
|
{
|
|
const long numreg = m.get_long(F_NUMREG);
|
|
const bool error = numreg == 0 || numreg > a._lastreg;
|
|
|
|
if (key != K_ENTER && !a._skip_giornale_check)
|
|
{
|
|
if (dr < gio.last_print())
|
|
{
|
|
f.error_box("La data dell'operazione e' antecedente al %s,\n"
|
|
"ultima stampa del libro giornale dell'esercizio %d",
|
|
gio.last_print().string(), ae);
|
|
if (error) return FALSE;
|
|
}
|
|
if (key == K_TAB && dr < gio.last_reg())
|
|
f.warning_box("La data dell'operazione e' antecedente al %s,\n"
|
|
"ultima registrazione sul libro giornale dell'esercizio %d",
|
|
gio.last_reg().string(), ae);
|
|
}
|
|
|
|
if (m.query_mode())
|
|
a.read_caus(m.get(F_CODCAUS), dr.year());
|
|
|
|
TRegistro& reg = a.causale().reg();
|
|
const TString codreg(reg.name());
|
|
if (codreg.not_empty())
|
|
{
|
|
if (reg.year() != dr.year())
|
|
{
|
|
const bool ok = reg.read(codreg, dr.year());
|
|
if (!ok) return FALSE;
|
|
a.read_caus(NULL, 0);
|
|
if (a.iva() != nessuna_iva)
|
|
m.field(F_CODREG).on_hit();
|
|
}
|
|
|
|
if (!a._skip_bollato_check)
|
|
{
|
|
if (dr < reg.last_print())
|
|
{
|
|
f.error_box("La data dell'operazione e' antecedente al %s,\n"
|
|
"ultima stampa del registro '%s' dell'anno %d",
|
|
reg.last_print().string(), (const char*)codreg, dr.year());
|
|
if (error) return FALSE;
|
|
}
|
|
if (key == K_TAB && dr < reg.last_reg())
|
|
f.warning_box("La data dell'operazione e' antecedente al %s,\n"
|
|
"ultima registrazione sul registro '%s' dell'anno %d",
|
|
reg.last_reg().string(), (const char*)codreg, dr.year());
|
|
}
|
|
|
|
if (reg.iva() != nessuna_iva && a._rel->controlla_liquidazione(dr, reg) == TRUE)
|
|
{
|
|
const char* const mese = itom(dr.month());
|
|
f.warning_box("La liquidazione IVA relativa al mese di %s e' gia' stata calcolata", mese);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
// Handler of the F_DATACOMP field on the modify mask
|
|
// Certified 90%
|
|
bool TPrimanota_application::datacomp_handler(TMask_field& f, KEY key)
|
|
{
|
|
TMask& m = f.mask();
|
|
|
|
if (key == K_TAB || key == K_ENTER)
|
|
{
|
|
const TDate dr(m.get(F_DATAREG)); // Data operazione
|
|
|
|
TString16 datacomp = f.get();
|
|
if (datacomp.empty())
|
|
{
|
|
datacomp = dr.string();
|
|
f.set(datacomp);
|
|
}
|
|
const TDate dc(datacomp); // Data di competenza
|
|
TEsercizi_contabili& esc = app()._esercizi;
|
|
const int ae = esc.date2esc(dc); // Esercizio corrispondente
|
|
|
|
const char* data = "del 74/ter";
|
|
if (f.dlg() == F_DATACOMP)
|
|
{
|
|
m.set(F_ANNOES, ae, TRUE); // Aggiorna anno esercizio in entrambe le pagine
|
|
data = "di competenza";
|
|
}
|
|
|
|
if (ae)
|
|
{
|
|
const int ar = esc.date2esc(dr); // Esercizio in corso
|
|
const int pr = esc.pred(ar); // Esercizio precedente
|
|
if (ae != ar && ae != pr)
|
|
{
|
|
TString e(80);
|
|
e << "La data " << data << " deve appartenere all'esercizio " << ar;
|
|
if (pr > 0) e << " o al " << pr;
|
|
return f.error_box(e);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m.is_running())
|
|
return f.error_box("La data %s non appartiene a nessun esercizio", data);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Handler of the F_DATA74TER field on the modify mask
|
|
// Certified 90%
|
|
bool TPrimanota_application::data74ter_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (!f.to_check(key)) return TRUE;
|
|
bool ok = datacomp_handler(f, key);
|
|
if (ok)
|
|
{
|
|
const TDate d74(f.get());
|
|
const TLibro_giornale& g = app().giornale();
|
|
if (d74 < g.last_print())
|
|
{
|
|
ok = f.error_box("La data per il 74/ter e' antecedente alla data di stampa "
|
|
"del libro giornale dell'esercizio %d", g.year());
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
|
|
bool TPrimanota_application::numdoc_handler(TMask_field& f, KEY key)
|
|
{
|
|
TMask& m = f.mask();
|
|
if (key == K_TAB && f.to_check(key, TRUE) && m.insert_mode() && app().is_saldaconto())
|
|
{
|
|
const TString n = f.get();
|
|
if (n.not_empty() && !app().npart_is_prot()) // Copiare numero documento nel numero partita?
|
|
{
|
|
if (m.field(F_NUMRIF).active() && m.get(F_NUMRIF).blank())
|
|
m.set(F_NUMRIF, n, TRUE);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TPrimanota_application::datadoc_handler(TMask_field& f, KEY key)
|
|
{
|
|
TMask& m = f.mask();
|
|
|
|
if (key == K_TAB && f.to_check(key, TRUE) && app().is_saldaconto())
|
|
{
|
|
const TDate dd(f.get()); // Fattura o nota credito
|
|
if (dd.ok())
|
|
{
|
|
if (m.insert_mode() && m.field(F_ANNORIF).active() && m.get(F_ANNORIF).empty())
|
|
m.set(F_ANNORIF, dd.year()); // copia anno documento
|
|
|
|
TPrimanota_application& a = app();
|
|
if (a.is_fattura())
|
|
{
|
|
if (m.insert_mode())
|
|
{
|
|
a.recalc_scadenze(dd);
|
|
}
|
|
else
|
|
{
|
|
if (a._pag)
|
|
a._pag->set_datadoc(dd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool TPrimanota_application::occas_code_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB)
|
|
{
|
|
const char* code = f.get();
|
|
if (*code)
|
|
{
|
|
TRelation occas(LF_OCCAS);
|
|
occas.curr().put("CFPI", code);
|
|
if (occas.read(_isequal) == NOERR)
|
|
{
|
|
TMask& m = f.mask();
|
|
m.autoload(occas);
|
|
m.send_key(K_TAB, O_COMUNE); // Forza decodifica comuni
|
|
m.send_key(K_TAB, O_COMUNENAS);
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TPrimanota_application::occas_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_SPACE && f.mask().is_running())
|
|
{
|
|
TMask& om = app().occas_mask();
|
|
om.run();
|
|
f.set_focus();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// Crea o aggiorna la riga contabile col totale documento
|
|
// Certified 99%
|
|
void TPrimanota_application::add_cgs_tot(TMask& m)
|
|
{
|
|
const bool corri = causale().corrispettivi();
|
|
const char tipo = corri ? ' ' : app().clifo();
|
|
int gruppo = 0, conto = 0;
|
|
long codice = corri ? 0L : m.get_long(tipo == 'C' ? F_CLIENTE : F_FORNITORE);
|
|
|
|
TSheet_field& ss = cgs();
|
|
const int riga_totale = type2pos('T');
|
|
|
|
// Cerca di preservare il gruppo-conto-sottoconto sulla riga totale
|
|
if (riga_totale >= 0)
|
|
{
|
|
TToken_string& rowt = ss.row(riga_totale);
|
|
gruppo = rowt.get_int(3);
|
|
conto = rowt.get_int();
|
|
if (corri)
|
|
codice = rowt.get_long();
|
|
}
|
|
|
|
TBill nuovo(gruppo, conto, codice, tipo);
|
|
if (!corri && (gruppo == 0 || conto == 0))
|
|
nuovo.find(); // Compila anche gruppo e conto in base al codice clifo
|
|
|
|
if (nuovo.gruppo() == 0 || nuovo.conto() == 0)
|
|
{
|
|
// Se l'utente non ha ancora specificato un conto lo prendo dalla prima riga della causale
|
|
causale().bill(1, nuovo);
|
|
|
|
// Nelle fatture si deve sempre aggiungere il codice clifo (in causale normalmente non c'e')
|
|
if (!corri)
|
|
nuovo.codclifo() = codice;
|
|
}
|
|
|
|
if (riga_totale >= 0)
|
|
{
|
|
TToken_string& row = ss.row(riga_totale);
|
|
const TBill vecchio(row, 2, 0x1);
|
|
if (!vecchio.empty() && nuovo != vecchio) // Se cambio cliente/fornitore
|
|
{
|
|
for (int i = 0; i < ss.items(); i++) if (i != riga_totale)
|
|
{
|
|
TToken_string& r = ss.row(i);
|
|
const TBill tacchia(r, 9, 0x1);
|
|
if (tacchia == vecchio)
|
|
{
|
|
nuovo.add_to(r, 9, 0x3); // Aggiorna contropartite
|
|
ss.force_update(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!_as400)
|
|
{
|
|
// Creazione/Aggiornamento riga totale
|
|
const real tot(m.get(F_TOTALE));
|
|
set_cgs_row(riga_totale, real2imp(tot, 'T'), nuovo, m.get(F_DESCR), 'T');
|
|
}
|
|
|
|
calcola_imp(); // Ricalcola totale IVA
|
|
calcola_saldo(); // Ricalcola sbilanci
|
|
}
|
|
|
|
// Handler of the F_CLIENTE & F_FORNITORE field on the modify mask
|
|
// Certified 99%
|
|
bool TPrimanota_application::clifo_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (!suspended_handler(f, key))
|
|
return FALSE;
|
|
|
|
if (key == K_TAB && f.active())
|
|
{
|
|
TPrimanota_application& a = app();
|
|
TMask& m = f.mask();
|
|
|
|
if (f.focusdirty() && a.is_nota_credito())
|
|
{
|
|
TPartite_array& p = a.partite();
|
|
if (m.edit_mode())
|
|
p.add_numreg(m.get_long(F_NUMREG));
|
|
|
|
const TPartita* game = p.first();
|
|
if (game != NULL && atol(f.get()) != game->conto().codclifo())
|
|
{
|
|
const bool del = f.yesno_box("Si desidera cancellare i pagamenti effettuati?");
|
|
if (!del) // Ripristina codice copiandolo dalla prima partita
|
|
{
|
|
TString cod; cod << game->conto().codclifo();
|
|
f.set(cod);
|
|
return TRUE;
|
|
}
|
|
f.set_dirty(); // yesno_box cleared the dirty flag
|
|
a.notify_cgline_deletion(-1);
|
|
}
|
|
}
|
|
|
|
const char cf = a.clifo();
|
|
const long codice = atol(f.get());
|
|
|
|
if (codice == 0)
|
|
{
|
|
m.hide(F_OCCASEDIT); // Spegni bottone occasionali
|
|
m.show(F_STATOPAIV); // Stato partita IVA
|
|
m.show(cf == 'C' ? F_PIVACLIENTE : F_PIVAFORNITORE); // Partita IVA
|
|
m.show(cf == 'C' ? F_COFICLIENTE : F_COFIFORNITORE); // Codice Fiscale
|
|
a.activate_numrif(TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
TRelation cliforel(LF_CLIFO); cliforel.add(LF_CFVEN, "TIPOCF=TIPOCF|CODCF=CODCF");
|
|
TRectype& clifo = cliforel.curr();
|
|
clifo.put(CLI_TIPOCF, cf);
|
|
clifo.put(CLI_CODCF, codice);
|
|
cliforel.read();
|
|
|
|
if (!m.is_running() || f.dirty())
|
|
{
|
|
a._conto_ricavo.set(clifo.get_int(CLI_GRUPPORIC),
|
|
clifo.get_int(CLI_CONTORIC),
|
|
clifo.get_long(CLI_SOTTOCRIC));
|
|
|
|
const int alleg = clifo.get_int(CLI_ALLEG);
|
|
TEdit_field& upi = m.efield(F_RIEPILOGO);
|
|
upi.check_type(alleg == 3 ? CHECK_REQUIRED : CHECK_NORMAL);
|
|
|
|
if (m.insert_mode() && m.get(F_CODPAG).empty())
|
|
{
|
|
const TString& s = clifo.get(CLI_CODPAG);
|
|
if (s.not_empty())
|
|
{
|
|
TEdit_field& cp = m.efield(F_CODPAG);
|
|
if (cp.active()) // Se il campo F_CODPAG e' attivo
|
|
{
|
|
cp.set(s); // Setta il codice di pagamento sulla maschera
|
|
cp.check(RUNNING_CHECK); // lo decodifica
|
|
cp.on_hit(); // lo ricopia eventualmente a pag.3
|
|
}
|
|
}
|
|
}
|
|
|
|
if (f.focusdirty() && a.is_saldaconto())
|
|
{
|
|
if (m.field(SK_VALUTA).active() && m.get(SK_VALUTA).empty())
|
|
{
|
|
const TString& valuta = clifo.get(CLI_CODVAL);
|
|
if (valuta.not_empty())
|
|
m.set(SK_VALUTA, valuta, TRUE);
|
|
}
|
|
|
|
if (a.is_fattura())
|
|
{
|
|
if (clifo.get(CLI_CODCAB).not_empty())
|
|
{
|
|
m.set(FS_VSABI, clifo.get(CLI_CODABI));
|
|
m.set(FS_VSCAB, clifo.get(CLI_CODCAB));
|
|
m.send_key(K_TAB, FS_VSCAB);
|
|
}
|
|
|
|
const TString& agente = cliforel.curr(LF_CFVEN).get(CLI_CODAG);
|
|
if (agente.not_empty())
|
|
{
|
|
m.set(FS_AGENTE, agente, TRUE);
|
|
m.send_key(K_TAB, FS_AGENTE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const bool occas = clifo.get_bool(CLI_OCCAS);
|
|
m.show(F_OCCASEDIT, occas); // Bottone Dati anagrafici
|
|
m.show(F_STATOPAIV, !occas); // Stato partita IVA
|
|
m.show(cf == 'C' ? F_PIVACLIENTE : F_PIVAFORNITORE, !occas); // Partita IVA
|
|
m.show(cf == 'C' ? F_COFICLIENTE : F_COFIFORNITORE, !occas); // Codice Fiscale
|
|
|
|
if (occas && a.is_fattura() && a.partite().first() != NULL)
|
|
{
|
|
f.warning_box("Attenzione, il saldaconto verra' eliminato!");
|
|
f.set_dirty(); // warning_box cleans the field!
|
|
}
|
|
a.activate_numrif(TRUE);
|
|
|
|
if (f.focusdirty())
|
|
{
|
|
a.add_cgs_tot(m);
|
|
if (occas && a.occas_mask().get(O_CODICE).blank())
|
|
m.send_key(K_SPACE, F_OCCASEDIT); // Lancia maschera occasionali
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
bool TPrimanota_application::IVA2bill(const TCodiceIVA& iva, TBill& bill)
|
|
{
|
|
const TCausale& cau = causale();
|
|
if (!cau.corrispettivi())
|
|
bill = _conto_ricavo;
|
|
return cau.IVA2bill(iva, bill);
|
|
}
|
|
|
|
|
|
// Handler of the F_CODIVA
|
|
// Certified 99%
|
|
bool TPrimanota_application::main_codiva_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.get().not_empty())
|
|
{
|
|
if (!suspended_handler(f, key))
|
|
return FALSE;
|
|
|
|
TPrimanota_application& a = app();
|
|
const real imp(a.ivas().row(1).get(0)); // Se il totale non e' stato spezzato
|
|
if (imp.is_zero())
|
|
{
|
|
TToken_string& row = a.ivas().row(0);
|
|
|
|
TMask& m = f.mask();
|
|
iva_notify(a.ivas(), 0, K_SPACE);
|
|
|
|
const TCodiceIVA iva(f.get());
|
|
const bool corr = a.causale().corrispettivi();
|
|
const bool acq3 = (a.iva() == iva_acquisti) && (row.get_int(2) == 3);
|
|
|
|
real tot = a.totale_documento(); // Calcola totale documento
|
|
real imposta; // Calcola imposta
|
|
if (!corr && !acq3)
|
|
imposta = iva.scorpora(tot);
|
|
|
|
row.add(tot.string(), 0); // imponibile
|
|
row.add(imposta.string(), 3); // imposta
|
|
|
|
if (iva.codice() != row.get(1))
|
|
{
|
|
row.add(iva.codice(), 1); // Aggiorna codice IVA
|
|
TBill bill; // Aggiorna conto della prima riga IVA
|
|
a.IVA2bill(iva, bill);
|
|
bill.add_to(row, 4, 0x7);
|
|
}
|
|
a.ivas().force_update(0);
|
|
|
|
iva_notify(a.ivas(), 0, K_ENTER);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// Riempie i campi valuta a zero in base agli altri
|
|
void TPrimanota_application::gioca_cambi(int force)
|
|
{
|
|
TMask& m = curr_mask();
|
|
if (m.get(SK_VALUTA).empty())
|
|
return;
|
|
|
|
const real totale = m.get(F_TOTALE);
|
|
const real totval = m.get(SK_TOTDOCVAL);
|
|
const real cambio = m.get(SK_CAMBIO);
|
|
|
|
if ( (force == 0x1 || totale.is_zero()) && !(totval.is_zero() || cambio.is_zero()) )
|
|
{
|
|
const TValuta cam(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
|
|
const real new_totale = cam.val2lit(totval);
|
|
if (new_totale != totale)
|
|
m.set(F_TOTALE, new_totale, TRUE);
|
|
}
|
|
|
|
if ( (force == 0x2 || totval.is_zero()) && !(totale.is_zero() || cambio.is_zero()) )
|
|
{
|
|
const TValuta cam(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
|
|
const real new_totval = cam.lit2val(totale);
|
|
if (new_totval != totval)
|
|
m.set(SK_TOTDOCVAL, new_totval, TRUE);
|
|
}
|
|
|
|
if ( (force == 0x4 || cambio.is_zero()) && !(totale.is_zero() || totval.is_zero()) )
|
|
{
|
|
real new_cambio = totale / totval; new_cambio.round(5);
|
|
if (new_cambio != cambio)
|
|
m.set(SK_CAMBIO, new_cambio, TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
// Handler of the F_TOTALE
|
|
// Certified 99%
|
|
bool TPrimanota_application::totdoc_handler(TMask_field& f, KEY key)
|
|
{
|
|
bool ok = TRUE;
|
|
TMask& m = f.mask();
|
|
|
|
if (key == K_TAB && f.focusdirty())
|
|
{
|
|
TPrimanota_application& a = app();
|
|
a.gioca_cambi();
|
|
|
|
if (a.iva() != nessuna_iva)
|
|
{
|
|
a.add_cgs_tot(m);
|
|
if (m.insert_mode()) // Se si e' in inserimento provoca ricalcolo
|
|
m.field(F_CODIVA).on_hit(); // dello sheet iva e delle scadenze
|
|
}
|
|
else
|
|
{
|
|
if (a.is_pagamento())
|
|
a.calcola_saldo();
|
|
}
|
|
}
|
|
|
|
if (key == K_ENTER)
|
|
{
|
|
const real totale(f.get());
|
|
if (totale.is_zero())
|
|
ok = yesno_box("Totale documento nullo: continuare ugualmente?");
|
|
|
|
if (ok)
|
|
{
|
|
const TValuta cambio(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
|
|
if (cambio.in_valuta())
|
|
{
|
|
const real totval(m.get(SK_TOTDOCVAL));
|
|
const real totlit = cambio.val2lit(totval);
|
|
if (totale != totlit)
|
|
ok = yesno_box("Il totale documento in lire dovrebbe essere %s: continuare ugualmente?",
|
|
totlit.string("."));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
bool TPrimanota_application::totdocval_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.focusdirty())
|
|
{
|
|
TPrimanota_application& a = app();
|
|
a.gioca_cambi();
|
|
|
|
TMask& m = f.mask();
|
|
if (a.is_fattura() && m.insert_mode())
|
|
a.set_scadenze(m);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Aggiunge o aggiorna la riga delle ritenute fiscali o sociali
|
|
// Certified 99%
|
|
void TPrimanota_application::add_cgs_rit(bool fiscali)
|
|
{
|
|
if (_as400)
|
|
return;
|
|
|
|
TMask& m = curr_mask();
|
|
const real imp(m.get(fiscali ? F_RITFIS : F_RITSOC)); // Determina importo
|
|
|
|
const char tipo = fiscali ? 'F' : 'S';
|
|
const int pos = type2pos(tipo); // Cerca la riga contabile
|
|
if (pos < 0) // Se non c'e' ...
|
|
{
|
|
if (!imp.is_zero()) // ... e l'importo e' valido
|
|
{ // crea una nuova riga di ritenute
|
|
const int riga = fiscali ? RIGA_RITENUTE_FISCALI : RIGA_RITENUTE_SOCIALI;
|
|
TBill conto; causale().bill(riga, conto);
|
|
const TString desc(causale().desc_agg(riga));
|
|
set_cgs_row(-1, real2imp(imp, tipo), conto, desc, tipo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (imp.is_zero()) // se l'importo e' nullo ...
|
|
reset_cgs_row(pos); // ... azzera la riga contabile
|
|
else // altrimenti ...
|
|
set_cgs_imp(pos, real2imp(imp, tipo)); // ... aggiorna importo
|
|
}
|
|
|
|
if (m.insert_mode())
|
|
m.field(F_CODIVA).on_hit(); // Ricalcola sheet iva e contabile
|
|
else
|
|
app().calcola_saldo(); // Ricalcola solo lo sbilancio
|
|
}
|
|
|
|
// Handler of the F_PROTIVA
|
|
bool TPrimanota_application::protiva_handler(TMask_field& f, KEY key)
|
|
{
|
|
bool ok = TRUE;
|
|
TMask& m = f.mask();
|
|
|
|
if (m.insert_mode())
|
|
{
|
|
if (key == K_ENTER && f.dirty())
|
|
{
|
|
const long protiva = atol(f.get());
|
|
const long protocol = app().causale().reg().protocol() + 1;
|
|
if (protiva != protocol)
|
|
ok = f.yesno_box("Accettare il protocollo IVA fuori sequenza: %ld invece di %ld",
|
|
protiva, protocol);
|
|
|
|
}
|
|
else
|
|
if (key == K_TAB && m.insert_mode() && app().npart_is_prot() &&
|
|
m.field(F_NUMRIF).active() && m.get(F_NUMRIF).blank())
|
|
{
|
|
const TString& piva = f.get();
|
|
if (piva.not_empty())
|
|
m.set(F_NUMRIF, piva, TRUE);
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
|
|
// Handler of the F_RITFIS
|
|
// Certified 99%
|
|
bool TPrimanota_application::ritfis_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.focusdirty())
|
|
app().add_cgs_rit(TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Handler of F_RITSOC
|
|
// Certified 99%
|
|
bool TPrimanota_application::ritsoc_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.focusdirty())
|
|
app().add_cgs_rit(FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
// Handler of F_CORRLIRE
|
|
// Certified 99%
|
|
bool TPrimanota_application::corrlire_handler(TMask_field& f, KEY key)
|
|
{
|
|
TMask& m = f.mask();
|
|
|
|
if (key == K_ENTER && f.get().empty())
|
|
{
|
|
if (m.get(F_CORRVALUTA).not_empty())
|
|
{
|
|
TMask_field& cv = m.field(F_CORRVALUTA);
|
|
cv.set_focusdirty();
|
|
cv.on_hit();
|
|
}
|
|
else
|
|
key = K_F8;
|
|
}
|
|
|
|
if (key == K_F8)
|
|
{
|
|
f.set(m.get(F_IMPONIBILI));
|
|
f.set_dirty();
|
|
m.reset(F_CORRVALUTA);
|
|
key = K_TAB;
|
|
}
|
|
if (key == K_TAB && f.focusdirty())
|
|
{
|
|
if (m.get(F_CORRVALUTA).empty())
|
|
{
|
|
const real cambio = m.get(F_CAMBIOINTRA);
|
|
if (cambio != ZERO && m.get(F_CORRVALUTA).empty())
|
|
{
|
|
real c(f.get());
|
|
c /= cambio;
|
|
m.set(F_CORRVALUTA, c.string());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (key == K_ENTER)
|
|
{
|
|
const TString im(m.get(F_IMPONIBILI));
|
|
const char* cl = f.get();
|
|
if (im != cl)
|
|
warning_box("Il corrispettivo in lire e' diverso dal totale degli imponibili");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Handler of F_CORRVALUTA
|
|
// Certified 99%
|
|
bool TPrimanota_application::corrvaluta_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_TAB && f.focusdirty())
|
|
{
|
|
TMask& m = f.mask();
|
|
if (m.get(F_CORRLIRE).empty())
|
|
{
|
|
const real cambio = m.get(F_CAMBIOINTRA);
|
|
if (cambio != ZERO)
|
|
{
|
|
real c = f.get();
|
|
c *= cambio;
|
|
m.set(F_CORRLIRE, c.string());
|
|
}
|
|
}
|
|
} else
|
|
if (key == K_ENTER && f.get().empty())
|
|
{
|
|
TMask_field& cl = f.mask().field(F_CORRLIRE);
|
|
cl.set_dirty();
|
|
cl.on_hit();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool TPrimanota_application::activate_numrif(bool init_pag)
|
|
{
|
|
CHECK(iva() != nessuna_iva, "Non esiste il numero riferimento in questa maschera!");
|
|
TMask& m = curr_mask();
|
|
|
|
bool shown = is_saldaconto(); // Il numero riferimento esiste
|
|
|
|
if (shown)
|
|
{
|
|
const bool hide = m.get_bool(F_SOLAIVA) || m.field(F_OCCASEDIT).shown();
|
|
if (hide) shown = FALSE;
|
|
}
|
|
|
|
if (shown != m.field(F_NUMRIF).shown())
|
|
{
|
|
m.show(F_ANNORIF, shown);
|
|
m.show(F_NUMRIF, shown);
|
|
if (shown)
|
|
{
|
|
if (m.get(F_ANNORIF).empty())
|
|
{
|
|
m.set(F_ANNORIF, m.get(F_DATADOC).right(4));
|
|
m.set(F_NUMRIF, m.get(_npart_is_prot ? F_PROTIVA : F_NUMDOC));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m.reset(F_ANNORIF);
|
|
m.reset(F_NUMRIF);
|
|
}
|
|
}
|
|
|
|
// Gestione pagina 3
|
|
const bool page = shown && is_fattura() && !m.get(F_NUMRIF).blank();
|
|
if (page != m.page_enabled(2))
|
|
{
|
|
m.enable_page(2, page);
|
|
if (page && init_pag && m.is_running())
|
|
{
|
|
if (m.edit_mode())
|
|
{
|
|
const TString16 dt(m.get(F_DATADOC));
|
|
set_pagamento(NULL, dt); // Reset pagamento
|
|
set_totale_pagamento(TRUE);
|
|
}
|
|
else
|
|
set_scadenze(m); // Inizializza pagamento
|
|
}
|
|
}
|
|
|
|
return shown;
|
|
}
|
|
|
|
// Handler del checkbox di movimento di sola IVA
|
|
bool TPrimanota_application::solaiva_handler(TMask_field& f, KEY key)
|
|
{
|
|
if (key == K_SPACE)
|
|
{
|
|
TMask& m = f.mask();
|
|
TPrimanota_application& a = app();
|
|
|
|
bool anchecg = f.get().empty();
|
|
bool recalcg = anchecg;
|
|
|
|
if (m.is_running() && a.is_fattura())
|
|
{
|
|
const TPartita* game = a.partite().first();
|
|
|
|
if (anchecg)
|
|
{
|
|
if (game != NULL)
|
|
{
|
|
m.set(F_ANNORIF, game->anno());
|
|
m.set(F_NUMRIF, game->numero());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bool del = TRUE;
|
|
if (game != NULL)
|
|
del = f.yesno_box("Si desidera cancellare il saldaconto?");
|
|
if (!del)
|
|
{
|
|
f.reset();
|
|
anchecg = TRUE;
|
|
recalcg = FALSE;
|
|
}
|
|
}
|
|
a.activate_numrif(TRUE);
|
|
}
|
|
|
|
m.show(F_SHEETCG, anchecg);
|
|
m.show(F_DARE, anchecg);
|
|
m.show(F_AVERE, anchecg);
|
|
|
|
if (m.is_running() && recalcg)
|
|
{
|
|
TSheet_field& iva = a.ivas();
|
|
const int righe = iva.items();
|
|
TProgind pi(righe, "Generazione righe contabilita'", FALSE, TRUE, 16);
|
|
|
|
TSheet_field& cg = a.cgs();
|
|
cg.reset();
|
|
|
|
a.add_cgs_tot(m); // Genera totale documento
|
|
if (m.get(F_RITFIS).not_empty()) a.add_cgs_rit(TRUE); // Genera ritenute fiscali
|
|
if (m.get(F_RITSOC).not_empty()) a.add_cgs_rit(FALSE); // Genera ritenute sociali
|
|
|
|
TToken_string oldrow(128);
|
|
for (int i = 0; i < righe; i++)
|
|
{
|
|
TToken_string& r = iva.row(i);
|
|
if (!r.empty_items())
|
|
{
|
|
oldrow = r;
|
|
r = "";
|
|
iva_notify(iva, i, K_SPACE); // Simula la creazione di una nuova riga iva
|
|
r = oldrow;
|
|
iva_notify(iva, i, K_ENTER);
|
|
}
|
|
pi.setstatus(i+1);
|
|
}
|
|
a.fill_sheet(m); // Aggiunge righe vuote
|
|
cg.force_update();
|
|
m.set_focus(); // Ripristina il focus al campo (a causa della progind)
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|