8d5d6540be
cg2.url Aggiunto menu colori cg2100.cpp Aggiunta gestione menu colori cg2100b.uml Accorciata colonna tipo cg2100c.uml Accorciata colonna tipo cg2102.cpp Gestione righe colorate cg2102.h Aggiunte funzioni gestione righe colorate cg3.cpp Aggiunti mastrini a video cg3.url Aggiunto menu dei mastrini a video conto.cpp MEGAFIGATA, velocizzato TBill conto.h Sembra che funzioni bene! git-svn-id: svn://10.65.10.50/trunk@3892 c028cbd2-c16b-5b4b-a496-9718f37d4682
2552 lines
73 KiB
C++
Executable File
2552 lines
73 KiB
C++
Executable File
#include <colors.h>
|
|
#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();
|
|
const int num_rows = cg.items();
|
|
for (int i = 0; i < num_rows; 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();
|
|
const int num_rows = rows.items();
|
|
TBill c; // Conto corrente (Buona questa!)
|
|
for (int i = 0; i < num_rows; 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;
|
|
c.get(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
|
|
{
|
|
TString_array& rows = ivas().rows_array();
|
|
TBill c; // Conto corrente
|
|
int users = 0;
|
|
for (int i = rows.items(); i >= 0 ; i--)
|
|
{
|
|
TToken_string& row = rows.row(i);
|
|
if (!row.empty_items())
|
|
{
|
|
c.get(row, 6, 0x0);
|
|
if (conto == c)
|
|
users++;
|
|
}
|
|
}
|
|
return users;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Gestione sheet CG
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TSheet_field& TPrimanota_application::cgs() const
|
|
{
|
|
const TMask* m = _msk[_iva == nessuna_iva ? 1 : 2];
|
|
CHECK(m, "Null cgs() mask");
|
|
TSheet_field& s = (TSheet_field&)m->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;
|
|
}
|
|
|
|
if (last)
|
|
{
|
|
for (int i = first; i < last; i++)
|
|
cg.disable_cell(n, i);
|
|
|
|
COLOR back_color, fore_color;
|
|
type2colors(tipo, back_color, fore_color);
|
|
cg.set_back_and_fore_color(back_color, fore_color, n);
|
|
cg.force_update(n);
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
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())
|
|
{
|
|
const bool ok = f.yesno_box("La contropartita della riga %d non e' completa:\n"
|
|
"Si desidera continuare ugualmente?", i+1);
|
|
if (!ok) return FALSE;
|
|
}
|
|
|
|
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 TImporto 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 = a.real2imp(real(row.get(0)), 'I'); // Imponibile
|
|
oldiva = a.real2imp(real(row.get(3)), 'I'); // Imposta
|
|
|
|
if (oldiva.is_zero() && cau.corrispettivi()) // In caso di corrispettivi ...
|
|
{
|
|
const TString zanicchi(row.get(1)); // Codice IVA
|
|
const TCodiceIVA i(zanicchi);
|
|
oldiva.valore() = i.scorpora(oldimp.valore()); // ... 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' ? RIGA_IVA_DETRAIBILE : RIGA_IVA_NON_DETRAIBILE;
|
|
TBill c; cau.bill(ri, c);
|
|
if (c.ok())
|
|
{
|
|
const TString80 d(cau.desc_agg(ri));
|
|
oldposiva = a.set_cgs_row(-1, a.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 -= 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 -= 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 (!detrarre && !contoiva.ok()) // Se non c'e' il conto IVA indetraibile ...
|
|
{ // ... somma imponibile e imposta
|
|
imponibile += imposta;
|
|
imposta = 0.0;
|
|
}
|
|
|
|
const TImporto newimp = a.real2imp(imponibile, 'I');
|
|
|
|
// Aggiorna conto sulla riga contabile
|
|
if (newpos < 0)
|
|
{
|
|
if (delimp >= 0)
|
|
{
|
|
a.reset_cgs_row(delimp); // Cancella vecchia riga
|
|
if (deliva > delimp) deliva--;
|
|
}
|
|
|
|
if (conto.ok() && !newimp.is_zero()) // Se c'e' imponibile ...
|
|
{ // crea una nuova riga contabile
|
|
const TString d(cau.desc_agg(2));
|
|
a.set_cgs_row(-1, newimp, conto, d, 'I');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const bool empty = a.add_cgs_imp(newpos, newimp);
|
|
if (empty) // Se la riga si e' azzerata ...
|
|
{ // ... cancellala
|
|
a.reset_cgs_row(newpos);
|
|
newpos = -1;
|
|
}
|
|
}
|
|
oldimp = newimp;
|
|
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
|
|
|
|
const TImporto newiva = a.real2imp(imposta, 'I');
|
|
if (newposiva < 0)
|
|
{
|
|
if (!imposta.is_zero()) // Se c'e' imposta ...
|
|
{ // ... crea nuova riga per l'IVA
|
|
const TString d(cau.desc_agg(ri));
|
|
newposiva = a.set_cgs_row(-1, newiva, contoiva, d, tipod);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const bool empty = a.add_cgs_imp(newposiva, newiva);
|
|
if (empty) // Se l'imposta si e' azzerata ...
|
|
{
|
|
a.reset_cgs_row(newposiva); // ... cancellala
|
|
newposiva = -1;
|
|
}
|
|
}
|
|
|
|
oldiva = newiva;
|
|
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& e = (const TEdit_field&)f;
|
|
const TRectype& piano = e.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();
|
|
if (key == K_TAB /* && m.is_running() */ && !f.empty())
|
|
{
|
|
TPrimanota_application& a = app();
|
|
const long max = a._lastreg+1;
|
|
|
|
a._skip_giornale_check = FALSE;
|
|
a._skip_bollato_check = FALSE;
|
|
|
|
const long num = atol(f.get());
|
|
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);
|
|
return 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);
|
|
return 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();
|
|
|
|
const int ae = a._esercizi.date2esc(dr); // Codice esercizio
|
|
if (ae <= 0)
|
|
return f.error_box("La data dell'operazione non appartiene a nessun esercizio");
|
|
|
|
TLibro_giornale& gio = a.giornale();
|
|
const int ar = dr.year(); // Anno per registri
|
|
if (m.query_mode() || gio.year() != ar)
|
|
{
|
|
ok = gio.read(ar);
|
|
if (!ok)
|
|
return f.error_box("Non esiste il libro giornale del %d", ar);
|
|
}
|
|
else
|
|
ok = TRUE;
|
|
|
|
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 del %d",
|
|
gio.last_print().string(), ar);
|
|
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 del %d",
|
|
gio.last_reg().string(), ar);
|
|
}
|
|
|
|
if (m.query_mode())
|
|
a.read_caus(m.get(F_CODCAUS), ar);
|
|
|
|
TRegistro& reg = a.causale().reg();
|
|
const TString codreg(reg.name());
|
|
if (codreg.not_empty())
|
|
{
|
|
if (reg.year() != ar)
|
|
{
|
|
const bool ok = reg.read(codreg, ar);
|
|
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' del %d",
|
|
reg.last_print().string(), (const char*)codreg, ar);
|
|
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' del %d",
|
|
reg.last_reg().string(), (const char*)codreg, ar);
|
|
}
|
|
|
|
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)
|
|
{
|
|
TMask& m = f.mask();
|
|
if (key == K_TAB && (f.dirty() || !m.is_running()))
|
|
{
|
|
const TString& code = f.get();
|
|
if (code.not_empty())
|
|
{
|
|
TRelation occas(LF_OCCAS);
|
|
occas.curr().put("CFPI", code);
|
|
if (occas.read(_isequal) == NOERR)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
TMask& m = f.mask();
|
|
const bool run = m.is_running();
|
|
|
|
if (key == K_TAB && (f.focusdirty() || !run))
|
|
{
|
|
TPrimanota_application& a = app();
|
|
|
|
bool anchecg = f.get()[0] != 'X';
|
|
bool recalcg = anchecg;
|
|
|
|
if (run && 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 (run && 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;
|
|
}
|
|
|
|
|