campo-sirio/ve/ve6100.cpp
angelo 258b268e94 Aggiunta possibilita' di scelta numero protocllo IVA.
git-svn-id: svn://10.65.10.50/trunk@4207 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-03-15 11:04:26 +00:00

1857 lines
62 KiB
C++
Executable File

// ve6100.cpp: programma di contabilizzazione documenti
// Orgiastica visione...
// L'anatra del dubbio dalle labbra di Vermouth.
//******************************************************************************
// \\\\\\\\ e *
// b \\\\\\\\ b *
// \\\\\\\\ e r d l *
// \\\\\\\\ *
// \\\\\\\\ i V o e h *
// L \\\\\\\\ *
// \\\\\\\\ b d *
// o \\\\\\\\ m a *
// +++++++++++++++++++++++++ b t *
// ++++++++++++++++++++++++++--------------------------------------------------|
// ++++++++++++++++++++++++++--------------------------------------------------|
// ++++++++++++++++++++++++ |---------------------------------------|
// u //////// u |---------------------------------------|
// ' //////// a | /\ /\ |
// //////// i | r / \ r / \ |
// a //////// \|/ / \ / \ l |
// ////////-----------------*---\ a / t \ / a \ /|
// //////// /|\ \ / \ / \ / |
// d //////// n | \ / \ / \ / |
// //////// l d | \/ a \/ l \/ |
//-----------------------------------------------------------------------------|
//
// Scared uh?
#include <applicat.h>
#include <relation.h>
#include <tabutil.h>
#include <mask.h>
#include <sheet.h>
#include <urldefid.h>
#include <progind.h>
#include <modaut.h>
#include "../cg/cg2101.h"
#include "../cg/cglib.h"
#include "../cg/saldacon.h"
#include "velib02.h"
#include "ve6100a.h"
#include <mov.h>
#include <rmov.h>
#include <rmoviva.h>
#include <clifo.h>
#include <cfven.h>
#include <occas.h>
#include <scadenze.h>
enum error_type {
no_error,
elaboration_error,
nr_es_error,
nr_reg_error,
nr_doc_error,
chg_stat_error,
clifo_error,
ultprot_error,
datadoc_error,
caus_error,
register_error,
change_error,
val_error,
codpag_error,
row_type_error,
no_rows_error,
conto_error,
movement_error,
mov_write_error,
generic_error
};
// TMovimentoPN_VE
// Classe derivata da TMovimentoPN per calcolare automaticamente le righe contabili
// una volta settate le righe iva e la riga di totale documento
// Sostanzialmente di tratta di aggiungere un metodo in piu' :
// recalc_cg_rows(), liberamente ispirato alla notify_iva() in cg2102.cpp
class TMovimentoPN_VE : public TMovimentoPN
{
TCausale * _caus;
protected:
// simula il K_SPACE di iva_notify
void create_row(int i);
// simula il K_ENTER di iva_notify
void enter_row(int i);
// verifica se si tratta di iva indetraibile
bool detraibile(TRectype& rec) const ;
// cerca la prima tra quelle di contabilita' che corrisponde al tipo indicato
int type2pos(char tipo);
// Trova nelle righe contabili un conto nelle righe di tipo prescelto
int bill2pos(const TBill& conto, char tipo);
// trasforma un real in TImporto, in base al tipo riga
TImporto real2imp(const real& r, char row_type);
// setta il record delle righe di contabilita'
int set_cg_rec(int n, const TImporto& imp, TBill& conto, const char* desc, char tipo);
// aggiunge l'importo indicato alla n-esima riga di contabilita'
bool add_cg_rec(int n, const TImporto& imp);
// Legge l'importo della riga n e lo ritorna col segno dovuto
TImporto get_cg_imp(int n);
// Setta l'importo della riga n
void set_cg_imp(int n, const TImporto& imp);
public:
// verifica se il movimento e' quadrato oppure ha qualche maledetto sbilancio
// ritorna TRUE, ovviamente, se everything's alright.
bool movement_ok() ;
// ricalcola le righe di contabilita' dalle righe iva presenti
// e verifica la quadratura del movimento. Ritorna TRUE se il movimento e' scrivibile
bool recalc_cg_rows(TCausale* caus = NULL);
TMovimentoPN_VE() {};
virtual ~TMovimentoPN_VE() {}
};
TImporto TMovimentoPN_VE::real2imp(const real& r, char row_type)
{
CHECK(_caus,"Orgggssbb..._caus pointer is NULL!");
bool dare;
if (row_type == 'S')
{
dare = _caus->sezione_ritsoc() == 'D';
}
else
{
dare = _caus->sezione_clifo() == 'D';
if (row_type != 'T' && row_type != 'F')
dare = !dare;
}
TImporto importo(dare ? 'D' : 'A', r);
return importo;
}
bool TMovimentoPN_VE::detraibile(TRectype& rec) const
{
CHECK(_caus,"Orgggssbb..._caus pointer is NULL!");
if (_caus->iva() == iva_vendite)
return TRUE;
if (rec.get_int(RMI_TIPODET) != 0)
return FALSE;
const real & p = _caus->reg().prorata();
return p < 100.0;
}
int TMovimentoPN_VE::bill2pos(const TBill& conto, char tipo)
{
const int items = cg_items();
for (int i = 0; i < items; i++)
{
TRectype& s = cg(i);
const char t = s.get_char(RMV_ROWTYPE);
if (t == tipo)
{
TBill c;
const int gr = s.get_int(RMV_GRUPPO);
const int co = s.get_int(RMV_CONTO);
const long so = s.get_long(RMV_SOTTOCONTO);
c.set(gr,co,so);
if (c == conto)
return i;
}
}
return -1;
}
int TMovimentoPN_VE::type2pos(char tipo)
{
const int items = cg_items();
for (int i = 0; i < items; i++)
{
TRectype& s = cg(i);
const char t = s.get_char(RMV_ROWTYPE);
if (t == tipo)
return i;
}
return -1;
}
void TMovimentoPN_VE::set_cg_imp(int n, const TImporto& imp)
{
TRectype& rec = cg(n);
rec.put(RMV_SEZIONE,imp.sezione());
rec.put(RMV_IMPORTO,imp.valore());
}
TImporto TMovimentoPN_VE::get_cg_imp(int n)
{
TRectype& rec = cg(n);
TImporto importo;
const char sez = rec.get_char(RMV_SEZIONE);
const real valore(rec.get_real(RMV_IMPORTO));
importo.set(sez,valore);
return importo;
}
bool TMovimentoPN_VE::add_cg_rec(int n, const TImporto& imp)
{
TImporto tot(get_cg_imp(n));
tot += imp;
//tot.normalize();
set_cg_imp(n, tot);
return tot.is_zero();
}
int TMovimentoPN_VE::set_cg_rec(int n, const TImporto& imp, TBill& conto,
const char* desc, char tipo)
{
const bool insert = n < 0;
if (insert) n = cg_items(); // Questa e' la prima riga di contabilita' vuota e disponibile
TRectype& rec = cg(n);
if (insert)
{
TRectype& head = lfile().curr();
const int annoes = head.get_int(MOV_ANNOES);
const long numreg = head.get_long(MOV_NUMREG);
TDate datareg(head.get_date(MOV_DATAREG));
rec.put(RMV_ANNOES,annoes);
rec.put(RMV_NUMREG,numreg);
rec.put(RMV_DATAREG,datareg);
}
rec.put(RMV_SEZIONE,imp.sezione());
rec.put(RMV_IMPORTO,imp.valore());
rec.put(RMV_TIPOC,conto.tipo());
rec.put(RMV_GRUPPO,conto.gruppo());
rec.put(RMV_CONTO,conto.conto());
rec.put(RMV_SOTTOCONTO,conto.sottoconto());
//rec.put(RMV_DESCR,conto.descrizione());
if (tipo == 'T') // Calcolo contropartita
{
TRectype& irec = iva(0);
const char t = irec.get_char(RMI_TIPOC);
const int gr = irec.get_int(RMI_GRUPPO);
const int co = irec.get_int(RMI_CONTO);
const long so = irec.get_long(RMI_SOTTOCONTO);
rec.put(RMV_TIPOCC,t);
rec.put(RMV_GRUPPOC,gr);
rec.put(RMV_CONTOC,co);
rec.put(RMV_SOTTOCONTOC,so);
}
else
{
const int pos = type2pos('T');
if (pos >= 0)
{
TRectype& crec = cg(pos);
const char t = crec.get_char(RMV_TIPOC);
const int gr = crec.get_int(RMV_GRUPPO);
const int co = crec.get_int(RMV_CONTO);
const long so = crec.get_long(RMV_SOTTOCONTO);
rec.put(RMV_TIPOCC,t);
rec.put(RMV_GRUPPOC,gr);
rec.put(RMV_CONTOC,co);
rec.put(RMV_SOTTOCONTOC,so);
}
}
rec.put(RMV_ROWTYPE,tipo);
return n;
}
void TMovimentoPN_VE::create_row(int i)
{
CHECK(_caus,"Orgggssbb..._caus pointer is NULL!");
TRectype& cur = iva(i);
real oldimp = cur.get_real(RMI_IMPONIBILE);
real oldiva = cur.get_real(RMI_IMPOSTA);
if (oldiva.is_zero() && _caus->corrispettivi()) // In caso di corrispettivi ...
{
const TString zanicchi(cur.get(RMI_CODIVA)); // Codice IVA
const TCodiceIVA i(zanicchi);
oldiva = i.scorpora(oldimp); // ... scorpora imposta dall'imponibile
}
const char tipod = detraibile(cur) ? 'D' : 'N';
if (type2pos(tipod) < 0 && !oldiva.is_zero())
{
const int ri = tipod == 'D' ? 3 : 4; // Calcola riga causale per l'IVA
TBill c; _caus->bill(ri, c);
if (c.ok())
{
const TString80 d(_caus->desc_agg(ri));
set_cg_rec(-1, real2imp(ZERO, 'I'), c, d, tipod);
}
else
if (ri == 4) // Se non esiste il conto IVA indetraibile ...
{ // ... somma imponibile e imposta
oldimp += oldiva;
oldiva = 0.0;
}
}
TBill oldconto;
const int gr = cur.get_int(RMI_GRUPPO);
const int co = cur.get_int(RMI_CONTO);
const long so = cur.get_long(RMI_SOTTOCONTO);
oldconto.set(gr,co,so);
if (oldconto.ok())
{
if (bill2pos(oldconto, 'I') < 0)
{
const TString d(_caus->desc_agg(2));
set_cg_rec(-1, real2imp(ZERO, 'I'), oldconto, d, 'I');
}
}
}
void TMovimentoPN_VE::enter_row(int i)
{
CHECK(_caus,"Orgggssbb..._caus pointer is NULL!");
TRectype& cur = iva(i);
real imponibile = cur.get_real(RMI_IMPONIBILE);
real imposta = cur.get_real(RMI_IMPOSTA);
if (imposta.is_zero() && _caus->corrispettivi()) // In caso di corrispettivi ...
{
const TString zanicchi(cur.get(RMI_CODIVA));
const TCodiceIVA i(zanicchi);
imposta = i.scorpora(imponibile); // ... scorpora imposta dall'imponibile
}
TBill conto;
const char t = cur.get_char(RMI_TIPOC);
const int gr = cur.get_int(RMI_GRUPPO);
const int co = cur.get_int(RMI_CONTO);
const long so = cur.get_long(RMI_SOTTOCONTO);
conto.set(gr,co,so,t);
int newpos = bill2pos(conto, 'I'); // Riga in cui andra' l'imponibile
const bool detrarre = detraibile(cur); // Determina se IVA detraibile
// Calcola riga causale col conto opportuno
const int ri = detrarre ? RIGA_IVA_DETRAIBILE : RIGA_IVA_NON_DETRAIBILE;
TBill contoiva; _caus->bill(ri, contoiva);
if (ri == 4 && !contoiva.ok()) // Se non c'e' il conto IVA indetraibile ...
{ // ... somma imponibile e imposta
imponibile += imposta;
imposta = 0.0;
}
// Aggiorna conto sulla riga contabile
if (newpos < 0) // conto non esistente: da inserire
{
const TImporto val(real2imp(imponibile, 'I'));
if (conto.ok() && !val.is_zero()) // Se c'e' imponibile ...
{ // crea una nuova riga contabile
const TString d(_caus->desc_agg(2));
set_cg_rec(-1, val, conto, d, 'I');
}
}
else
{
TImporto val(real2imp(imponibile, 'I'));
add_cg_rec(newpos, val);
}
// Aggiorna conto IVA sulla riga contabile
const char tipod = detrarre ? 'D' : 'N';
int newposiva = type2pos(tipod);
if (newposiva < 0)
{
if (!imposta.is_zero()) // Se c'e' imposta ...
{ // ... crea nuova riga per l'IVA
const TImporto val(real2imp(imposta, 'I'));
const TString d(_caus->desc_agg(ri));
set_cg_rec(-1, val, contoiva, d, tipod);
}
}
else
{
const TImporto val(real2imp(imposta, 'I'));
add_cg_rec(newposiva, val);
}
}
bool TMovimentoPN_VE::movement_ok()
{
TImporto tot_imp;
TImporto imp;
const int max = cg_items();
for (int i = 0; i < max; i++)
{
TRectype& r = cg(i);
const char sez = r.get_char(RMV_SEZIONE);
const real val(r.get_real(RMV_IMPORTO));
imp.set(sez,val);
tot_imp+=imp;
}
if (!tot_imp.is_zero())
return FALSE;
return TRUE;
}
bool TMovimentoPN_VE::recalc_cg_rows(TCausale* caus)
{
const int righe = iva_items();
bool external_caus = TRUE;
if (caus == NULL)
{
external_caus = FALSE;
TRectype& head = lfile().curr();
TString16 codcau(head.get(MOV_CODCAUS));
int year = head.get_int(MOV_ANNOIVA);
_caus = new TCausale (codcau,year);
}
else
_caus = caus;
for (int i=0; i<righe; i++)
{
create_row(i);
enter_row(i);
}
if (!external_caus)
{
delete _caus;
_caus = NULL;
}
return movement_ok();
}
// TIVA_element
// classe di elementi da memorizzare nel TAssoc_array (vedi sotto) _righe_iva
class TIVA_element : public TObject
{
real _imp;
real _iva;
real _ali;
public:
real& imp() { return _imp;} // Imponibile
real& iva() { return _iva;} // Iva
real& ali() { return _ali;} // Aliquota %
void zero(){ _imp = 0.0; _iva = 0.0; _ali = 0.0; }
virtual TObject* dup() const { return new TIVA_element(*this); }
TIVA_element& operator = (TIVA_element& a);
TIVA_element& operator += (const TRiga_documento& a);
TIVA_element() {_imp = 0.0; _iva = 0.0; _ali = 0.0;}
~TIVA_element() {};
};
TIVA_element& TIVA_element::operator=(TIVA_element& a)
{
_imp = a.imp(); _iva = a.iva(); _ali = a.ali();
return *this;
}
TIVA_element& TIVA_element::operator+=(const TRiga_documento& a)
// It's horrible, I know.
{
_imp += a.imponibile(); _iva += a.imposta(); _ali = a.iva().aliquota();
return *this;
}
// TContabilizzazione_app
// Applicazione di contabilizzazione documenti
class TContabilizzazione_app : public TApplication
{
TString16 _cod_el; // codice elaborazione immesso
TString16 _spin_cod, // codice iva spese d'incasso
_spbo_cod; // codice iva spese bolli
TDate _data_reg; // data di registrazione immessa
TDate _data_ini; // data di inizio intervallo
TDate _data_fine; // data di fine intervallo
bool _auto_data; // se TRUE prende in automatico la data di registrazione dalla data documento
bool _sc_enabled; // se TRUE il saldaconto di ditta e' abilitato
bool _can_write; // se TRUE e' abilitata la scrittura. Non appena rileva un errore rimane a FALSE for this instance
bool _nump_cfg; // se TRUE prende il numero rif. partita dal numero protocollo
byte _nump_iva; // se 1 prende il numero protocollo da registro iva, se 2 prende il numero protocollo dal numero doc.
TMask *_msk; // maschera di selezione dati
TRelation *_clifo; // relazione dei clienti e fornitori + cfven
TLocalisamfile *_attiv, // file delle attivita' (per far funzionare TRegistro)
*_fcaus, // file delle causale (per far funzionare TCausale)
*_docfile, // file dei documenti (per far funzionare TDocumento)
*_rdocfile, // file delle righe documento (per far funzionare TDocumento)
*_frcaus, // file delle righe causali (per far funzionare TCausale)
*_part, // file delle partite (per far funzionare TPartita)
*_scad, // file delle scadenze (per far funzionare TPartita)
*_pags, // file dei pagamenti (per far funzionare TPartita)
*_anamag; // file delle anagrafiche di magazzino
TTable *_cpg, // tabella condizioni di pagamento
*_gmc, // tabella gruppi/sottogruppi merceologici
*_rfa, // tabella raggruppamenti fiscali
*_cve, // tabella categorie di vendita
*_val, // tabella valute estere
*_tri, // tabella tipi di riga
*_prs, // tabella prestazioni
*_spp, // tabella spese
*_caa, // tabella categorie acquisto articoli
*_cra, // tabella categorie ricavo articoli
*_cco; // tabella categorie contabili
TDocumento *_doc; // documento corrente
TMovimentoPN_VE *_movimento; // movimento di prima nota costruito sul documento corrente
TPagamento *_pagamento; // pagamento corrente, ricalcolato prima di scrivere le scadenze
TAssoc_array _righe_iva; // array per la memorizzazione delle righe iva raggruppate in codesto modo:
// CODICE_IVA+TIPOCF+GRUPPO+CONTO+SOTTOCONTO
// una volta completo, tale array viene scorso per comporre le righe IVA
// di _movimento.
TCausale *_caus; // causale del documento corrente
TArray_sheet *_num_sheet; // Array sheet selezionabile dei codici numerazione
TString_array _tipi_doc; // Array di stringhe contenente i tipi documenti da elaborare
error_type _error; // Errore rilevato durante l'elaborazione
long _total_docs; // Totale documenti contabilizzati.
char _final_doc_status; // Valore per lo stato finale del documento
TToken_string _search_seq; // Sequenza di ricerca del conto costo/ricavo la correttezza dell'ordinamento
// va controllata nel programma di modifica parametri:
// "" = fine ordinamento
// CF = cliente fornitore
// CA = causale
// AR = articolo (costo/ricavo)
// GM = gruppo merceologico
// SM = sottogruppo merceologico
// RF = raggruppamento fiscale
// CV = categoria di vendita
// CC = categoria contabile
// Gli utlimi 6 fanno parte della ricerca per costi ricavi, in particolare AR,GM,SM e RF
// non possono essere interrotti da CV o CC. Ad es. CA|CF|AR|CV|GM|CC|RF non e' valida come stringa
// di ricerca.
TBill _sco_perc_bill, _sco_imp_bill, // Conti per gli sconti a percentuale ed importi (dalla configurazione)
_spin_billa, _spin_billv,
_spbo_billa, _spbo_billv;
protected: // TApplication
bool sc_enabled() const ;
// Funzione per ricercare il conto di costo/ricavo
error_type search_costo_ricavo(TBill& conto, const TRiga_documento& r);
// Funzione atomica per aggiungere le righe di spese d'incasso e bolli al TAssoc_array _righe_iva
void calculate_spese(real& spese, real& sp_iva, int ndec, bool is_incasso);
// Funzione per aggiungere le righe di spese d'incasso e bolli al TAssoc_array _righe_iva (chiama calculate_spese())
error_type add_spese_inbo();
// Funzione per aggiungere la riga iva al TAssoc_array _righe_iva
error_type add_iva_row(const TBill& conto, const TRiga_documento& r);
// Crea le righe iva su _movimento
error_type create_iva_rows();
// Crea la riga di totale documento
error_type create_total_doc_row();
// Cambia lo stato del documento
error_type change_doc_status();
// Compila la testata del movimento
error_type compile_head_mov();
// Compila le righe del movimento
error_type compile_rows_mov();
// Compila le scadenze
error_type compile_scad();
// Coontrolla se lo stato ed il tipo del documento sono validi e rispettano la selezione
bool doc_tipo_stato_ok();
// calcola il pagamento
void calc_pagament();
// scrive le scadenze
error_type write_scadenze();
// scrive il movimento e le scadenze
error_type write_all();
// Visualizza l'ultimo errore rilevato
void display_error();
// Contabilizza il documento
void contabilize_document();
// Contabilizza i documenti
void contabilize();
// Le 4 seguenti non hanno bisogno di commenti
virtual bool menu(MENU_TAG mt);
virtual bool create();
virtual bool destroy();
virtual void on_config_change();
// Handler del codice elaborazione differita
static bool handle_cod_eld(TMask_field& f, KEY k);
// Handler dell'intervallo di date
static bool handle_data_range(TMask_field& f, KEY k);
// Handler della data di registrazione
static bool handle_data_reg(TMask_field& f, KEY k);
// Handler del pulsante di selezione codici numerazione
static bool handle_select(TMask_field& f, KEY k);
// Ritorna il TArray_sheet contenente le selezioni sui codici numerazione
// Costruisce lo sheet dei codici numerazione
void build_num_sheet();
TArray_sheet* get_num_sheet() const { return _num_sheet; }
public:
// Verifica se non ci sono stati errori
bool good() const { return _error == no_error;}
error_type status() { return _error; }
void set_status(error_type e) { _error = e; }
TContabilizzazione_app() {_msk = NULL; _num_sheet = NULL;}
virtual ~TContabilizzazione_app() { }
};
inline TContabilizzazione_app& app() { return (TContabilizzazione_app&) main_app(); }
bool TContabilizzazione_app::handle_data_range(TMask_field& f, KEY k)
{
if (k==K_ENTER && f.dirty())
{
TMask& m = f.mask();
TDate da(m.get_date(F_DATA_INI));
TDate a(m.get_date(F_DATA_FIN));
m.field(F_DATA_REG).set_dirty();
//if (a == botime || da == botime) return TRUE;
if (a < da)
{
f.error_box("La data di inizio deve essere minore della data di fine.");
return FALSE;
}
if ((a - da) > 15)
{
f.error_box("L'intervallo tra le date non puo' eccedere i 15 giorni.");
return FALSE;
}
}
return TRUE;
}
bool TContabilizzazione_app::handle_data_reg(TMask_field& f, KEY k)
{
if (k==K_ENTER && f.dirty())
{
TMask& m = f.mask();
TDate data_reg(f.get());
if (data_reg == botime) return TRUE;
TDate da(m.get_date(F_DATA_INI));
//if (!da.ok()) return TRUE;
if ((data_reg - da) > 15)
{
f.error_box("L'intervallo tra la data di registrazione e la data di inizio non puo' eccedere i 15 giorni.");
return FALSE;
}
if (data_reg < da)
{
f.error_box("La data di registrazione non puo' essere minore della data di inizio.");
return FALSE;
}
}
return TRUE;
}
bool TContabilizzazione_app::handle_cod_eld(TMask_field& f, KEY k)
{
if (f.to_check(k) && k == K_TAB) // se e' cambiato ricostruisce anche lo sheet dei codici numerazione
{
app()._cod_el = f.get(); // aggiorna il codice elaborazione per la build_num_sheet()
f.mask().disable(DLG_OK);
app().build_num_sheet();
}
return TRUE;
}
bool TContabilizzazione_app::handle_select(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TMask& m = f.mask();
TArray_sheet* s = app().get_num_sheet();
if (s->run())
{
if (s->checked() != 0) // Hai selezionato qualcosa ?
m.enable(DLG_OK); // allora abilita il pulsante di conferma
else
m.disable(DLG_OK);
}
}
return TRUE;
}
void TContabilizzazione_app::build_num_sheet()
{
_num_sheet->destroy();
TTable eld("%ELD");
TTable num("%NUM");
TString s1,s2,s3;
TString16 tipon1,tipon2,tipon3,tipon4,tipon5; // tipi documento validi per la numerazione
long pos;
eld.put("CODTAB",_cod_el);
if (eld.read() == NOERR)
{
TToken_string t;
s1.format("%-20s",(const char*)eld.get("S2"));
s3 = eld.get("S7");
_final_doc_status = eld.get("S4")[0];
for (int i=0;i<5;i++)
{
t = s1.mid(i*4,4); // Tipo documento
if (t.trim().empty()) break;
t.add(s3.mid(i,1)); // Stato iniziale
_tipi_doc.add(t); // Aggiunge questo tipo documento alla lista
}
for (pos=0,num.first();num.good();num.next(),pos++) // scorre tutte le numerazioni possibili
{
TToken_string t;
t.add(" ");
t.add(num.get("CODTAB"));
t.add(num.get("S0"));
_num_sheet->add(t);
s2 = num.get("S2"); // reperisce i tipi documento validi per questa numerazione
tipon1 = s2.mid(0,4);
tipon2 = s2.mid(4,4);
tipon3 = s2.mid(8,4);
tipon4 = s2.mid(12,4);
tipon5 = s2.mid(16,4);
const int n1 = s1.find(tipon1);
const int n2 = s1.find(tipon2);
const int n3 = s1.find(tipon3);
const int n4 = s1.find(tipon4);
const int n5 = s1.find(tipon5);
if ((tipon1.empty() || n1<0) && (tipon2.empty() || n2<0) &&
(tipon3.empty() || n3<0) && (tipon4.empty() || n4<0) &&
(tipon5.empty() || n5<0))
_num_sheet->disable_row(pos);
else
_num_sheet->enable_row(pos);
}
}
}
void TContabilizzazione_app::on_config_change()
{
TPartita::carica_allineamento();
}
bool TContabilizzazione_app::create()
{
TApplication::create();
if (!has_module(CGAUT))
{
error_box("Impossibile eseguire il programma se il modulo Contabilita' Generale non e' abilitato");
return FALSE;
}
_error = no_error;
_can_write = TRUE;
_caus = NULL;
_pagamento = NULL;
_movimento = NULL;
_msk = new TMask("ve6100a");
_msk->set_handler(F_CODICE_ELAB,handle_cod_eld);
_msk->set_handler(F_DATA_INI,handle_data_range);
_msk->set_handler(F_DATA_FIN,handle_data_range);
_msk->set_handler(F_DATA_REG,handle_data_reg);
_msk->set_handler(DLG_USER,handle_select);
_num_sheet = new TArray_sheet(-1,-1,-4,-4,"Codici numerazione",
"@1|Cod. numerazione|Descrizione@50");
_docfile = new TLocalisamfile(LF_DOC);
_rdocfile = new TLocalisamfile(LF_RIGHEDOC);
_doc = new TDocumento;
_cpg = new TTable("%CPG");
_tri = new TTable("%TRI");
_val = new TTable("%VAL");
_prs = new TTable("PRS");
_spp = new TTable("SPP");
_caa = new TTable("CAA");
_cra = new TTable("CRA");
_gmc = new TTable("GMC");
_rfa = new TTable("RFA");
_cve = new TTable("CVE");
_cco = new TTable("CCO");
_clifo = new TRelation(LF_CLIFO);
_clifo->add(LF_CFVEN,"TIPOCF=TIPOCF|CODCF=CODCF");
_fcaus = new TLocalisamfile(LF_CAUSALI);
_frcaus = new TLocalisamfile(LF_RCAUSALI);
_part = new TLocalisamfile(LF_PARTITE);
_scad = new TLocalisamfile(LF_SCADENZE);
_pags = new TLocalisamfile(LF_PAGSCA);
_attiv = new TLocalisamfile(LF_ATTIV); // Altrimenti TRegistro non va!
_anamag = new TLocalisamfile(LF_ANAMAG);
TConfig conf(CONFIG_DITTA);
_search_seq = conf.get("RICERCACR","ve");
// costruisce la stringa che controlla la ricerca del conto costo/ricavo
// Attenzione! non esegue alcun controllo di consistenza sulla corretta sequenza
// presuppone che il programma di configurazione abbia generato correttamente
// il tutto.
if (_search_seq.items() == 0)
{
error_box("Non e' abilitata alcuna ricerca per il conto di costo/ricavo in configurazione.");
return FALSE;
}
_sc_enabled = conf.get_bool("GesSal","cg");
_nump_cfg = conf.get_bool("RifPro","cg");
int gr,co;
long so;
gr = conf.get_int("SCOPRCODCON","ve",1);
co = conf.get_int("SCOPRCODCON","ve",2);
so = conf.get_long("SCOPRCODCON","ve",3);
_sco_perc_bill.set(gr,co,so);
gr = conf.get_int("SCOIMCODCON","ve",1);
co = conf.get_int("SCOIMCODCON","ve",2);
so = conf.get_long("SCOIMCODCON","ve",3);
_sco_imp_bill.set(gr,co,so);
gr = conf.get_int("SPINCODCONA","ve",1);
co = conf.get_int("SPINCODCONA","ve",2);
so = conf.get_long("SPINCODCONA","ve",3);
_spin_billa.set(gr,co,so);
gr = conf.get_int("SPINCODCONV","ve",1);
co = conf.get_int("SPINCODCONV","ve",2);
so = conf.get_long("SPINCODCONV","ve",3);
_spin_billv.set(gr,co,so);
gr = conf.get_int("SPBOCODCONA","ve",1);
co = conf.get_int("SPBOCODCONA","ve",2);
so = conf.get_long("SPBOCODCONA","ve",3);
_spbo_billa.set(gr,co,so);
gr = conf.get_int("SPBOCODCONV","ve",1);
co = conf.get_int("SPBOCODCONV","ve",2);
so = conf.get_long("SPBOCODCONV","ve",3);
_spbo_billv.set(gr,co,so);
_spin_cod = conf.get("SPINCODIVA","ve");
_spbo_cod = conf.get("SPBOCODIVA","ve");
dispatch_e_menu(BAR_ITEM(1));
return TRUE;
}
bool TContabilizzazione_app::destroy()
{
if (_msk) delete _msk;
if (_num_sheet) delete _num_sheet;
if (_docfile) delete _docfile;
if (_rdocfile) delete _rdocfile;
if (_doc) delete _doc;
if (_cpg) delete _cpg;
if (_tri) delete _tri;
if (_val) delete _val;
if (_gmc) delete _gmc;
if (_rfa) delete _rfa;
if (_cve) delete _cve;
if (_cco) delete _cco;
if (_prs) delete _prs;
if (_spp) delete _spp;
if (_caa) delete _caa;
if (_cra) delete _cra;
if (_fcaus) delete _fcaus;
if (_frcaus) delete _frcaus;
if (_part) delete _part;
if (_scad) delete _scad;
if (_pags) delete _pags;
if (_clifo) delete _clifo;
if (_attiv) delete _attiv;
if (_anamag) delete _anamag;
return TApplication::destroy();
}
bool TContabilizzazione_app::menu(MENU_TAG mt)
{
while (_msk->run() == K_ENTER)
{
_cod_el = _msk->get(F_CODICE_ELAB);
_data_ini = _msk->get_date(F_DATA_INI);
_data_fine = _msk->get_date(F_DATA_FIN);
_data_reg = _msk->get_date(F_DATA_REG);
_auto_data = _msk->get_bool(F_DATA_AUTO);
_nump_iva = _msk->get_int(F_SELPROT);
//_data_fine++;
contabilize();
}
return FALSE;
}
error_type TContabilizzazione_app::search_costo_ricavo(TBill& conto, const TRiga_documento& r)
{
const int items = _search_seq.items();
TLocalisamfile & cli_file = _clifo->lfile(); // YES, arriva qui dentro quando la relazione e' gia' posizionata
const bool is_cli = cli_file.get(CLI_TIPOCF) == "C";
bool skip_art_related = FALSE;
bool skip_clifo = _clifo->bad();
TCodiceIVA codiva(r.get("CODIVA"));
const char t = r.tipo().tipo();
int gr,co;
long so;
switch (t)
{
case 'O': // righe omaggio come articoli spiaccicato identico (avranno imponibile 0)
case 'M': // righe di merce
{
// posiziona l'anagrafica sull'articolo specificato sulla ..iga
_anamag->put("CODART",r.get("CODART"));
if (_anamag->read() != NOERR) // se non trova l'articolo saltera' anche gmc,smc,rfa.
skip_art_related = TRUE;
// Scorre la stringa di ricerca
for (int i=0;good() && i<items;i++)
{
TString16 tok(_search_seq.get(i));
if (tok == "CF")
{
if (skip_clifo) continue;
gr = cli_file.get_int(CLI_GRUPPORIC);
co = cli_file.get_int(CLI_CONTORIC);
so = cli_file.get_long(CLI_SOTTOCRIC);
conto.set(gr,co,so);
if (conto.ok()) break; // se lo trova esce (tutti != 0)
}
else
if (tok == "CA")
{
CHECK(_caus,"Orgggssbb..._caus pointer is NULL!");
if (_caus->IVA2bill(codiva,conto)) break; // se lo trova esce
}
else
if (tok == "AR")
{
if (skip_art_related) continue;
gr = _anamag->get_int(is_cli ? "GRUPPOV" : "GRUPPOA");
co = _anamag->get_int(is_cli ? "CONTOV" : "CONTOA");
so = _anamag->get_long(is_cli ? "SOTTOCV" : "SOTTOCA");
conto.set(gr,co,so);
if (!conto.ok()) // se il conto non c'e' guarda la categoria acquisti/vendite
{
TTable *t = is_cli ? _cra : _caa;
t->put("CODTAB",_anamag->get(is_cli ? "CATCONV" : "CATCONA"));
if (t->read() == NOERR)
{
gr = atoi(t->get("S1"));
co = atoi(t->get("S2"));
so = atol(t->get("S3"));
conto.set(gr,co,so);
}
}
if (conto.ok()) break;
}
else
if (tok == "GM" || tok == "SM" || tok == "RF")
{
if (skip_art_related) continue;
const bool is_fis = tok == "RF";
TTable * tab = is_fis ? _rfa : _gmc;
TString codtab(_anamag->get(is_fis ? "GRMERC" : "RAGGFIS"));
if (tok == "GM")
codtab.cut(2); // gli ultimi 2 si riferiscono al sottogruppo.
tab->put("CODTAB",codtab);
if (tab->read() == NOERR)
{
gr = tab->get_int(is_cli ? "I3" : "I0");
co = tab->get_int(is_cli ? "I4" : "I1");
so = tab->get_long(is_cli ? "I5" : "I2");
conto.set(gr,co,so);
}
if (conto.ok()) break;
}
else
if (tok == "CV" || tok == "CC")
{
const bool is_cve = tok == "CV";
if (is_cve && !is_cli) continue; // se e' un fornitore salta questa condizione
TTable* t = is_cve ? _cve : _cco;
TString cod(is_cve ? _doc->get("CATVEN") : "");
if (cod.empty())
{
if (skip_clifo) continue; // se non aveva trovato il cliente salta al prossimo
cod = _clifo->lfile(LF_CFVEN).get(is_cve ? CFV_CATVEN : CFV_CODCATC);
}
t->put("CODTAB",cod);
if (t->read() == NOERR)
{
const bool x =(is_cve || is_cli);
gr = t->get_int(x ? "I3" : "I0");
co = t->get_int(x ? "I4" : "I1");
so = t->get_long(x ? "I5": "I2");
conto.set(gr,co,so);
}
if (conto.ok()) break;
}
}
break; // case 'M'
}
case 'P': // righe prestazione
case 'S': // righe spese
{
TTable* tab = t == 'P' ? _prs : _spp;
tab->put("CODTAB",r.get("CODART"));
if (tab->read()==NOERR)
{
gr = tab->get_int(is_cli ? "I0" : "I3");
co = tab->get_int(is_cli ? "I1" : "I4");
so = tab->get_long(is_cli ? "I2" : "I5");
conto.set(gr,co,so);
}
break; // case 'P','S'
}
case 'C': // righe sconti (TBI) (reperire l'imposta e l'imponibile normalizzare. Il conto e' nei parametri)
// quale sconto deve reperire dalla configurazione? Sconto ad importo o sconto a percentuale?
if (!r.get("SCONTO").empty()) // se c'e' la percentuale reperisce il conto dello sconto a percentuale
conto = _sco_perc_bill;
else // altrimenti quello dello sconto ad importo
conto = _sco_imp_bill;
break; // case 'C'
case 'D': // righe descrizioni (saltare)
default :
break;
} // end of switch
if (good() && !conto.find())
_error = conto_error;
return _error;
}
bool TContabilizzazione_app::doc_tipo_stato_ok()
// Verifica che il tipo documento corrente esista tra i tipi previsti dalla elaborazione
// differita selezionata
{
const int items = _tipi_doc.items();
bool found = FALSE;
const TString16 tipo(_doc->tipo().codice());
const char stato = _doc->stato();
for (int i=0;i<items && !found;i++)
{
TToken_string& t = _tipi_doc.row(i);
const TString16 tipox(t.get(0));
const char statox = t.get(1)[0];
if (tipo == tipox && stato == statox)
found = TRUE;
}
return found;
}
bool TContabilizzazione_app::sc_enabled() const
{
bool rt = _sc_enabled;
if (_caus != NULL) rt &= _caus->saldaconto();
return rt;
}
error_type TContabilizzazione_app::compile_head_mov()
// Compila la testata
{
TEsercizi_contabili esc;
TLocalisamfile& mov = _movimento->lfile();
TRectype& mov_rec = mov.curr();
// Reperisce la data documento
TDate datadoc(_doc->data());
if (!datadoc.ok())
{
_error = datadoc_error;
return _error;
}
// reperisce la data di registrazione, che e' anche la data di competenza ed
// eventualmente la data74ter se nel registro della causale vi e' scritta l'informazione
// sulle agenzie di viaggio.
// se si e' specificata la data automatica prende invece la data del documento
TDate data_reg(_auto_data ? datadoc : _data_reg);
esc.update();
// reperisce il codice anno esercizio,
int cod_es = esc.date2esc(data_reg);
if (cod_es <= 0)
{
_error = nr_es_error;
return _error;
}
// reperisce l'ultimo numero di registrazione disponibile
mov.last();
const long numreg = mov.get_int(MOV_NUMREG) + 1;
if (mov.status() != NOERR || numreg < 1)
{
_error = nr_reg_error;
return _error;
}
TCodice_numerazione cod_num(_doc->numerazione());
// calcola il numero documento aggiungendo l'eventuale prefisso/postfisso.
TString numdoc(cod_num.complete_num(_doc->numero()));
if (numdoc.empty() || cod_num.status() != NOERR)
{
_error = nr_doc_error;
return _error;
}
numdoc.upper(); // Il numero documento e' uppercase!
// Istanzia la causale del documento corrente...
const TTipo_documento& tipo = _doc->tipo();
const TString codcaus(tipo.causale());
_caus = new TCausale(codcaus,data_reg.year());
if (!_caus->ok())
{
_error = caus_error;
return _error;
}
// per reperire il tipo documento ed il tipo movimento
// reperisce la descrizione dal tipo documento e la completa con la data documento ed il
// numero documento
TString descr(tipo.riferimento());
if (descr.empty()) descr = tipo.descrizione();
descr << " n. " << _doc->numero();
descr << " del " << datadoc.string();
// Codice registro IVA
TRegistro& registro = _caus->reg();
if (!registro.ok())
{
_error = register_error;
return _error;
}
long ult_prot;
if (_nump_iva == 1) // Reperisce l'ultimo numero di protocollo dal registro IVA
{
ult_prot = registro.protocol() +1;
if (ult_prot < 1)
{
_error = ultprot_error;
return _error;
}
}
else // oppure dal numero di documento
ult_prot = _doc->numero();
// Reperisce la valuta
TDate datacam(_doc->get_date("DATACAMBIO"));
TString codval(_doc->valuta());
real cambio(_doc->cambio());
codval.trim();
if (codval == "LIT")
{
codval = "";
cambio = ZERO;
}
if (codval.not_empty())
{
_val->put("CODTAB",codval);
if (_val->read() != NOERR)
{
_error = val_error;
return _error;
}
}
// Reperisce il cambio
if ((cambio != ZERO && codval.empty()) ||
cambio == ZERO && codval.not_empty())
{
_error = change_error;
return _error;
}
// Dati del cliente...
TString tipocf(_doc->get("TIPOCF"));
long codcf = _doc->get_long("CODCF");
TString occas;
{
TLocalisamfile& cli_file = _clifo->lfile();
cli_file.put(CLI_TIPOCF,tipocf); cli_file.put(CLI_CODCF,codcf);
if (_clifo->read(_isequal) == NOERR) // posiziona il cliente una volta per tutte
{
if (cli_file.get_bool(CLI_OCCAS))
{
occas = _doc->get("OCFPI");
TLocalisamfile ocf(LF_OCCAS);
ocf.put(OCC_CFPI,occas);
if (ocf.read() != NOERR)
{
_error = clifo_error;
return _error;
}
}
}
else
{
_error = clifo_error;
return _error;
}
}
// Codice pagamento
TString codpag(_doc->get("CODPAG"));
if (sc_enabled() || codpag.not_empty()) // La condizione di pagamento va controllata
{ // se e' abilitato il saldaconto o se e' stata inserita
_cpg->put("CODTAB",codpag);
if (_cpg->read() != NOERR)
{
_error = codpag_error;
return _error;
}
}
// Mo' riempie il record della incornata (testata)
mov_rec.zero();
mov_rec.put(MOV_ANNOES,cod_es); mov_rec.put(MOV_NUMREG,numreg);
mov_rec.put(MOV_DATAREG,data_reg); mov_rec.put(MOV_DATACOMP,data_reg);
mov_rec.put(MOV_DATADOC,datadoc);
if (registro.agenzia_viaggi()) mov_rec.put(MOV_DATA74TER,data_reg);
mov_rec.put(MOV_NUMDOC,numdoc); mov_rec.put(MOV_TIPODOC,_caus->tipo_doc());
mov_rec.put(MOV_CODCAUS,_caus->codice()); mov_rec.put(MOV_DESCR,descr);
mov_rec.put(MOV_TIPOMOV,char(_caus->tipomov()+'0')); mov_rec.put(MOV_ANNOIVA,data_reg.year());
mov_rec.put(MOV_REG,registro.name());
mov_rec.put(MOV_PROTIVA,ult_prot); mov_rec.put(MOV_CODVAL,codval);
mov_rec.put(MOV_CAMBIO,cambio); mov_rec.put(MOV_TIPO,tipocf);
mov_rec.put(MOV_DATACAM,datacam);
mov_rec.put(MOV_CODCF,codcf); mov_rec.put(MOV_OCFPI,occas);
mov_rec.put(MOV_CODPAG,codpag);
if (_caus->intra())
{
mov_rec.put(MOV_CODVALI,codval);mov_rec.put(MOV_CAMBIOI,cambio);
real corrval(_doc->imponibile());
real corrlire = corrval*cambio;
if (codval.not_empty() && codval != "LIT")
{
mov_rec.put(MOV_CORRLIRE,corrlire);
mov_rec.put(MOV_CORRVALUTA,corrval);
} else
mov_rec.put(MOV_CORRLIRE,corrval);
}
real totdocval(_doc->totale_doc());
real totdoclit = totdocval * cambio;
if (codval.not_empty() && codval != "LIT")
{
mov_rec.put(MOV_TOTDOC,totdoclit);
mov_rec.put(MOV_TOTDOCVAL,totdocval);
} else
mov_rec.put(MOV_TOTDOC,totdocval);
return _error;
}
void TContabilizzazione_app::calculate_spese(real& spese, real& sp_iva, int ndec, bool is_incasso)
{
char tipo;
int gr,co;
long so;
const bool is_cli = _doc->get("TIPOCF") == "C";
const TBill& zio = is_incasso ? (is_cli ? _spin_billv : _spin_billa) : (is_cli ? _spbo_billv : _spbo_billa);
TIVA sp_cod(is_incasso ? _spin_cod : _spbo_cod);
TIVA_element el_tmp;
TString key;
sp_iva = iva(spese,sp_cod,ndec);
tipo = zio.tipo();
gr = zio.gruppo();
co = zio.conto();
so = zio.sottoconto();
key.format("5|%-4s|%c|%3d|%3d|%6ld",(const char*)sp_cod.codice(),tipo,gr,co,so);
const bool exists = _righe_iva.is_key(key);
TIVA_element& el = (exists ? (TIVA_element&)_righe_iva[key] : el_tmp);
el.imp() = spese;
el.iva() = sp_iva;
el.ali() = sp_cod.aliquota();
_righe_iva.add(key,el,exists);
}
error_type TContabilizzazione_app::add_spese_inbo()
// Aggiunge le righe di spese incasso/bolli
{
real tot_netto, sp_incasso, sp_bolli;
real iva_sp_incasso, iva_sp_bolli;
const int ndec = _doc->in_valuta() ? 3 : 0;
// Aggiunge le spese d'incasso
tot_netto = _doc->totale_netto();
sp_incasso = _doc->spese_incasso(tot_netto,ndec,_netto/*TRUE*/);
if (sp_incasso != 0.0)
calculate_spese(sp_incasso,iva_sp_incasso,ndec,_netto/*TRUE*/);
// Aggiunge le spese bolli
tot_netto += sp_incasso + iva_sp_incasso;
sp_bolli = _doc->bolli(tot_netto,ndec, _netto/*TRUE*/);
if (sp_bolli != 0)
calculate_spese(sp_bolli,iva_sp_bolli,ndec,FALSE);
return _error;
}
error_type TContabilizzazione_app::add_iva_row(const TBill& conto, const TRiga_documento& r)
// Aggiunge le righe iva all'assoc_array di raggruppamento
{
TIVA_element el_tmp;
TString cod(r.iva().codice());
const char tipo = conto.tipo();
const int gr = conto.gruppo();
const int co = conto.conto();
const long so = conto.sottoconto();
TString key;
const char tipo_r = r.tipo().tipo();
int ord=0;
// Ordine con cui vengono immesse le righe IVA:
// merce, omaggi, prestazioni, spese, bolli/spese d'incasso, sconti.
switch (tipo_r)
{
case 'M':
ord = 1;
break;
case 'O':
ord = 2;
break;
case 'P':
ord = 3;
break;
case 'S':
ord = 4;
break;
case 'C':
ord = 6;
break;
default: break;
}
key.format("%d|%-4s|%c|%3d|%3d|%6ld",ord,(const char*)cod,tipo,gr,co,so);
const bool exists = _righe_iva.is_key(key);
TIVA_element& el = (exists ? (TIVA_element&)_righe_iva[key] : el_tmp);
el += r;
_righe_iva.add(key,el,exists);
return no_error;
}
error_type TContabilizzazione_app::create_iva_rows()
{
const int items = _righe_iva.items();
const bool in_valuta = _doc->in_valuta();
TRectype& head = _movimento->lfile().curr();
int gr,co;
long so;
char tipo;
TToken_string key;
TString_array key_arr;
TString16 codiva;
TBill conto;
const int annoes = head.get_int(MOV_ANNOES);
const long numreg = head.get_long(MOV_NUMREG);
real cambio = head.get_real(MOV_CAMBIO);
real imponibile,imposta;
_righe_iva.get_keys(key_arr);
key_arr.sort();
//TIVA_element* cur = (TIVA_element*)_righe_iva.first_item();
TIVA_element cur;
for (int i = 0; i<items/* && cur != NULL*/;i++)
{
//key =_righe_iva.get_hashobj()->key();
key = key_arr.row(i);
cur = (TIVA_element&) _righe_iva[key];
codiva = key.get(1);
tipo = key.get_char(2);
gr = key.get_int(3);
co = key.get_int(4);
so = atol(key.get(5));
conto.set(gr,co,so,tipo);
conto.find();
imponibile = cur.imp();
if (in_valuta)
{
imponibile = cur.imp() * cambio; // imponibile in lire
imposta = (imponibile * cur.ali()) / 100.0; // questa e' l'imposta ricalcolata
}
else
imposta = cur.iva();
// In contabilita' abbiamo 2 decimali...
imponibile.ceil(2);
imposta.ceil(2);
TRectype& rec_iva = _movimento->iva(i);
rec_iva.put(RMI_ANNOES,annoes);
rec_iva.put(RMI_NUMREG,numreg);
rec_iva.put(RMI_NUMRIG,i+1); // La numerazione comincia da 1
rec_iva.put(RMI_CODIVA,codiva);
rec_iva.put(RMI_IMPONIBILE,imponibile);
rec_iva.put(RMI_IMPOSTA,imposta);
rec_iva.put(RMI_TIPOCR,conto.tipo_cr());
rec_iva.put(RMI_INTRA,_caus->intra());
rec_iva.put(RMI_TIPOC,conto.tipo());
rec_iva.put(RMI_GRUPPO,conto.gruppo());
rec_iva.put(RMI_CONTO,conto.conto());
rec_iva.put(RMI_SOTTOCONTO,conto.sottoconto());
//cur = (TIVA_element*)_righe_iva.succ_item();
}
return _error;
}
error_type TContabilizzazione_app::create_total_doc_row()
// Crea la riga contabile di totale documento
{
TRectype& rec_cg = _movimento->cg(0);
TRectype& head = _movimento->lfile().curr();
const int annoes = head.get_int(MOV_ANNOES);
const long numreg = head.get_long(MOV_NUMREG);
TDate datareg(head.get_date(MOV_DATAREG));
real totdoc(head.get_real(MOV_TOTDOC));
char rowtype = 'T';
TLocalisamfile& cli_file = _clifo->lfile();
TString16 tipocf(cli_file.get(CLI_TIPOCF));
const long codcf = cli_file.get_long(CLI_CODCF);
int gruppo = 0, conto = 0;
// Trova il mastro del cliente/fornitore
// cerca prima sul record del cliente/fornitore
if (_clifo->good())
{
gruppo = cli_file.get_int(CLI_GRUPPO);
conto = cli_file.get_int(CLI_CONTO);
}
// poi sulla categoria di vendita (solo per i clienti)
if ((gruppo == 0 || conto == 0) && tipocf == "C")
{
TString16 cod_cve(_clifo->lfile(LF_CFVEN).get(CFV_CATVEN));
_cve->put("CODTAB",cod_cve);
if (_cve->read() == NOERR)
{
gruppo = _cve->get_int("I3");
conto = _cve->get_int("I4");
}
}
TString descr;
descr = head.get(MOV_DESCR);// La descrizione della riga di totale documento la prende dalla testata
// se ancora non e' stato trovato piglia quello della causale
if (gruppo == 0 || conto == 0)
{
TBill zio;
_caus->bill(1,zio);
gruppo = zio.gruppo();
conto = zio.conto();
}
if (gruppo == 0 || conto == 0)
_error = conto_error;
TRectype& first_iva_row = _movimento->iva(0);
const char tc = first_iva_row.get_char(RMI_TIPOC);
const int grc = first_iva_row.get_int(RMI_GRUPPO);
const int coc = first_iva_row.get_int(RMI_CONTO);
const long soc =first_iva_row.get_long(RMI_SOTTOCONTO);
rec_cg.put(RMV_ANNOES,annoes);rec_cg.put(RMV_NUMREG,numreg);
rec_cg.put(RMV_NUMRIG,1); rec_cg.put(RMV_SEZIONE,tipocf == "C" ? "D" : "A");
rec_cg.put(RMV_DATAREG,datareg); rec_cg.put(RMV_TIPOC,tipocf);
rec_cg.put(RMV_GRUPPO,gruppo);rec_cg.put(RMV_CONTO,conto);
rec_cg.put(RMV_SOTTOCONTO,codcf); rec_cg.put(RMV_DESCR,descr);
rec_cg.put(RMV_TIPOCC,tc); rec_cg.put(RMV_GRUPPOC,grc);
rec_cg.put(RMV_CONTOC,coc);rec_cg.put(RMV_SOTTOCONTOC,soc);
rec_cg.put(RMV_IMPORTO,totdoc); rec_cg.put(RMV_ROWTYPE,rowtype);
return _error;
}
error_type TContabilizzazione_app::compile_rows_mov()
// Compila le righe
{
const int rows = _doc->rows();
_righe_iva.destroy(); // resetta l'assoc_array delle righe di iva
for (int i=1; good() && i<=rows; i++) // browse all this fucked document rows
{
const TRiga_documento& r= (*_doc)[i];
TString16 tiporiga(r.get("TIPORIGA"));
_tri->put("CODTAB",tiporiga);
if (_tri->read() == NOERR) // controlla l'esistenza della riga
{
TBill conto;
const char tipo = r.tipo().tipo();
if (tipo != 'D')
{
search_costo_ricavo(conto,r); // l'errore eventuale viene settato qui dentro
if (good())
add_iva_row(conto,r);
}
}
else
_error = row_type_error;
}
if (good() && _righe_iva.items() == 0)
_error = no_rows_error;
// Crea le righe per le spese d'incasso e bolli
if (good())
add_spese_inbo();
// Crea le righe di IVA
if (good())
create_iva_rows();
// Crea la riga di totale documento
if (good())
create_total_doc_row();
// crea le righe di contabilita'
if (good())
if (!_movimento->recalc_cg_rows(_caus)) _error = movement_error;
return _error;
}
void TContabilizzazione_app::calc_pagament()
{
TRectype& head = _movimento->lfile().curr();
TString16 codpag(head.get(MOV_CODPAG));
TString16 data(_doc->get("DATAINSC"));
_pagamento = new TPagamento(codpag, data);
real totspese = _doc->spese();
real totimposte = _doc->imposta();
real totimponibili = _doc->totale_doc() - totimposte - totspese;
const bool valuta = head.get(MOV_CODVAL).not_empty();
if (valuta)
{
const real change(head.get_real(MOV_CAMBIO));
real val1 = totimponibili * change;
real val2 = totimposte * change;
real val3 = totspese * change;
_pagamento->set_total_valuta( totimponibili, totimposte, totspese, change, val1, val2 ,val3);
}
else
_pagamento->set_total( totimponibili, totimposte, totspese );
_pagamento->set_rate_auto( );
}
error_type TContabilizzazione_app::write_scadenze()
// Scrive le scadenze. Liberamente tratto da cg2104.cpp.
{
calc_pagament();
const TRectype& head = _movimento->lfile().curr();
const long nreg = head.get_long(MOV_NUMREG);
const int anno = head.get_int(MOV_ANNOIVA);
const TString numpart(head.get(_nump_cfg ? MOV_PROTIVA : MOV_NUMDOC));
//TPartita* oldgame = partite().first();
TPartita* newgame = NULL;
int nuova_riga = 0;
if (anno > 0 && !numpart.blank())
{
const int tmov = _caus->tipomov();
const TString desc(head.get(MOV_DESCR));
const TString codpag(head.get(MOV_CODPAG));
const TString codcaus(_caus->codice());
const TString v(head.get(MOV_CODVAL));
const TDate d(head.get_date(MOV_DATACAM));
const real c(head.get_real(MOV_CAMBIO));
const TValuta cambio(v, d, c);
const TString agente(_doc->get("CODAG"));
const char sezione = _movimento->cg(0).get_char(RMV_SEZIONE); // Dare/Avere
TBill clifo;
const char tipocf = head.get_char(MOV_TIPO);
const long codcf = head.get_long(MOV_CODCF);
clifo.set(0,0,codcf,tipocf);
newgame = new TPartita(clifo, anno, numpart);
const int row = newgame->prima_fattura(nreg); // Riga fattura di questo movimento
TRiga_partite& partita = row <= 0 ? newgame->new_row() : newgame->riga(row);
nuova_riga = partita.get_int(PART_NRIGA);
CHECK(_pagamento,"E che diavolo! Ti avevo detto di calcolare prima _pagamento");
TPagamento& pag = *_pagamento;
// put data on partita
partita.put(PART_TIPOMOV, tmov);
partita.put(PART_NREG, nreg);
partita.put(PART_NUMRIG, 1);
partita.put(PART_DATAREG, head.get_date(MOV_DATAREG));
partita.put(PART_DATADOC, head.get_date(MOV_DATADOC));
partita.put(PART_NUMDOC, head.get(MOV_NUMDOC));
partita.put(PART_DESCR, desc);
partita.put(PART_CODCAUS, codcaus);
partita.put(PART_REG, _caus->reg().name());
partita.put(PART_PROTIVA, head.get_long(MOV_PROTIVA));
partita.put(PART_SEZ, sezione);
const real totdoc(head.get_real(MOV_TOTDOC));
partita.put(PART_IMPTOTDOC, totdoc);
cambio.put(partita);
const bool in_valuta = cambio.in_valuta();
real imponibile, imponibile_val;
for (int i = pag.n_rate()-1; i >= 0; i--)
{
if (in_valuta)
imponibile_val += pag.tval_rata(i);
imponibile += pag.tlit_rata(i);
}
partita.put(PART_IMPORTO, imponibile);
partita.put(PART_IMPORTOVAL, imponibile_val);
partita.put(PART_IMPOSTA, pag.imposta());
partita.put(PART_SPESE, pag.spese());
const TString abipr(_doc->get("CODABIP")),
cabpr(_doc->get("CODCABP")),
abi(_doc->get("CODABIA")),
cab(_doc->get("CODCABP"));
partita.elimina_rata(-1); // Elimina tutte le rate eventuali
const int nr = pag.n_rate();
for (i = 0; i < nr; i++)
{
TRiga_scadenze& scadenza = partita.new_row();
scadenza.put(SCAD_CODPAG, codpag); // Codice pagamento
scadenza.put(SCAD_CODAG, agente); // Codice agente
scadenza.put(SCAD_DATASCAD, pag.data_rata(i)); // Data scadenza
scadenza.put(SCAD_IMPORTO, pag.tlit_rata(i)); // Importo
if (in_valuta)
scadenza.put(SCAD_IMPORTOVAL, pag.tval_rata(i)); // Importo in valuta
scadenza.put(SCAD_TIPOPAG, pag.tipo_rata(i)); // Tipo pagamento
scadenza.put(SCAD_ULTCLASS, pag.ulc_rata(i)); // Ulteriore classificazione
scadenza.put(SCAD_CODABIPR, abipr); // Ns ABI
scadenza.put(SCAD_CODCABPR, cabpr); // Ns CAB
scadenza.put(SCAD_CODABI, abi); // Vs ABI
scadenza.put(SCAD_CODCAB, cab); // Vs CAB
// scadenza.put(SCAD_DESCR, ????); // Note
}
}
if (newgame != NULL) // Se non ho cancellato il numero partita ...
{
if (!newgame->write()) // Salva nuova partita
error_box("Si e' verificato un errore scrivendo le scadenze del documento.");
delete newgame;
}
if (_pagamento != NULL)
{
delete _pagamento;
_pagamento = NULL;
}
return _error;
}
error_type TContabilizzazione_app::write_all()
// Scrive il movimento e le scadenze, gestendo la rinumerazione se il movimento e' gia presente
{
// N.B: _error non viene settato, per non stampare il messaggio di errore 2 volte.
// basta solo ritornare qualcosa di != da no_error, per evitare le operazioni successive
// a write_all
TRectype& head = _movimento->lfile().curr();
long numreg = head.get_long(MOV_NUMREG);
while (_movimento->write() == _isreinsert)
head.put(MOV_NUMREG,++numreg);
if (_movimento->status() != NOERR)
{
error_box("Errore %d scrivendo il movimento %ld.",_movimento->status(),numreg);
return generic_error;
}
if (sc_enabled()) write_scadenze();
return no_error;
}
error_type TContabilizzazione_app::change_doc_status()
// Cambia lo stato del documento
{
TLocalisamfile d(LF_DOC);
_doc->stato(_final_doc_status);
if (_doc->head().rewrite(d) != NOERR)
_error = chg_stat_error;
return _error;
}
void TContabilizzazione_app::display_error()
{
TString msg;
TString numerazione = _doc->numerazione();
const long numero = _doc->numero();
switch (_error)
{
case elaboration_error:
msg.format("Il documento %s/%ld non rientra tra i tipi documento validi per l'elaborazione."
"Verificare i tipi documento ed il loro stato iniziale sul codice elaborazione inserito.",(const char*)numerazione,numero);
break;
case nr_es_error:
msg.format("Rilevato un codice esercizio errato contabilizzando il documento %s/%ld."
"Verificare l'esistenza e la correttezza della tabella esercizi e della data del documento.",(const char*)numerazione,numero);
break;
case nr_reg_error:
msg.format("Rilevato un numero di registrazione errato contabilizzando il documento %s/%ld."
"Verificare l'integrita' del file movimenti.",(const char*)numerazione,numero);
break;
case nr_doc_error:
msg.format("Rilevato un numero di documento errato contabilizzando il documento %s/%ld."
"Verificare il numero documento e il codice numerazione inseriti in tabella.",(const char*)numerazione,numero);
break;
case chg_stat_error:
msg.format("Rilevato un errore cambiando lo stato al documento %s/%ld."
"Verificare l'integrita' del file documenti.",(const char*)numerazione,numero);
break;
case clifo_error:
msg.format("Rilevato un errore caricando le informazioni del Cli/Fo sul documento %s/%ld."
"Verificare l'esistenza delle informazioni inserite sul file documenti e Cli/Fo.",(const char*)numerazione,numero);
break;
case ultprot_error:
msg.format("Rilevato un numero di protocollo IVA errato relativamente al documento %s/%ld."
"Verificare le informazioni inserite sul registro %s/%d.",(const char*)numerazione,numero,
(const char*) _caus->reg().name(),_caus->reg().year());
break;
case datadoc_error:
msg.format("Rilevato una data documento vuota relativamente al documento %s/%ld."
"Verificare l'informazione inserita.",(const char*)numerazione,numero);
break;
case caus_error:
msg.format("Rilevato un errore caricando la causale relativamente al documento %s/%ld."
"Verificare l'esistenza del codice causale inserito.",(const char*)numerazione,numero);
break;
case register_error:
msg.format("Rilevato un errore caricando il registro relativamente al documento %s/%ld."
"Verificare l'esistenza del codice causale/registro inseriti.",(const char*)numerazione,numero);
break;
case change_error:
msg.format("Rilevato un cambio senza valuta relativamente al documento %s/%ld."
"Verificare la correttezza delle informazioni inserite.",(const char*)numerazione,numero);
break;
case val_error:
msg.format("Rilevato un codice valuta inesistente relativamente al documento %s/%ld."
"Verificare la correttezza della informazione inserita.",(const char*)numerazione,numero);
break;
case codpag_error:
msg.format("Rilevato un codice pagamento non esistente relativamente al documento %s/%ld."
"Verificare l'esistenza del codice pagamento inserito.",(const char*)numerazione,numero);
break;
case row_type_error:
msg.format("Rilevato un codice tipo riga non esistente relativamente al documento %s/%ld."
"Verificare l'esistenza dei vari codici riga inseriti.",(const char*)numerazione,numero);
break;
case no_rows_error:
msg.format("Nessuna riga iva contabile e' stata trovata relativamente al documento %s/%ld."
"Verificare l'esistenza dei vari codici riga inseriti.",(const char*)numerazione,numero);
break;
case conto_error:
msg.format("Rilevato un conto di costo/ricavo inesistente relativamente al documento %s/%ld."
"Verificare l'esistenza dei conti associati alle righe.",(const char*)numerazione,numero);
break;
case movement_error:
msg.format("Rilevato uno sbilancio nel movimento relativamente al documento %s/%ld."
"Verificare la correttezza degli importi delle righe.",(const char*)numerazione,numero);
break;
case mov_write_error:
msg.format("Rilevato un errore in scrittura movimento relativamente al documento %s/%ld."
"Verificare la consistenza dei files.",(const char*)numerazione,numero);
break;
default:
msg.format("E' stato rilevato un errore generico contabilizzando il documento %s/%ld.",
(const char*)numerazione,numero);
break;
}
warning_box(msg);
_error = no_error; // reset error, as any other one would do, so you can show me the other ones.
_can_write = FALSE; // But from now on u cannot write anymore. U must exit this program and repair errors occurred.
}
void TContabilizzazione_app::contabilize_document()
{
_movimento = new TMovimentoPN_VE;
//_doc->compile_summary(); // ricalcola il documento
compile_head_mov();
if (good()) compile_rows_mov();
if (good() && _can_write)
if (write_all() == no_error) // Se la scrittura e' andata ok...
{
_total_docs++;
change_doc_status();
}
if (_caus != NULL)
{
delete _caus;
_caus = NULL;
}
delete _movimento;
}
void TContabilizzazione_app::contabilize()
{
TRelation doc_rel(LF_DOC);
TLocalisamfile righe_doc(LF_RIGHEDOC);
TRectype da(LF_DOC),a(LF_DOC);
const long items = _num_sheet->items();
int year_from = _data_ini.year();
int year_to = _data_fine.year();
TString16 codnum;
TString msg,filt_expr;
_total_docs = 0;
da.put("DATADOC",_data_ini);
da.put("PROVV","D");
da.put("ANNO",year_from);
a.put("DATADOC",_data_fine);
a.put("PROVV","D");
a.put("ANNO",year_to);
for (long i=0L; i<items;i++) // Scorre per tutte le numerazioni dello sheet
if (_num_sheet->checked(i)) // Se la numerazione corrente e' stata selezionata
{ // istanzia un cursore per la numerazione corrente, con i limiti di data
codnum = _num_sheet->row(i).get(1);
filt_expr = "CODNUM=\"";
filt_expr << codnum << "\"";
TCursor doc_cur(&doc_rel,filt_expr,3,&da,&a);
const long cur_items = doc_cur.items(); // Scorre tutti i documenti che rientrano nell'intervallo selezionato
if (cur_items == 0)
{
warning_box("Non vi sono documenti da contabilizzare per il codice numerazione %s",(const char*)codnum);
continue;
}
msg = "Contabilizzazione documenti ";
msg << codnum << " dal ";
msg << _data_ini.string() << " al ";
msg << _data_fine.string();
#ifdef DBG
TProgind p(cur_items,msg,TRUE,TRUE,1);
#else
TProgind p(cur_items,msg,FALSE,TRUE,1);
#endif
long j = 0;
#ifdef DBG
for (;j<cur_items && !p.iscancelled();j++)
#else
for (;j<cur_items;j++)
#endif
{
p.setstatus(j+1);
doc_cur = j;
if (_doc->read(doc_cur.curr()) != NOERR) continue; // legge il documento
if (codnum != _doc->get("CODNUM")) continue; // patch del cazzo
if (doc_tipo_stato_ok()) // controlla che il tipo documento e lo stato siano coerenti con la ELD selezionata
contabilize_document();
else
{
// ATTENZIONE!: se non ha ancora cominciato a contabilizzare, eventuali
// documenti con tipo o stato differenti vengono semplicemente scartati
// senza segnalare errori
if (_total_docs > 0)
_error = elaboration_error;
}
if (!good())
display_error();
}
#ifdef DBG
if (p.iscancelled()) break;
#endif
}
if (_total_docs > 0)
message_box("Totale documenti contabilizzati: %ld",_total_docs);
}
int ve6100 (int argc, char **argv)
{
TContabilizzazione_app a;
a.run(argc,argv,"Contabilizzazione documenti");
return TRUE;
}