campo-sirio/cg/cg2105.cpp
guy ceb86a9c6b cg0500.cpp Corretta lettura anno iva da config
cg2100.cpp     Rifatta gestione pagamento immediato
cg2102.cpp     COrretto handler della data di registrazione
cg2104.cpp     Corretta gestione numero di riferimento partita
cg2105.cpp     Proposto in automatico l'importo dei pagamenti
cg2200.cpp     Azzerata ad ogni ciclo la maschera dei provisori
cg3100.cpp     Eliminati tutti gli accessi diretti alla tabella esercizi
cg3600.cpp     Aggiunta gestione e salvataggio colonne
cglib04.cpp    Tolti accessi diretti alla tabella degli esercizi
pagament.cpp   Corretta creazione nuove rate rispettando le classificazioni


git-svn-id: svn://10.65.10.50/trunk@3985 c028cbd2-c16b-5b4b-a496-9718f37d4682
1996-12-10 08:23:20 +00:00

1849 lines
56 KiB
C++
Executable File

#include <defmask.h> // Serve per DLG_NEWREC
#include "cg2100p.h" // Campi maschere partite e pagamenti
#ifdef __EXTRA__
#include "saldacon.h"
#include "sc0100p.h"
#include "cglib.h"
#else
#include "cg2100.h" // Campi maschere prima nota
#include "cg2102.h" // Applicazione di prima nota
#endif
#include <causali.h> // Archivio causali
#include <clifo.h> // Archivio clienti/fornitori
#include <mov.h> // Archivio movimenti di prima nota
#include <pagsca.h> // Archivio pagamenti
#include <partite.h> // Archivio partite
#include <scadenze.h> // Archivio scadenze
///////////////////////////////////////////////////////////
// Definizione Maschera partite
///////////////////////////////////////////////////////////
class TGame_mask : public TMask
{
const TBill _conto; // Conto fisso del cliente/fornitore
long _numreg; // Numero movimento contabile
int _numrig; // Riga contabile corrente (prima = 1!)
TImporto _importo; // Importo su riga contabile
TImporto _residuo, _resval; // Residuo della riga contabile
int _riga_partite; // Riga corrente delle partite
bool _changed; // Flag di modifica partite
bool _valfirst; // La colonna della valuta precede le lire
TDecoder _causali; // Decodificatore delle causali
protected:
static bool annopart_handler(TMask_field& f, KEY k);
static bool numpart_handler(TMask_field& f, KEY k);
static bool partite_notify(TSheet_field& partite, int r, KEY k);
static bool scadenze_notify(TSheet_field& partite, int r, KEY k);
static bool show_all_handler(TMask_field& f, KEY k);
static bool edit_scadenza_handler(TMask_field& f, KEY k);
static bool nuovo_handler(TMask_field& f, KEY k);
static bool cambio_handler(TMask_field& f, KEY k);
void add_importo(TToken_string& s, const TImporto& i, bool val = FALSE, int pos = -1);
void add_descrizione(TToken_string& s, const TRiga_partite& riga, int pos = -1);
TImporto get_importo(TToken_string& s, int pos) const;
void fill_partite();
void aggiorna_residuo();
int update_partita(const TRectype& game, const TImporto& s, const TImporto& d,
const TImporto& p, const TImporto& i, int prow);
int update_partita(const TPartita& game, int prow);
int update_partita(const TRectype& game, int prow);
void update_saldo_clifo();
int nuova_riga(TPartita& partita, tipo_movimento tm) const;
int nuovo_pagamento(TPartita& partita, int nriga, int rata, tipo_movimento tm) const;
bool edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp) const;
char calcola_sezione(tipo_movimento tm = tm_pagamento) const;
long number_distance(const char* key, const char* num) const;
bool same_number(const char* key, const char* num) const;
void append_conto(TString& s) const;
#ifdef __EXTRA__
bool edit_fattura(TPartita& p, int nriga);
bool prima_nota(const long nreg);
#endif
const TRiga_partite* cerca_prima_riga() const;
void aggiorna_valuta(const TValuta& val);
void aggiorna_sorelle(const TRiga_partite& part) const;
public:
TSheet_field& partite() const { return (TSheet_field&)field(P_PARTITE); }
TSheet_field& scadenze() const { return (TSheet_field&)field(P_SCADENZE); }
const TBill& conto() const { return _conto; }
const TImporto& residuo(bool val) const { return val ? _resval : _residuo; }
bool changed() const { return _changed; }
TGame_mask(const TBill& bill, long numreg, int riga);
virtual ~TGame_mask() {}
};
///////////////////////////////////////////////////////////
// Maschera pagamenti
///////////////////////////////////////////////////////////
class TPay_mask : public TMask
{
TDate _datadoc;
real _da_pagare, _pagabile;
const TGame_mask& _parent;
tipo_movimento _tipomov;
TDecoder _causale;
bool _assigned;
bool _can_solder;
protected:
static bool importo_handler(TMask_field& f, KEY k);
static bool importolire_handler(TMask_field& f, KEY k);
static bool saldo_handler(TMask_field& f, KEY k);
static bool datapag_handler(TMask_field& f, KEY k);
static bool conto_handler(TMask_field& f, KEY k);
static bool descr_handler(TMask_field& f, KEY k);
void gioca_cambi(int force = 0x0);
static bool sottoconto_handler(TMask_field& f, KEY k);
#ifdef __EXTRA__
static bool datareg_handler(TMask_field& f, KEY k);
static bool datadoc_handler(TMask_field& f, KEY k);
static bool numdoc_handler(TMask_field& f, KEY k);
static bool sezione_handler(TMask_field& f, KEY k);
#endif
public:
void set_pag(const TRectype& oldpag, const TRiga_scadenze& scad, const TImporto& importo);
void get_pag(TRectype& oldpag, TRectype& somma) const;
bool assigned() const { return _assigned; }
bool unassigned() const { return !_assigned; }
tipo_movimento tipo() const { return _tipomov; }
void attiva_valuta(bool on);
TPay_mask(const TGame_mask& parent, int mode);
virtual ~TPay_mask();
};
#ifdef __EXTRA__
const char* const PAYMASK = "sc0100b";
#else
const char* const PAYMASK = "cg2100s";
#endif
TPay_mask::TPay_mask(const TGame_mask& parent, int mod)
: TMask(PAYMASK), _parent(parent),
_causale(LF_CAUSALI, CAU_CODCAUS, CAU_DESCR)
{
set_mode(mod);
enable(DLG_DELREC, edit_mode());
set_handler(S_SOTTOCONTO, sottoconto_handler);
#ifdef __EXTRA__
xvt_statbar_set(mod == MODE_MOD ? "Modifica" : "Inserimento", TRUE);
hide(E_CODPAG); hide(E_DESPAG);
set_handler(E_DATAREG, datareg_handler);
set_handler(E_DATADOC, datadoc_handler);
set_handler(E_NUMDOC, numdoc_handler);
set_handler(E_SEZIONE, sezione_handler);
set_handler(E_TOTALE, TSaldaconto_app::totale_handler);
if (app().gestione_valuta())
{
show(-3);
set_handler(E_TOTDOCVAL, TSaldaconto_app::totval_handler);
set_handler(E_VALUTA, TSaldaconto_app::valuta_handler);
set_handler(E_DATACAMBIO, TSaldaconto_app::datacambio_handler);
set_handler(E_CAMBIO, TSaldaconto_app::cambio_handler);
}
else
hide(-3);
hide(S_RESIDUOPAG);
hide(-2); // I campi relativi alla contropartita non vengono gestiti
hide(E_IMPOSTE);
set_handler(E_DESCR, descr_handler);
set_handler(S_DESCAGG, descr_handler);
const char a = TPartita::allineamento_richiesto(parent.conto().tipo());
field(E_NUMRIF).set_justify(a == 'R');
disable(E_ANNORIF);
disable(E_NUMRIF);
#endif
}
TPay_mask::~TPay_mask()
{
#ifdef __EXTRA__
xvt_statbar_set("Estratto conto", TRUE);
#endif
}
void TPay_mask::attiva_valuta(bool in_valuta)
{
if (in_valuta)
{
set_handler(S_IMPORTOVAL, importo_handler);
set_handler(S_IMPORTO, importolire_handler);
}
else
set_handler(S_IMPORTO, importo_handler);
enable(S_RITENUTE, !in_valuta); // dis/abilita ritenute
enable(S_IMPORTOVAL, in_valuta);
if (in_valuta)
{
reset(S_RITENUTE);
}
else
{
reset(S_IMPORTOVAL_SCAD);
reset(S_IMPORTOVAL);
}
}
void TPay_mask::set_pag(const TRectype& oldpag, const TRiga_scadenze& scad,
const TImporto& residuo)
{
const TPartita& p = scad.partita();
const int nrigp = oldpag.get_int(PAGSCA_NRIGP);
const TRiga_partite& sum = p.riga(nrigp);
_assigned = oldpag.get_int(PAGSCA_NRIGA) != TPartita::UNASSIGNED;
_tipomov = (tipo_movimento)sum.get_int(PART_TIPOMOV);
const TRiga_partite& fatt = _assigned ? scad.riga() : sum;
TRelation rel(LF_PAGSCA); // Working relation
rel.add(LF_PARTITE, "ANNO=ANNO|NUMPART=NUMPART");
rel.curr() = oldpag;
rel.curr(LF_PARTITE) = sum;
autoload(rel); // Load current record on mask
TMask_field& group = field(S_RATA);
TString prompt(80);
const TBill& k = p.conto();
switch (k.tipo())
{
case 'C': prompt << "Cliente"; break;
case 'F': prompt << "Fornitore"; break;
default : prompt << "Conto " << k.gruppo() << ' ' << k.conto(); break;
}
prompt << ' ' << k.sottoconto() << ' ';
prompt << "Partita:" << p.anno() << ' ' << p.numero()
<< " Riga:" << oldpag.get_int(PAGSCA_NRIGA)
<< " Rata:" << oldpag.get_int(PAGSCA_NRATA);
if (assigned())
prompt << " del " << scad.get_date(SCAD_DATASCAD).string();
#ifndef __EXTRA__
else
prompt << " del " << sum.get_date(PART_DATAPAG).string();
#endif
group.set_prompt(prompt);
set(S_NUMDOC, fatt.get(PART_NUMDOC)); // Numero documento
set(S_DATADOC, fatt.get(PART_DATADOC)); // Data documento
set(S_NUMPROT, fatt.get(PART_PROTIVA)); // Protocollo IVA
TString desfat = fatt.get(PART_DESCR); // Descrizione fattura
if (desfat.empty()) // Se e' vuota ...
{
desfat = fatt.get(PART_CODCAUS);
desfat = _causale.decode(desfat); // ... usa descrizione causale
}
set(S_DESCR, desfat);
bool in_valuta = fatt.in_valuta();
#ifdef __EXTRA__
const bool prima_riga = p.first() == p.last();
if (!in_valuta && prima_riga)
in_valuta = app().gestione_valuta();
enable(E_VALUTA, prima_riga); // La valuta puo' essere cambiata solo sulle partite nuove
#endif
show(-3, in_valuta); // Visualizza campi relativi alla valuta
attiva_valuta(in_valuta); // Attiva campi e handlers relativi alla valuta
const char sez_fat = fatt.sezione();
set(S_SEZIONE_SCAD, sez_fat == 'A' ? "A" : "D"); // Sezione della riga
if (assigned())
{
set(S_IMPORTO_SCAD, scad.get(SCAD_IMPORTO)); // Importo della rata
if (in_valuta)
set(S_IMPORTOVAL_SCAD, scad.get(SCAD_IMPORTOVAL)); // Importo in valuta
TImporto res_rat = scad.residuo(in_valuta);
res_rat.normalize(sez_fat);
_da_pagare = res_rat.valore(); // Calcola residuo in valuta
TReal_field& res = (TReal_field&)field(S_RESIDUORATA);
res.set_decimals(in_valuta ? 3 : 0);
if (get(S_SALDOACC)[0] != 'S')
res.set(_da_pagare.string());
}
else
{
hide(S_RESIDUORATA); // Se non assegnato nascondi residuo rata
_da_pagare = ZERO;
}
set_handler(S_SALDOACC, saldo_handler);
real oldimp = oldpag.get_real(in_valuta ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO);
if (!in_valuta)
oldimp += oldpag.get_real(PAGSCA_RITENUTE);
// Ricorda l'importo da pagare
_da_pagare += oldimp;
#ifndef __EXTRA__
_pagabile = _parent.residuo(in_valuta).valore();
TReal_field& resp = (TReal_field&)field(S_RESIDUOPAG);
resp.set_decimals(in_valuta ? 3 : 0);
resp.set(_pagabile.string());
_pagabile += oldimp;
#endif
// Il flag di saldo/acconto e' attivo solo se non ci sono acconti, cioe':
// pagamento non assegnato o con data documento antecedente quella della fattura
_can_solder = _assigned;
if (_can_solder)
{
const tipo_movimento tm = sum.tipo();
_can_solder = !(tm == tm_nota_credito || tm == tm_insoluto);
if (_can_solder)
{
const TDate datasca(fatt.get(PART_DATADOC));
const TDate datapag(sum.get(PART_DATADOC));
_can_solder = datapag >= datasca;
}
}
// Mostra saldo solo se non e' ne' un acconto, ne' una nota di credito
enable(S_SALDOACC, _can_solder);
#ifdef __EXTRA__
enable(E_SEZIONE, oldpag.get_char(PAGSCA_ACCSAL) != 'S');
#else
set_handler(S_GRUPPO, conto_handler);
set_handler(S_CONTO, conto_handler);
const bool mostra_conto = !sum.is_nota_credito();
show(-2, mostra_conto); // mostra/nasconde conto contropartita
#endif
// Gestione data-pagamento: non puo' precedere la data del documento
_datadoc = sum.get_date(PART_DATADOC);
set_handler(S_DATAPAG, datapag_handler);
const bool mostra_ritenute = !sum.is_nota_credito();
show(S_RITENUTE, mostra_ritenute);
}
void TPay_mask::get_pag(TRectype& newpag, TRectype& sum) const
{
TRelation rel(LF_PAGSCA); // Working relation
rel.add(LF_PARTITE, "ANNO=ANNO|NUMPART=NUMPART");
rel.curr() = newpag;
rel.curr(LF_PARTITE) = sum;
autosave(rel); // Load current record from mask
newpag = rel.curr();
sum = rel.curr(LF_PARTITE);
}
// Riempie i campi valuta a zero in base agli altri
void TPay_mask::gioca_cambi(int force)
{
const real totale = get(S_IMPORTO);
const real totval = get(S_IMPORTOVAL);
#ifdef __EXTRA__
const TValuta cambio(*this, E_VALUTA, E_DATACAMBIO, E_CAMBIO);
#else
const TValuta cambio(_parent, P_VALUTA, P_DATACAMBIO, P_CAMBIO);
#endif
if ( (force == 0x1 || totale.is_zero()) && !(totval.is_zero() || cambio.in_lire()) )
{
const real new_totale = cambio.val2lit(totval);
if (new_totale != totale)
set(S_IMPORTO, new_totale, TRUE);
}
if ( (force == 0x2 || totval.is_zero()) && !(totale.is_zero() || cambio.in_lire()))
{
const real new_totval = cambio.lit2val(totale);
if (new_totval != totval)
set(S_IMPORTOVAL, new_totval, TRUE);
}
#ifdef __EXTRA__
if ( (force == 0x4 || cambio.in_lire()) && !(totale.is_zero() || totval.is_zero()))
{
real new_cambio = totale / totval; new_cambio.round(5);
if (new_cambio != cambio.cambio())
set(E_CAMBIO, new_cambio, TRUE);
}
#endif
}
bool TPay_mask::importo_handler(TMask_field& f, KEY k)
{
TPay_mask& m = (TPay_mask&)f.mask();
if (k == K_F8)
{
real imp;
#ifdef __EXTRA__
const bool in_valuta = m.field(S_IMPORTOVAL).active();
m._pagabile = m.get_real(in_valuta ? E_TOTDOCVAL : E_TOTALE);
if (m._assigned)
imp = fnc_min(m._da_pagare, m._pagabile);
else
imp = m._pagabile;
#else
if (m.field(S_RESIDUORATA).shown() && m.field(S_RESIDUOPAG).shown())
imp = fnc_min(m._da_pagare, m._pagabile);
else
imp = m.field(S_RESIDUORATA).shown() ? m._da_pagare : m._pagabile;
#endif
if (m.field(S_RITENUTE).active())
imp -= real(m.get(S_RITENUTE));
f.set(imp.string());
k = K_TAB;
}
if (k == K_TAB && f.focusdirty())
{
const bool in_valuta = m.field(S_IMPORTOVAL).active();
if (in_valuta)
m.gioca_cambi();
real i(f.get());
if (m.field(S_RITENUTE).active())
i += real(m.get(S_RITENUTE));
TMask_field& sa = m.field(S_SALDOACC);
if (m._can_solder && m.mode() == NO_MODE)
{
if (i >= m._da_pagare)
sa.set("S");
/*
Eliminato perche' rende ingestibili due pagamenti in valuta a saldo
if (in_valuta) sa.enable(i != m._da_pagare);
*/
}
if (sa.get()[0] != 'S')
{
real residuo = m._da_pagare;
if (m.tipo() == tm_insoluto)
residuo += i;
else
residuo -= i;
m.set(S_RESIDUORATA, residuo);
}
else
m.reset(S_RESIDUORATA);
const real residuopag(m._pagabile - i);
m.set(S_RESIDUOPAG, residuopag);
}
return TRUE;
}
bool TPay_mask::importolire_handler(TMask_field& f, KEY k)
{
TPay_mask& m = (TPay_mask&)f.mask();
if (k == K_F8)
{
#ifdef __EXTRA__
if (m.unassigned())
f.set(m.get(E_TOTALE));
else
#endif
m.send_key(k, S_IMPORTOVAL);
}
if (f.to_check(k))
m.gioca_cambi();
return TRUE;
}
bool TPay_mask::saldo_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TMask& m = f.mask();
m.set_mode(MODE_QUERY);
TMask_field& imp = m.field(m.field(S_IMPORTOVAL).active() ? S_IMPORTOVAL : S_IMPORTO);
imp.set_dirty();
imp.on_hit();
m.set_mode(NO_MODE);
}
return TRUE;
}
bool TPay_mask::sottoconto_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
if (k == K_ENTER && f.mask().insert_mode() && f.get().empty())
ok = f.error_box("Contropartita obbligatoria");
return ok;
}
bool TPay_mask::datapag_handler(TMask_field& f, KEY k)
{
if (f.to_check(k))
{
const TDate datapag(f.get());
TPay_mask& m = (TPay_mask&)f.mask();
if (datapag < m._datadoc)
return f.error_box("La data del pagamento e' inferiore alla data del documento %s",
m._datadoc.string());
}
return TRUE;
}
bool TPay_mask::conto_handler(TMask_field& f, KEY k)
{
if (k == K_TAB && f.focusdirty())
{
TMask& m = f.mask();
TBill conto; conto.get(m, S_GRUPPO, S_CONTO, S_SOTTOCONTO);
const TString& desc = conto.descrizione();
if (desc.empty())
m.reset(S_SOTTOCONTO);
m.set(S_DESCRCONTO, desc);
}
return TRUE;
}
///////////////////////////////////////////////////////////
// Maschera gestione nuovo pagamento / fattura
///////////////////////////////////////////////////////////
class TNew_mask : public TMask
{
bool _allow_fatt;
protected:
static bool tipomov_handler(TMask_field& f, KEY k);
public:
TNew_mask(char tipocf, bool fatt, bool edit);
virtual ~TNew_mask() {}
};
bool TNew_mask::tipomov_handler(TMask_field& f, KEY k)
{
if (k == K_ENTER)
{
TNew_mask& m = (TNew_mask&)f.mask();
if (!m._allow_fatt && f.get() == "1")
return f.error_box("Non e' possibile utilizzare una fattura come pagamento");
}
return TRUE;
}
TNew_mask::TNew_mask(char tipocf, bool fatt, bool edit)
: TMask("cg2100n"), _allow_fatt(fatt)
{
TMask_field& tipomov = field(P_NUOVO);
#ifdef __EXTRA__
tipomov.set_handler(tipomov_handler);
tipomov.enable();
tipomov.set(_allow_fatt ? "1" : "3");
if (!_allow_fatt)
set_caption("Nuovo pagamento");
#else
tipomov.disable();
#endif
enable(P_ANNO, edit);
enable(P_NUMERO, edit);
if (edit) first_focus(P_NUMERO);
const char a = TPartita::allineamento_richiesto(tipocf);
field(P_NUMERO).set_justify(a == 'R');
}
///////////////////////////////////////////////////////////
// Maschera partite
///////////////////////////////////////////////////////////
void TGame_mask::append_conto(TString& s) const
{
switch (conto().tipo())
{
case 'C':
s << "Cliente"; break;
case 'F':
s << "Fornitore"; break;
default:
s << "Conto " << conto().gruppo() << ' ' << conto().conto(); break;
}
s << ' ' << conto().sottoconto();
}
TGame_mask::TGame_mask(const TBill& bill, long numreg, int riga)
: TMask("cg2100p"), _conto(bill), _numreg(numreg), _numrig(riga),
_changed(FALSE), _valfirst(FALSE), _causali(LF_CAUSALI, "CODCAUS", "DESCR")
{
TString descr(80);
append_conto(descr);
descr << ' ' << ((TBill&)_conto).descrizione();
set(P_DESCR, descr);
#ifdef __EXTRA__
xvt_statbar_set("Estratto conto", TRUE);
disable(-3); // Disabilita gestione valuta
hide(P_RESIDUO);
hide(P_RESIDUOVAL);
#else
TValuta val;
const TRiga_partite* row = cerca_prima_riga();
if (row != NULL)
{
val.get(*row); // Legge valuta standard dalla partita
set(P_ANNO, row->get(PART_ANNO)); // Propone anno e partita
set(P_NUMERO, row->get(PART_NUMPART));
}
else
{
TMask& cm = app().curr_mask(); // Legge valuta dal movimento
val.get(cm, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
if (cm.id2pos(F_ANNORIF) > 0) // Se in testata c'e' l'anno di riferimento
{
set(P_ANNO, cm.get(F_ANNORIF)); // Propone anno e partita
set(P_NUMERO, cm.get(F_NUMRIF));
}
}
val.set(*this, P_VALUTA, P_DATACAMBIO, P_CAMBIO);
enable(-3, val.in_valuta());
#endif
set_handler(P_ANNO, annopart_handler);
set_handler(P_NUMERO, numpart_handler);
set_handler(P_SHOWALL, show_all_handler);
set_handler(P_NUOVO, nuovo_handler);
set_handler(P_CAMBIO, cambio_handler);
TSheet_field& games = partite();
games.set_notify(partite_notify);
scadenze().set_notify(scadenze_notify);
scadenze().sheet_mask().set_handler(100, edit_scadenza_handler);
fill_partite(); // Riempie sheet partite
}
///////////////////////////////////////////////////////////
// Handlers dei campi e della maschera principale
///////////////////////////////////////////////////////////
bool TGame_mask::annopart_handler(TMask_field& f, KEY k)
{
if (k == K_TAB && f.focusdirty() && f.get().not_empty())
{
TMask_field& n = f.mask().field(P_NUMERO);
n.set_dirty();
numpart_handler(n, k);
}
return TRUE;
}
bool TGame_mask::numpart_handler(TMask_field& f, KEY k)
{
if (k == K_TAB && f.focusdirty())
{
const TGame_mask& m = (const TGame_mask&)f.mask();
const int anno = m.get_int(P_ANNO); // Anno partita da cercare
if (anno > 0)
{
const TString key = f.get(); // Numero partita da cercare
int best_match = 0; // Partita piu' somigliante
long min_dist = 10000000L; // Livello di somiglianza migliore
TSheet_field& sheet = m.partite();
for (int i = 0; i < sheet.items(); i++)
{
TToken_string& row = sheet.row(i);
if (anno == row.get_int(0)) // Se corrisponde l'anno e ...
{
const long dist = m.number_distance(key, row.get());
if (i == 0 || dist < min_dist)
{
min_dist = dist;
best_match = i;
if (dist == 0L)
break;
}
}
}
sheet.select(best_match); // seleziona la partita
}
}
return TRUE;
}
bool TGame_mask::show_all_handler(TMask_field& f, KEY k)
{
TGame_mask& gm = (TGame_mask&)f.mask();
if (k == K_SPACE && gm.is_running())
{
gm.fill_partite();
}
return TRUE;
}
bool TGame_mask::cambio_handler(TMask_field& f, KEY k)
{
if (k == K_TAB && f.focusdirty())
{
TGame_mask& gm = (TGame_mask&)f.mask();
const bool needed = app().partite().mov2rig(gm._numreg, gm._numrig) > 0;
if (needed && yesno_box("Aggiornare gli importi dei pagamenti?"))
{
const TValuta val(gm, P_VALUTA, P_DATACAMBIO, P_CAMBIO);
gm.aggiorna_valuta(val);
}
gm.aggiorna_residuo();
}
return TRUE;
}
///////////////////////////////////////////////////////////
// Metodi dei campi e della maschera principale
///////////////////////////////////////////////////////////
// Aggiorna il campo con il residuo da spendere sui pagamenti
void TGame_mask::aggiorna_residuo()
{
#ifndef __EXTRA__
_importo = app().get_cgs_imp(_numrig-1); // Importo sulla riga contabile
_residuo = _importo;
TPartite_array& giochi = app().partite();
const TImporto speso = giochi.importo_speso(_numreg, _numrig);
_residuo -= speso; // Residuo della riga
const char sez = calcola_sezione(); // Sezione di riferimento
_residuo.normalize(sez);
set(P_RESIDUO, _residuo.valore());
const TValuta cambio(*this, P_VALUTA, P_DATACAMBIO, P_CAMBIO);
if (cambio.in_valuta())
{
// Importo della riga contabile senza differenza cambi
_resval = _importo;
const TImporto abb_diff = giochi.importo_speso(_numreg, _numrig, FALSE, 0x6);
_resval -= abb_diff;
cambio.lit2val(_resval);
const TImporto spesoval = giochi.importo_speso(_numreg, _numrig, TRUE, 0x1);
_resval -= spesoval; // Residuo della riga
_resval.normalize(sez);
set(P_RESIDUOVAL, _resval.valore());
}
#endif
}
// Scandisce tutte le partite per cercare la prima del movimento corrente
const TRiga_partite* TGame_mask::cerca_prima_riga() const
{
const TRiga_partite* riga = app().partite().mov2rig(_numreg, _numrig);
return riga;
}
void TGame_mask::aggiorna_valuta(const TValuta& val)
{
TPartite_array& pa = app().partite();
for (TPartita* game = pa.first(); game; game = pa.next())
{
for (int r = game->last(); r > 0; r = game->pred(r))
{
const TRiga_partite& riga = game->riga(r);
for (int s = riga.rate(); s > 0; s--)
{
const TRiga_scadenze& scad = riga.rata(s);
for (int p = scad.last(); p > 0; p = scad.pred(p))
{
TRiga_partite& sum = game->riga(p);
if (sum.get_long(PART_NREG) == _numreg &&
sum.get_int(PART_NUMRIG) == _numrig)
{
TRectype pag(scad.row(p));
real imp(pag.get(PAGSCA_IMPORTOVAL));
val.val2lit(imp);
pag.put(PAGSCA_IMPORTO, imp); // Converte in lire l'importo in valuta
#ifdef __EXTRA__
game->modifica_pagamento(pag, val, TRUE);
#else
app().notify_edit_pagamento(*game, pag, val);
#endif
}
}
}
}
}
fill_partite();
}
/*
void TGame_mask::aggiorna_sorelle(const TRiga_partite& part) const
{
TPartite_array& pa = app().partite();
for (TPartita* game = pa.first(); game; game = pa.next())
{
for (int r = game->last(); r > 0; r = game->pred(r))
{
TRiga_partite& row = game->riga(r);
if (row.get_long(PART_NREG) == _numreg && row.get_int(PART_NUMRIG) == _numrig)
{
row.put(PART_DESCR, part.get(PART_DESCR));
row.put(PART_DATAPAG, part.get(PART_DATAPAG));
row.put(PART_TIPOPAG, part.get(PART_TIPOPAG));
}
}
}
}
*/
bool TGame_mask::partite_notify(TSheet_field& partite, int r, KEY k)
{
TGame_mask& gm = (TGame_mask&)partite.mask();
if (k == K_TAB)
{
const bool changing_row = gm._riga_partite != r;
if (!changing_row)
return TRUE;
main_app().begin_wait();
gm._riga_partite = r;
TSheet_field& sheet = gm.scadenze();
TString_array& scadenze = sheet.rows_array(); // Array delle righe
scadenze.destroy(); // Azzera righe
TToken_string& row = partite.row(r);
const int anno = row.get_int(0); // Anno partita
const TString16 num = row.get(); // Numero partita
gm.set(P_ANNO, anno); // Aggiorna campi di ricerca
gm.set(P_NUMERO, num);
TValuta prima_valuta; // Codice prima valuta
if (anno > 0)
{
const TBill& zio = gm.conto(); // Conto cliente/fornitore
TPartita* game = app().partite().exist(zio, anno, num); // Cerca la partita tra quelle editate
const bool should_delete_game = (game == NULL); // Ricorda di fare delete
if (should_delete_game) // Se non c'era ...
game = new TPartita(zio, anno, num); // ... creane una temporanea
TImporto tot_lit, tot_val;
TToken_string riga_fattura(80);
const int lastrow = game->last();
if (lastrow > 0)
prima_valuta.get(game->riga(lastrow));
const bool in_valuta = prima_valuta.in_valuta();
for (int ri = game->first(); ri <= lastrow; ri = game->succ(ri))
{
const TRiga_partite& riga = game->riga(ri);
if (!riga.is_fattura())
continue;
riga_fattura.cut(0);
riga_fattura.add(ri);
riga_fattura.add("");
riga_fattura.add(riga.get(PART_DATADOC));
riga_fattura.add(""); // Data scad
gm.add_descrizione(riga_fattura, riga);
gm.add_importo(riga_fattura, riga.importo(FALSE, 0x1));
if (in_valuta)
gm.add_importo(riga_fattura, riga.importo(TRUE, 0x1), TRUE);
else
riga_fattura.add("");
riga_fattura.add(riga.get(PART_NREG));
riga_fattura.add(riga.get(PART_DATAREG));
riga_fattura.add(riga.get(PART_NUMDOC));
riga_fattura.add(riga.get(PART_PROTIVA));
riga_fattura.add(riga.get(PART_TIPOMOV));
scadenze.add(riga_fattura);
for (int ra = 1; ra <= riga.rate(); ra++)
{
const TRiga_scadenze& scad = riga.rata(ra);
TToken_string& row = scadenze.row(scadenze.add(riga_fattura));
row.add(ra, 1);
row.add(scad.get(SCAD_DATASCAD), 3);
gm.add_importo(row, scad.importo(FALSE), FALSE, 5);
if (in_valuta)
gm.add_importo(row, scad.importo(TRUE), TRUE, 6);
const TString& descr = scad.get(SCAD_DESCR);
if (descr.not_empty())
row.add(descr, 4);
const bool blocked = scad.get_bool(SCAD_BLOCCATA);
row.add(blocked ? "X" : " ", 13);
const int lastp = scad.last();
for (int pa = scad.first(); pa <= lastp; pa = scad.succ(pa))
{
const TRectype& pag = scad.row(pa);
const TRiga_partite& sum = game->riga(pa);
const char sez = sum.sezione();
TToken_string& row = scadenze.row(scadenze.add(""));
row.add(ri);
row.add(ra);
row.add(sum.get(PART_DATADOC));
row.add(sum.get(PART_DATAPAG));
gm.add_descrizione(row, sum);
const TImporto imp(sez, pag.get_real(PAGSCA_IMPORTO));
if (in_valuta)
{
gm.add_importo(row, imp);
gm.add_importo(row, TImporto(sez, pag.get_real(PAGSCA_IMPORTOVAL)), TRUE);
}
else
{
gm.add_importo(row, imp);
row.add("");
}
row.add(sum.get(PART_NREG));
row.add(sum.get(PART_DATAREG));
row.add(sum.get(PART_NUMDOC));
row.add("");
row.add(sum.get(PART_TIPOMOV));
row.add(pa);
// Le ritenute non possono esistere in valuta
if (!in_valuta)
{
const TImporto rit(sez, pag.get_real(PAGSCA_RITENUTE));
if (!rit.is_zero())
{
TToken_string& rrit = scadenze.row(scadenze.add(""));
rrit.add("Ritenute professionali", 4);
gm.add_importo(rrit, rit, FALSE);
rrit.add(sum.get(PART_TIPOMOV), 11);
}
}
// Gli abbuoni e le differenze cambio esistono solo se e' a saldo
if (pag.get_char(PAGSCA_ACCSAL) == 'S')
{
const TImporto abb(sez, pag.get_real(PAGSCA_ABBUONI));
if (!abb.is_zero())
{
TToken_string& rabb = scadenze.row(scadenze.add(""));
const char tipo_abb = pag.get_char(PAGSCA_PASSATT);
rabb.add("Abbuoni ", 4);
rabb << (tipo_abb == 'A' ? "attivi" : "passivi");
if (in_valuta)
{
TImporto abb_lit = abb;
prima_valuta.val2lit(abb_lit);
gm.add_importo(rabb, abb_lit, FALSE);
gm.add_importo(rabb, abb, TRUE);
}
else
{
gm.add_importo(rabb, abb, FALSE);
rabb.add("");
}
rabb.add(sum.get(PART_TIPOMOV), 11);
}
// Le differenze cambio possono esistere solo in valuta
if (in_valuta)
{
const TImporto diff(sez, pag.get_real(PAGSCA_DIFFCAM));
if (!diff.is_zero())
{
TToken_string& rdiff = scadenze.row(scadenze.add(""));
rdiff.add("Differenza cambio", 4);
gm.add_importo(rdiff, diff);
rdiff.add(sum.get(PART_TIPOMOV), 11);
}
}
} // Il pagamento era a saldo
} // Fine ciclo sui pagamenti della rata
TToken_string& rsal = scadenze.row(scadenze.add(""));
rsal.add("Saldo rata ", 4); rsal << ra;
if (!scad.chiusa())
{
TImporto sl = scad.residuo(FALSE);
gm.add_importo(rsal, sl);
tot_lit += sl;
if (in_valuta)
{
sl = scad.residuo(TRUE, 0xB);
gm.add_importo(rsal, sl, TRUE);
tot_val += sl;
}
}
}
}
TRecord_array& unas = game->unassigned();
const int lastp = unas.last_row();
for (int pa = unas.first_row(); pa <= lastp; pa = unas.succ_row(pa))
{
const TRectype& pag = unas.row(pa);
const TRiga_partite& sum = game->riga(pa);
const char sez = sum.sezione();
TToken_string& row = scadenze.row(scadenze.add(""));
row.add(pag.get(PAGSCA_NRIGA));
row.add(pag.get(PAGSCA_NRATA));
row.add(sum.get(PART_DATADOC));
row.add(sum.get(PART_DATAPAG));
gm.add_descrizione(row, sum);
TImporto imp(sez, pag.get_real(PAGSCA_IMPORTO));
gm.add_importo(row, imp);
tot_lit += imp;
const real& impval = pag.get_real(PAGSCA_IMPORTOVAL);
if (!impval.is_zero())
{
imp.set(sum.sezione(), impval);
imp.normalize();
gm.add_importo(row, imp, TRUE);
tot_val += imp;
}
else
row.add("");
row.add(sum.get(PART_NREG));
row.add(sum.get(PART_DATAREG));
row.add(sum.get(PART_NUMDOC));
row.add("");
row.add(sum.get(PART_TIPOMOV));
row.add(pa);
const TImporto rit(sez, pag.get_real(PAGSCA_RITENUTE));
if (!rit.is_zero())
{
TToken_string& row = scadenze.row(scadenze.add(""));
row.add("Ritenute professionali", 4);
gm.add_importo(row, rit, FALSE);
row.add(sum.get(PART_TIPOMOV), 11);
tot_lit += rit;
}
}
if (lastrow > 0)
{
TToken_string& sp = scadenze.row(scadenze.add(""));
sp.add("Saldo partita", 4);
if (prima_valuta.in_valuta())
sp << ' ' << prima_valuta.codice();
#ifdef __EXTRA__
prima_valuta.set(gm, P_VALUTA, P_DATACAMBIO, P_CAMBIO);
#endif
gm.add_importo(sp, tot_lit);
gm.add_importo(sp, tot_val, TRUE);
}
if (should_delete_game)
delete game;
}
if (prima_valuta.in_valuta() != gm._valfirst)
{
sheet.swap_columns(106, 107); // Scambia le colonne dell'importo in lire e in valuta
gm._valfirst = !gm._valfirst;
}
if (sheet.items() > 0)
sheet.select(0, TRUE);
else
sheet.force_update();
main_app().end_wait();
}
if (k == K_INS)
{
gm.send_key(K_CTRL + 'N', 0, &partite); // Simula la pressione del tasto nuovo
return FALSE; // Rifiuta l'aggiunta di una riga
}
return TRUE;
}
bool TGame_mask::scadenze_notify(TSheet_field& scadenze, int r, KEY k)
{
if (k == K_INS)
{
TGame_mask& gm = (TGame_mask&)scadenze.mask();
gm.send_key(K_CTRL + 'N', 0, &scadenze); // Simula la pressione del tasto nuovo
return FALSE; // Rifiuta l'aggiunta di una riga
}
return TRUE;
}
// Complesso algoritmo per calcolare la sezione di una nuova riga partita
char TGame_mask::calcola_sezione(tipo_movimento tm) const
{
char sezione = ' ';
const char tipoc = conto().tipo();
#ifndef __EXTRA__
const TCausale& causale = app().causale();
tm = (tipo_movimento)causale.tipomov();
sezione = causale.sezione(1); // Usa la sezione della causale
#endif
if (sezione <= ' ') // Se non c'e' la sezione bell'e' ch'e' pronta
{
if (tm == tm_fattura || tm == tm_insoluto) // calcola in base al tipo movimento e
sezione = (tipoc == 'C') ? 'D' : 'A'; // al tipo cliente/fornitore
else
sezione = (tipoc == 'C') ? 'A' : 'D';
}
#ifndef __EXTRA__
// Gestione compensazioni
if (tipoc > ' ') // Se il tipo e' C o F
{
TBill bill; causale.bill(1, bill); // Legge primo conto causale
const char tc = bill.tipo();
if (tc > ' ' && tc != tipoc)
sezione = (sezione == 'D') ? 'A' : 'D'; // scambia segno
}
#endif
return sezione;
}
int TGame_mask::nuova_riga(TPartita& partita, tipo_movimento tm) const
{
const int una_riga = partita.last(); // Memorizza una riga valida
TRiga_partite& part = partita.new_row(); // Creazione nuova riga vuota
const int nriga = part.get_int(PART_NRIGA); // Nuova riga
// Copia dati movimento corrente
part.put(PART_NREG, _numreg); // Numero operazione
part.put(PART_NUMRIG, _numrig); // Riga su cui ho cliccato
// Forza il gruppo/conto cliente corretto
part.put(PART_GRUPPOCL, conto().gruppo());
part.put(PART_CONTOCL, conto().conto());
part.put(PART_TIPOMOV, (int)tm);
if (una_riga > 0)
{
const char* valuta = partita.riga(una_riga).get(PART_CODVAL);
part.put(PART_CODVAL, valuta);
}
#ifdef __EXTRA__
const TDate oggi(TODAY);
const char* s = oggi.string();
part.put(PART_DATADOC, s);
part.put(PART_DATAREG, s);
#else
// Setta il cambio corrente
const TValuta valuta(*this, P_VALUTA, P_DATACAMBIO, P_CAMBIO);
valuta.put(part);
TMask& cm = app().curr_mask();
const TCausale& causale = app().causale();
part.put(PART_NUMDOC, cm.get(F_NUMDOC));
part.put(PART_DATADOC, cm.get(F_DATADOC));
part.put(PART_DATAREG, cm.get(F_DATAREG));
part.put(PART_DESCR, cm.get(F_DESCR));
part.put(PART_DATAPAG, cm.get(F_DATAREG));
part.put(PART_TIPOPAG, 1);
const TRiga_partite* prima = (tm != tm_fattura) ? cerca_prima_riga() : NULL;
if (prima != NULL && prima != &part)
{
part.put(PART_DESCR, prima->get(PART_DESCR));
part.put(PART_DATAPAG, prima->get(PART_DATAPAG));
part.put(PART_TIPOPAG, prima->get(PART_TIPOPAG));
}
// Copia dati causale corrente
part.put(PART_CODCAUS, causale.codice());
if (causale.iva() != nessuna_iva)
{
part.put(PART_REG, cm.get(F_CODREG));
part.put(PART_PROTIVA, cm.get(F_PROTIVA));
}
#endif
const char sezione = calcola_sezione(tm);
// Memorizza solo la sezione (importi nulli)
part.put(PART_SEZ, sezione);
part.put(PART_SEZABB, sezione);
part.put(PART_SEZDIFCAM, sezione);
return nriga;
}
int TGame_mask::nuovo_pagamento(TPartita& partita, int nriga, int rata, tipo_movimento tm) const
{
#ifdef __EXTRA__
const int nrigp = nuova_riga(partita, tm);
#else
int nrigp = partita.mov2rig(_numreg, _numrig); // Cerca riga partita relativa alla riga rmov
if (nrigp <= 0) // Devo creare una nuova riga di partita
nrigp = nuova_riga(partita, tm);
#endif
TRectype& pagamento = partita.pagamento(nriga, rata, nrigp); // Crea nuovo pagamento
// Calcola riga causale per la contropartita in base al tipo pagamento
int caus = 2;
if (nriga != TPartita::UNASSIGNED)
{
const TRiga_partite& fatt = partita.riga(nriga);
const TRiga_scadenze& scad = fatt.rata(rata);
const int tp = scad.get_int(SCAD_TIPOPAG);
caus = partita.tipopag2causale(tp);
TRiga_partite& somma = partita.riga(nrigp);
somma.put(PART_TIPOPAG, tp);
somma.put(PART_CODVAL, fatt.get(PART_CODVAL));
pagamento.put(PAGSCA_CODABIPR, scad.get(SCAD_CODABIPR));
pagamento.put(PAGSCA_CODCABPR, scad.get(SCAD_CODCABPR));
pagamento.put(PAGSCA_CODABI, scad.get(SCAD_CODABI));
pagamento.put(PAGSCA_CODCAB, scad.get(SCAD_CODCAB));
pagamento.put(PAGSCA_CODAG, scad.get(SCAD_CODAG));
}
#ifndef __EXTRA__
const TCausale& causale = app().causale();
TBill contro; causale.bill(caus, contro); // Legge conto contropartita
if (caus != 2 && contro.empty()) // Se non specificato ...
causale.bill(caus = 2, contro); // ... prende il primo
contro.put(pagamento, TRUE); // Scrive conto contropartita
#endif
return nrigp;
}
bool TGame_mask::edit_scadenza_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TMask& m = f.mask();
const int nriga = m.get_int(101); // Numero riga fattura
if (nriga == 0)
return FALSE; // Ho cliccato su di un saldo (per sbaglio!)
TGame_mask& gm = (TGame_mask&)(m.get_sheet()->mask());
const TBill& bill = gm.conto(); // Clifo
TSheet_field& sp = gm.partite();
TToken_string& spr = sp.row(sp.selected());
const int anno = spr.get_int(0); // Anno
const TString numero = spr.get(); // Numero
TPartite_array& giochi = app().partite();
TPartita* was = giochi.exist(bill, anno, numero); // Controlla esistenza nell'array
TPartita& game = was ? *was : giochi.partita(bill, anno, numero);
long nreg = m.get_long(108); // Numero registrazione
const int nrata = m.get_int(102); // Rata selezionata (puo' essere 0)
int nrigp = m.get_int(113); // Pagamento selezionato (puo' essere 0)
if (nrata != 0 && nrigp == 0)
{
if (m.get_bool(114))
{
if (was == NULL) giochi.destroy(game);
return f.error_box("La rata %d e' bloccata.", nrata);
}
#ifndef __EXTRA__
const TValuta parval(game.riga(nriga));
const TValuta curval(gm, P_VALUTA, P_DATACAMBIO, P_CAMBIO);
if (parval != curval)
{
TString c = parval.codice();
if (c.empty()) c = "lire";
if (was == NULL) giochi.destroy(game);
return f.error_box("La fattura deve essere pagata in %s.", (const char*)c);
}
#endif
tipo_movimento tm;
#ifdef __EXTRA__
TMask* nm = new TNew_mask(gm.conto().tipo(), FALSE, FALSE);
nm->set(P_ANNO, game.anno());
nm->set(P_NUMERO, game.numero());
const KEY k = nm->run();
if (k == K_ENTER)
tm = (tipo_movimento)nm->get_int(P_NUOVO);
else
{
if (was == NULL) giochi.destroy(game);
return FALSE;
}
delete nm;
#else
tm = (tipo_movimento)app().causale().tipomov();
#endif
nrigp = gm.nuovo_pagamento(game, nriga, nrata, tm);
nreg = gm._numreg;
}
bool cambiato = FALSE;
if (nrigp > 0) // Si vuole editare un pagamento
{
if (nreg == gm._numreg)
{
cambiato = gm.edit_pagamento(game, nriga, nrata, nrigp);
if (cambiato)
{
#ifdef __EXTRA__
game.rewrite(); // In extra-contabile salvo subito!
#endif
}
}
else
{
#ifdef __EXTRA__
gm.prima_nota(nreg);
#else
if (was == NULL) giochi.destroy(game);
return f.error_box("Modificare il movimento %ld", nreg);
#endif
}
}
else
{ // Si vogliono editare le rate
#ifdef __EXTRA__
if (nreg > 0)
gm.prima_nota(nreg);
else
cambiato = gm.edit_fattura(game, nriga);
#else
if (nreg != gm._numreg || nrata == 0)
{
if (nreg == 0)
f.error_box("Utilizzare la gestione extra-contabile");
else
f.error_box("Modificare il movimento %ld", nreg);
if (was == NULL) giochi.destroy(game);
return FALSE;
}
#endif
}
if (cambiato)
{
if (m.is_running()) // Se la maschera e' aperta la chiudo
m.stop_run(K_FORCE_CLOSE);
TSheet_field& ss = gm.scadenze();
const int rs = ss.selected(); // Memorizza la riga corrente
gm.fill_partite(); // Aggiorna elenco partite
if (rs < ss.items()) // Se esiste ancora ...
ss.select(rs); // ... riporta la selezione sulla riga corrente
gm._changed = TRUE;
}
}
return TRUE;
}
bool TGame_mask::nuovo_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TGame_mask& gm = (TGame_mask&)f.mask();
int anno;
TString numero;
#ifdef __EXTRA__
const bool allow_fatt = TRUE;
#else
const bool allow_fatt = FALSE;
#endif
TMask* new_game = new TNew_mask(gm.conto().tipo(), allow_fatt, TRUE);
tipo_movimento tm;
#ifndef __EXTRA__
const TMask& cm = app().curr_mask();
tm = (tipo_movimento)app().causale().tipomov();
new_game->set(P_NUOVO, tm);
if (tm == tm_nota_credito)
{
new_game->set(P_ANNO, cm.get(F_ANNORIF));
new_game->set(P_NUMERO, cm.get(F_NUMRIF));
}
#endif
k = new_game->run();
tm = (tipo_movimento)new_game->get_int(P_NUOVO);
anno = new_game->get_int(P_ANNO);
numero = new_game->get(P_NUMERO);
// Distruzione maschera di richiesta
delete new_game; new_game = NULL;
if (k == K_ENTER)
{
// Creazione nuova partita
TPartita& game = app().partite().partita(gm.conto(), anno, numero);
bool edit = FALSE;
// N.B. Le fatture non possone essere editate in modo contabile
if (tm != tm_fattura)
{
const int nriga = TPartita::UNASSIGNED;
const int nrata = TPartita::UNASSIGNED;
const int nrigp = gm.nuovo_pagamento(game, nriga, nrata, tm);
edit = gm.edit_pagamento(game, nriga, nrata, nrigp);
#ifdef __EXTRA__
if (edit) game.rewrite();
#endif
}
#ifdef __EXTRA__
else
edit = gm.edit_fattura(game, 0);
#endif
if (edit)
{
gm.set(P_ANNO, anno);
gm.set(P_NUMERO, numero);
gm._changed = TRUE;
// Aggiorna sheet partite: aggiunge la nuova partita e lo riordina
gm.fill_partite();
} // Sono state apportate modifiche
}
}
return TRUE;
}
///////////////////////////////////////////////////////////
// Metodi della maschera delle partite
///////////////////////////////////////////////////////////
void TGame_mask::add_importo(TToken_string& s, const TImporto& i, bool valuta, int pos)
{
if (i.is_zero())
s.add("", pos);
else
{
TString80 v;
TImporto n(i); n.normalize();
if (valuta)
{
v = n.valore().string(0, 3);
const int sep = v.find('.');
v[sep] = ',';
}
else
v = n.valore().string(0, 0);
v << ' ' << n.sezione();
s.add(v, pos);
}
}
void TGame_mask::add_descrizione(TToken_string& s, const TRiga_partite& riga, int pos)
{
const TString& desc = riga.get(PART_DESCR);
if (desc.empty())
{
const TString& caus = riga.get(PART_CODCAUS);
if (caus.not_empty())
s.add(_causali.decode(caus), pos);
else
s.add("", pos);
}
else
s.add(desc, pos);
}
TImporto TGame_mask::get_importo(TToken_string& s, int pos) const
{
const TFixed_string imp(s.get(pos));
const real i(imp);
const char sez = imp.right(1)[0];
return TImporto(sez, i);
}
int TGame_mask::update_partita(const TRectype& riga,
const TImporto& saldo, const TImporto& doc,
const TImporto& pag, const TImporto& imp, int prow)
{
TSheet_field& games = partite();
TToken_string &r = games.row(prow); // Stringa di lavoro per lo sheet
if (!riga.empty()) // Esiste veramente
{
r.cut(0);
r.add(riga.get(PART_ANNO)); r.right_just(4); // Mette gli spazi se ce n'e' bisogno
r.add(riga.get(PART_NUMPART));
r.add(riga.get(PART_DATADOC));
r.add(riga.get(PART_NUMDOC));
add_importo(r, saldo);
add_importo(r, doc);
add_importo(r, pag);
add_importo(r, imp);
r.add(riga.get(PART_DESCR));
}
else
{
r.add("", 4);
r.add("", 5);
r.add("", 6);
r.add("", 7);
}
if (prow >= 0)
{
games.force_update(prow);
update_saldo_clifo();
games.force_update(games.items()-1);
aggiorna_residuo();
}
else
prow = partite().items()-1;
if (prow == 0)
{
const char all = TPartita::allineamento_richiesto(conto().tipo());
field(P_NUMERO).set_justify(all == 'R');
}
return prow;
}
int TGame_mask::update_partita(const TPartita& part, int prow)
{
int r = part.prima_fattura();
if (r <= 0) r = part.first();
TImporto saldo, doc, pag, imp;
part.calcola_saldo(saldo, doc, pag, imp);
return update_partita(part.riga(r), saldo, doc, pag, imp, prow);
}
int TGame_mask::update_partita(const TRectype& riga, int prow)
{
TImporto saldo, doc, pag, imp;
TRectype rec = riga;
const int err = TPartita::read_saldo(rec, saldo, doc, pag, imp);
return update_partita(rec, saldo, doc, pag, imp, prow);
}
void TGame_mask::update_saldo_clifo()
{
TString_array& s = partite().rows_array();
TImporto sal, doc, pag, imp;
for (int i = 0; i < s.items(); i++)
{
TToken_string& r = s.row(i);
if (r.get_int(0) > 0)
{
sal += get_importo(r, 4);
doc += get_importo(r, -1);
pag += get_importo(r, -1);
imp += get_importo(r, -1);
}
else
break;
}
TToken_string& r = s.row(s.add("", i));
r.add("");
r.add("");
r.add(TDate(TODAY).string());
r.add("");
add_importo(r, sal);
add_importo(r, doc);
add_importo(r, pag);
add_importo(r, imp);
r.add("Saldo ");
append_conto(r);
}
long TGame_mask::number_distance(const char* k, const char* n) const
{
TString16 key(k); key.upper(); key.trim();
const int kl = key.len();
TString16 num(n); num.upper(); num.trim();
const int nl = num.len();
long dist = 0;
for (int i = kl-1; i >= 0; i--)
{
const char kc = i < kl ? key[i] : 0;
const char nc = i < nl ? num[i] : 0;
const long d = abs(kc - nc) * (kl - i) * 32;
dist += d;
}
return dist;
}
bool TGame_mask::same_number(const char* key, const char* num) const
{
TString16 k(key); k.upper(); k.trim();
TString16 n(num); n.upper(); n.trim();
return k == n;
}
void TGame_mask::fill_partite()
{
const int annorif = get_int(P_ANNO); // Anno corrente
const TString numrif = get(P_NUMERO); // Partita corrente
const bool all = get(P_SHOWALL).not_empty(); // Visualizza anche partite chiuse
TString_array& a = partite().rows_array();
a.destroy();
app().begin_wait();
TPartite_array& giochi = app().partite();
for (TPartita* gioco = giochi.first(); gioco != NULL; gioco = giochi.next())
{
// Visualizza solo le partite con almeno una riga! Non posso scaricarle a priori in quanto
// potrebbero essere state cancellate proprio ora e quindi devo tenerle cosi' per aggiornare
// correttamente gli archivi.
if (gioco->ok())
{
const TBill& k = gioco->conto();
bool u = (k.tipo() > ' ' && k.sottoconto() == conto().sottoconto()) || k == conto();
if (u && !all && gioco->chiusa() && gioco->mov2rig(_numreg, _numrig) <= 0)
u = FALSE;
if (u)
update_partita(*gioco, -1);
}
else
{ // Se la partita e' vuota ...
if (!gioco->is_on_file()) // ... e non esiste su file
giochi.destroy(*gioco); // posso eliminarla tranquillamente
}
}
TLocalisamfile partita(LF_PARTITE);
TRectype& curpar = partita.curr();
curpar.zero();
if (conto().tipo() > ' ') // Ignora gruppo e conto dei clifo
{
curpar.put(PART_TIPOCF, conto().tipo());
curpar.put(PART_SOTTOCONTO, conto().codclifo());
}
else
conto().put(curpar); // Scrive completamente i conti normali
const TRectype filter(curpar); // Record campione
for (int err = partita.read(_isgreat);
err == NOERR && curpar == filter;
err = partita.read(_isgreat))
{
if (!giochi.exist(curpar))
{
if (all || curpar.get_bool(PART_CHIUSA) == FALSE)
update_partita(curpar, -1);
}
// Forza lettura partita successiva nella prossima read
curpar.put(PART_NRIGA, (int)TPartita::UNASSIGNED);
}
a.sort();
for (int r = a.items()-1; r > 0; r--)
{
TToken_string& row = a.row(r);
if (annorif == row.get_int(0) && same_number(numrif, row.get(1)))
break;
}
update_saldo_clifo();
partite().force_update();
aggiorna_residuo();
if (a.items() > 1)
{
_riga_partite = -1;
partite().select(r, TRUE);
}
else
{
scadenze().destroy();
}
app().end_wait();
}
bool TGame_mask::edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp) const
{
TRectype oldpag = p.pagamento(nriga, nrata, nrigp);
TRiga_partite& somma = p.riga(nrigp);
const bool nuovo = oldpag.get(PAGSCA_ACCSAL) != "S" &&
oldpag.get_real(PAGSCA_IMPORTO).is_zero() &&
oldpag.get_real(PAGSCA_RITENUTE).is_zero();
// We must create masks on the heap
TPay_mask* pm = new TPay_mask(*this, nuovo ? MODE_INS : MODE_MOD);
TPay_mask& m = *pm;
if (nriga == TPartita::UNASSIGNED)
{
TRiga_scadenze& scaden = somma.new_row(); // Crea una rata falsa
scaden.put(SCAD_DATASCAD, somma.get(PART_DATADOC));
m.set_pag(oldpag, scaden, _residuo);
somma.destroy_rows(); // Distrugge la rata falsa
}
else
{
const TRiga_scadenze& scaden = p.rata(nriga, nrata);
m.set_pag(oldpag, scaden, _residuo);
}
if (nuovo) // Inizializza automaticamente l'importo
{
TMask_field& imp = m.field(S_IMPORTO);
imp.set_dirty();
imp.on_key(K_F8);
}
KEY key = m.run();
if (key == K_DEL)
{
const bool truly = yesno_box("Confermare l'eliminazione");
if (!truly) key = K_ESC;
}
if (key == K_ESC && nuovo)
key = K_DEL;
if (key != K_ESC)
{
TRectype newpag(oldpag);
if (key == K_DEL)
{
newpag.zero(PAGSCA_ACCSAL); // Non puo' essere un saldo
newpag.zero(PAGSCA_IMPORTO); // Azzera importo ...
newpag.zero(PAGSCA_IMPORTOVAL); // .. anche in valuta
newpag.zero(PAGSCA_RITENUTE); // Azzera ritenute
}
else
{
m.get_pag(newpag, somma);
}
const TValuta val(somma);
#ifdef __EXTRA__
p.modifica_pagamento(newpag, val, TRUE);
#else
if (somma.is_nota_credito())
p.modifica_pagamento(newpag, val, TRUE);
else
app().notify_edit_pagamento(p, newpag, val);
#endif
}
delete pm;
return key != K_ESC;
}
#ifndef __EXTRA__
///////////////////////////////////////////////////////////
// Edit delle partite
///////////////////////////////////////////////////////////
bool TPrimanota_application::edit_partite(const TMask& m, int riga)
{
const char tipo = m.get(CG_TIPO)[0];
const char rt = m.get(CG_ROWTYPE)[0];
if (rt == 'T' && tipo <= ' ') // Nelle note di credito DEVE essere un clifo
return FALSE;
const int gruppo = m.get_int(CG_GRUPPO);
const int conto = m.get_int(CG_CONTO);
const long sottoconto = m.get_long(CG_SOTTOCONTO);
TBill b(gruppo, conto, sottoconto, tipo); // Legge il conto della riga selezionata
// Esci se il conto della riga cliente non e' valido
if (!b.ok())
return m.field(CG_SOTTOCONTO).error_box("Conto incompleto");
// Aggiorna conto sulla riga contabile
b.add_to(cgs().row(riga), 3, 0x0);
TMovimentoPN* pn = (TMovimentoPN*)get_relation();
curr_mask().autosave(*pn); // Aggiorna i dati della testata sulle partite
partite().update_reg(pn->curr());
// Esecuzione maschera di selezione partite
TGame_mask* mask = new TGame_mask(b, pn->curr().get_long(MOV_NUMREG), riga+1);
mask->run();
const bool changed = mask->changed();
delete mask;
if (changed)
{
cgs().force_update(); // Aggiornamento righe contabili
calcola_saldo();
}
return changed;
}
#endif