campo-sirio/cg/cg2102.cpp
guy 8d5d6540be cg0600.cpp Tolto file principale _saldi e usato uno temporaneo
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
1996-11-12 15:18:10 +00:00

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;
}