campo-sirio/src/cg/cg1312.cpp

468 lines
14 KiB
C++
Raw Normal View History

#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <isam.h>
#include <progind.h>
#include <recarray.h>
#include <recset.h>
#include <utility.h>
#include <validate.h>
#include <modaut.h>
#include "cgsaldac.h"
#include "cglib03.h"
#include "cg1300m.h"
#include <clifo.h>
#include <mov.h>
#include <occas.h>
#include <rmoviva.h>
#include <pagsca.h>
#define AGR_PCON1 201
#define AGR_PCON2 202
enum tiporeg { vendita = 1, acquisto = 2 };
///////////////////////////////////////////////////////////
// TCheck_ivadiff_mask
///////////////////////////////////////////////////////////
class TCheck_ivadiff_mask : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TCheck_ivadiff_mask() : TAutomask("cg1300m") { }
};
// Carica lo sheet in base alle impostazioni correnti (F_CLIFO, F_COFI)
bool TCheck_ivadiff_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_CODDITTA:
break;
case F_ANNO:
break;
default: break;
}
return true;
}
///////////////////////////////////////////////////////////
// TCheck_ivadiff
///////////////////////////////////////////////////////////
static bool partita_chiusa_al(const TPartita& p, const TDate& d)
{
bool c = p.chiusa();
if (c)
{
const TImporto imp = p.calcola_saldo_al(true, d, d, d);
c = imp.is_zero();
}
return c;
}
class TCheck_ivadiff : public TSkeleton_application
{
protected:
bool ivadiff_chiusa(const TRectype& mov, const TDate& fine) const;
void check_year(long firm, int year);
bool is_date_ok(const TDate& d, int liqmonth, int year) const;
public:
virtual void main_loop();
};
bool TCheck_ivadiff::ivadiff_chiusa(const TRectype& mov, const TDate& fine) const
{
bool chiusa = false;
const long numreg = mov.get_long(MOV_NUMREG);
TLocalisamfile id(LF_IVADIFF);
TRectype& rid = id.curr();
rid.put(MOV_NUMREG, numreg);
int err = id.read(_isgteq);
if (err == NOERR && rid.get_long(MOV_NUMREG) == numreg)
{
bool some_pag = false; // Ci sono pagamenti?
TImporto tot;
for (; err == NOERR && rid.get_long(MOV_NUMREG) == numreg; err = id.next())
{
const TDate data = rid.get("DATAREGP");
if (data > fine)
continue;
if (data == fine && rid.get_long("NUMREGP") == numreg)
continue; // Ignora pagamento automatico dopo un anno
const real imp = rid.get(RMI_IMPOSTA);
if (!imp.is_zero())
{
const char sez = rid.get_char("SEZIONE");
tot += TImporto(sez, imp);
if (!some_pag && rid.get_int(MOV_TIPOMOV) > 1)
some_pag = true;
}
}
chiusa = some_pag && tot.valore() < 0.01;
}
return chiusa;
}
bool TCheck_ivadiff::is_date_ok(const TDate& d, int liqmonth, int year) const
// true se la data passata va considerata nel
// ricalcolo dei progressivi mensili per il mese e anno
// selezionati. Vedi cg4301.cpp per maggiori informazioni
// sul nuovo filtro di selezione movimenti.
{
const int regyear = d.year();
return (regyear == year && liqmonth != 12) || (regyear == year + 1 && liqmonth == 12);
}
void TCheck_ivadiff::check_year(long firm, int year)
{
if (!(has_module(SCAUT, CHK_DONGLE) && ini_get_bool(CONFIG_DITTA, "cg", "GesSal")))
{
warning_box("Per l'iva differita o per cassa <20> necessario il saldaconto");
return;
}
const long old_firm = prefix().get_codditta();
prefix().set_codditta(firm);
TString16 key; key.format("%05ld%04d", firm, year);
TRectype & lia = (TRectype &) cache().get("%LIA", key);
const TString4 freqviva = lia.get("S7");
TRelation rel(LF_MOV);
rel.add(LF_RMOVIVA,"NUMREG=NUMREG");
rel.add(LF_PCON,"GRUPPO=GRUPPO|CONTO=CONTO",1,LF_RMOVIVA,AGR_PCON1);
rel.add(LF_PCON,"GRUPPO=GRUPPO|CONTO=CONTO|SOTTOCONTO=SOTTOCONTO",1,LF_RMOVIVA,AGR_PCON2);
rel.add(LF_CAUSALI,"CODCAUS=CODCAUS");
TCursor cur(&rel, "", 4);
TLocalisamfile & mov = cur.relation()->lfile();
TLocalisamfile & rmoviva = cur.relation()->lfile(LF_RMOVIVA);
TRectype from(cur.curr()); from.zero();
TRectype to(from);
TString8 fromreg("~"), toreg("0");
TRelation regrel("REG");
TCursor reg(&regrel);
TString4 codreg;
long items = reg.items();
const TDate fromdate(1, 1, year);
const TDate todate(31, 12, year);
TString filter;
for (reg = 0L; reg.pos() < items; ++reg)
{
codreg = reg.curr().get("CODTAB").mid(4);
if (codreg < fromreg)
fromreg = codreg;
if (codreg > toreg)
toreg = codreg;
}
from.put(MOV_REG, fromreg);
to.put(MOV_REG, toreg);
filter.format("BETWEEN(DATAREG,%ld,%ld)&&NUM(LIQDIFF==\"X\")", fromdate.date2ansi(), todate.date2ansi());
cur.freeze(false);
cur.setregion(from, to);
cur.setfilter(filter);
items = cur.items();
cur.freeze();
TString pimsg;
pimsg << TR("Ricalcolo IVA differita ditta ") << firm << TR(" anno ") << year;
TProgress_monitor pi(items, pimsg, false);
for (cur = 0L; cur.pos() < items; ++cur)
{
if (!pi.set_status(cur.pos()))
break;
const TString4 codreg = mov.get("REG");
TString16 s; s << year; s << format("%-3s", (const char *) codreg);
const TRectype & reg = cache().get("REG", s);
TDate date = mov.get(MOV_DATAREG);
const int liqmonth = mov.get_int(MOV_MESELIQ);
const TString4 tipodoc = mov.get(MOV_TIPODOC);
const bool corrisp = reg.get_bool("B0");
tipo_movimento tm = (tipo_movimento)mov.get_int(MOV_TIPOMOV);
const tiporeg tipomov = (tiporeg) reg.get_int("I0"); // 1=Vendite; 2=Acquisti
// Inizio gestione IVA differita
bool dok = is_date_ok(date, liqmonth, year);
TPartite_array arrpart; // Partite interessate
TPointer_array pagscatt; // Righe di pagsca interessate
if (tm == tm_fattura)
{
const bool iva_diff = is_IVA_diff(mov.curr());
const bool id_chiusa = ivadiff_chiusa(mov.curr(), TDate(31,12,year-1));
if (!dok && id_chiusa)
continue; // Salta vecchi movimenti differiti gi<67> chiusi
// Sezione preferita per fatture decisa in base a vendita->'A' o acquisto->'D'
const char sezfat = tipomov == vendita ? 'D' : 'A';
const char sezpag = (sezfat=='D') ? 'A' : 'D';
const long numreg = mov.get_long(MOV_NUMREG);
real tot_incassato, tot_da_incassare;
bool game_found = false;
arrpart.add_numreg(numreg);
const TPartita* p = arrpart.first();
const int row = p ? p->mov2rig(numreg, 0) : 0;
game_found = row > 0;
if (game_found && !id_chiusa)
{
const TRiga_partite& rp = p->riga(row);
TDate orizzonte = todate; // caso tradizionale
TImporto pg_per, nc_per;
rp.calcola_pagato_periodo(fromdate+1L, orizzonte, pg_per, nc_per, &pagscatt);
if (pagscatt.items() >= 2)
{
// Fondo tra loro le righe generate dallo stesso pagamento
for (int p = pagscatt.last(); p > 0; p--)
{
const TRectype& p0 = (const TRectype&)pagscatt[p];
const TRectype& p1 = (const TRectype&)pagscatt[p-1];
if (p0.get_int(PAGSCA_NRIGP) == p1.get_int(PAGSCA_NRIGP))
{
const real imp = p0.get_real(PAGSCA_IMPORTO);
((TRectype&)p1).add(PAGSCA_IMPORTO, imp);
pagscatt.destroy(p, true);
}
}
}
if (iva_diff)
{
TPointer_array pagscaold;
TImporto pg_tot, nc_tot;
rp.calcola_pagato_periodo(TDate(0L), orizzonte, pg_tot, nc_tot, &pagscaold);
// Controllo se ci siam persi delle note di credito negli anni scorsi
if (!nc_tot.is_zero() && pagscaold.items() > pagscatt.items())
{
FOR_EACH_ARRAY_ITEM(pagscaold, i, obj)
{
const TRectype& pagsca = *(const TRectype*)obj;
const int anno = pagsca.get_int(PAGSCA_ANNO);
const int nrigp = pagsca.get_int(PAGSCA_NRIGP);
// Appartiene all'anno scorso?
if (anno < year && nrigp < 999) // 9999 on pagsca -> 999 on ivadiff
{
const TPartita& p = arrpart.partita(pagsca);
const TRiga_partite& rp = p.riga(nrigp);
// E' veramente una nota di credito?
if (rp.tipo() == tm_nota_credito)
{
bool found = false;
FOR_EACH_ARRAY_ITEM(pagscatt, j, ps)
{
if (ps == obj)
{
found = true;
break;
}
}
if (!found)
{
TLocalisamfile id(LF_IVADIFF);
id.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG));
id.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG));
id.put("NUMPRO", nrigp);
if (id.read(_isequal) != NOERR || id.get_int("ANNOLIQ") == 0)
pagscatt.add(obj);
}
}
}
}
}
TImporto incasso = pg_tot;
TImporto saldo = rp.importo(false);
incasso += nc_tot;
saldo += incasso;
saldo.normalize(sezfat);
incasso.normalize(sezpag);
if (saldo.valore() > ZERO)
tot_da_incassare = saldo.valore();
if (incasso.valore() > ZERO)
tot_incassato = incasso.valore();
}
}
}
do
{
const int rmi_tipoatt = max(rmoviva.get_int(RMI_TIPOATT), 1); // Poteva capitare tipoatt == 0
const TString4 codiva = rmoviva.get(RMI_CODIVA);
TCodiceIVA civa(codiva);
if (!civa.ok())
{
error_box(FR("Codice IVA \"%s\" non riconosciuto alla riga %d del movimento %ld."),
(const char*)codiva, rmoviva.get_int(RMI_NUMRIG), rmoviva.get_long(RMI_NUMREG));
continue;
}
const real imponibile_orig = rmoviva.get_real(RMI_IMPONIBILE);
const real imposta_orig = rmoviva.get_real(RMI_IMPOSTA);
const real lordo_orig = imponibile_orig + imposta_orig;
if (tm == tm_fattura)
{
const char sezfat = tipomov == vendita ? 'D' : 'A';
const TDate datareg = mov.get(MOV_DATAREG);
TLocalisamfile id(LF_IVADIFF);
id.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG));
id.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG));
id.put("NUMPRO", 0);
if (id.read(_isequal) != NOERR)
{
id.zero();
id.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG));
id.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG));
id.put("NUMPRO", 0);
id.put(PART_TIPOMOV, tm);
id.put("TIPOATT", rmi_tipoatt);
id.put("ANNOLIQ", datareg.year());
int mesereg = datareg.month();
if (freqviva == "T")
{
const int resto = mesereg % 3;
if (resto > 0)
mesereg += 3-resto;
}
id.put("MESELIQ", mesereg);
id.put("TIPOIVA", tipomov == 2 ? 2 : 1);
id.put("TIPODIFF", 1);
id.put(MOV_DATAREG, mov.get(MOV_DATADOC));
id.put(RMI_CODIVA, codiva);
id.put("SEZIONE", sezfat);
id.put("IMPORTO", imponibile_orig+imposta_orig);
id.put(RMI_IMPONIBILE, imponibile_orig);
id.put(RMI_IMPOSTA, imposta_orig);
const int ew = id.write();
if (ew != NOERR)
cantwrite_box(id.description());
}
}
if (!pagscatt.empty())
{
const char sezpag = tipomov == vendita ? 'A' : 'D';
real totfat = mov.get(MOV_TOTDOC);
real tot = totfat;
TLocalisamfile id(LF_IVADIFF);
TRectype& idcurr = id.curr();
FOR_EACH_ARRAY_ITEM(pagscatt, r, obj)
{
const TRectype& pagsca = *(TRectype*)obj;
const int nrigp = pagsca.get_int(PAGSCA_NRIGP);
id.zero();
idcurr.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG));
idcurr.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG));
CHECKD(nrigp > 0, "Invalid NRIGP ", nrigp);
idcurr.put("NUMPRO", min(nrigp, 999));
if (id.read(_isequal, _lock) != NOERR)
{
id.zero();
idcurr.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG));
idcurr.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG));
idcurr.put("NUMPRO", min(nrigp, 999));
idcurr.put(MOV_DATAREG, mov.get(MOV_DATADOC));
idcurr.put("TIPOATT", rmi_tipoatt);
idcurr.put("TIPOIVA", tipomov == 2 ? 2 : 1);
idcurr.put("TIPODIFF", 1);
idcurr.put(RMI_CODIVA, codiva);
TImporto pagtmp;
bool ultimo = false;
tipo_movimento tipomov_pag = tm_pagamento;
if (nrigp > 0)
{
const TPartita& p = arrpart.partita(pagsca);
const TRiga_partite& rp = p.riga(nrigp);
tipomov_pag = rp.tipo();
idcurr.put(PART_TIPOMOV, tipomov_pag);
idcurr.put("NUMREGP", rp.get(PART_NREG));
idcurr.put("NUMRIGP", rp.get(PART_NUMRIG));
TDate d = rp.get(PART_DATAPAG);
if (!d.ok())
d = rp.get(PART_DATADOC);
if (!d.ok())
d = rp.get(PART_DATAREG);
idcurr.put("DATAREGP", d);
idcurr.put("ANNOLIQ", d.year());
pagtmp = p.importo_pagsca(pagsca);
pagtmp.normalize(sezpag);
ultimo = (r == pagscatt.last()) && partita_chiusa_al(p, todate);
}
int meseliq = id.get_date("DATAREGP").month();
if (freqviva == "T")
{
const int resto = meseliq % 3;
if (resto > 0)
meseliq += 3-resto;
}
idcurr.put("MESELIQ", meseliq);
idcurr.put("SEZIONE", pagtmp.sezione());
real val_imp = pagtmp.valore() * lordo_orig / tot;
real val_iva = civa.scorpora(val_imp, TCurrency::get_firm_dec());
idcurr.put("IMPORTO", val_imp + val_iva);
idcurr.put(RMI_IMPONIBILE, val_imp);
idcurr.put(RMI_IMPOSTA, val_iva);
if (id.write() != NOERR)
cantwrite_box(id.description());
}
}
}
} while (cur.next_match(LF_RMOVIVA));
}
prefix().set_codditta(firm);
}
void TCheck_ivadiff::main_loop()
{
TCheck_ivadiff_mask m;
while (m.run() == K_ENTER)
check_year(m.get_long(F_CODDITTA), m.get_int(F_ANNO));
}
void controlla_ivadiff(int argc, char* argv[])
{
TCheck_ivadiff cp;
cp.run(argc, argv, TR("Ricalcolo IVA differita"));
}