campo-sirio/cg/cg2102.cpp

3631 lines
103 KiB
C++
Raw Normal View History

#include <automask.h>
#include <colors.h>
#include <dongle.h>
#include <execp.h>
#include <msksheet.h>
#include <progind.h>
#include <tabutil.h>
#include <toolfld.h>
#include <urldefid.h>
#include <utility.h>
#include <validate.h>
#include "cg2100.h"
#include "cg2102.h"
#include "cg21sld.h"
#include <clifo.h>
#include <cfven.h>
#include <pconti.h>
#include <doc.h>
#include <occas.h>
///////////////////////////////////////////////////////////
// Funzioni di decodifica/calcolo
///////////////////////////////////////////////////////////
// Determina il tipo di una riga contabile in formato TToken_string
char TPrimanota_application::row_type(const TToken_string& s)
{
char t = ' ';
if (s.full())
{
s.get(CG_ROWTYPE%DLG_USER-1, t); // Can't use cgs().cid2index() here!
if (!((t >= 'A' && t <= 'Z')||((t >= '0' && t <= '9')))) // is not alphanumeric?
t = ' ';
}
return t;
}
// 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(FR("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 TString4 _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;
const 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)
{
const int dec = TCurrency::get_firm_dec();
real imposta = imponibile * percent / (percent + CENTO);
imposta.round(dec);
imponibile -= imposta;
return imposta;
}
// Calcola il totale del documento tenendo conto del segno della prima riga
// e di quella delle ritenute sociali sulla causale, ritenute fiscali e reverse charge
real TPrimanota_application::totale_documento()
{
const TMask& m = curr_mask();
real tot = m.get(F_TOTALE); // Legge totale
const real ritfis = m.get(F_RITFIS);
tot += ritfis; // Somma ritenute fiscali
const real ritsoc = m.get(F_RITSOC);
const real revcha = m.get(F_REVCHARGE);
const bool swapt = test_swap(false); // Totale invertito ?
const bool swaps = test_swap(true); // Ritenute sociali invertite ?
if (swapt ^ swaps) // Somma ritenute sociali con segno
{
tot -= ritsoc;
tot -= revcha;
}
else
{
tot += ritsoc;
tot += revcha;
}
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) && !f.empty())
{
const TEdit_field& c = (const TEdit_field&)f;
const TBrowse* b = c.browse();
CHECKD(b, "Can't check suspension of an 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(TR("Il codice '%s' <20> sospeso e non puo' essere utilizzato"), sf);
}
}
return true;
}
///////////////////////////////////////////////////////////
// Funzioni di ricerca
///////////////////////////////////////////////////////////
int TPrimanota_application::type2pos(char tipo)
{
TString_array& a = app().cgs().rows_array();
FOR_EACH_ARRAY_ROW(a, i, s)
{
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& a = app().cgs().rows_array();
FOR_EACH_ARRAY_ROW(a, i, s)
{
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& a = app().cgs().rows_array();
TBill c; // Conto corrente (Buona questa!)
FOR_EACH_ARRAY_ROW(a, i, r)
{
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_EACH_ARRAY_ROW(rows, i, row)
{
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");
return m->sfield(F_SHEETCG);
}
// 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%
Patch level : 2.0 604 Files correlati : cg0.exe cg0500a.msk cg2.exe cg2100s.msk Ricompilazione Demo : [ ] Commento : CM20044 Causale senza tipo documento e con tipo movimento fattura. Mi propone la pagina delle scandenze completamente vuota pur avendo indicato il codice pagamento in testata. La seguente pagina riconosce il pagamento solo se clicco sul botone di reset. CM20045 Causale senza tipo documento e con tipo movimento nota di credito. Mi lascia registrare in prima nota senza portarmi nella gestione partite per chiudere le eventuali fatture.Come faccio ? ATTENZIONE: eliminata possibilita' di creare note di credito senza tipo documento CM20046 Causale senza tipo documento e con tipo movimento fattura o nota di credito. In prima nota non viene mai controllato il totale della testata presente nel campo "Voci per saldaconto" con quanto viene indicato poi nelle righe. CM20047 Causale senza tipo documento e con tipo movimento fattura/nota di credito. Se inserisco una registrazione con tipo movimento nota credito e passo successivamente ad una registrazione con causale con tipo movimento fattura, pur mettendo il codice di pagamento, la procedura non propone la pagina delle scadenze.Questo non accade se esco dalla prima nota dopo la registrazione della nota credito e rientro per registrare la fattura. CM20048 Inserisco un pagamento a fronte di un movimento nato da causale senza tipo documento e tipo movimento fattura. Se in testa indico il numero e la data del documento va tutto bene fino a che non seleziono la rata che intendo pagare, ma quando do conferma nella finestra del pagamento, la procedura mi riporta nella maschera della prima nota senza passare da quella delle partite. Solo cliccando di nuovo su conferma, la procedura mi apre la maschera delle partite. Se non indico i riferimenti del documento sulla testata della registrazione, va tutto bene. git-svn-id: svn://10.65.10.50/trunk@11508 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-10-17 08:28:05 +00:00
TImporto TPrimanota_application::get_cgs_imp(int n) const
{
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 100%
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 100%
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 = false;
switch (row_type)
{
case 'S':
case 'V':
dare = causale().sezione_ritsoc() == 'D';
break;
default:
dare = causale().sezione_clifo() == 'D';
if (row_type != 'T' && row_type != 'F')
dare = !dare;
break;
}
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; // Range di colonne da disabilitare
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
case 'V': // Reverse charge
case '1': // Scissione pagamenti art, 17-ter DPR 633/72
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 o contropartita saldaconto
break;
default:
last = 0; // Solo contabile
break;
}
bool needs_update = false;
if (last > first)
{
for (int i = first; i < last; i++)
cg.disable_cell(n, i);
if (first == 0)
{
for (short cc = CG_CUP; cc <= CG_DCIG; cc++)
cg.disable_cell(n, cc - FIRST_FIELD);
}
needs_update = true;
}
COLOR back_color, fore_color;
type2colors(tipo, back_color, fore_color);
if (back_color != NORMAL_BACK_COLOR || fore_color != NORMAL_COLOR)
{
cg.set_back_and_fore_color(back_color, fore_color, n);
needs_update = true;
}
if (needs_update)
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, const char* cms, const char* fas)
{
TSheet_field& cg = cgs();
if (n < 0) n = cg.first_empty();
TToken_string& row = cg.row(n);
row.cut(0);
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);
TBill contro(irow, 5, 0x3);
if (contro.ok()) // Errore MI3599
row.add(contro.string(0x3));
else
row.add(" | | | | ");
}
else
{
const int pos = type2pos('T');
if (pos >= 0)
{
TBill contro(cg.row(pos), 2, 0x3);
if (contro.ok())
row.add(contro.string(0x3));
}
else
row.add(" | | | | ");
}
row.add(tipo, CG_ROWTYPE-FIRST_FIELD);
disable_cgs_cells(n, tipo);
return n;
}
HIDDEN int compare_rows(const TSortable& o1, const TSortable& o2, void* jolly)
{
// Totale, Rit.Fisc., Rit.Soc., da riga IVA, riga contabile, IVA detr., IVA non detr.
const char* const sort_order = "TFSVI DN1APRC";
const TToken_string& r1 = (const TToken_string&)o1;
const TToken_string& r2 = (const TToken_string&)o2;
const TPrimanota_application& a = *(TPrimanota_application*)jolly;
const char c1 = a.row_type(*r1);
const char c2 = a.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()
{
const bool pagamento = is_pagamento();
const long numreg = curr_mask().get_long(F_NUMREG);
bool rowtypes_present = false;
TSheet_field& s = cgs();
TString_array& rows = s.rows_array();
for (int i = rows.items()-1; i >= 0; i--)
{
TToken_string& r = rows.row(i);
const char rt = row_type(r);
rowtypes_present |= (rt > ' ');
if (can_remove(r))
{
bool ok = true;
if (pagamento && rt == 'K')
{
ok = !partite().utilizzata(numreg, i+1);
if (ok)
cg_notify(s, i, K_DEL);
}
if (ok)
rows.destroy(i, true);
}
}
if (!pagamento && rowtypes_present) // Il pagamento e' gia' ordinato
rows.TArray::sort(compare_rows, &app()); // Pack and sort array
}
bool TPrimanota_application::ci_sono_importi(const TSheet_field& s) const
{
TImporto imp;
FOR_EACH_SHEET_ROW(s, r, riga) if (riga && !riga->empty_items())
{
imp = *riga;
if (!imp.is_zero())
return true;
}
Patch level : 2.0 604 Files correlati : cg0.exe cg0500a.msk cg2.exe cg2100s.msk Ricompilazione Demo : [ ] Commento : CM20044 Causale senza tipo documento e con tipo movimento fattura. Mi propone la pagina delle scandenze completamente vuota pur avendo indicato il codice pagamento in testata. La seguente pagina riconosce il pagamento solo se clicco sul botone di reset. CM20045 Causale senza tipo documento e con tipo movimento nota di credito. Mi lascia registrare in prima nota senza portarmi nella gestione partite per chiudere le eventuali fatture.Come faccio ? ATTENZIONE: eliminata possibilita' di creare note di credito senza tipo documento CM20046 Causale senza tipo documento e con tipo movimento fattura o nota di credito. In prima nota non viene mai controllato il totale della testata presente nel campo "Voci per saldaconto" con quanto viene indicato poi nelle righe. CM20047 Causale senza tipo documento e con tipo movimento fattura/nota di credito. Se inserisco una registrazione con tipo movimento nota credito e passo successivamente ad una registrazione con causale con tipo movimento fattura, pur mettendo il codice di pagamento, la procedura non propone la pagina delle scadenze.Questo non accade se esco dalla prima nota dopo la registrazione della nota credito e rientro per registrare la fattura. CM20048 Inserisco un pagamento a fronte di un movimento nato da causale senza tipo documento e tipo movimento fattura. Se in testa indico il numero e la data del documento va tutto bene fino a che non seleziono la rata che intendo pagare, ma quando do conferma nella finestra del pagamento, la procedura mi riporta nella maschera della prima nota senza passare da quella delle partite. Solo cliccando di nuovo su conferma, la procedura mi apre la maschera delle partite. Se non indico i riferimenti del documento sulla testata della registrazione, va tutto bene. git-svn-id: svn://10.65.10.50/trunk@11508 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-10-17 08:28:05 +00:00
return false;
}
real TPrimanota_application::calcola_saldo() const
{
const bool pag = is_pagamento() && !_as400;
TImporto importo, bilancio, saldaconto;
TSheet_field& cgrows = cgs();
FOR_EACH_SHEET_ROW_BACK(cgrows, i, r)
{
importo = *r;
bilancio += importo;
if (pag)
{
const char tipo = row_type(*r);
if (strchr("ACGKP", tipo) != NULL) // Abbuoni attivi, differenze cambio, spese, ...
saldaconto += importo;
}
}
TMask& m = curr_mask();
bilancio.normalize();
const real& sbil = bilancio.valore();
const char sez = bilancio.is_zero() ? 'Z' : bilancio.sezione();
switch (sez)
{
case 'D':
m.set(F_DARE, sbil);
m.reset(F_AVERE);
break;
case 'A':
m.reset(F_DARE);
m.set(F_AVERE, sbil);
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 sbil;
}
HIDDEN bool imptot_error(const TImporto& imptot, const TImporto& impsal, bool val)
{
TImporto cassa(impsal); cassa.swap_section();
TImporto residuo(imptot); residuo -= cassa; residuo.normalize(imptot.sezione());
bool ok = true;
// if (!residuo.is_zero())
if (abs(residuo.valore()) >= 0.001)
{
TPrimanota_application& a = app();
const TMask& m = a.curr_mask();
TString4 codval;
if (val)
codval = m.get(SK_VALUTA);
TCurrency euro(imptot.valore(), codval);
TString msg(255);
if (is_true_value(codval))
msg << TR("Il totale documento in valuta") << ' ' << codval;
else
msg << TR("Il totale documento inserito");
msg << TR(" <20> ") << euro.string(true) << ' ' << imptot.sezione() << ",\n";
euro.set_num(cassa.valore());
msg << TR("i pagamenti e le spese ammontano a ")
<< euro.string(true) << ' ' << cassa.sezione() << ",\n";
euro.set_num(residuo.valore());
msg << TR("per cui il residuo <20> ") << euro.string(true);
if (impsal.is_zero())
{
/* fastidioso per Pragma
msg << TR("\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 TCurrency saldo(a.calcola_saldo());
if (!saldo.is_zero())
{
const char* ss = saldo.string(true);
if (*ss == '-') ss++;
const TRectype& rec = cache().get("%VAL", TCurrency::get_firm_val());
const char* name = rec.get("S0");
return f.error_box(FR("Il movimento <20> sbilanciato di %s %s."), ss, name);
}
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.insert_mode() ? NUMREG_PROVVISORIO : m.get_long(F_NUMREG);
const bool in_valuta = is_true_value(m.get(SK_VALUTA));
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())
{
TBill c(r, 2, 0x1);
if (!c.ok())
return f.error_box(FR("Il conto della riga %d non e' completo"), i+1);
if (m.insert_mode() && c.sospeso())
return f.error_box(FR("Il conto della riga %d e' sospeso"), i+1);
TBill co(r, 10, 0x0);
if (!co.empty() && !co.ok())
{
const bool ok = f.yesno_box(FR("La contropartita della riga %d non e' completa:\n"
"Si desidera continuare ugualmente?"), i+1);
if (!ok) return false;
}
if (app().is_transaction())
{
// Controlla esistenza conti nelle transazioni (visto che non c'e' controllo in inserimento)
if (!c.find())
return f.error_box("Il conto della riga %d non esiste", i+1);
if (!co.empty() && !co.find())
return f.error_box("Il conto di contropartita della riga %d non esiste", i+1);
}
empty = false;
if (paga || nota)
{
const char tipo = row_type(r);
if (tipo == 'K' || tipo == 'T' || a._as400)
{
const int currig = i+1;
const TImporto speso = a.partite().importo_speso(numreg, currig);
bool errato = importo != speso;
if (errato && a._as400 && speso.is_zero())
errato = false;
if (nota && errato && speso.is_zero())
{
const int annorif = m.get_int(F_ANNORIF);
const TString& numrif = m.get(F_NUMRIF);
if (annorif > 0 && !numrif.blank() &&
yesno_box(FR("Si desidera generare automaticamente la partita %d %s?"),
annorif, (const char*)numrif))
{
const TBill bill(r, 2, 0x1);
errato = !a.crea_partita(bill, annorif, numrif, currig, importo);
}
}
if (errato)
{
TString msg(128);
const TCurrency euro(speso.valore());
msg.format("L'importo sul saldaconto della riga %d <20> %s", currig, (const char*)euro.string(true));
if (!speso.is_zero())
msg << (speso.sezione() == 'A' ? TR(" Avere") : TR(" Dare"));
bool ok = false;
if (m.edit_mode() && speso.is_zero())
{
msg << TR("\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)
{
if (tipo == 'G') // Le spese non si trovano sul saldaconto
{
const TExchange cam(m.get(SK_VALUTA), m.get_real(SK_CAMBIO));
TCurrency spe(importo.valore()); spe.change_value(cam);
const TImporto imp_spe(importo.sezione(), spe.get_num());
saldaconto_val += imp_spe;
} else
if (tipo == 'K' || tipo == 'T')
saldaconto_val += a.partite().importo_speso(numreg, i+1, true, 0x1);
}
}
}
}
}
if (empty)
return f.error_box(TR("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;
Patch level : 2.0 604 Files correlati : cg0.exe cg0500a.msk cg2.exe cg2100s.msk Ricompilazione Demo : [ ] Commento : CM20044 Causale senza tipo documento e con tipo movimento fattura. Mi propone la pagina delle scandenze completamente vuota pur avendo indicato il codice pagamento in testata. La seguente pagina riconosce il pagamento solo se clicco sul botone di reset. CM20045 Causale senza tipo documento e con tipo movimento nota di credito. Mi lascia registrare in prima nota senza portarmi nella gestione partite per chiudere le eventuali fatture.Come faccio ? ATTENZIONE: eliminata possibilita' di creare note di credito senza tipo documento CM20046 Causale senza tipo documento e con tipo movimento fattura o nota di credito. In prima nota non viene mai controllato il totale della testata presente nel campo "Voci per saldaconto" con quanto viene indicato poi nelle righe. CM20047 Causale senza tipo documento e con tipo movimento fattura/nota di credito. Se inserisco una registrazione con tipo movimento nota credito e passo successivamente ad una registrazione con causale con tipo movimento fattura, pur mettendo il codice di pagamento, la procedura non propone la pagina delle scadenze.Questo non accade se esco dalla prima nota dopo la registrazione della nota credito e rientro per registrare la fattura. CM20048 Inserisco un pagamento a fronte di un movimento nato da causale senza tipo documento e tipo movimento fattura. Se in testa indico il numero e la data del documento va tutto bene fino a che non seleziono la rata che intendo pagare, ma quando do conferma nella finestra del pagamento, la procedura mi riporta nella maschera della prima nota senza passare da quella delle partite. Solo cliccando di nuovo su conferma, la procedura mi apre la maschera delle partite. Se non indico i riferimenti del documento sulla testata della registrazione, va tutto bene. git-svn-id: svn://10.65.10.50/trunk@11508 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-10-17 08:28:05 +00:00
const int riga_cf = a.cerca_conto_cf(contocf);
if (riga_cf < 0)
{
TString msg(80); msg = TR("Non esiste una riga contabile riferita al ");
msg << (contocf.tipo() == 'C' ? TR("cliente") : TR("fornitore")) << ' ';
msg << contocf.codclifo() << ":\n";
if (m.edit_mode())
{
msg << TR("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 << TR("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;
TWait_cursor hourglass;
TImporto importo; importo = row;
const bool causale_ok = causale().codice()[0] > ' ';
// Se la seconda riga e' vuota la genero completamente dalla prima
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(0);
}
}
if (contro.ok())
{
importo.swap_section(); // Inverto la sezione D/A
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;
int i;
for (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 ...
{
long sotto = rowi.get_long(12);
if (sotto == 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 long sotto = row.get_long(12);
if (sotto == 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);
long sotto = first.get_long(12);
if (sotto == 0) // Se la prima riga non ha contropartita ...
{
conto.add_to(first, 9, 0x3); // ... copiaci la mia partita
cg.force_update(first_not_empty);
}
sotto = row.get_long(12);
if (sotto == 0) // Se non ho contropartita ...
{
TBill contro(first, 2, 0x3); // ... copiala dalla prima riga
contro.add_to(row, 9, 0x3);
cg.force_update(r);
}
}
}
}
int TPrimanota_application::crea_somma_spese(TImporto& imp)
{
TBill cassa; causale().bill(2, cassa);
const TString 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;
}
void TPrimanota_application::update_saldo_riga(int r)
{
TMask& m = curr_mask();
if (m.id2pos(F_SHEETCG) < 0)
return;
TSheet_field& sheet = m.sfield(F_SHEETCG);
TToken_string row = sheet.row(r);
TBill bill; bill.get(row, 2, 0x1);
if (bill.ok())
{
const int annoes = m.get_int(F_ANNOES);
// Legge il saldo finale del conto
TBalance bilancio;
bilancio.read(bill, annoes, false, false);
TImporto saldo = bilancio.saldo_finale();
// Sottrae (somma algebricamente) il valore iniziale del conto
const TConto* conto = _saldi.find(bill, annoes);
if (conto != NULL)
{
saldo += TImporto('D', conto->dare());
saldo += TImporto('A', conto->avere());
}
// Somma l'importo delle singole righe con quel conto
for (int i = sheet.items()-1; i >= 0; i--)
{
row = sheet.row(i);
if (!row.empty_items())
{
TBill zio; zio.get(row, 2, 0x1);
if (zio == bill)
{
TImporto da; da = row;
saldo += da;
}
}
}
TString80 s; // Stringa di lavoro
// Trasforma il saldo in stringa
saldo.normalize();
if (!saldo.is_zero())
{
const TCurrency imp = saldo.valore();
s = imp.string(true);
s << ' ' << saldo.sezione();
}
bill.set(m, F_GRUPPO, F_CONTO, F_SOTTOCONTO); // Stampa conto
m.set(F_SALDOCONTO, s); // Stampa saldo
// Controlla se il conto ha attivato il controllo del segno
s = bill.string(); // Chiave del sottoconto da controllare
if (bill.tipo() > ' ') // Per i clienti/fornitori devo controllare il solo gruppo/conto
{
const int pipe = s.rfind('|');
s.cut(pipe);
}
const TRectype& pcon = cache().get(LF_PCON, s);
const char sez = pcon.get_char(PCN_SEZSALDI);
bool red = false;
if (sez > ' ' && !saldo.is_zero()) // Il conto ha impostato il controllo della sezione!
red = sez != saldo.sezione();
// Scrive in nero o rosso la parola Saldo
s = TR("Saldo");
if (red)
{
s.upper();
s.insert("@b$[r]");
}
m.field(F_SALDOCONTO).set_prompt(s);
}
}
bool TPrimanota_application::cg_notify(TSheet_field& cg, int r, KEY k)
{
static TImporto old_spesa;
static bool delete_l = false;
static bool selecting = 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
}
if (k == K_INS) // La riga non esiste ancora
return true;
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;
else
old_spesa.valore() = ZERO;
break;
case K_TAB:
if (!selecting)
{
TMask& sm = cg.sheet_mask();
sm.enable(DLG_DELREC, tipo <= ' ' || tipo == 'K' || tipo == 'G');
sm.enable(CG_RATEO, tipo <= ' ');
sm.enable(CG_RISCONTO, tipo <= ' ');
if (row.empty_items())
{
selecting = true;
cg.select(r, 1); // Vado alla prima colonna delle righe vuote
selecting = false;
}
a.update_saldo_riga(r);
}
break;
case K_DEL:
if (tipo == 'G')
{
if (old_spesa.is_zero())
old_spesa = row;
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 TString desc(a.causale().desc_agg(k));
const char sez = a.causale().sezione(k);
const real imp = cg.mask().get_real(K_RESIDUO);
TImporto importo(sez, imp); importo.normalize();
if (tipo == 'G')
{
const char sezbanca = a.causale().sezione(2);
if (sezbanca == sez)
importo.swap_section();
}
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.post_select(i);
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();
}
}
cg.check_row(r);
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();
const int pos = cg.cid2index(CG_DESCR);
const TFixed_string old = cg.row(first).get(pos);
if (old.blank() || f.get().find(old) >= 0)
{
cg.row(first).add(f.get(), pos);
cg.force_update(first);
}
}
}
}
if (k == K_ENTER && f.get().empty())
{
if (f.mask().get(F_CODCAUS).empty())
return f.error_box(TR("La descrizione del documento <20> necessaria in assenza 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();
TMask& m = f.mask();
if (k == K_F8 && a.is_pagamento())
{
const TMask& cm = a.curr_mask();
const long numreg = cm.insert_mode() ? NUMREG_PROVVISORIO : cm.get_long(F_NUMREG);
const TImporto speso = a.partite().importo_speso(numreg, currig+1);
const char* ss = speso.valore().string();
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
a.update_saldo_riga(currig);
}
}
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;
m.reset(id); // Aggiorna maschera e ...
row.add("", id - CG_DARE); // ... riga dello sheet
}
if (!m.is_running())
{
a.calcola_saldo(); // Aggiorna saldo e residuo
a.update_saldo_riga(currig);
}
}
if (k == K_ENTER && f.dirty() && m.is_running())
{
a.calcola_saldo(); // Aggiorna saldo e residuo
a.update_saldo_riga(currig);
}
return true;
}
TSheet_field& TPrimanota_application::pags() const
{
CHECK(is_fattura(), "Can't use rate sheet without a fattura");
TMask& m = *_msk[iva() == nessuna_iva ? 1 : 2];
return m.sfield(FS_RATESHEET);
}
///////////////////////////////////////////////////////////
// Gestione sheet IVA
///////////////////////////////////////////////////////////
// Ritorna lo sheet delle righe IVA
// Certified 100%
TSheet_field& TPrimanota_application::ivas() const
{
TSheet_field& s = _msk[2]->sfield(F_SHEETIVA);
return s;
}
// Gestione del campo imponibile sullo sheet iva
// Certified 99%
bool TPrimanota_application::imponibile_handler(TMask_field& f, KEY key)
{
if (key == K_TAB && f.dirty())
{
TMask& m = f.mask();
TString4 iva(m.get(102));
if (iva.blank())
{
iva = app().curr_mask().get(F_CODIVA);
if (iva.not_empty())
m.set(102, iva, true);
}
if (iva.not_empty() && !app().causale().corrispettivi())
{
const real& percent = cod2IVA(m);
const real imponibile(f.get());
const int dec = TCurrency::get_firm_dec();
real imposta;
if (dec == 0) // Siamo in ancora in LIRE!
{
imposta = abs(imponibile) * percent / CENTO;
imposta.ceil();
if (imponibile.sign() < 0) imposta = -imposta;
}
else
{
imposta = imponibile * percent / CENTO;
imposta.round(dec);
}
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();
const TCodiceIVA iva(f.get());
if (m.get_int(107) == 0)
{
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());
}
if (app().iva() == iva_acquisti)
{
const int det = iva.detraibilita();
if (det > 0)
m.set(103, det);
}
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(TR("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& m = f.mask();
TMask_field& ci = m.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)
{
TMask& m = f.mask();
if ((key == K_ENTER || key == K_TAB) && f.dirty())
{
const real imponibile(m.get(101));
const real percent = app().causale().corrispettivi() ? ZERO : cod2IVA(m);
const int dec = TCurrency::get_firm_dec();
real imposta;
if (dec == 0)
{
imposta = abs(imponibile) * percent / CENTO;
imposta.ceil();
if (imponibile.sign() < 0) imposta = -imposta;
}
else
{
imposta = imponibile * percent / CENTO;
imposta.round(dec);
}
const real val(f.get());
if (val != imposta)
{
const TCurrency euro(imposta);
f.warning_box(FR("L'imposta dovrebbe essere %s"), euro.string(true));
}
} else
if (key == K_F8)
{
real imposta(f.get());
if (imposta.is_zero())
{
real imponibile(m.get(101));
const real& percent = cod2IVA(m);
imposta = scorpora(imponibile, percent);
m.set(101, imponibile);
f.set(imposta.string());
}
else
f.warning_box(TR("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_EACH_ARRAY_ROW(rows, r, row) if (!row->empty_items())
{
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 righe 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.is_zero()) continue;
const real imposta(r.get(3));
if (!imposta.is_zero()) continue;
rows.destroy(i, false);
}
rows.pack(); // Pack array
}
int TPrimanota_application::get_importi_iva(const TToken_string& row,
real& imp_det, real& iva_det,
real& imp_ind, real& iva_ind)
{
real imptot; row.get(0, imptot); // Importo scritto nella riga iva
TString4 zanicchi; row.get(1, zanicchi); // Codice IVA
TString4 codind; row.get(2, codind); // Codice indetraibilit<69>
real ivatot; row.get(3, ivatot); // Imposta scritta nella riga iva
int annodoc = app()._msk[2]->get_date(F_DATADOC).year();
if (annodoc <= 0)
{
annodoc = app()._msk[2]->get_date(F_DATAREG).year();
if (annodoc <= 0)
annodoc = TDate(TODAY).year();
}
const TCausale& caus = app().causale();
const TMovimentoPN& mov = (const TMovimentoPN&)*app().get_relation();
return mov.analizza_riga_IVA(imptot, ivatot, caus, annodoc, zanicchi, codind,
imp_det, iva_det, imp_ind, iva_ind);
}
// Certified 50%
bool TPrimanota_application::iva_notify(TSheet_field& iva, int r, KEY k)
{
static int oldpos[2],oldposiva[2];
static TImporto oldimp[2], oldiva[2];
static bool selecting = false;
TPrimanota_application& a = app();
if (a._as400)
return true;
if (k == K_INS || k == K_CTRL+K_DEL)
return true;
TToken_string& row = iva.row(r);
const TCausale& cau = a.causale();
if (k == K_TAB)
{
if (!selecting && row.empty_items())
{
selecting = true;
iva.select(r, 1); // Vado alla prima colonna delle righe vuote
selecting = false;
}
return true;
}
if (k == K_SPACE)
{
real imp_det, iva_det, imp_ind, iva_ind;
get_importi_iva(row, imp_det, iva_det, imp_ind, iva_ind);
for (int d = 0; d < 2; d++)
{
const char tipod = d ? 'D' : 'N';
oldimp[d] = a.real2imp(d ? imp_det : imp_ind, 'I'); // Imponibile
oldiva[d] = a.real2imp(d ? iva_det : iva_ind, tipod); // Imposta
oldposiva[d] = type2pos(tipod);
if (oldposiva[d] < 0 && !oldiva[d].is_zero())
{
TBill c;
int ri = 0;
if (d)
{
if (iva.mask().get_bool(F_LIQDIFF))
cau.bill(ri = RIGA_IVA_DIFFERITA, c); else
if (iva.mask().get_bool(F_IVAXCASSA))
cau.bill(ri = RIGA_IVA_PER_CASSA, c);
if (!c.ok())
cau.bill(ri = RIGA_IVA_DETRAIBILE, c);
}
else
cau.bill(ri = RIGA_IVA_NON_DETRAIBILE, c);
if (c.ok())
{
const TString80 desc(cau.desc_agg(ri));
oldposiva[d] = a.set_cgs_row(-1, a.real2imp(ZERO, 'I'), c, desc, tipod);
}
}
TBill oldconto(row, 6);
if (oldconto.ok())
{
oldpos[d] = bill2pos(oldconto, 'I');
if (oldpos[d] < 0)
{
const TString desc(cau.desc_agg(2));
oldpos[d] = a.set_cgs_row(-1, a.real2imp(ZERO, 'I'), oldconto, desc, 'I');
}
}
else
oldpos[d] = -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)
{
real imp_det, iva_det, imp_ind, iva_ind;
get_importi_iva(row, imp_det, iva_det, imp_ind, iva_ind);
for (int d = 0; d < 2; d++)
{
const real imponibile = d ? imp_det : imp_ind;
const real imposta = d ? iva_det : iva_ind;
int delimp = -1, deliva = -1; // Eventuali righe contabili da cancellare
if (oldpos[d] >= 0) // Se il conto esisteva anche prima ...
{ // sottrai il vecchio imponibile
TImporto i(a.get_cgs_imp(oldpos[d]));
i -= oldimp[d];
i.normalize();
a.set_cgs_imp(oldpos[d], i);
if (i.is_zero())
delimp = oldpos[d];
}
if (oldposiva[d] >= 0) // Se conto IVA esisteva anche prima ...
{ // sottrai la vecchia imposta
TImporto i(a.get_cgs_imp(oldposiva[d]));
i -= oldiva[d];
i.normalize();
a.set_cgs_imp(oldposiva[d], i);
if (i.is_zero())
deliva = oldposiva[d];
}
TBill conto(row, 6);
int newpos = bill2pos(conto, 'I'); // Riga in cui andra' l'imponibile
TImporto newimp = a.real2imp(imponibile, 'I');
newimp.normalize();
// Aggiorna conto sulla riga contabile
if (newpos < 0)
{
TString saved_descr;
if (delimp >= 0)
{
TSheet_field& s = a.cgs();
saved_descr = s.row(delimp).get(8); // Memorizza vecchia descrizione
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
if (saved_descr.blank())
saved_descr = cau.desc_agg(2);
newpos = a.set_cgs_row(-1, newimp, conto, saved_descr, '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;
}
else
{
if (delimp >= 0 && delimp != newpos)
{
a.reset_cgs_row(delimp); // Cancella vecchia riga
if (deliva > delimp) deliva--;
}
}
}
oldimp[d] = newimp;
oldpos[d] = newpos;
// Aggiorna conto IVA sulla riga contabile
const char tipod = d ? '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
TImporto newiva = a.real2imp(imposta, 'I');
newiva.normalize();
if (newposiva < 0)
{
if (!imposta.is_zero()) // Se c'e' imposta ...
{ // ... crea nuova riga per l'IVA
TBill contoiva;
int ri = 0;
if (d)
{
if (iva.mask().get_bool(F_LIQDIFF))
cau.bill(ri = RIGA_IVA_DIFFERITA, contoiva); else
if (iva.mask().get_bool(F_IVAXCASSA))
cau.bill(ri = RIGA_IVA_PER_CASSA, contoiva);
if (!contoiva.ok())
cau.bill(ri = RIGA_IVA_DETRAIBILE, contoiva);
}
else
cau.bill(ri = RIGA_IVA_NON_DETRAIBILE, contoiva);
const TString desc(cau.desc_agg(ri));
cau.bill(ri, contoiva);
newposiva = a.set_cgs_row(-1, newiva, contoiva, desc, 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[d] = newiva;
oldposiva[d] = newposiva;
} // for (int d = 0; d < 2; d++)
TMask& m = a.curr_mask();
if (m.get_int(F_ANNOIVA) >= 2015 && a.clifo() == 'C') // Controllo split-payment
{
const int r_norm = type2pos('D');
const int r_split = type2pos('1');
const bool split_needed = r_norm >= 0 && a.is_split_payment();
if (split_needed)
{
TImporto imp_split = a.get_cgs_imp(r_norm); imp_split.swap_section();
if (r_split < 0)
{
TToken_string row_norm = a.cgs().row(r_norm);
TBill iva_split(row_norm, 3);
const char* desc = TR("IVA art. 17-ter D.P.R. 633/1972)");
a.set_cgs_row(-1, imp_split, iva_split, desc, '1');
}
else
a.set_cgs_imp(r_split, imp_split);
}
else
{
if (r_split >= 0)
a.reset_cgs_row(r_split);
}
}
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 (m.insert_mode() && a.is_fattura())
{
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.eur2val(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));
pimposta.round(pag.round(inv));
real pimponibile(pag.imponibile(inv));
pimponibile.round(pag.round(inv));
if (pimposta != imposta || pimponibile != imponibile)
a.set_scadenze(m); // Ricalcola rate
}
}
return true;
}
// Handler dello sheet
// Certified 99%
bool TPrimanota_application::iva_handler(TMask_field& f, KEY k)
{
if ((k == K_TAB && !f.mask().is_running()) || k == K_ENTER)
{
const TCurrency imp(app().calcola_imp());
if (k == K_ENTER)
{
const TCurrency tot(app().totale_documento());
if (imp != tot)
{
const TString t = tot.string(true);
const TString i = imp.string(true);
return error_box(FR("La somma del totale documento e delle ritenute (%s) <20> 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())
{
const TFixed_string codiva = row.get(1);
if (codiva.blank())
return error_box(FR("Il codice IVA della riga %d <20> obbligatorio"), i+1);
TBill c(row, 5, 0x1);
if (!c.ok() || !c.find())
return error_box(FR("Il conto della riga iva %d <20> 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' ? TR("clienti") : TR("fornitori");
ok = f.error_box(FR("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;
TMask& m = f.mask();
if (key == K_TAB && f.dirty())
{
const TEdit_field& e = (const TEdit_field&)f;
const TRectype& piano = e.browse()->cursor()->curr();
int spric = piano.get_int(PCN_TIPOSPRIC);
if (app().iva() == iva_vendite)
{
if (spric == 2 || spric == 3)
{
const TCausale& caus = app().causale();
const TString& td = caus.tipo_doc();
if (td == "FV" || td == "NC" || td == "ND")
spric = 4;
}
}
TString16 s; if (spric > 0) s << spric;
m.set(105, s, true); // Setta il campo spesa-ricavo della riga IVA
}
return true;
}
bool TPrimanota_application::cg_sottoconto_handler(TMask_field& f, KEY k)
{
if (!suspended_handler(f, k))
return false;
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 ((k == K_TAB && f.focusdirty()) || (gruppo == 0 && conto == 0))
{
TBill c(0, 0, codice, f.dlg() > 300 ? 'F' : 'C');
c.find(); // 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;
}
void TPrimanota_application::link_mastrino(const TBill& bill) const
{
if (bill.ok())
{
TPrimanota_application& a = app();
const TMask& cm = a.curr_mask();
int anno = cm.get_int(F_ANNOES);
if (anno <= 0)
{
TDate date = cm.get(F_DATACOMP);
if (!date.ok())
{
date = cm.get_date(F_DATAREG);
if (!date.ok())
date = TDate(TODAY);
}
anno = a._esercizi.date2esc(date);
}
TFilename ininame; ininame.tempdir(); ininame.add("mastrino.ini");
if (anno > 0)
{
TConfig ini(ininame, "Transaction");
ini.set("Action", "Modify");
ini.set_paragraph("24");
ini.set(RMV_ANNOES, anno);
const char tipo[2] = { bill.tipo(), '\0' };
ini.set(RMV_TIPOC, tipo); // Non esiste la TConfig::set(const char* name, char value);
ini.set(RMV_GRUPPO, bill.gruppo());
ini.set(RMV_CONTO, bill.conto());
ini.set(RMV_SOTTOCONTO, bill.sottoconto());
}
if (ininame.exist())
{
TString cmd;
cmd << "cg3 -5 -i" << ininame;
TExternal_app app(cmd);
app.run();
ininame.fremove();
}
}
}
bool TPrimanota_application::mastrino_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
const TMask& m = f.mask();
TBill bill; bill.get(m, F_GRUPPO, F_CONTO, F_SOTTOCONTO);
app().link_mastrino(bill);
}
return true;
}
bool TPrimanota_application::sheet_mastrino_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
const TMask& m = f.mask();
const char tipo = m.get(CG_TIPO)[0];
const short id_sotto = CG_SOTTOCONTO + (tipo <= ' ' ? 0 : (tipo == 'C' ? 100 : 200));
TBill bill; bill.get(m, CG_GRUPPO, CG_CONTO, id_sotto, CG_TIPO);
app().link_mastrino(bill);
}
return true;
}
class TRR_mask : public TAutomask
{
bool _rateo;
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
bool test_date(TOperable_field& d, int signum);
void notify(TSheet_field& s, int row, KEY k) const;
public:
bool split_row(TSheet_field& s);
TRR_mask(bool is_rateo);
};
void TRR_mask::notify(TSheet_field& s, int row, KEY k) const
{
if (s.dlg() == F_SHEETIVA)
app().iva_notify(s, row, k);
else
app().cg_notify(s, row, k);
}
bool TRR_mask::test_date(TOperable_field& d, int signum)
{
const TDate date = d.get();
if (!date.ok())
return error_box(TR("Data non valida"));
const int codes = app().curr_mask().get_int(F_ANNOES);
TEsercizi_contabili esc;
TDate inies, fines;
if (!esc.code2range(codes, inies, fines))
return error_box(TR("E' necessario specificare una esercizio valido"));
if (signum < 0 && date >= inies)
return error_box(FR("La data deve precedere il %s"), inies.stringa());
if (signum == 0 && (date < inies || date > fines))
return error_box(FR("La data deve appartenere all'esercizio %d"), codes);
if (signum > 0 && date <= fines)
return error_box(FR("La data deve seguire il %s"), fines.stringa());
return true;
}
bool TRR_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
bool ok = true;
switch (o.dlg())
{
case 101:
if (e == fe_modify || e == fe_close)
ok = test_date(o, _rateo ? 0 : -1);
break;
case 102:
if (e == fe_modify || e == fe_close)
ok = test_date(o, _rateo ? +1 : 0);
break;
default:
break;
}
return ok;
}
bool TRR_mask::split_row(TSheet_field& s)
{
const int sel = s.selected();
CHECKD(sel >= 0 && sel < s.items(), "Bad selection:", sel);
TMask& main_mask = s.mask();
TMask& row_mask = s.sheet_mask();
TEsercizi_contabili esc;
const int codes = main_mask.get_int(F_ANNOES);
TDate inies, fines;
if (!esc.code2range(codes, inies, fines))
return error_box(TR("Specificare una data di competenza per il movimento"));
const TDate dataini = get_date(101), datafin = get_date(102);
const real tot_range = datafin - dataini + 1;
const real in_range = (_rateo ? (fines-dataini) : (datafin-inies)) + 1;
const real out_range = tot_range - in_range;
const bool iva_sheet = s.dlg() == F_SHEETIVA;
const short col1 = iva_sheet ? IVA_IMPONIBILE : CG_DARE;
const short col2 = iva_sheet ? IVA_IMPOSTA : CG_AVERE;
const short col3 = iva_sheet ? IVA_GRUPPO : CG_GRUPPO;
const real old_imp1 = row_mask.get(col1);
const real old_imp2 = row_mask.get(col2);
real new_imp1[2], new_imp2[2];
new_imp1[0] = real(old_imp1 * in_range / tot_range).round(2);
new_imp2[0] = real(old_imp2 * in_range / tot_range).round(2);
new_imp1[1] = old_imp1 - new_imp1[0];
new_imp2[1] = old_imp2 - new_imp2[0];
for (int i = 0; i < 2; i++)
{
TToken_string& new_row = s.row(-1);
const int new_sel = s.rows_array().find(new_row);
notify(s, new_sel, K_SPACE); // Notifica l'intenzione di modificare i valori
row_mask.set(col1, new_imp1[i]);
row_mask.set(col2, new_imp2[i]);
if (i == 1)
{
// Utilizza i conti scritti nei paramentri ditta
TConfig ini(CONFIG_DITTA, "cg");
row_mask.reset(col3-1); // Forza conto normale
if (_rateo)
{
row_mask.set(col3+0, ini.get("RateiG"));
row_mask.set(col3+1, ini.get("RateiC"));
row_mask.set(col3+2, ini.get("RateiS"), 0x2);
}
else
{
row_mask.set(col3+0, ini.get("RiscontiG"));
row_mask.set(col3+1, ini.get("RiscontiC"));
row_mask.set(col3+2, ini.get("RiscontiS"), 0x2);
}
}
// Trasferisce tutta la maschera nella rispettiva riga dello sheet
FOR_EACH_MASK_FIELD(row_mask, j, f) if (f->shown() && f->dlg() > DLG_USER)
new_row.add(f->get(), s.cid2index(f->dlg()));
notify(s, new_sel, K_ENTER); // Notifica l'avvenuta modifica dei valori
}
notify(s, sel, K_SPACE); // Riposiziona selezione sulla riga corrente da cancellare
return true;
}
TRR_mask::TRR_mask(bool is_rateo)
: TAutomask(is_rateo ? TR("Rateo") : TR("Risconto"), 1, 24, 4), _rateo(is_rateo)
{
add_button_tool(DLG_OK, "", TOOL_OK);
add_button_tool(DLG_CANCEL, "", TOOL_CANCEL);
add_date(101, 0, PR("Dal "), 1, 1).check_type(CHECK_REQUIRED);
add_date(102, 0, PR("Al "), 1, 2).check_type(CHECK_REQUIRED);
set_handlers();
}
bool TPrimanota_application::sheet_rateo_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TMask& row_mask = f.mask();
if (row_mask.is_running() && row_mask.check_fields())
{
TRR_mask rateo_mask(true);
if (rateo_mask.run() == K_ENTER)
{
TSheet_field& s = *row_mask.get_sheet();
rateo_mask.split_row(s);
row_mask.send_key(K_SPACE, DLG_DELREC);
}
}
}
return true;
}
bool TPrimanota_application::sheet_risconto_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TMask& row_mask = f.mask();
if (row_mask.is_running() && row_mask.check_fields())
{
TRR_mask risconto_mask(false);
if (risconto_mask.run() == K_ENTER)
{
risconto_mask.split_row(*row_mask.get_sheet());
row_mask.send_key(K_SPACE, DLG_DELREC);
}
}
}
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)
{
if (key == K_TAB && f.to_check(key, true))
{
TMask& m = f.mask();
TPrimanota_application& a = app();
if (a.autodeleting() == 0x3)
return true; // Non effettuare controlli inutili in cancellazione
a._skip_giornale_check = false;
a._skip_bollato_check = false;
const TRectype& mov = cache().get(LF_MOV, f.get());
if (!mov.empty())
{
bool ok = true;
if (mov.get_bool(MOV_STAMPATO))
{
ok = f.yesno_box(TR("Il movimento e' gia' stato stampato sul libro giornale:\n"
"si desidera continuare ugualmente?"));
a._skip_giornale_check = ok;
}
if (ok && mov.get_bool(MOV_REGST))
{
ok = f.yesno_box(TR("Il movimento e' gia' stato stampato sul bollato:\n"
"si desidera continuare ugualmente?"));
a._skip_bollato_check = ok;
}
if (ok && mov.get_bool(MOV_INVIATO))
{
ok = f.yesno_box(TR("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(MOV_DATAREG), true);
m.set(F_CODCAUS, mov.get(MOV_CODCAUS));
f.set_focusdirty(false);
ok = m.stop_run(K_AUTO_ENTER);
}
else
{
m.reset(F_NUMREG);
if (a.lnflag())
m.stop_run(K_FORCE_CLOSE);
}
return ok;
}
}
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);
TEdit_field& numreg = m.efield(F_NUMREG);
TString16 filter; if (cau.full()) filter << MOV_CODCAUS << "==\"" << cau << '"';
numreg.browse()->set_filter(filter);
const TipoIVA i = app().cau2IVA(cau, ann); // Cerca causale e suo tipo
if (i != iva_errata)
return suspended_handler(f, key); // Controlla sospensione
else
return error_box(TR("Causale non presente in archivio"));
}
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))
{
if (!suspended_handler(f, key))
return false;
TMask& m = f.mask();
const int ann = m.get_int(F_ANNOIVA);
const TString& cau = f.get();
const TCausale c(cau, ann);
if (!c.ok())
return false;
const TCausale& k = app().causale();
const TString& msg = c.compatible(k);
if (msg.not_empty()) // La causale non e' compatibile
{
if (m.insert_mode() && !app()._sal_dirty)
{
// Cambio la maschera al volo
if (app().force_mask_swap(k, c))
{
TString4 provv;
provv << c.provvisorio();
m.set(F_PROVVISORIO, provv);
if (c.iva() != nessuna_iva && m.id2pos(F_SOLAIVA) > 0)
m.set(F_SOLAIVA, c.soloiva() ? "X" : " ");
return true;
}
}
return error_box(msg);
}
if (key == K_TAB)
{
app().read_caus(cau, ann);
app().cgs().force_update();
TString4 provv;
provv << c.provvisorio();
m.set(F_PROVVISORIO, provv);
if (c.iva() != nessuna_iva)
m.set(F_SOLAIVA, c.soloiva() ? "X" : " ");
}
}
return true;
}
// Handler of the F_DATAREG field
// Certified 70%
bool TPrimanota_application::datareg_handler(TMask_field& f, KEY key)
{
bool ok = true;
if (key == K_TAB && f.focusdirty() || key == K_ENTER)
{
const TDate oggi(TODAY);
TDate dr(f.get()); // Data dell'operazione
if (dr > oggi)
{
#ifdef DBG
if (!yesno_box(TR("La data dell'operazione <20> superiore quella di sistema:\nContinuare ugualmente?")))
return false;
#else
return f.error_box(TR("La data dell'operazione <20> superiore quella di sistema"));
#endif
}
TMask& m = f.mask();
if (dr == oggi && m.query_mode() && !m.field(F_NUMREG).empty())
{
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, m.get(F_NUMREG));
if (mov.read() == NOERR)
dr = mov.get_date(MOV_DATAREG);
}
TPrimanota_application& a = app();
TMask_field* ixc = m.find_by_id(F_IVAXCASSA);
if (ixc)
ixc->enable(gestione_IVAxCassa(dr));
const int ae = a._esercizi.date2esc(dr); // Codice esercizio
if (ae <= 0)
return f.error_box(TR("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(FR("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(FR("La data dell'operazione <20> 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(FR("La data dell'operazione <20> 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 TString4 codreg = reg.name();
if (codreg.full())
{
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(FR("La data dell'operazione <20> antecedente al %s,\n"
"ultima stampa del registro '%s' del %d"),
reg.last_print().string(), (const char*)codreg, ar);
if (error) return false;
}
if (f.dirty() && dr < reg.last_reg())
f.warning_box(FR("La data dell'operazione <20> 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(FR("La liquidazione IVA relativa al mese di %s <20> gi<67> 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();
// DATACOMP new way
if (key == K_ENTER)
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 = TR("La data del 74/ter");
if (f.dlg() == F_DATACOMP)
{
m.set(F_ANNOES, ae, true); // Aggiorna anno esercizio in entrambe le pagine
data = TR("La data di competenza");
if (dc > dr)
{
bool ok = false;
const TString& ca = m.get(F_CODCAUS);
if (ca.not_empty()) // Controlla ratei e risconti
{
TConfig ini(CONFIG_DITTA, "cg");
const TString& ra = ini.get("RrCcRa");
const TString& ri = ini.get("RrCcRi");
ok = (ca == ra) || (ca == ri);
}
if (!ok)
return f.error_box(TR("La data di competenza non puo' superare la data di registrazione"));
}
}
if (ae > 0)
{
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.format(FR("%s deve appartenere all'esercizio %d"), data, ar);
if (pr > 0) e << TR(" o all'esercizio ") << pr;
return f.error_box(e);
}
const TDate chiusura = app()._esercizi[ae].chiusura();
if (chiusura.ok() && dc <= chiusura)
{
f.error_box(FR("%s <20> antecedente al %s,\ndata di chiusura dell'esercizio %d"),
data, chiusura.stringa(), ae);
// Errore non bloccante
}
}
else
{
if (m.is_running())
return f.error_box(FR("%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;
const TDate dr(f.mask().get(F_DATAREG)); // Data operazione
const TDate d74(f.get()); // Data 74/ter
if (d74 > dr)
return true;
if (d74.year() < dr.year()-1)
return error_box(FR("La data 74/ter non puo' essere antecedente all'anno %d"), dr.year()-1);
const TLibro_giornale g(d74.year());
if (!g.ok())
return error_box(TR("La data 74/ter non appartiene ad un esercizio valido"));
if (d74 < g.last_print())
{
const char* lp = g.last_print().string();
return f.error_box(FR("La data 74/ter e' antecedente al %s,\n"
"data di stampa del libro giornale del %d"), lp, g.year());
}
return true;
}
bool TPrimanota_application::numdoc_handler(TMask_field& f, KEY key)
{
if (f.to_check(key, true))
{
TMask& m = f.mask();
if (key == K_TAB && m.insert_mode() && app().is_saldaconto())
{
if (!f.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, f.get(), true);
}
}
}
// Controllo documenti duplicati
if (key == K_ENTER && !f.empty() && app().iva() != nessuna_iva)
{
TMask& m = f.mask();
const int annodoc = m.get_date(F_DATADOC).year();
const long fornitore = m.get_long(F_FORNITORE);
if (annodoc > 0 && fornitore > 0)
{
// SELECT NUMREG,DATAREG,DATADOC,NUMDOC FROM MOV
// WHERE TIPO='F' AND CODCF=F_FORNITORE AND REG<>'' AND
// NUMDOC=F_NUMDOC AND DATAREG>=F_DATADOC AND NUMREG<>F_NUMREG
TString filter;
filter << '(' << MOV_NUMDOC << "=\"" << f.get() << "\")&&(" << MOV_REG << "!=\"\")";
if (m.edit_mode())
filter << "&&(" << MOV_NUMREG << "!=\"" << m.get(F_NUMREG) << "\")";
TRelation rel(LF_MOV);
TRectype& rec = rel.curr();
TRectype recfrom(rec);
recfrom.put(MOV_TIPO, app().iva() == iva_acquisti ? "F" : "C");
recfrom.put(MOV_CODCF, fornitore);
recfrom.put(MOV_DATAREG, TDate(1, 1, annodoc));
TRectype recto(recfrom);
recto.put(MOV_DATAREG, TDate(31, 12, annodoc+1));
TCursor cur(&rel, filter, 3, &recfrom, &recto);
const TRecnotype items = cur.items();
cur.freeze();
for (cur = 0; cur.pos() < items; ++cur)
{
const int ad = rec.get_date(MOV_DATADOC).year();
if (ad == annodoc)
return yesno_box("Il documento %d / %s <20> gi<67> stato inserito con la registrazione %ld\nSi desidera continuare ugualmente?",
annodoc, (const char*)f.get(), rec.get_long(MOV_NUMREG));
}
}
}
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())
{
if (m.get_bool(FS_RECALC)) // Evita scancellamenti indesiderati
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.full())
{
TRelation occas(LF_OCCAS);
occas.curr().put(OCC_CFPI, code);
if (occas.read(_isequal) == NOERR)
{
m.autoload(occas);
if (m.field(O_COFI).empty() && !isdigit(code[0]) && cf_check(m.get(O_STATONAS), code))
m.set(O_COFI, code, 1);
if (m.field(O_PAIV).empty() && isdigit(code[0]) && pi_check(m.get(O_STATONAS), code))
m.set(O_PAIV, code, 1);
m.send_key(K_TAB, O_COMUNE); // Forza decodifica comuni
m.send_key(K_TAB, O_COMUNENAS);
}
}
}
return true;
}
bool TPrimanota_application::occas_cfpi_handler(TMask_field& f, KEY key)
{
TMask& om = f.mask();
if (key == K_TAB && (f.focusdirty() || !om.is_running()))
{
TString16 cofi = om.get(O_COFI);
if (cofi.empty())
cofi = om.get(O_CODICE);
if (cf_check(om.get(O_STATONAS), cofi))
{
int giorno = atoi(cofi.mid(9,2));
om.set(O_SESSO, giorno > 40 ? "F" : "M");
if (om.field(O_COMUNENAS).empty())
om.set(O_COMUNENAS, cofi.mid(11,4), 0x2);
if (om.field(O_DATANAS).empty())
{
const TFixed_string mesi("ABCDEHLMPRST");
const int mese = mesi.find(cofi[8])+1;
int anno = atoi(cofi.mid(6,2));
if (giorno > 0 && mese > 0 && anno > 0)
{
giorno %= 40;
anno += anno < 5 ? 2000 : 1900;
om.set(O_DATANAS, TDate(giorno, mese, anno));
}
}
}
}
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();
const long oldcode = rowt.get_long();
if (corri)
codice = oldcode; // I corrispettivi non hanno un cliente in testata
else
{
if (m.insert_mode()) // Errore MI3567: se cambio cliente ripesca conto
{
if (codice != oldcode) // Se cambia il codice cliente ...
gruppo = conto = 0; // ... forza il ricalcolo del gruppo-conto
}
}
}
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)
{
if (riga_totale >= 0) // Dare e Avere potrebbero essere disabilitati
{
TToken_string& r = ss.row(riga_totale);
if (row_type(r) == 'T')
{
r.rtrim(2);
ss.enable_cell(riga_totale, 0);
ss.enable_cell(riga_totale, 1);
}
}
}
else
{
// Creazione/Aggiornamento riga totale
real tot = m.get(F_TOTALE);
if (app().is_split_payment())
{
calcola_imp(); // Ricalcola totale IVA
tot -= m.get_real(F_IMPOSTE);
}
TString80 descr;
if (riga_totale >= 0)
{
const int idx_des = ss.cid2index(CG_DESCR);
descr = ss.row(riga_totale).get(idx_des);
}
if (descr.blank())
descr = m.get(F_DESCR);
TImporto imp = real2imp(tot, 'T');
imp.normalize();
set_cgs_row(riga_totale, imp, nuovo, 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();
const TPartita* game = p.first();
if (game != NULL && atol(f.get()) != game->conto().codclifo())
{
const bool del = f.yesno_box(TR("Si desidera cancellare i pagamenti effettuati?"));
if (!del) // Ripristina codice copiandolo dalla prima partita
{
TString8 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(m, 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));
if (a._conto_ricavo.find() && a._conto_ricavo.sospeso())
{
f.error_box(TR("Il conto di ricavo e' sospeso"));
a._conto_ricavo.set(0,0,0);
}
const int alleg = clifo.get_int(CLI_ALLEG);
TEdit_field& upi = m.efield(F_RIEPILOGO);
upi.check_type(alleg == 3 ? CHECK_REQUIRED : CHECK_NORMAL);
TEdit_field& cp = m.efield(F_CODPAG);
if ((f.focusdirty() && m.is_running()) || (cp.empty() && !m.is_running()))
{
const TString& oldpag = cp.get();
const TString& s = clifo.get(CLI_CODPAG);
if (s != oldpag)
{
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 (cf == 'F' && app().causale().valintra())
{
const TString& valintra = clifo.get(CLI_VALINTRA);
if (valintra.full())
m.set(F_VALUTAINTRA, valintra, true);
}
}
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())
{
const TRectype& clifov = cliforel.curr(LF_CFVEN);
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);
}
if (clifov.get(CFV_CODCABPR).not_empty())
{
m.set(FS_NSABI, clifov.get(CFV_CODABIPR));
m.set(FS_NSCAB, clifov.get(CFV_CODCABPR));
m.send_key(K_TAB, FS_NSCAB);
}
const TString& agente = clifov.get(CLI_CODAG);
if (agente.full())
{
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
if (!occas)
m.set(F_STATOPAIV, clifo.get(CLI_STATOPAIV));
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(TR("Attenzione, il saldaconto verr<72> eliminato!"));
f.set_dirty(); // warning_box cleans the field!
}
a.activate_numrif(m, 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
TMask_field* ixc = m.find_by_id(F_IVAXCASSA);
if (ixc)
{
TString16 paiv = clifo.get(CLI_PAIV);
if (paiv.blank() && occas)
paiv = a.occas_mask().get(O_PAIV);
const int alleg = clifo.get_int(CLI_ALLEG);
const bool ic = ixc->active() && (alleg < 5 || alleg == 7) && paiv.full() && !m.get_bool(F_LIQDIFF);
ixc->set(ic ? "X" : "");
}
}
}
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)
{
static bool __in_handler = false;
if (key == K_TAB && !f.empty() && !__in_handler)
{
if (!suspended_handler(f, key))
return false;
__in_handler = true;
TPrimanota_application& a = app();
const real imp(a.ivas().row(1).get(0));
if (a.iva() == iva_acquisti && a.causale().intra())
{
const real iva(f.mask().get_real(F_RITFIS));
if (iva.is_zero())
{
TCodiceIVA codiva(f.get());
const real totale = f.mask().get_real(F_TOTALE);
const real imposta = codiva.imposta(totale);
f.mask().set(F_RITFIS, imposta, true);
}
}
if (imp.is_zero()) // Se il totale documento non <20> stato spezzato
{
TToken_string& row = a.ivas().row(0);
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
const int det = iva.detraibilita();
if (det > 0) row.add(det, 2);
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);
}
__in_handler = false;
}
return true;
}
// Scandisce le righe IVA detraibili e forza il conto corretto in base ai flag IVA in testata
static void force_iva_det_bill()
{
TSheet_field& cgs = app().cgs();
TMask& mask = cgs.mask();
const TCausale& cau = app().causale();
TBill contoiva;
int ri = 0;
if (mask.get_bool(F_LIQDIFF))
cau.bill(ri = RIGA_IVA_DIFFERITA, contoiva); else
if (mask.get_bool(F_IVAXCASSA))
cau.bill(ri = RIGA_IVA_PER_CASSA, contoiva);
if (ri <= 0 || !contoiva.ok())
cau.bill(ri = RIGA_IVA_DETRAIBILE, contoiva);
TToken_string conto(contoiva.string(0x3));
const TString80 descragg(cau.desc_agg(ri));
const int rowtype = cgs.cid2index(CG_ROWTYPE);
const int tp = cgs.cid2index(CG_TIPO);
const int gr = cgs.cid2index(CG_GRUPPO);
const int co = cgs.cid2index(CG_CONTO);
const int sc = cgs.cid2index(CG_SOTTOCONTO);
const int des = cgs.cid2index(CG_DESCR);
FOR_EACH_SHEET_ROW(cgs, r, row)
{
const TString4 type(row->get(rowtype));
if (type == "D")
{
row->add(conto.get(0), tp);
row->add(conto.get(), gr);
row->add(conto.get(), co);
row->add(conto.get(), sc);
row->add(conto.get(), sc + 1);
row->add(descragg, des);
}
}
cgs.force_update();
}
bool TPrimanota_application::is_split_payment() const
{
bool yes = false;
const TMask& m = curr_mask();
if (clifo() == 'C' && m.get_int(F_ANNOIVA) >= 2015)
{
const TRectype& cliente = cache().get_rec(LF_CLIFO, "C", m.get(F_CLIENTE));
if (cliente.get_bool(CLI_SPLITPAY))
{
TRelation rel(LF_MOV);
rel.add(LF_PARTITE, "NREG==NUMREG", 2);
m.autosave(rel);
yes = ::is_split_payment(rel.curr()); // Controlla reverse charge e ritenute
}
}
return yes;
}
// Handler of the F_LIQDIFF
// Certified 99%
bool TPrimanota_application::liqdiff_handler(TMask_field& f, KEY key)
{
if (key == K_SPACE && f.mask().is_running())
force_iva_det_bill();
if (key == K_ENTER && f.get().full())
{
if (f.mask().get_bool(F_IVAXCASSA))
return f.error_box(TR("Non <20> ammessa IVA per cassa a liquidazione differita"));
if (app().is_fattura() && app().is_split_payment())
return f.error_box(TR("Non <20> ammessa la liquidazione differita con split payment"));
}
return true;
}
// Handler of the F_IVAXCASSA
// Certified 99%
bool TPrimanota_application::ivaxcassa_handler(TMask_field& f, KEY key)
{
if (key == K_SPACE && f.mask().is_running())
force_iva_det_bill();
if (key == K_ENTER && f.get().full())
{
if (app().is_fattura() && app().is_split_payment())
return f.error_box(TR("Non <20> ammessa IVA per cassa con split payment"));
}
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_real(F_TOTALE);
const real totval = m.get_real(SK_TOTDOCVAL);
const real cambio = m.get_real(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.val2eur(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.eur2val(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(6);
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();
Patch level : 2.0 604 Files correlati : cg0.exe cg0500a.msk cg2.exe cg2100s.msk Ricompilazione Demo : [ ] Commento : CM20044 Causale senza tipo documento e con tipo movimento fattura. Mi propone la pagina delle scandenze completamente vuota pur avendo indicato il codice pagamento in testata. La seguente pagina riconosce il pagamento solo se clicco sul botone di reset. CM20045 Causale senza tipo documento e con tipo movimento nota di credito. Mi lascia registrare in prima nota senza portarmi nella gestione partite per chiudere le eventuali fatture.Come faccio ? ATTENZIONE: eliminata possibilita' di creare note di credito senza tipo documento CM20046 Causale senza tipo documento e con tipo movimento fattura o nota di credito. In prima nota non viene mai controllato il totale della testata presente nel campo "Voci per saldaconto" con quanto viene indicato poi nelle righe. CM20047 Causale senza tipo documento e con tipo movimento fattura/nota di credito. Se inserisco una registrazione con tipo movimento nota credito e passo successivamente ad una registrazione con causale con tipo movimento fattura, pur mettendo il codice di pagamento, la procedura non propone la pagina delle scadenze.Questo non accade se esco dalla prima nota dopo la registrazione della nota credito e rientro per registrare la fattura. CM20048 Inserisco un pagamento a fronte di un movimento nato da causale senza tipo documento e tipo movimento fattura. Se in testa indico il numero e la data del documento va tutto bene fino a che non seleziono la rata che intendo pagare, ma quando do conferma nella finestra del pagamento, la procedura mi riporta nella maschera della prima nota senza passare da quella delle partite. Solo cliccando di nuovo su conferma, la procedura mi apre la maschera delle partite. Se non indico i riferimenti del documento sulla testata della registrazione, va tutto bene. git-svn-id: svn://10.65.10.50/trunk@11508 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-10-17 08:28:05 +00:00
TPrimanota_application& a = app();
if (key == K_TAB && f.focusdirty())
{
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 TCurrency totale(real(f.get()));
if (totale.get_num().is_zero())
ok = yesno_box(TR("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 TCurrency totlit(cambio.val2eur(totval));
if (totale != totlit)
ok = f.yesno_box(FR("Il totale documento dovrebbe essere %s: continuare ugualmente?"),
totlit.string(true));
}
}
Patch level : 2.0 604 Files correlati : cg0.exe cg0500a.msk cg2.exe cg2100s.msk Ricompilazione Demo : [ ] Commento : CM20044 Causale senza tipo documento e con tipo movimento fattura. Mi propone la pagina delle scandenze completamente vuota pur avendo indicato il codice pagamento in testata. La seguente pagina riconosce il pagamento solo se clicco sul botone di reset. CM20045 Causale senza tipo documento e con tipo movimento nota di credito. Mi lascia registrare in prima nota senza portarmi nella gestione partite per chiudere le eventuali fatture.Come faccio ? ATTENZIONE: eliminata possibilita' di creare note di credito senza tipo documento CM20046 Causale senza tipo documento e con tipo movimento fattura o nota di credito. In prima nota non viene mai controllato il totale della testata presente nel campo "Voci per saldaconto" con quanto viene indicato poi nelle righe. CM20047 Causale senza tipo documento e con tipo movimento fattura/nota di credito. Se inserisco una registrazione con tipo movimento nota credito e passo successivamente ad una registrazione con causale con tipo movimento fattura, pur mettendo il codice di pagamento, la procedura non propone la pagina delle scadenze.Questo non accade se esco dalla prima nota dopo la registrazione della nota credito e rientro per registrare la fattura. CM20048 Inserisco un pagamento a fronte di un movimento nato da causale senza tipo documento e tipo movimento fattura. Se in testa indico il numero e la data del documento va tutto bene fino a che non seleziono la rata che intendo pagare, ma quando do conferma nella finestra del pagamento, la procedura mi riporta nella maschera della prima nota senza passare da quella delle partite. Solo cliccando di nuovo su conferma, la procedura mi apre la maschera delle partite. Se non indico i riferimenti del documento sulla testata della registrazione, va tutto bene. git-svn-id: svn://10.65.10.50/trunk@11508 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-10-17 08:28:05 +00:00
if (a.iva() == nessuna_iva && a.is_fattura())
{
TBill bill;
const int riga_cf = a.cerca_conto_cf(bill);
if (riga_cf >= 0)
{
TImporto imp = a.get_cgs_imp(riga_cf);
if (imp.valore() != m.get_real(F_TOTALE))
ok = f.error_box(FR("Il totale documento non corrisponde alla riga %d:\ndovrebbe essere %s"),
riga_cf+1, imp.valore().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_ritenute(char tipo)
{
if (_as400)
return;
TMask& m = curr_mask();
const real imp = m.get(tipo=='F' ? F_RITFIS : (tipo=='S' ? F_RITSOC : F_REVCHARGE)); // Determina importo
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 = tipo=='F' ? RIGA_RITENUTE_FISCALI : (tipo== 'S' ? RIGA_RITENUTE_SOCIALI : RIGA_REVERSE_CHARGE);
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(FR("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 100%
bool TPrimanota_application::ritfis_handler(TMask_field& f, KEY key)
{
if (key == K_TAB && f.focusdirty())
app().add_cgs_ritenute('F');
return true;
}
// Handler of F_RITSOC
// Certified 100%
bool TPrimanota_application::ritsoc_handler(TMask_field& f, KEY key)
{
if (key == K_TAB && f.focusdirty())
app().add_cgs_ritenute('S');
return true;
}
// Handler of F_REVCHARGE
// Certified 100%
bool TPrimanota_application::revcharge_handler(TMask_field& f, KEY key)
{
if (key == K_TAB && f.focusdirty())
app().add_cgs_ritenute('V');
return true;
}
HIDDEN void inventa_cambio_intra(TMask& m)
{
const TString& codval = m.get(F_VALUTAINTRA);
if (codval.not_empty() && TCurrency::get_firm_val() != codval)
{
TTable cam("CAM");
cam.put("CODTAB", codval);
const int err = cam.read(_isgteq);
bool yes = err != NOERR;
if (!yes)
{
TString16 v = cam.get("CODTAB");
v.cut(3).rtrim();
yes = v != codval;
}
if (yes)
m.set(F_CAMBIOINTRA, cache().get("%VAL", codval, "S4"));
}
}
// Handler of F_DATAINTRA
// Certified 99%
bool TPrimanota_application::dataintra_handler(TMask_field& f, KEY key)
{
// Se la data INTRA e' vuota allora copiala dalla data di competenza normale
if (key == K_ENTER && f.empty())
{
f.set(f.mask().get(F_DATAREG));
}
return true;
}
// Handler of F_CORRLIRE
// Certified 99%
bool TPrimanota_application::corrlire_handler(TMask_field& f, KEY key)
{
TMask& m = f.mask();
TMask_field& cv = m.field(F_CORRVALUTA);
if (key == K_ENTER && f.get().empty())
{
if (!cv.empty())
{
cv.set_focusdirty();
cv.on_hit();
}
else
key = K_F8;
}
if (key == K_F8)
{
f.set(m.get(F_IMPONIBILI));
f.set_dirty();
cv.set("");
key = K_TAB;
}
if (key == K_TAB && f.focusdirty())
{
if (cv.empty())
{
if (m.field(F_CAMBIOINTRA).empty())
inventa_cambio_intra(m);
const TExchange cambio(m.get(F_VALUTAINTRA), m.get_real(F_CAMBIOINTRA));
TCurrency imp(real(f.get()));
imp.change_value(cambio);
cv.set(imp.get_num().string());
}
}
if (key == K_ENTER)
{
const real im(m.get(F_IMPONIBILI));
const real cl(f.get());
if (im != cl)
{
const TRectype& rec = cache().get("%VAL", TCurrency::get_firm_val());
const char* name = (const char*)rec.get("S0");
warning_box(FR("Il corrispettivo in %s e' diverso dal totale degli imponibili"), name);
}
}
return true;
}
// Handler of F_CORRVALUTA
// Certified 99%
bool TPrimanota_application::corrvaluta_handler(TMask_field& f, KEY key)
{
TMask& m = f.mask();
TMask_field& cl = m.field(F_CORRISPETTIVO);
if (key == K_TAB && f.focusdirty())
{
if (cl.empty())
{
if (m.field(F_CAMBIOINTRA).empty())
inventa_cambio_intra(m);
const TExchange cambio(m.get(F_VALUTAINTRA), m.get_real(F_CAMBIOINTRA));
TCurrency imp(real(f.get()), cambio);
imp.change_to_firm_val();
cl.set(imp.get_num().string());
}
}
else
{
if (key == K_ENTER && f.get().empty())
{
cl.set_dirty();
cl.on_hit();
}
}
return true;
}
bool TPrimanota_application::activate_numrif(TMask& m, bool init_pag)
{
// Il numero riferimento esiste
bool shown = is_saldaconto() && (is_fattura() || is_nota_credito());
if (shown)
{
if (m.id2pos(F_SOLAIVA) >= 0) // Maschera moviventi IVA
{
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.field(F_ANNORIF).empty())
{
m.set(F_ANNORIF, m.get_date(F_DATADOC).year());
const bool use_protiva = _npart_is_prot && m.id2pos(F_PROTIVA) > 0;
m.set(F_NUMRIF, m.get(use_protiva ? 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 TString& 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(TR("Si desidera cancellare il saldaconto?"));
if (!del)
{
f.reset();
anchecg = true;
recalcg = false;
}
}
a.activate_numrif(m, 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, TR("Generazione righe contabilit<69>"), false, true);
TSheet_field& cg = a.cgs();
cg.reset();
a.add_cgs_tot(m); // Genera totale documento
if (!m.efield(F_RITFIS).empty()) a.add_cgs_ritenute('F'); // Genera ritenute fiscali
if (!m.efield(F_RITSOC).empty()) a.add_cgs_ritenute('S'); // Genera ritenute sociali
if (!m.efield(F_REVCHARGE).empty()) a.add_cgs_ritenute('V'); // Genera reverse charge
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;
}
// Handler del bottone di collegamento ai documenti
bool TPrimanota_application::linkdoc_handler(TMask_field& f, KEY key)
{
if (key == K_SPACE)
{
const TRectype& mov = app().get_relation()->curr();
TRectype doc(LF_DOC);
doc.put(DOC_PROVV, mov.get(MOV_DPROVV));
doc.put(DOC_ANNO, mov.get(MOV_DANNO));
doc.put(DOC_CODNUM,mov.get(MOV_DCODNUM));
doc.put(DOC_NDOC, mov.get(MOV_DNDOC));
doc.edit();
}
return true;
}
bool TPrimanota_application::quadratura_handler(TMask_field& f, KEY key)
{
if (key == K_SPACE)
{
TMask& m = f.mask();
TSheet_field& shiva = m.sfield(F_SHEETIVA);
const real totdoc = app().totale_documento();
TGeneric_distrib distrib(totdoc, TCurrency::get_firm_dec());
real totdist;
if (!shiva.empty())
{
FOR_EACH_SHEET_ROW(shiva, o, orow)
{
const real o_imponibile = orow->get(0);
const real o_imposta = orow->get(3);
if (!o_imponibile.is_zero() || !o_imposta.is_zero())
distrib.add(o_imponibile + o_imposta);
totdist += o_imponibile + o_imposta;
}
}
if (app()._perc_attesa_fld.full())
{
TFieldref f(app()._perc_attesa_fld, LF_CLIFO);
TRelation cliforel(LF_CLIFO); cliforel.add(LF_CFVEN, "TIPOCF=TIPOCF|CODCF=CODCF");
TRectype& clifo = cliforel.curr();
real perc;
if (m.field(F_CLIENTE).shown())
{
clifo.put(CLI_TIPOCF, "C");
clifo.put(CLI_CODCF, m.get(F_CLIENTE));
}
else
{
clifo.put(CLI_TIPOCF, "F");
clifo.put(CLI_CODCF, m.get(F_FORNITORE));
}
if (cliforel.read() == NOERR)
perc = f.read(cliforel);
real perc_reale = ((totdoc - totdist) * CENTO) / totdist;
perc_reale.round(2);
if (perc != perc_reale)
{
if (!yesno_box("La percentuale su questo documento <20> %s\nmentre dovrebbe essere %s:\nContinuare ugualmente ?", perc_reale.stringa(), perc.stringa()))
return false;
}
}
FOR_EACH_SHEET_ROW(shiva, n, nrow)
{
const real o_imponibile = nrow->get(0);
const real o_imposta = nrow->get(3);
if (!o_imponibile.is_zero() || !o_imposta.is_zero())
{
const TString4 zanicchi(nrow->get(1)); // Codice IVA
const TCodiceIVA i(zanicchi);
real n_imponibile = distrib.get();
real n_imposta = i.scorpora(n_imponibile);
if (n_imponibile != o_imponibile || n_imposta != o_imposta)
{
app().iva_notify(shiva, n, K_SPACE);
nrow->add(n_imponibile.string(), 0);
nrow->add(n_imposta.string(), 3);
app().iva_notify(shiva, n, K_ENTER);
}
}
}
shiva.force_update();
}
return true;
}