88467f8086
Gestione fatture a zero git-svn-id: svn://10.65.10.50/branches/R_10_00@23136 c028cbd2-c16b-5b4b-a496-9718f37d4682
505 lines
14 KiB
C++
Executable File
505 lines
14 KiB
C++
Executable File
// Programma di gestione autotrasportatori.
|
||
#include <applicat.h>
|
||
#include <automask.h>
|
||
#include <progind.h>
|
||
#include <relation.h>
|
||
#include <tabutil.h>
|
||
|
||
#include <causali.h>
|
||
#include <rcausali.h>
|
||
#include <mov.h>
|
||
#include <rmoviva.h>
|
||
|
||
#include "cg2101.h"
|
||
#include "cg2103.h"
|
||
#include "cg4a00a.h"
|
||
#include "cglib01.h"
|
||
|
||
static int __anno;
|
||
|
||
bool cau_filter1 (const TRelation *r)
|
||
{
|
||
bool rt = false;
|
||
const TRectype& rec = r->curr(LF_CAUSALI);
|
||
|
||
if (rec.get(CAU_TIPODOC) == "ST") // Solo i tipi documento STorno
|
||
{
|
||
TString16 cod; cod << __anno << rec.get(CAU_REG);
|
||
const TRectype& reg = cache().get("REG", cod);
|
||
const bool b1 = reg.get_bool("B1");
|
||
const int i9 = reg.get_int("I9");
|
||
if (b1 && i9 <= 1) // Il registro deve avere la X di sospensione NORMALE
|
||
{
|
||
cod.format("%s|1", (const char*)rec.get(CAU_CODCAUS));
|
||
const TRectype& rcau = cache().get(LF_RCAUSALI, cod);
|
||
rt = rcau.get_char(RCA_TIPOCF) == 'C';
|
||
}
|
||
}
|
||
|
||
return rt;
|
||
}
|
||
|
||
bool cau_filter2(const TRelation *r)
|
||
{
|
||
bool rt = false;
|
||
const TRectype& rec = r->curr(LF_CAUSALI);
|
||
const TString& tipo = rec.get(CAU_TIPODOC);
|
||
if (tipo == "FV" || tipo == "NC") // Solo i tipi documento Fatture Vendita
|
||
{
|
||
TString16 cod; cod << __anno << rec.get(CAU_REG);
|
||
const TRectype& reg = cache().get("REG", cod);
|
||
rt = !reg.get_bool("B1");
|
||
}
|
||
|
||
return rt;
|
||
}
|
||
|
||
class TGestAutoTrasp_mask : public TAutomask
|
||
{
|
||
TAssoc_array _caudef;
|
||
TCursor *_cur;
|
||
TRelation *_rel;
|
||
TTable *_reg;
|
||
|
||
protected:
|
||
void fill_sheet(const short id);
|
||
const long get_last_nreg();
|
||
const long get_last_nprot();
|
||
void swap_sign(TMovimentoPN&);
|
||
|
||
public:
|
||
virtual bool on_key(KEY k);
|
||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
void write_movs();
|
||
TGestAutoTrasp_mask();
|
||
virtual ~TGestAutoTrasp_mask();
|
||
};
|
||
|
||
TGestAutoTrasp_mask::TGestAutoTrasp_mask() : TAutomask("cg4a00a")
|
||
{
|
||
_rel = new TRelation(LF_MOV);
|
||
_cur = NULL;
|
||
_reg = new TTable("REG");
|
||
}
|
||
|
||
TGestAutoTrasp_mask::~TGestAutoTrasp_mask()
|
||
{
|
||
if (_cur)
|
||
delete _cur;
|
||
delete _rel;
|
||
delete _reg;
|
||
}
|
||
|
||
bool TGestAutoTrasp_mask::on_key(KEY k)
|
||
{
|
||
if (k == K_SHIFT + K_F12)
|
||
{
|
||
// Abilita la cella del numero prot. registro corrispondente alla riga
|
||
// corrente dello spreadsheet
|
||
if (focus_field().dlg() == F_SHEET_CAUSALI)
|
||
{
|
||
TSheet_field& sf = sfield(F_SHEET_CAUSALI);
|
||
const int rs = sf.selected();
|
||
sf.enable_column(F_NUMPROT - F_CAUMOV);
|
||
|
||
const int items = sf.items();
|
||
for (int i=0; i<items; i++)
|
||
sf.disable_cell(i, F_NUMPROT - F_CAUMOV);
|
||
|
||
sf.enable_cell(rs, F_NUMPROT - F_CAUMOV);
|
||
sf.force_update(rs);
|
||
}
|
||
}
|
||
|
||
return TAutomask::on_key(k);
|
||
}
|
||
|
||
void TGestAutoTrasp_mask::fill_sheet(const short id)
|
||
{
|
||
const TDate fromdate = get_date(F_DADATA);
|
||
const TDate todate = get_date(F_ADATA);
|
||
const TString4 codreg = get(F_CODREG);
|
||
|
||
if (fromdate.ok() && todate.ok() && codreg.full())
|
||
{
|
||
TRectype fromrec(LF_MOV);
|
||
TRectype torec(LF_MOV);
|
||
TString filter;
|
||
filter << "(REG==\"" << codreg << "\")";
|
||
filter << "&&((STAMPATO!=\"X\")&&(REGST!=\"X\"))";
|
||
fromrec.put(MOV_DATAREG, fromdate);
|
||
torec.put(MOV_DATAREG, todate);
|
||
|
||
if (_cur)
|
||
delete _cur;
|
||
|
||
_cur = new TCursor(_rel, filter, 2, &fromrec, &torec);
|
||
TRectype& rc = _cur->curr();
|
||
const TRecnotype items = _cur->items();
|
||
TProgress_monitor pi(items, TR("Selezione movimenti..."));
|
||
|
||
TLocalisamfile causali(LF_CAUSALI);
|
||
|
||
// Azzera lo sheet
|
||
TSheet_field& sf = sfield(F_SHEET_CAUSALI);
|
||
TString_array& sa = sf.rows_array();
|
||
sa.destroy();
|
||
|
||
//azzera l'array
|
||
_caudef.destroy();
|
||
for (*_cur = 0L; _cur->pos() < items; ++(*_cur))
|
||
{
|
||
if (!pi.add_status(1))
|
||
break;
|
||
const TString4 caus = rc.get(MOV_CODCAUS);
|
||
if (!_caudef.is_key(caus)) // Se non <20> stata ancora aggiunta questa causale...
|
||
{
|
||
TToken_string* tt = new TToken_string;
|
||
|
||
tt->add(caus, 0);
|
||
_caudef.add(caus, new TString16);
|
||
causali.put(CAU_CODCAUS, caus);
|
||
|
||
const bool ok = causali.read() == NOERR;
|
||
tt->add(ok ? causali.get(CAU_DESCR) : TR("** Non presente **"), 1);
|
||
tt->add(ok ? causali.get(CAU_TIPODOC) : "**", 2);
|
||
|
||
sa.add(tt);
|
||
}
|
||
}
|
||
|
||
sf.force_update(); // Aggiorna lo sheet
|
||
|
||
if (items == 0)
|
||
{
|
||
warning_box(TR("Non vi sono operazioni da effettuare nell'intervallo specificato."));
|
||
set_focus_field(id);
|
||
}
|
||
}
|
||
}
|
||
|
||
bool TGestAutoTrasp_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
||
{
|
||
switch (o.dlg())
|
||
{
|
||
case F_DADATA:
|
||
if (e == fe_modify || e == fe_init)
|
||
{
|
||
__anno = e == fe_modify ? atoi(o.get().right(4)) : 0;
|
||
set(F_ANNO, __anno);
|
||
|
||
TCursor* cur1 = efield(F_CAUS).browse()->cursor();
|
||
cur1->set_filterfunction(cau_filter1, TRUE);
|
||
|
||
TCursor* cur2 = sfield(F_SHEET_CAUSALI).sheet_mask().efield(F_CAUDEF).browse()->cursor();
|
||
cur2->set_filterfunction(cau_filter2, TRUE);
|
||
|
||
if (e == fe_modify)
|
||
fill_sheet(o.dlg());
|
||
}
|
||
break;
|
||
case F_ADATA:
|
||
case F_CODREG:
|
||
if (e == fe_modify)
|
||
fill_sheet(o.dlg());
|
||
break;
|
||
case F_SHEET_CAUSALI:
|
||
if (e == se_query_add)
|
||
return FALSE;
|
||
else
|
||
if (e == fe_close) // Controllo sulla presenza dei codici causale nello spreadsheet
|
||
{
|
||
TSheet_field& sf = sfield(F_SHEET_CAUSALI);
|
||
bool error = TRUE;
|
||
for (int i=0; i < sf.items(); i++)
|
||
{
|
||
TToken_string& tt = sf.row(i);
|
||
const TString16 c = tt.get(F_CAUDEF - F_CAUMOV);
|
||
if (!c.blank())
|
||
{
|
||
error = FALSE;
|
||
break;
|
||
}
|
||
}
|
||
if (error)
|
||
{
|
||
if (sf.items() == 0)
|
||
error_box(TR("Non vi sono movimenti in sospensione da stornare nel periodo indicato."));
|
||
else
|
||
error_box(TR("E' necessario indicare almeno una causale definitiva."));
|
||
}
|
||
|
||
return !error;
|
||
}
|
||
break;
|
||
case F_NUMPROT:
|
||
case F_CAUDEF:
|
||
if (e == fe_modify)
|
||
{
|
||
|
||
TString16 cod;
|
||
cod << __anno;
|
||
cod << o.mask().get(F_CAUDEFREG);
|
||
_reg->put("CODTAB", cod);
|
||
if (_reg->read() == NOERR)
|
||
{
|
||
if (o.dlg() == F_NUMPROT)
|
||
{
|
||
_reg->put("I5", o.mask().get_long(F_NUMPROT));
|
||
_reg->rewrite();
|
||
|
||
TSheet_field& sf = sfield(F_SHEET_CAUSALI);
|
||
|
||
const int rs = sf.selected();
|
||
sf.enable_column(F_NUMPROT - F_CAUMOV, FALSE);
|
||
sf.force_update(rs);
|
||
}
|
||
|
||
o.mask().set(F_NUMPROT, _reg->get_long("I5"));
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
const long TGestAutoTrasp_mask::get_last_nreg()
|
||
{
|
||
TLocalisamfile& mov = _rel->lfile();
|
||
const int key = mov.getkey();
|
||
long nr = 1L;
|
||
|
||
if (!mov.empty())
|
||
{
|
||
mov.setkey(1);
|
||
mov.last();
|
||
nr = mov.get_long(MOV_NUMREG) + 1L;
|
||
mov.setkey(key);
|
||
}
|
||
return nr;
|
||
}
|
||
|
||
const long TGestAutoTrasp_mask::get_last_nprot()
|
||
{
|
||
long rt = 0l;
|
||
TString16 cod;
|
||
cod << __anno;
|
||
cod << get(F_CODREG);
|
||
_reg->put("CODTAB", cod);
|
||
if (_reg->read() == NOERR)
|
||
rt = _reg->get_long("I5");
|
||
return rt;
|
||
}
|
||
|
||
void TGestAutoTrasp_mask::swap_sign(TMovimentoPN& m)
|
||
{
|
||
// Scambia il segno sulla testata
|
||
TRectype& h = m.curr();
|
||
real r;
|
||
|
||
r = ZERO - h.get_real(MOV_TOTDOC);
|
||
h.put(MOV_TOTDOC, r);
|
||
r = ZERO - h.get_real(MOV_TOTDOCVAL);
|
||
h.put(MOV_TOTDOCVAL, r);
|
||
|
||
// e su tutte le righe iva
|
||
const int items = m.iva_items();
|
||
for (int i=0; i<items;i++)
|
||
{
|
||
TRectype& rec = m.iva(i);
|
||
r = ZERO - rec.get_real(RMI_IMPONIBILE);
|
||
rec.put(RMI_IMPONIBILE, r);
|
||
r = ZERO - rec.get_real(RMI_IMPOSTA);
|
||
rec.put(RMI_IMPOSTA, r);
|
||
}
|
||
}
|
||
|
||
void TGestAutoTrasp_mask::write_movs()
|
||
{
|
||
TSheet_field& sf = sfield(F_SHEET_CAUSALI);
|
||
|
||
// Compila _caudef, per la corrispondenza con le causali definitive
|
||
const int items = sf.items();
|
||
for (int i=0; i<items;i++)
|
||
{
|
||
TToken_string& tt = sf.row(i);
|
||
TString& s = (TString&)_caudef[tt.get(0)];
|
||
s = tt.get(F_CAUDEF - F_CAUMOV);
|
||
}
|
||
|
||
const TDate dataop = get(F_DATAOP);
|
||
|
||
TEsercizi_contabili esc;
|
||
const int annoes = esc.date2esc(dataop);
|
||
|
||
// Riutilizzo del cursore
|
||
const TRecnotype cur_items = _cur->items();
|
||
TRectype& curr_rec = _cur->curr();
|
||
TMovimentoPN mpn_sosp; // Movimento di prima nota in sospensione
|
||
TMovimentoPN mpn_storno; // Movimento di prima nota di storno sul reg. sospensione
|
||
TMovimentoPN mpn_definitivo; // Movimento di prima nota solo IVA sul registro definitivo
|
||
TRectype& mpn_sosp_rec = mpn_sosp.curr();
|
||
TRectype& mpn_storno_rec = mpn_storno.curr();
|
||
TRectype& mpn_definitivo_rec = mpn_definitivo.curr();
|
||
|
||
_cur->freeze();
|
||
|
||
TProgind pi(cur_items, TR("Creazione movimenti..."), FALSE, TRUE);
|
||
int err = NOERR;
|
||
int movs = 0;
|
||
|
||
// Scorre i movimenti selezionati sul registro in sospensione
|
||
for (*_cur = 0L; _cur->pos() < cur_items && err == NOERR; ++(*_cur))
|
||
{
|
||
pi.addstatus(1);
|
||
|
||
const TString4 cod_caus = curr_rec.get(MOV_CODCAUS);
|
||
const TString4 cod_caus_def = (TString&)_caudef[cod_caus];
|
||
if (cod_caus_def.blank())
|
||
continue;
|
||
|
||
mpn_sosp_rec = curr_rec;
|
||
if (mpn_sosp.read(_isequal) == NOERR)
|
||
{
|
||
// Il prossimo numero di registrazione <20>...
|
||
long nr = get_last_nreg();
|
||
long nsosp = mpn_sosp_rec.get_long(MOV_NUMREG);
|
||
|
||
// Azzera le righe dei movimenti da scrivere
|
||
mpn_storno.destroy_rows(nr);
|
||
mpn_definitivo.destroy_rows(nr+1);
|
||
|
||
// Sistema il movimento definitivo
|
||
TCausale def_caus((TString&)_caudef[mpn_sosp_rec.get(MOV_CODCAUS)], __anno);
|
||
mpn_definitivo_rec = mpn_sosp_rec;
|
||
mpn_definitivo_rec.put(MOV_NUMREG, nr+1);
|
||
mpn_definitivo_rec.put(MOV_PROTIVA, def_caus.reg().protocol()+1);
|
||
mpn_definitivo_rec.put(MOV_DATAREG, dataop);
|
||
mpn_definitivo_rec.put(MOV_DATACOMP, dataop);
|
||
mpn_definitivo_rec.put(MOV_ANNOES, annoes);
|
||
mpn_definitivo_rec.put(MOV_ANNOIVA, dataop.year());
|
||
mpn_definitivo_rec.put(MOV_CODCAUS, def_caus.codice());
|
||
mpn_definitivo_rec.put(MOV_REG, def_caus.reg().name());
|
||
mpn_definitivo_rec.put(MOV_TIPODOC, def_caus.tipo_doc());
|
||
|
||
// Flag operazione stampata in definitiva, solo per quelli in sospensione ed il movimento di storno,
|
||
// il movimento definitivo non va flaggato.
|
||
mpn_sosp_rec.put(MOV_STAMPATO, true);
|
||
mpn_sosp_rec.put(MOV_REGST, true);
|
||
|
||
// Sistema il movimento di storno a partire da quello in sospensione
|
||
TCausale storno_caus(get(F_CAUS), __anno); // Forse <20> ridondante ma serve per tener aggiornato il nr. protocollo
|
||
mpn_storno_rec = mpn_sosp_rec;
|
||
mpn_storno_rec.put(MOV_NUMREG, nr);
|
||
mpn_storno_rec.put(MOV_PROTIVA, storno_caus.reg().protocol()+1);
|
||
mpn_storno_rec.put(MOV_DATAREG, dataop);
|
||
mpn_storno_rec.put(MOV_DATACOMP, dataop);
|
||
mpn_storno_rec.put(MOV_ANNOES, annoes);
|
||
mpn_storno_rec.put(MOV_ANNOIVA, dataop.year());
|
||
mpn_storno_rec.put(MOV_CODCAUS, storno_caus.codice());
|
||
mpn_storno_rec.put(MOV_REG, storno_caus.reg().name());
|
||
mpn_storno_rec.put(MOV_TIPODOC, storno_caus.tipo_doc());
|
||
|
||
// Aggiunge le righe IVA
|
||
const int iva_items = mpn_sosp.iva_items();
|
||
for (int j=0; j<iva_items; j++)
|
||
{
|
||
TRectype& vv = mpn_storno.iva(j);
|
||
TRectype& ff = mpn_definitivo.iva(j);
|
||
|
||
vv = mpn_sosp.iva(j);
|
||
ff = mpn_sosp.iva(j);
|
||
|
||
vv.put(RMI_NUMREG, nr);
|
||
vv.zero(RMI_RIGAIMP);
|
||
vv.put(RMI_ANNOES, annoes);
|
||
|
||
ff.put(RMI_NUMREG, nr+1);
|
||
ff.zero(RMI_RIGAIMP);
|
||
ff.put(RMI_ANNOES, annoes);
|
||
}
|
||
|
||
// Se <20> effettivamente una causale di storno, cambia il segno al totale documento ed alle righe IVA
|
||
if (storno_caus.sezione_clifo() == 'A')
|
||
swap_sign(mpn_storno);
|
||
|
||
// Scrive il movimento di storno solo IVA sul reg in sospensione
|
||
while ((err = mpn_storno.write()) == _isreinsert)
|
||
{
|
||
mpn_storno_rec.put(MOV_NUMREG, ++nr); // Gestisce la rinumerazione
|
||
}
|
||
|
||
if (err == NOERR)
|
||
{
|
||
movs++;
|
||
// Scrive il movimento definitivo
|
||
while ((err = mpn_definitivo.write()) == _isreinsert)
|
||
mpn_definitivo_rec.put(MOV_NUMREG, ++nr);
|
||
|
||
if (err == NOERR)
|
||
{
|
||
movs++;
|
||
err = mpn_sosp.rewrite(); // Aggiorna il movimento in sospensione con i flags aggiornati
|
||
if (err != NOERR)
|
||
error_box(FR("Errore %d in fase di riscrittura del movimento di sospensione nr. %d."), err, nsosp);
|
||
}
|
||
else
|
||
error_box(FR("Errore %d in fase di scrittura del movimento definitivo. Movimento di sospensione nr. %d."), err, nsosp);
|
||
}
|
||
else
|
||
error_box(FR("Errore %d in fase di scrittura del movimento di storno. Movimento di sospensione nr. %d."), err, nsosp);
|
||
}
|
||
}
|
||
|
||
_cur->freeze(FALSE);
|
||
|
||
message_box(FR("Totale movimenti generati: %d"), movs);
|
||
}
|
||
|
||
class TGestAutoTrasp_app : public TSkeleton_application
|
||
{
|
||
TGestAutoTrasp_mask * _msk;
|
||
|
||
protected:
|
||
virtual bool create();
|
||
virtual bool destroy();
|
||
virtual void main_loop();
|
||
public:
|
||
TGestAutoTrasp_app () {};
|
||
virtual ~TGestAutoTrasp_app () {};
|
||
};
|
||
|
||
bool TGestAutoTrasp_app::create()
|
||
{
|
||
_msk = new TGestAutoTrasp_mask();
|
||
open_files(LF_MOV, LF_ATTIV, 0);
|
||
return TSkeleton_application::create();
|
||
}
|
||
|
||
bool TGestAutoTrasp_app::destroy()
|
||
{
|
||
delete _msk;
|
||
return TSkeleton_application::destroy();
|
||
}
|
||
|
||
void TGestAutoTrasp_app::main_loop()
|
||
{
|
||
while (_msk->run() != K_QUIT)
|
||
{
|
||
if (yesno_box(TR("Procedere con la creazione dei movimenti?")))
|
||
{
|
||
_msk->write_movs();
|
||
_msk->reset();
|
||
}
|
||
}
|
||
}
|
||
|
||
int cg4a00(int argc, char* argv[])
|
||
{
|
||
TGestAutoTrasp_app app;
|
||
app.run(argc, argv, TR("Gestione Autotrasportatori"));
|
||
return 0;
|
||
}
|