campo-sirio/cg/cg4a00.cpp
guy 88467f8086 Correzioni su reverse charge e note di credito IVA per cassa
Gestione fatture a zero

git-svn-id: svn://10.65.10.50/branches/R_10_00@23136 c028cbd2-c16b-5b4b-a496-9718f37d4682
2015-11-30 16:14:27 +00:00

505 lines
14 KiB
C++
Executable File
Raw Blame History

// 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;
}