campo-sirio/ef/ef0800.cpp
guy c85ed9c594 Patch level : 2.0 508
Files correlati     : ef0.exe ef0100a.msk ef0300a.msk ef0800a.msk
Ricompilazione Demo : [ ]
Commento            :

GF20044
Pur avendo inserito, nella relativa tabella, le banche di presentazione
quando cerco di inserire una distinta sulla bamca xy appare il seguente
messaggio d'errore:"VALORE NON VALIDO PER BANCA DI PRESENTAZIONE XY"

GF20045
Nella pagina parametri banche di presentazione se vado in ricerca non mi
appare la denominazione della Banca.

GF20046
Ho generato degli effetti raggruppati creando tre ricevute bancarie
dell'importo della fattura al netto dell'importo della nota di credito,
nell'operazione contabile di contabilizzazione della relativa distinta di
presentazione non riesce a chiudere correttamente le partite o meglio crea
in fondo alla partita delle righe 9999 rata 9999 invece di chiudere la rata
corrispondente.


git-svn-id: svn://10.65.10.50/trunk@11283 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-06-24 12:57:40 +00:00

1493 lines
50 KiB
C++
Executable File

/*
ef0800.cpp: programma di contabilizzazione effetti
Ho visto ombre di sconforto riemergere dal passato...
al largo dei bastioni di Orione
_|_|_
^/ . ..\^
___[=========]___
___-==++""" . /. . . \ . """++==-___
__-+"" __\ .. . . | .. . | . . . /__ ""+-__
/\__+-"" `-----=====\_ <O> _/=====-----' ""-+__/\
_/_/ ""="" \_\_
_________ .-~~~-..---..-~~~-. __________
-~.--<<<<<<<`-...--'.---.`--...-'>>>>>>>--.~-
=~~.-~ ````\\_`(`._.')'_//'''' ~-.~~=
[(o)/ ``.._..'' \(o)
.___________________ _-_
.\==============_=_/ ____.---'---`---.____
. \_ \ \----._________.----/
. \ \ / / `-_-'
. __,--`.`-'..'-_
. /____ ||
. `--.____,-'
Did you see my apogee ?
*/
#include <applicat.h>
#include <automask.h>
#include <modaut.h>
#include <progind.h>
#include <relation.h>
#include <sheet.h>
#include "../cg/cg2101.h"
#include "../cg/cg2103.h"
#include "../cg/cgsaldac.h"
#include "../cg/cglib02.h"
#include "../ve/velib.h"
#include "ef0301.h"
#include "ef0800a.h"
#include <mov.h>
#include <rmov.h>
#include <rmoviva.h>
#include <clifo.h>
#include <effetti.h>
#include <pagsca.h>
#include <doc.h>
#define CGROWS_LIMIT 96 // Limite imposto da invii/ricezioni
#define DIST_INCASSO 'I'
#define DIST_SBF 'B'
#define DIST_SCONTO 'S'
// TContabilizzazione_mask
class TContabilizzazione_mask : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& f, TField_event e, long jolly);
public:
TContabilizzazione_mask();
};
// TContabilizzazione_effetti_app
// Applicazione di contabilizzazione effetti
class TContabilizzazione_effetti_app : public TSkeleton_application
{
TDate _data_op; // Data operazione
TString16 _cod_caus; // Codice causale
TString16 _cod_caus_pag; // Codice causale pagamenti
int _cod_es; // Codice/anno esercizio
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
real _total_mov, // Totale del movimento corrente
_total_mov_val;// Same as above but in valuta
TString _desc_inc, _desc_pag; // Descrizioni movimento generato
TMask *_msk; // maschera di selezione dati
// TLocalisamfile *_attiv, // file delle attivita' (per far funzionare TRegistro)
// *_fcaus, // file delle causale (per far funzionare TCausale)
// *_frcaus, // file delle righe causali (per far funzionare TCausale)
// *_effetti, // file degli effetti (per TDistinta)
// *_reffetti, // file delle righe effetti (per TDistinta)
// *_cessionari, // file dei cessionari (per TDistinta)
// *_part, // file delle partite (per far funzionare TPartita)
// *_scad, // file delle scadenze (per far funzionare TPartita)
// *_pags, // file dei pagamenti (per far funzionare TPartita)
// *_clifo, // file dei clienti
// *_doc, // file dei documenti
// *_pcon; // file piano dei conti
TBill _banca, // conto di contropartita della banca
_cliente, // conto di contropartita del cliente
_trandiffcam; // conto di transizione per differenze cambi
TArray_sheet *_dist_sheet; // array_sheet di distinte selezionabili per la conatabilizzazione
TDistinta *_distinta; // Distinta per le elaborazioni
TPartite_array *_part_array; // Array di partite da scrivere
TMovimentoPN *_movimento; // Movimento di prima nota
TSaldo_agg _saldo; // Saldo da aggiornare
TCausale *_caus; // Causale contabile per le elaborazioni
error_type _error; // Errore rilevato durante l'elaborazione
long _total_bills; // Totale distinte contabilizzate.
int _cur_dist_row;// Numero di riga distinta corrente (per visualizzazione errore)
bool _dett_rate_att;// Dettaglia le rate su effetti attivi
bool _dett_rate_pas;// Dettaglia le rate su effetti passivi
protected: // TApplication
// Compila la testata del movimento
void compile_head_mov();
// Compila la riga di partita
void compile_riga_partita(TRiga_partite& riga, const TEffetto& effetto, const TRectype& riga_effetto, int numrig);
// Compila la riga di pagamento
void compile_riga_pagamento(TRectype& riga_pagamento, const TEffetto& effetto, const TRectype& riga_effetto, char acc_sal);
// Funzione di aggiornamento saldi una volta generato il movimento
void aggiorna_saldi();
// scrive il movimento e le scadenze
error_type write_all(bool chage_status = TRUE);
// cerca il conto di contropartita per la distinta corrente (setta _banca)
error_type search_bank_counter_bill(int tipopag=0);
// cerca il conto clienti
error_type search_clifo_bill(char tipo, const long codcf);
// ritorna la sezione corretta per la riga di partita
char sezione() const;
// Ordina le righe di un effetto
int sort_eff(TRecord_array& sorted);
// aggiunge una riga all'array dei clienti da una riga effetto
bool add_cg_row(const TEffetto& eff, const TRectype& reff, TArray& customers, TAssoc_array& banks, bool add_desc);
// somma ad una riga all'array dei clienti una riga effetto
void sum_cg_row(const TRectype& reff, TArray& customers, TAssoc_array& banks);
// aggiunge le righe spese al movimento
bool add_spese_rows(const real& spese);
// aggiunge riga pagamento da riga effetto
void compile_saldac(const TEffetto& eff, const TRectype& reff,
TImporto& abbuoni_att, TImporto& abbuoni_pas, TArray& differenze_cam,
TArray& customers);
// Controlla se il pagamento dell'effetto avra' differenze cambio
bool has_diffcam(const TEffetto& eff) const;
// Aggiunge una riga contabile al movimento
void join_row(const TRectype& row);
// unisce gli array clienti/banche nel record array delle righe contabili
void join_rows(TArray& customers, TAssoc_array& banks,
const TImporto& abbuoni_att, const TImporto& abbuoni_pas,
const TArray& differenze_cam, const real& spese);
// Visualizza l'ultimo errore rilevato
void display_error();
// Contabilizza l'effetto corrente
void contabilize_bill(const char tipo, const long numero);
// Contabilizza gli effetti
void contabilize();
// costruisce lo sheet delle distinte
void build_dist_sheet();
// Handler della selezione distinte
static bool handle_select(TMask_field& f, KEY k);
// Handler del pulsante di reset
static bool handle_reset(TMask_field& f, KEY k);
// Le 4 seguenti non hanno bisogno di commenti
virtual void main_loop();
virtual bool create();
virtual bool destroy();
virtual void on_config_change();
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; }
TArray_sheet& dist_sheet() { return *_dist_sheet; }
TContabilizzazione_effetti_app() : _msk(NULL) {}
virtual ~TContabilizzazione_effetti_app() { }
};
inline TContabilizzazione_effetti_app& app() { return (TContabilizzazione_effetti_app&) main_app(); }
// TContabilizzazione_mask
bool TContabilizzazione_mask::on_field_event(TOperable_field& f, TField_event e, long jolly)
{
switch (f.dlg())
{
case F_DATA_OP:
if (e == fe_modify || e == fe_close)
{
const TDate data = f.get();
TEsercizi_contabili esc;
if (esc.date2esc(data) <= 0)
return error_box(TR("La data deve appartenere ad un esercizio valido"));
}
break;
case F_RESET:
if (e == fe_button)
{
app().dist_sheet().check(-1, FALSE);
reset(F_DISTINTE);
}
break;
case F_SELECT:
if (e == fe_button)
{
TArray_sheet& sh = app().dist_sheet();
if (sh.run() == K_ENTER)
set(F_DISTINTE,sh.checked());
}
break;
default:
break;
}
return TRUE;
}
TContabilizzazione_mask::TContabilizzazione_mask()
: TAutomask("ef0800a")
{
}
// TContabilizzazione_effetti_app
void TContabilizzazione_effetti_app::build_dist_sheet()
{
TRelation eff_rel(LF_EFFETTI);
TCursor cur_dist(&eff_rel,"TIPODIST!=\"\"",4);
TRectype& rec = cur_dist.curr();
const long items = cur_dist.items();
_dist_sheet->destroy(); // resetta lo sheet delle distinte
if (items > 0)
{
cur_dist.freeze();
cur_dist = 0;
long ndist_prec = rec.get_long(EFF_NDIST);
char tipo_prec = rec.get_char(EFF_TIPODIST);
TString16 codabi, codcab, codval;
char tipocf;
bool enabled = TRUE;
int num_eff = 0;
for (long i = 0; i < items; i++)
{
cur_dist = i;
const long ndist = rec.get_long(EFF_NDIST);
const char tipo = rec.get_char(EFF_TIPODIST);
if (ndist != ndist_prec || tipo != tipo_prec)
{
TToken_string * t = new TToken_string;
t->add(" ");t->add(tipo_prec);
t->add(ndist_prec);
t->add(num_eff);
t->add(codabi);
t->add(codcab);
t->add(codval);
t->add(tipocf);
t->add(rec.get(EFF_DATADIST));
const long pos = _dist_sheet->add(t); //aggiunge una riga allo sheet delle distinte
_dist_sheet->enable_row(pos, enabled);
ndist_prec = ndist;
tipo_prec = tipo;
enabled = TRUE;
num_eff = 0;
}
if (num_eff == 0)
{
codabi = rec.get(EFF_CODABIP); // Memorizza dati della prima riga
codcab = rec.get(EFF_CODCABP);
codval = rec.get(EFF_CODVAL);
tipocf = rec.get_char(EFF_TIPOCF);
}
num_eff++; // numero di effetti che compongono la distinta
//enabled &= !rec.get_bool(EFF_EFFCONT);
}
TToken_string * t = new TToken_string;
t->add(" ");t->add(tipo_prec);
t->add(ndist_prec);
t->add(num_eff);
t->add(codabi);
t->add(codcab);
t->add(rec.get(EFF_CODVAL));
t->add(rec.get(EFF_TIPOCF));
t->add(rec.get(EFF_DATADIST));
const long pos = _dist_sheet->add(t); //aggiunge una riga allo sheet delle distinte
_dist_sheet->enable_row(pos, enabled);
}
}
bool TContabilizzazione_effetti_app::handle_reset(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
app()._dist_sheet->check(-1, FALSE);
f.mask().reset(F_DISTINTE);
}
return TRUE;
}
bool TContabilizzazione_effetti_app::handle_select(TMask_field& f, KEY k)
{
if (k==K_SPACE) // ricerca
{
TArray_sheet* sh = app()._dist_sheet;
if (sh->run() == K_ENTER)
f.mask().set(F_DISTINTE,sh->checked());
}
return TRUE;
}
void TContabilizzazione_effetti_app::on_config_change()
{
TPartita::carica_allineamento();
TConfig conf(CONFIG_DITTA, "ef");
_cod_caus = conf.get("CODCAUS"); // implementare programma di gestione parametri effetti
_cod_caus_pag = conf.get("CODCAUSPAG"); // implementare programma di gestione parametri effetti
_desc_inc = conf.get("DESCINC", NULL, -1, "Distinta d'incasso");
_desc_pag = conf.get("DESCPAG", NULL, -1, "Ordine di pagamento");
_dett_rate_att = conf.get_bool("DETRATATT"); // Dettaglio rate su effetti attivi
_dett_rate_pas = conf.get_bool("DETRATPAS"); // Dettaglio rate su effetti passivi
const long trans = conf.get_long("DIFFCAMS");
if (trans > 0)
_trandiffcam.set(conf.get_int("DIFFCAMG"), conf.get_int("DIFFCAMC"), trans);
_sc_enabled = conf.get_bool("GesSal","cg");
if (!has_module(CGAUT) && _sc_enabled)
{
error_box(TR("Impossibile contabilizzare gli effetti se il modulo Contabilita' Generale non e' abilitato"));
stop_run();
}
}
bool TContabilizzazione_effetti_app::create()
{
open_files(LF_TAB, LF_TABCOM, LF_CAUSALI, LF_RCAUSALI,
LF_EFFETTI, LF_REFFETTI, LF_CESS,
LF_MOV, LF_RMOV, LF_PARTITE, LF_SCADENZE, LF_PAGSCA,
LF_DOC, LF_CLIFO, LF_ATTIV, LF_PCON, LF_SALDI, 0);
_caus = NULL;
_error = no_error;
_can_write = TRUE;
_msk = new TContabilizzazione_mask();
_distinta = new TDistinta;
_movimento = new TMovimentoPN;
_dist_sheet = new TArray_sheet(-1, -1, -4, -4, TR("Selezione distinte"),
HR("@1|Tipo|Numero distinta@R|Numero effetti@R|ABI@5|CAB@5|Valuta|C/F|Data Dist."));
_part_array = new TPartite_array;
return TSkeleton_application::create();
}
bool TContabilizzazione_effetti_app::destroy()
{
if (_msk) delete _msk;
if (_caus) delete _caus;
if (_distinta) delete _distinta;
if (_movimento) delete _movimento;
if (_dist_sheet) delete _dist_sheet;
if (_part_array) delete _part_array;
return TApplication::destroy();
}
void TContabilizzazione_effetti_app::main_loop()
{
build_dist_sheet();
// Preselezione della distinta specificata sulla riga di comando
if (argc() >= 4)
{
const char tip = *argv(2);
const long num = atol(argv(3));
for (int r = 0; r < _dist_sheet->items(); r++)
{
TToken_string& row = _dist_sheet->row(r);
if (row.get_char(1) == tip && row.get_long(2) == num)
{
_dist_sheet->check(r);
break;
}
}
_msk->set(F_DISTINTE, _dist_sheet->checked());
}
_msk->set(F_DETT_RATE_ATT, _dett_rate_att ? "X" : "");
_msk->set(F_DETT_RATE_PAS, _dett_rate_pas ? "X" : "");
while (_msk->run() == K_ENTER)
{
if (!_dist_sheet->one_checked())
{
error_box(TR("Nessuna distinta selezionata"));
continue;
}
_data_op = _msk->get_date(F_DATA_OP);
TEsercizi_contabili esc;
_cod_es = esc.date2esc(_data_op);
_dett_rate_att = _msk->get_bool(F_DETT_RATE_ATT);
_dett_rate_pas = _msk->get_bool(F_DETT_RATE_PAS);
// Salva parametri per la prossima volta
{
TConfig conf(CONFIG_DITTA, "ef");
conf.set("DETRATATT", _dett_rate_att ? "X" : "");
conf.set("DETRATPAS", _dett_rate_pas ? "X" : "");
}
contabilize();
_msk->reset(F_DISTINTE);
build_dist_sheet();
}
}
void TContabilizzazione_effetti_app::display_error()
{
TString msg;
switch (_error)
{
case clifo_error:
msg.format(FR("Non e' possibile reperire il cliente/fornitore relativamente alla distinta %c %ld. "
"Controllare la riga %d"),_distinta->tipodist(), _distinta->ndist(),_cur_dist_row+1);
break;
case bank_error:
msg.format(FR("Non e' possibile reperire i conti di contropartita per la banca di presentazione "
"relativamente alla distinta %c %ld. Controllare la tabella e la causale."),_distinta->tipodist(), _distinta->ndist());
break;
case cau_abb_error:
msg.format(FR("Non e' possibile reperire i conti per gli abbuoni\n"
"o le differenze cambi dalla causale '%s'"), _caus->codice());
break;
case cau_spe_error:
msg.format(FR("Non e' possibile reperire il conto per le spese\n"
"dalla causale '%s'"), _caus->codice());
break;
case datadoc_error:
msg.format(FR("La data distinta %s non appartiene ad un esercizio valido"),
(const char*)_distinta->data_dist().string());
break;
default: // Errori generici o non indicati vengono visualizzati nel punto dell'errore
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.
}
bool TContabilizzazione_effetti_app::add_cg_row(const TEffetto& eff, const TRectype& reff, TArray& customers, TAssoc_array& banks, bool add_desc)
{
const long numreg = _movimento->curr().get_long(MOV_NUMREG);
real imp = reff.get_real(REFF_IMPORTO);
TRectype* c_rec = new TRectype(LF_RMOV);
// setta i valori per la riga cliente
c_rec->put(RMV_ANNOES,_cod_es);
c_rec->put(RMV_DATAREG,_data_op);
c_rec->put(RMV_NUMREG,numreg);
c_rec->put(RMV_SEZIONE,_caus->sezione_clifo());
_cliente.put(*c_rec);
if (_sc_enabled)
c_rec->put(RMV_ROWTYPE,"K");
TString80 desc;
if (_cliente.tipo() == 'F')
{
if (imp >= ZERO)
desc = TR("Pag. ft.");
else
desc = TR("Nota cr.");
}
else
{
if (imp >= ZERO)
desc = TR("Inc. ft.");
else
desc = TR("Nota cr.");
}
desc << ' ' << reff.get(REFF_NFATT);
if (_cliente.tipo() == 'C')
desc << TR(" sc. ") << eff.get(EFF_DATASCAD);
c_rec->put(RMV_DESCR, desc);
if (add_desc)
{
TString80 head_desc = _movimento->curr().get(MOV_DESCR);
head_desc << ' ' << desc;
_movimento->curr().put(MOV_DESCR, head_desc);
}
// setta i valori per la riga banca
TRectype b_r(*c_rec);
TString16 key;
key.format("%3d%3d%6ld",_banca.gruppo(),_banca.conto(),_banca.sottoconto());
const bool is_present = banks.is_key(key);
TRectype& b_rec = is_present ? (TRectype&)banks.find(key) : b_r;
// setta i valori
if (!is_present) // nuova banca? allora setta la sezione ed il conto
{
const int tipopag = eff.get_int(EFF_TIPOPAG);
int nriga = 2;
if (_sc_enabled && tipopag>1 && tipopag<8)
nriga = tipopag+1;
b_rec.put(RMV_SEZIONE,_caus->sezione(nriga));
b_rec.put(RMV_TIPOC,_banca.tipo());
b_rec.put(RMV_GRUPPO,_banca.gruppo());
b_rec.put(RMV_CONTO,_banca.conto());
b_rec.put(RMV_SOTTOCONTO,_banca.sottoconto());
if (_sc_enabled)
b_rec.put(RMV_ROWTYPE,"I");
b_rec.zero(RMV_DESCR);
}
real b_imp = b_rec.get_real(RMV_IMPORTO) + imp; // aggiorna l'importo per questa banca
b_rec.put(RMV_IMPORTO,b_imp);
banks.add(key,b_rec,is_present);
c_rec->put(RMV_IMPORTO,imp);
customers.add(c_rec);
return !is_present;
}
void TContabilizzazione_effetti_app::sum_cg_row(const TRectype& reff, TArray& customers, TAssoc_array& banks)
{
const real imp = reff.get_real(REFF_IMPORTO);
// setta i valori per la riga cliente
TRectype& c_rec = (TRectype&)customers[customers.last()];
const real c_imp = imp + c_rec.get_real(RMV_IMPORTO);
c_rec.put(RMV_IMPORTO, c_imp);
// setta i valori per la riga banca
TString16 key;
key.format("%3d%3d%6ld",_banca.gruppo(),_banca.conto(),_banca.sottoconto());
TRectype& b_rec = (TRectype&)banks.find(key);
const real b_imp = b_rec.get_real(RMV_IMPORTO) + imp; // aggiorna l'importo per questa banca
b_rec.put(RMV_IMPORTO,b_imp);
}
void TContabilizzazione_effetti_app::join_row(const TRectype& row)
{
const int n = _movimento->cg_items();
TRectype& riga = _movimento->cg(n);
riga = row;
riga.put(RMV_NUMRIG, n+1);
riga.put(RMV_ANNOES,_cod_es);
riga.put(MOV_DATAREG,_data_op);
}
bool TContabilizzazione_effetti_app::add_spese_rows(const real& spese)
{
if (spese.is_zero())
return FALSE;
TRectype& row_spese = _movimento->cg(-1);
TRectype& row_banca = _movimento->cg(-1);
TBill conto_spese; _caus->bill(11, conto_spese);
const char sez_spese = _caus->sezione(11);
const char sez_banca = sez_spese == 'D' ? 'A' : 'D';
row_spese.put(RMV_ANNOES,_cod_es);
row_spese.put(RMV_DATAREG,_data_op);
row_spese.put(RMV_SEZIONE, sez_spese);
row_spese.put(RMV_IMPORTO, spese);
conto_spese.put(row_spese);
_banca.put(row_spese, TRUE);
row_spese.put(RMV_DESCR, _caus->desc_agg(11));
if (_sc_enabled)
row_spese.put(RMV_ROWTYPE, 'G');
row_banca.put(RMV_ANNOES,_cod_es);
row_banca.put(RMV_DATAREG,_data_op);
row_banca.put(RMV_SEZIONE, sez_banca);
row_banca.put(RMV_IMPORTO, spese);
_banca.put(row_banca);
conto_spese.put(row_banca, TRUE);
if (_sc_enabled)
row_banca.put(RMV_ROWTYPE, 'L');
return TRUE;
}
void TContabilizzazione_effetti_app::join_rows(TArray& customers, TAssoc_array& banks,
const TImporto& abbuoni_att,
const TImporto& abbuoni_pas,
const TArray& differenze_cam,
const real& spese)
{
// aggiunge prima i record delle righe relative ai clienti
const int customer_items = customers.items();
for (int j=0; j<customer_items;j++)
join_row((const TRectype&) customers[j]);
// e poi i record delle righe relative alle banche
const int bank_items = banks.items();
TRectype* row;
for (j=0,row = (TRectype*)banks.first_item(); row != NULL && j<bank_items;j++,row = (TRectype *)banks.succ_item())
join_row(*row);
// infine abbuoni e differenze cambio
if (_sc_enabled)
{
TBill zio;
TRectype riga(_movimento->cg(0));
if (!abbuoni_pas.is_zero())
{
_caus->bill(9, zio); zio.put(riga);
if (!zio.ok()) _error = cau_abb_error;
riga.put(RMV_SEZIONE, abbuoni_pas.sezione());
riga.put(RMV_IMPORTO, abbuoni_pas.valore());
riga.put(RMV_ROWTYPE, "P");
join_row(riga);
}
if (!abbuoni_att.is_zero())
{
_caus->bill(10, zio); zio.put(riga);
if (!zio.ok()) _error = cau_abb_error;
riga.put(RMV_SEZIONE, abbuoni_att.sezione());
riga.put(RMV_IMPORTO, abbuoni_att.valore());
riga.put(RMV_ROWTYPE, "A");
join_row(riga);
}
if (differenze_cam.items() > 0)
{
TImporto diffcam;
for (int i = differenze_cam.items()-1; i >= 0; i--)
{
const TRectype& rec = (const TRectype&)differenze_cam[i];
TImporto dc(rec.get_char(RMV_SEZIONE), rec.get_real(RMV_IMPORTO));
diffcam += dc;
}
_caus->bill(13, zio);
if (!zio.ok())
_error = cau_abb_error;
zio.put(riga);
riga.put(RMV_SEZIONE, diffcam.sezione());
riga.put(RMV_IMPORTO, diffcam.valore());
riga.put(RMV_ROWTYPE, "C");
join_row(riga);
if (_trandiffcam.ok() && (customers.items() > 1 || differenze_cam.items() > 1))
{
TRectype& rec = _movimento->cg(_movimento->cg_items()-1);
_trandiffcam.put(rec); _trandiffcam.put(rec, TRUE);
riga.put(RMV_SEZIONE, diffcam.sezione() == 'D' ? 'A' : 'D');
_trandiffcam.put(riga); _trandiffcam.put(riga, TRUE);
riga.zero(RMV_ROWTYPE);
join_row(riga);
for (int i = 0; i < differenze_cam.items(); i++)
{
const TRectype& rec = (const TRectype&)differenze_cam[i];
join_row(rec);
}
}
}
}
if (add_spese_rows(spese))
{
const char tipocf = ((const TRectype&)customers[0]).get_char(RMV_TIPOC);
if (tipocf == 'C')
_total_mov -= spese;
else
_total_mov += spese;
}
}
error_type TContabilizzazione_effetti_app::search_clifo_bill(char tipo, const long codcf)
{
_error = no_error;
TString16 key;
key.format("%c|%ld", tipo, codcf);
const TRectype & clifo = cache().get(LF_CLIFO, key);
if (clifo.empty())
_cliente.set(0,0,0);
else
_cliente.set(clifo.get_int(CLI_GRUPPO), clifo.get_int(CLI_CONTO), codcf, tipo);
if (!_cliente.ok()) // se non e' valido, reperiscilo dalla riga #1 della causale
{
_caus->bill(1,_cliente); // conto della riga 1
_cliente.codclifo() = codcf;
if (!_cliente.ok())
_error = clifo_error;
}
return _error;
}
error_type TContabilizzazione_effetti_app::search_bank_counter_bill(int tipopag)
{
// reperisce i codici ABI e CAB della banca presentazione effetti dalla
// distinta e va a cercarli sulla tabella BNP di ditta.
// La banca di presentazione effetti e' una unica per tutta la distinta
// e non puo' essere vuota
_error = no_error;
if (tipopag == 0) // cerca sulla tabella e poi sulla 2a riga di causale
{
_banca.set(0,0,0); // resetta il conto...
TString16 codtab(_distinta->abip());
codtab << _distinta->cabp();
const TRectype& bnp = cache().get("BNP", codtab);
if (!bnp.empty())
{
const char* fg;
const char* fc;
const char* fs;
const char tipodist = _distinta->tipodist();
switch (tipodist)
{
case DIST_SBF:
fg = "I3"; fc = "I4"; fs = "I5";
break;
case DIST_SCONTO:
fg = "I6"; fc = "I7"; fs = "I8";
break;
case DIST_INCASSO: // Default
default:
if (_distinta->tipocf() == 'F')
{
fg = "I9"; fc = "I10"; fs = "I11";
}
else
{
fg = "I0"; fc = "I1"; fs = "I2";
}
break;
}
const int g = bnp.get_int(fg);
const int c = bnp.get_int(fc);
const long s = bnp.get_long(fs);
_banca.set(g,c,s);
}
// se non ha trovato la banca oppure il conto, verifica che vi sia
// il conto sulla riga 2 della causale (solo se SC non abilitato)
if (!_banca.ok() && !_sc_enabled)
_caus->bill(2,_banca); // conto della riga 2
// se il saldaconto non e' abilitato, il conto di contropartita sulla causale
// va verificato per ogni riga di distinta, a seconda del tipo di pagamento.
}
else
{
// cerca il conto relativo alla riga di causale:
// 1 Rimessa diretta o contanti (banca) riga 2
// 2 Tratta riga 3
// 3 Ricevuta bancaria riga 4
// 4 Cessione riga 5
// 5 Paghero' riga 6
// 6 Lettera di credito riga 7
// 7 Tratta accettata riga 8
// 8 Rapporti interban. diretti riga 2
// 9 Bonifici riga 2
_caus->bill(tipopag>0 && tipopag<8 ? tipopag+1:2,_banca);
}
if (!_banca.ok())
_error = bank_error;
return _error;
}
char TContabilizzazione_effetti_app::sezione() const
{
char sezione = ' ';
const char tipoc = _cliente.tipo();
tipo_movimento tm = (tipo_movimento)_caus->tipomov();
sezione = _caus->sezione(1); // Usa la sezione della causale
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';
}
return sezione;
}
void TContabilizzazione_effetti_app::compile_head_mov()
{
CHECK(_caus,"Causale non allocata");
TLocalisamfile& mov = _movimento->lfile();
mov.last();
const long numreg = mov.get_long(MOV_NUMREG)+1; // Calcola il numero di registrazione
const TDate datadist(_distinta->data_dist());
const TDate datacam(_distinta->data_cam());
const TString80 codval(_distinta->codval());
const real cambio(_distinta->cambio());
const long ndist = _distinta->ndist();
TEsercizi_contabili esc;
if (esc.date2esc(datadist) <= 0)
{
if (!yesno_box(FR("Attenzione: la data distinta %s non appartiene ad un esercizio valido:\n"
"Si desidera proseguire ugualmente?"), (const char*)datadist.string()))
{
_can_write = FALSE;
return;
}
}
TString des;
des = (_distinta->tipocf() == 'F') ? _desc_pag : _desc_inc;
des << ' ';
switch (_distinta->tipopag())
{
case 1: des << TR("rimessa diretta"); break;
case 2: des << TR("tratta"); break;
case 3: des << TR("ricevuta bancaria"); break;
case 4: des << TR("cessione"); break;
case 5: des << TR("paghero'"); break;
case 6: des << TR("lettera di credito"); break;
case 7: des << TR("tratta accettata"); break;
case 8: des << TR("rapp. interb. dir."); break;
case 9: des << TR("bonifico"); break;
default: des.rtrim(); break;
}
des << TR(" n.") << ndist;
mov.zero();
mov.put(MOV_DESCR,des);
mov.put(MOV_NUMREG,numreg);
mov.put(MOV_ANNOES,_cod_es);
mov.put(MOV_DATAREG,_data_op);
mov.put(MOV_DATACOMP,_data_op);
mov.put(MOV_DATADOC,datadist);
mov.put(MOV_NUMDOC,ndist);
mov.put(MOV_TIPODOC,_caus->tipo_doc());
mov.put(MOV_CODCAUS,_caus->codice());
mov.put(MOV_TIPOMOV,_caus->tipomov());
if (codval.not_empty())
{
mov.put(MOV_CODVAL, codval);
mov.put(MOV_DATACAM, _distinta->data_cam());
real cambio = _distinta->cambio();
const bool eurocambio = _distinta->contro_euro();
const TExchange chg(codval, cambio, eurocambio ? _exchange_contro : _exchange_base);
if (eurocambio && mov.curr().exist(MOV_CONTROEURO))
{
mov.put(MOV_CONTROEURO, eurocambio);
cambio = chg.get_contro_change();
}
else
{
cambio = chg.get_base_change();
}
mov.put(MOV_CAMBIO, cambio);
}
// MOV_TOTDOC e MOV_TOTDOCVAL vengono completati prima della scrittura del movimento
// e solo nel caso di saldaconto abilitato
}
void TContabilizzazione_effetti_app::compile_riga_partita(TRiga_partite& riga, const TEffetto& effetto, const TRectype& riga_effetto, int numrig)
{
const TRectype& head_mov = _movimento->curr();
riga.put(PART_TIPOMOV,_caus->tipomov());
riga.put(PART_TIPOPAG,effetto.get(EFF_TIPOPAG));
riga.put(PART_NREG,head_mov.get(MOV_NUMREG));
riga.put(PART_NUMRIG,numrig);
riga.put(PART_DATAREG,head_mov.get(MOV_DATAREG));
riga.put(PART_DATADOC,head_mov.get(MOV_DATADOC));
riga.put(PART_DATAPAG,effetto.get(EFF_DATASCAD));
riga.put(PART_CODCAUS,head_mov.get(MOV_CODCAUS));
riga.put(PART_NUMDOC,head_mov.get(MOV_NUMDOC)); // Sarebbe il numero della distinta...
riga.put(PART_DESCR, head_mov.get(MOV_DESCR));
riga.put(PART_SEZ,sezione());
const real imp = riga_effetto.get(REFF_IMPORTO);
const real imp_val = riga_effetto.get(REFF_IMPORTOVAL);
riga.put(PART_CODVAL,effetto.get(EFF_CODVAL));
riga.put(PART_DATACAM,effetto.get_date(EFF_DATACAMBIO));
real cambio = effetto.get(EFF_CAMBIO);
riga.put(PART_CAMBIO, cambio);
if (effetto.get_bool(EFF_CONTROEURO))
{
if (!((TRectype&)riga).exist(PART_CONTROEURO))
{
const TExchange chg(effetto.get(EFF_CODVAL), cambio, _exchange_contro);
const real cc = chg.get_base_change();
riga.put(PART_CAMBIO, cc);
}
else
riga.put(PART_CONTROEURO, TRUE);
}
riga.put(PART_TIPOCF,_cliente.tipo());
riga.put(PART_SOTTOCONTO,_cliente.sottoconto());
riga.put(PART_IMPTOTDOC,effetto.get(EFF_IMPORTO));
riga.put(PART_IMPTOTVAL,effetto.get(EFF_IMPORTOVAL));
// PART_GRUPPOCL e PART_CONTOCL sono gia' compilati dalla TPartita::new_row()
// Aggiorna il totale movimento in lire e totale movimento in valuta (solo con saldaconto abilitato)
if (_sc_enabled)
{
_total_mov += imp;
_total_mov_val += imp_val;
}
}
void TContabilizzazione_effetti_app::compile_riga_pagamento(TRectype& riga_pagamento, const TEffetto& effetto, const TRectype& riga_effetto, char acc_sal)
{
// ANNO, NUMPART, NRIGA, NRATA, NRIGP dovrebbero essere gia' compilati
riga_pagamento.put(PAGSCA_TIPOC,_cliente.tipo());
riga_pagamento.put(PAGSCA_SOTTOCONTO,_cliente.sottoconto());
riga_pagamento.put(PAGSCA_ACCSAL,acc_sal);
riga_pagamento.put(PAGSCA_IMPORTO,riga_effetto.get_real(REFF_IMPORTO));
riga_pagamento.put(PAGSCA_IMPORTOVAL,riga_effetto.get_real(REFF_IMPORTOVAL));
riga_pagamento.put(PAGSCA_TIPOCC,_banca.tipo());
riga_pagamento.put(PAGSCA_GRUPPOC,_banca.gruppo());
riga_pagamento.put(PAGSCA_CONTOC,_banca.conto());
riga_pagamento.put(PAGSCA_SOTTOCONTC,_banca.sottoconto());
riga_pagamento.put(PAGSCA_CODABI, effetto.get(EFF_CODABI));
riga_pagamento.put(PAGSCA_CODCAB, effetto.get(EFF_CODCAB));
riga_pagamento.put(PAGSCA_CODABIPR, effetto.get(EFF_CODABIP));
riga_pagamento.put(PAGSCA_CODCABPR, effetto.get(EFF_CODCABP));
// Cerca l'eventuale codice agente sul documento
TString key(30);
key << riga_effetto.get(REFF_PROVV) << "|";
key << riga_effetto.get(REFF_ANNODOC) << "|";
key << riga_effetto.get(REFF_CODNUM) << "|";
key << riga_effetto.get(REFF_NFATT);
const TRectype & doc = cache().get(LF_DOC, key);
if (!doc.empty())
riga_pagamento.put(PAGSCA_CODAG, doc.get(DOC_CODAG));
}
void TContabilizzazione_effetti_app::compile_saldac(const TEffetto& eff,
const TRectype& reff, TImporto& abbuoni_att, TImporto& abbuoni_pas,
TArray& differenze_cam, TArray& customers)
{
int anno = reff.get_int(REFF_ANNO);
TString16 numpart = reff.get(REFF_NUMPART);
// Ricava il numero della fattura.
TString16 numdoc_to_search = reff.get(REFF_CODNUM);
TString16 nfatt = reff.get(REFF_NFATT);
TCodice_numerazione cn;
if (numdoc_to_search.not_empty() && nfatt.not_empty() && real::is_natural(nfatt))
{
cn.read(numdoc_to_search);
const long nf = atol(nfatt);
cn.complete_num(nf, numdoc_to_search);
}
else // se gli estremi della fattura non sono compilati si piglia il numero della partita
numdoc_to_search = numpart;
if (anno == 0 || numpart.empty()) // Se non sono gia' settati sulla riga effetto...
{
anno = reff.get_int(REFF_ANNODOC);// ... li va a prendere dagli estremi fattura...
if (numdoc_to_search.not_empty())
{
numpart = numdoc_to_search;
}
else // ...oppure dalla testata movimento.
{ // Appunto: da verificare se facciamo cosi' o generiamo un errore...
anno = eff.get_date(EFF_DATADIST).year();
const char all = TPartita::allineamento_richiesto(eff.get_char(EFF_TIPOCF));
if (all == 'R')
numpart.format("%7ld", eff.get_long(EFF_NDIST));
else
numpart.format("%ld", eff.get_long(EFF_NDIST));
numdoc_to_search = numpart; // A mali estremi... estremi rimedi
}
}
TPartita * partita = _part_array->exist(_cliente,anno,numpart);
if (partita == NULL) // Se la partita non esiste nell'array la aggiunge
{
partita = new TPartita(_cliente,anno,numpart);
_part_array->insert(partita);
}
TRiga_partite& riga_part = partita->new_row();
// Compila la riga di partita
const int numrig = customers.items();
compile_riga_partita(riga_part,eff,reff, numrig);
// Compila la riga di pagamento:
// reperire il numero della riga partita (nrigp) appena aggiunta
const int nrigp = riga_part.get_int(PART_NRIGA);
((TRectype&)reff).put(REFF_NRIGP, nrigp);
// scorrere le righe della partita (nriga) per trovare il riferimento alla fattura di cui si sta effettuando il pagamento
// se non la si trova allora... nriga = UNASSIGNED
const int uns = (int)TPartita::UNASSIGNED;
int nriga = reff.get_int(REFF_NRIGA);
if (nriga == 0 || nriga == uns)
{
nriga = uns;
for (int r = partita->last(); r > 0; r = partita->pred(r))
{
const TRiga_partite& rpart = partita->riga(r);
const TString16 numdoc = rpart.get(PART_NUMDOC);
if (numdoc == numdoc_to_search && rpart.is_fattura())
{
nriga = r;
break;
}
}
}
// reperire il numero di rata (nrata) dalla riga effetto
const int nrata = reff.get_int(REFF_NRATA);
char acc_sal = 'A';
if (partita->esiste(nriga,nrata)) // calcola se e' a saldo o in acconto della rata
{
acc_sal = reff.get_char(REFF_ACCSAL);
if (acc_sal != 'S' && acc_sal != 'A')
acc_sal = 'A'; // Potrebbe succedere che il ACCSAL sia vuoto
}
else
{
if (nriga != uns)
nriga = uns; // E' praticamente impossibile che si trovi la fattura
// senza le proprie scadenze. Al limite settiamo il numero di riga per non assegnati.
}
// Creo una nuova riga di pagamento
TRectype& old_riga_pagamento = partita->pagamento(nriga,nrata,nrigp);
// compilo i campi di riga_pagamento
TRectype riga_pagamento(old_riga_pagamento);
compile_riga_pagamento(riga_pagamento,eff,reff, acc_sal);
// Aggiorno il pagamento generando eventuali abbuoni
char old_ap, new_ap;
TImporto old_abb, new_abb, old_diffcam, new_diffcam;
const TString16 codval = eff.get(EFF_CODVAL);
const TDate datacam = eff.get(EFF_DATACAMBIO);
real cambio = eff.get(EFF_CAMBIO);
exchange_type et = eff.get_bool(EFF_CONTROEURO) ? _exchange_contro : _exchange_base;
if (et == _exchange_contro)
{
if (!((TRectype&)riga_part).exist(PART_CONTROEURO))
{
const TExchange chg(codval, cambio, et);
cambio = chg.get_base_change();
et = _exchange_base;
riga_part.put(PART_CAMBIO, cambio);
}
}
const TValuta valuta_eff(codval, datacam, cambio, et);
partita->modifica_pagamento(riga_pagamento, valuta_eff,
old_ap, old_abb, old_diffcam,
new_ap, new_abb, new_diffcam, TRUE);
// Se ci sono abbuoni o differenze cambio...
if (!new_abb.is_zero() || !new_diffcam.is_zero())
{
if (new_ap == 'A')
{
abbuoni_att -= new_abb; // Sottraggo perche' va in sezione opposta
abbuoni_att.normalize();
}
if (new_ap == 'P')
{
abbuoni_pas -= new_abb; // Sottraggo perche' va in sezione opposta
abbuoni_pas.normalize();
}
if (!new_diffcam.is_zero())
{
// Sottraggo perche' va in sezione opposta
TImporto dc = new_diffcam;
dc.normalize(); dc.swap_section();
TRectype* row = new TRectype(LF_RMOV);
differenze_cam.add(row);
row->put(RMV_SEZIONE, dc.sezione());
row->put(RMV_IMPORTO, dc.valore());
TBill zio; _caus->bill(13, zio);
zio.put(*row);
TString80 str; str << TR("ft. ") << nfatt;
row->put(RMV_DESCR, str);
}
TRectype& last = (TRectype&)customers[customers.last()];
TImporto imp(last.get_char(RMV_SEZIONE), last.get_real(RMV_IMPORTO));
imp += new_abb; // Incremento con abbuoni
imp += new_diffcam; // Incremento con differenze cambi
last.put(RMV_SEZIONE, imp.sezione());
last.put(RMV_IMPORTO, imp.valore());
}
}
void TContabilizzazione_effetti_app::aggiorna_saldi()
{
CHECK(_movimento, "Movimento non valido passato ad aggiorna_saldi()");
TLocalisamfile& mov = _movimento->lfile();
const TDate datareg(mov.get_date(MOV_DATAREG));
tiposal tsal = _caus->apertura() ? apertura :
(_caus->chiusura() ? chiusura : normale);
_saldo.reset(); // Inizializza saldi
_saldo.set_movprovv(FALSE);
_saldo.set_tipo_saldo(tsal);
_saldo.set_anno_es(mov.get_int(MOV_ANNOES));
_saldo.set_num_ulmov(mov.get_long(MOV_NUMREG));
_saldo.set_data_ulmov(datareg);
_saldo.set_movimentato(TRUE);
const int cgitems = _movimento->cg_items();
for (int i = 0; i < cgitems; i++)
{
const TRectype& r = _movimento->cg(i);
TImporto import(r.get_char("SEZIONE"), r.get_real("IMPORTO"));
TBill conto; conto.get(r);
_saldo.aggiorna(conto, import, TRUE);
}
_saldo.registra();
}
error_type TContabilizzazione_effetti_app::write_all(bool change_status)
{
TRectype& head = _movimento->lfile().curr();
long numreg = head.get_long(MOV_NUMREG);
if (_movimento->cg_items() >= 2) // Non ha senso un movimento di una riga sola
{
TRectype& head = _movimento->lfile().curr();
head.put(MOV_TOTDOC,_total_mov);
head.put(MOV_TOTDOCVAL,_total_mov_val);
const long orig_numreg = numreg;
while (_movimento->write() == _isreinsert)
head.put(MOV_NUMREG,++numreg);
if (_movimento->status() != NOERR)
{
error_box(FR("E' stato rilevato l'errore %d scrivendo il movimento %ld."),_movimento->status(),numreg);
_error = generic_error;
}
if (good()) // nessun errore ?
{
aggiorna_saldi();
if (_sc_enabled) // Debbo scrivere anche le partite ?
{
if (numreg > orig_numreg) // Ha effettuato una rinumerazione ?
{
// Allora scorre le partite in _part_array e aggiorna il campo NREG delle righe di ognuna
for (TPartita * p = _part_array->first(); p != NULL; p = _part_array->next())
// Scorre le righe della partita corrente
for (int n = p->last(); n > 0; n = p->pred(n))
{
TRiga_partite& riga = p->riga(n);
if (riga.get_long(PART_NREG) == orig_numreg) // sostituisce il numero registrazione con quello nuovo
riga.put(PART_NREG, numreg);
}
}
if (!_part_array->write()) // L'errore viene gia' segnalato dalla partita
_error = generic_error;
}
}
}
if (good() && change_status) // deve anche cambiare lo stato alla distinta ?
{
TDistinta& distinta = *_distinta;
const int items = distinta.items();
for (int n = 0; n < items; n++)
{
TRectype& eff = distinta[n];
eff.put(EFF_EFFCONT, TRUE);
eff.put(EFF_NUMREG, numreg);
}
int err = distinta.rewrite();
if (err != NOERR)
{
error_box(FR("E' stato rilevato l'errore %d aggiornando lo stato della distinta %c %ld."),err,distinta.tipodist(),distinta.ndist());
_error = generic_error;
}
}
return _error;
}
bool TContabilizzazione_effetti_app::has_diffcam(const TEffetto& eff) const
{
bool yes = FALSE;
if (eff.in_valuta()) // Considera solo effetti in valuta
{
const TExchange cambio(eff);
TLocalisamfile partite(LF_PARTITE);
for (int n = 1; yes == FALSE && n <= eff.rows_r(); n++)
{
const TRectype& riga = eff.row_r(n);
if (riga.get_char(REFF_ACCSAL) != 'S') // Ignora righe non saldanti
continue;
partite.put(PART_TIPOCF, eff.get(EFF_TIPOCF));
partite.put(PART_GRUPPO, 0);
partite.put(PART_CONTO, 0);
partite.put(PART_SOTTOCONTO, eff.get(EFF_CODCF));
partite.put(PART_ANNO, riga.get(REFF_ANNO));
partite.put(PART_NUMPART, riga.get(REFF_NUMPART));
partite.put(PART_NRIGA, riga.get(REFF_NRIGA));
int err = partite.read();
if (err == NOERR)
{
const TExchange cambiofatt(partite.curr());
yes = cambiofatt != cambio;
}
else
NFCHECK("Effetto pagante fattura fantasma");
}
}
return yes;
}
static void build_eff_key(const TRectype& row, TString& str, int level)
{
int anno = row.get_int(REFF_ANNO);
if (anno <= 0)
anno = row.get_int(REFF_ANNODOC);
TString16 part = row.get(REFF_NUMPART);
if (part.blank() || part == "0")
part = row.get(REFF_NFATT);
int riga = row.get_int(REFF_NRIGA);
if (riga <= 0)
riga = 1;
if (level > 0)
{
const int rata = row.get_int(REFF_NRATA);
str.format("%04d|%s|%04d|%04d", anno, (const char*)part, riga, rata);
if (level > 1)
{ // Devo fare in modo che le fatture precedano le note doi credito nell'array delle righe effetto
int tipo = 2;
if (row.get_real(REFF_IMPORTO) <= ZERO)
tipo = 1; // Nota di credito
str << '|' << tipo;
}
}
else
str.format("%04d|%s|%04d", anno, (const char*)part, riga);
}
static int sort_eff_func(const TObject** o1, const TObject** o2)
{
const TRectype& r1 = *((TRectype*)*o1);
const TRectype& r2 = *((TRectype*)*o2);
TString80 s1, s2;
build_eff_key(r1, s1, 2);
build_eff_key(r2, s2, 2);
return s2.compare(s1);
}
int TContabilizzazione_effetti_app::sort_eff(TRecord_array& rows)
{
rows.sort(sort_eff_func); // Ordina per anno/partita/fattura/rata
// Raggruppa le righe riferite alla stessa rata
TString last_key, curr_key;
for (int i = rows.last_row(); i > 0; i--)
{
TRectype& row = rows[i];
build_eff_key(row, curr_key, 1);
if (curr_key == last_key) // Hanno la stessa rata per cui sommo e cancello l'ultima riga
{
real importo = rows[i+1].get(REFF_IMPORTO);
importo += row.get_real(REFF_IMPORTO);
row.put(REFF_IMPORTO, importo);
rows.destroy_row(i+1, TRUE);
}
else
last_key = curr_key;
}
return rows.rows();
}
void TContabilizzazione_effetti_app::contabilize_bill(const char tipo, const long numero)
{
TDistinta& distinta = *_distinta;
TLocalisamfile& mov = _movimento->lfile();
// tiene 2 array di record separati: uno per i clienti ed uno per le banche,
// alla fine, prima di scrivere il movimento, li riunisce nel record array di
// _movimento, per metterli in ordine, prima le righe clienti e poi le righe delle banche
// L'array delle banche e' un assoc_array, con indice sul gruppo/conto/sottoconto
// per effettuare il raggruppamento
TArray customers;
TAssoc_array banks;
TArray differenze_cam;
TImporto abbuoni_att, abbuoni_pas;
bool reset_bank = FALSE;
_total_mov = 0.0;
_total_mov_val = 0.0;
distinta.read(tipo,numero,_lock); // Sblocca da solo quella precedente
if (_caus != NULL)
delete _caus;
const TString& cc = distinta.tipocf() == 'F' ? _cod_caus_pag : _cod_caus;
_caus = new TCausale(cc, _data_op.year());
if (!_caus->ok())
{
_error = generic_error;
error_box(FR("Causale '%s' non valida o non presente in parametri effetti"), cc);
return;
}
//Cerca il conto della contropartita della banca di presentazione.
//Nel caso in cui sia presente sulla tabella BNP (selezione anche per
//tipo distinta) il conto sara' unico per tutti; se invece non e' presente sul file oppure il conto
//di contropartita e' vuoto, andra' reperito per ogni effetto, a seconda della causale
//impostata e del tipo di pagamento (quest'ultimo solo nel caso di saldaconto abilitato); altrimenti si
//terra' per buono sempre quello della seconda riga della casuale .
//E' chiaro che nella maggioranza dei casi si avra' sempre un unico conto di contropartita, definito
//nella tabella BNP.
//Non meno importante: nel caso avessimo piu' conti di contropartita per le banche
//si dovra' procedere ad un raggruppamento, sommando gli importi (mentre invece le righe
//clienti non dovranno subire tale procedimento.
//Infine: a causa del cazzutissimo limite di 99 righe contabili settato in invii/ricezioni
//si dovranno generare piu' movimenti per un stessa distinta se le righe eccedono tale
//valore (come avere le palle sopra un'incudine ed una mazza ferrata che sta per piombare a tutta forza...)
search_bank_counter_bill();
if (!good())
return; // _error's already set
real spese = distinta[0].get(EFF_SPESE);
TBill conto_cassa, conto_spese;
if (!spese.is_zero())
{
_caus->bill(11, conto_spese);
if (!conto_spese.ok())
{
_error = cau_spe_error;
return;
}
}
bool dettaglio_rate = FALSE;
if (distinta.tipocf() == 'F')
dettaglio_rate = _dett_rate_pas;
else
dettaglio_rate = _dett_rate_att;
const int items = distinta.items(); // Perche' sul file effetti il numero riga distinta e' un long ??
// compila la testata
compile_head_mov();
// _cur_dist_row e' un int sebbene su file sia un long: TArray::items() ritorna un int!!
for (_cur_dist_row = 0; _cur_dist_row<items; _cur_dist_row++) // scorre le righe della distinta (effetti)
{
const TEffetto& eff = distinta[_cur_dist_row];
const long codcf = eff.get_long(EFF_CODCF);
const char tipo = eff.get_tipo();
search_clifo_bill(tipo, codcf);
if (!good()) break;
// se la banca non e' stata settata cerca il conto sulla causale a seconda del tipo di pagamento di questo effetto
if (!_banca.ok() || reset_bank)
{
search_bank_counter_bill(eff.get_int(EFF_TIPOPAG));
if (!good()) break;
reset_bank = TRUE; // forza la ricerca del conto della banca ad ogni riga distinta
}
const bool force_break = !_trandiffcam.ok() && has_diffcam(eff);
TRecord_array sorted = ((TEffetto&)eff).righe();
sort_eff(sorted);
TString last_key, curr_key;
for (int n = 1; n <= sorted.rows(); n++)
{
const TRectype& riga = sorted[n];
build_eff_key(riga, curr_key, 0);
if (n == 1 || (dettaglio_rate && curr_key != last_key))
{
add_cg_row(eff, riga, customers, banks, FALSE);
last_key = curr_key;
}
else
sum_cg_row(riga, customers, banks);
if (_sc_enabled)
compile_saldac(eff, riga, abbuoni_att, abbuoni_pas, differenze_cam, customers);
// Calcola il numero di righe contabili generate fino ad ora.
// per i clienti e' sempre vero, mentre per le banche dipende
// se e' stato fatto un raggruppamento
int nrows = customers.items() + banks.items();
if (_sc_enabled)
{
if (!abbuoni_att.is_zero()) nrows++;
if (!abbuoni_pas.is_zero()) nrows++;
nrows+=differenze_cam.items();
}
if (!spese.is_zero())
nrows += 2;
if (nrows > 0 && force_break) // Se ci sono differenze cambio ...
nrows = CGROWS_LIMIT; // ... allora forza cambio movimento
if (nrows >= CGROWS_LIMIT) // se sono arrivato al limite massimo, scrivo questo movimento
{
// Unisce le righe banche e clienti nel record_array delle righe contabili
if (good() && _can_write)
{
join_rows(customers, banks, abbuoni_att, abbuoni_pas, differenze_cam, spese);
if (good())
write_all(FALSE); // non cambiare lo stato della distinta, cambialo solo alla fine
}
if (good())
{
_movimento->destroy_rows(mov.get_long(MOV_NUMREG)); // azzera le righe..
_part_array->destroy(); // e l'array delle partite
customers.destroy();
banks.destroy();
differenze_cam.destroy();
abbuoni_att = abbuoni_pas = TImporto('A', ZERO);
_total_mov = ZERO;
_total_mov_val = ZERO;
spese = ZERO;
// compila la testata del nuovo movimento
compile_head_mov();
}
}
if (!good()) break;
}
} // Ciclo su effetti
if (good() && _can_write) // scrive il movimento residuo ...
{
if (customers.items() > 0)
join_rows(customers, banks, abbuoni_att, abbuoni_pas, differenze_cam, spese);
if (good() && write_all() == no_error) // Se la scrittura e' andata ok...
_total_bills++; // incrementa il numero di distinte contabilizzate
}
_movimento->destroy_rows(mov.get_long(MOV_NUMREG)); // azzera le righe..
_part_array->destroy(); // e l'array delle partite
}
void TContabilizzazione_effetti_app::contabilize()
{
_total_bills = 0;
const long cur_items = _dist_sheet->items(); // Quante distinte in totale ?
TProgind p(cur_items, TR("Contabilizzazione effetti"), FALSE, TRUE);
for (long j = 0; j < cur_items; j++)
{
p.setstatus(j+1);
if (_dist_sheet->checked(j))
{
TToken_string& t = _dist_sheet->row(j);
const char tipo = t.get_char(1);
const long numero = t.get_long(2);
contabilize_bill(tipo,numero);
if (!good())
display_error();
}
}
if (_total_bills > 0)
message_box(FR("Totale distinte contabilizzate: %ld"),_total_bills);
}
int ef0800 (int argc, char* argv[])
{
TContabilizzazione_effetti_app a;
a.run(argc,argv,TR("Contabilizzazione effetti"));
return TRUE;
}