campo-sirio/fe/fe0100.cpp
mtollari 8d71207ffe Patch level : 12.0 278
Files correlati     : fe0.exe fe0100a.msk
Commento            :

Eliminata la generazione della blacklist dalla comunicazione polivalente

git-svn-id: svn://10.65.10.50/branches/R_10_00@23227 c028cbd2-c16b-5b4b-a496-9718f37d4682
2016-09-09 13:08:51 +00:00

1535 lines
42 KiB
C++
Executable File

#include <applicat.h>
#include <automask.h>
#include <colors.h>
#include <defmask.h>
#include <golem.h>
#include <modaut.h>
#include <progind.h>
#include <recarray.h>
#include <relation.h>
#include <reputils.h>
#include <tabmod.h>
#include <utility.h>
#include <alleg.h>
#include <attiv.h>
#include <causali.h>
#include <clifo.h>
#include <mov.h>
#include <nditte.h>
#include <occas.h>
#include <partite.h>
#include <pconti.h>
#include <rmoviva.h>
#include "fe0100a.h"
#include "felib.h"
#include "../cg/cglib01.h"
const char* const INVALID_NUMDOC = "???????";
long MANUAL_ROW = 900000L;
///////////////////////////////////////////////////////////
// Utility
///////////////////////////////////////////////////////////
enum TExclusion_mode { em_normale, em_importo_limite, em_no_allegato,
em_fiscalita_agevolata, em_estero, em_intra,
em_art8, em_data_limite, em_passaggi_interni,
em_inviato, em_altro };
static const char* mode2string(TExclusion_mode motivo)
{
const char* msg = "";
switch (motivo)
{
case em_importo_limite : msg = TR("Importo non rilevante"); break;
case em_no_allegato : msg = TR("Soggetto da non inserire in allegato"); break;
case em_fiscalita_agevolata: msg = TR("Soggetto residente in stato a fiscalità agevolata"); break;
case em_estero : msg = TR("Soggetto residente all'estero"); break;
case em_intra : msg = TR("Movimento intra"); break;
case em_data_limite : msg = TR("Data fuori dal limite della comunicazione"); break;
case em_art8 : msg = TR("Soggetto all'articolo 8 (del dpr 26-10-1972)"); break;
case em_passaggi_interni : msg = TR("Passaggi interni"); break;
case em_inviato : msg = TR("Inviato in definitivo"); break;
default : msg = TR("Altri motivi"); break;
}
return msg;
}
///////////////////////////////////////////////////////////
// TSpesometro_msk
///////////////////////////////////////////////////////////
class TSpesometro_msk : public TAutomask
{
TMaskmode _mode;
bool _sheet_dirty;
TExclusion_mode _why;
TLog_report* _log;
TString16 _partita_IVA, _codice_fiscale;
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
void alleg_sort(TSheet_field& s) const;
void load_sheet();
bool save_sheet();
bool save_if_dirty();
void set_dirty(bool d = true);
bool send_fatt(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const;
bool send_nota_variazione(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const;
bool send_estero(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const;
void build_outname(TFilename& n) const;
int get_date_range(TDate& dal, TDate& al) const;
protected:
TRecnotype last_user_progr() const;
TRecnotype nuovo_progr() const;
bool check_rows(bool show_error);
void enable_buttons();
void save_anagr(const TAnagrafica& anag, TSpesometro_set& operaz) const;
bool send_rec(const TRectype& alleg, TSpesometro_set& operaz);
TExclusion_mode segnala_movimento(const TRectype& mov, TExclusion_mode motivo);
//bool fattura_associata(long numreg_var, TDate& datafatt, TString& numdoc) const;
bool azzera_alleg(TAssoc_array& manuali) const;
public:
TRecnotype genera_alleg();
bool elabora_alleg();
bool send_alleg();
bool recall_alleg() const;
TExclusion_mode elabora_movimento(const TRectype& mov, TBaseisamfile& falleg);
bool salva_allegato(const TRectype& mov, TBaseisamfile& falleg, TRecnotype& progr,
const real& corrispettivo, const real& imposta, int tipope);
TExclusion_mode validate_clifo(const TRectype& mov);
TExclusion_mode validate_mov(const TRectype& mov);
TSpesometro_msk();
~TSpesometro_msk() { save_profile(); }
};
TSpesometro_msk::TSpesometro_msk() : TAutomask("fe0100a"), _mode(MODE_QUERY), _log(NULL)
{
load_profile();
set_dirty(false);
const long codditta = prefix().get_codditta();
const TAnagrafica ditta(LF_NDITTE, codditta);
_partita_IVA = ditta.partita_IVA();
if (_partita_IVA.blank())
_codice_fiscale = ditta.codice_fiscale();
else
{
if (_partita_IVA[0] == '8' || _partita_IVA[0] == '9')
{
_codice_fiscale = _partita_IVA;
_partita_IVA.cut(0);
}
}
}
TExclusion_mode TSpesometro_msk::segnala_movimento(const TRectype& mov, TExclusion_mode motivo)
{
if (_why == em_normale) // Aggiorna motivo esclusione se normale
{
_why = motivo;
bool segnala = true;
if (_why != em_fiscalita_agevolata && get(F_TIPO) == "BL") // Segnalo solo black list
segnala = false;
if (segnala)
{
const long numreg = mov.get_long(MOV_NUMREG);
const char tipocf = mov.get_char(MOV_TIPO);
const long codcf = mov.get_long(MOV_CODCF);
TString msg;
if (codcf > 0)
{
const TAnagrafica a(tipocf, codcf, mov.get(MOV_OCFPI));
msg.format(FR("Mov. %7ld %s %s: "), numreg,
tipocf=='F' ? TR("For.") : TR("Cli."), (const char*)a.ragione_sociale());
msg << mode2string(motivo);
if (a.estero() && a.stato_estero_UNICO().blank())
msg << " (Codice UNICO non specificato)";
}
else
{
msg.format(FR("Mov. %7ld %s senza codice: "), numreg, tipocf=='F' ? TR("For.") : TR("Cli."));
}
msg.strip_double_spaces();
_log->log(1, msg);
}
}
return motivo;
}
TExclusion_mode TSpesometro_msk::validate_clifo(const TRectype& mov)
{
const char tipocf = mov.get_char(MOV_TIPO);
const long codcf = mov.get_long(MOV_CODCF);
const TString16 ocfpi = mov.get(MOV_OCFPI);
if (tipocf <= ' ' || (codcf <= 0 && ocfpi.blank()))
return segnala_movimento(mov, em_no_allegato);
#ifdef DBG
if (codcf == 269)
int ok=false;
#endif
TString8 key; key.format("%c|%ld", tipocf, codcf);
const TRectype& rec_clifo = cache().get(LF_CLIFO, key);
const int alleg = rec_clifo.get_int(CLI_ALLEG);
TString4 stato = rec_clifo.get(CLI_STATOCF); // Può cambiare per occasionali
if (alleg == 4)
{
const long codalleg = rec_clifo.get_long(CLI_CODALLEG);
if (codalleg > 0L)
{
key.format("%c|%ld", tipocf, codalleg);
const TRectype& rec_alleg = cache().get(LF_CLIFO, key);
if (!rec_alleg.empty())
{
((TRectype&)mov).put(MOV_CODCF, codalleg);
return validate_clifo(mov);
}
}
}
if (ocfpi.full())
{
const TRectype& rec_occas = cache().get(LF_OCCAS, ocfpi);
stato = rec_occas.get(OCC_STATO);
}
else
{
if (alleg == 1)
return segnala_movimento(mov, em_no_allegato);
if (alleg == 5)
return segnala_movimento(mov, em_intra);
if (stato.blank() && alleg == 9) // Flag extra CEE incoerente
return segnala_movimento(mov, em_estero);
}
if (stato.full())
{
// I clienti privati vanno inclusi anche se residenti in stati esteri in black list
if (ocfpi.blank() && alleg != 6)
{
const TRectype& rec_sta = cache().get("%STA", stato);
if (rec_sta.get_bool("B0") || rec_sta.get_bool("B1")) // Black list o San Marino
return segnala_movimento(mov, em_fiscalita_agevolata);
}
return segnala_movimento(mov, em_estero);
}
return em_normale; // se arriva qui il clifo è da considerare
}
TExclusion_mode TSpesometro_msk::validate_mov(const TRectype& mov)
{
// Ignora eventuale vecchio movimento IVA (ANNOIVA < 2012)
const int anno = mov.get_int(MOV_ANNOIVA);
if (anno < 2012)
return segnala_movimento(mov, em_data_limite);
#ifdef DBG
if (mov.get_long(MOV_NUMREG) ==14224)
int sn = 1;
#endif
const char tipocf = mov.get_char(MOV_TIPO);
const real impmin = get_real(F_IMPMIN);
if (tipocf == 'C' && impmin > ZERO && abs(mov.get_real(MOV_TOTDOC)) <= impmin)
return segnala_movimento(mov, em_importo_limite);
const TString& keytok = mov.get(MOV_NUMREG);
TRecord_array righe_iva(keytok, LF_RMOVIVA);
real tot_imponibile, tot_imposta;
//calcolo di imponibile ed imposta di tutte le righe iva del movimento
for (int r = righe_iva.last_row(); r > 0; r = righe_iva.pred_row(r))
{
const TRectype& rmi = righe_iva.row(r);
const TCodiceIVA ci(rmi.get(RMI_CODIVA));
const int natura_operazione = ci.allegato(tipocf);
if (natura_operazione <= 0 || natura_operazione > 5)
continue;
tot_imponibile += rmi.get_real(RMI_IMPONIBILE);
tot_imposta += rmi.get_real(RMI_IMPOSTA);
}
if (tot_imponibile.is_zero() && tot_imposta.is_zero())
return segnala_movimento(mov, em_importo_limite);
if (tipocf == 'C' && abs(tot_imponibile) < impmin)
return segnala_movimento(mov, em_importo_limite);
TExclusion_mode em = validate_clifo(mov);
if (em != em_normale)
return em;
// Trova i movimenti INTRA
if (!mov.get_real(MOV_CORRLIRE).is_zero() || !mov.get_real(MOV_CORRVALUTA).is_zero())
em = segnala_movimento(mov, em_intra);
return em;
}
TExclusion_mode TSpesometro_msk::elabora_movimento(const TRectype& mov, TBaseisamfile& falleg)
{
TExclusion_mode em = validate_mov(mov);
const char tipocf = mov.get_char(MOV_TIPO);
const long codcf = mov.get_long(MOV_CODCF);
const TString4 tipodoc = mov.get(MOV_TIPODOC);
const TDate datareg = mov.get_date(MOV_DATAREG);
const int anno = get_int(F_ANNO);
TString4 tipope = "FE"; // Default = Fattura emessa
if (em == em_fiscalita_agevolata)
{
tipope = "BL";
} else
if (em == em_estero)
{
if (tipocf == 'C')
tipope = "FN";
}
else
{
const bool is_nota = fe_is_nota_variazione(mov);
if (tipocf == 'F')
{
tipope = is_nota ? "NR" : "FR";
}
else
{
tipope = is_nota ? "NE" : "FE";
}
}
real tot_imponibile, tot_imposta;
int tipo_iva = 1; // Normale
real ser_imponibile, mer_imponibile;
if (em != em_importo_limite)
{
const TString& keytok = mov.get(MOV_NUMREG);
TRecord_array righe_iva(keytok, LF_RMOVIVA);
//calcolo di imponibile ed imposta di tutte le righe iva del movimento
for (int r = righe_iva.last_row(); r > 0; r = righe_iva.pred_row(r))
{
const TRectype& rmi = righe_iva.row(r);
const TCodiceIVA ci(rmi.get(RMI_CODIVA));
int natura_operazione = ci.allegato(tipocf);
if (natura_operazione <= 0 || natura_operazione > 5)
continue; // Scarta codici IVA non rilevanti
if (natura_operazione > tipo_iva)
tipo_iva = natura_operazione;
// Esportazioni
const bool art_8 = ci.get("S2") == "20" && ci.get("S3") == "1";
if (art_8)
segnala_movimento(mov, em_art8);
const TString4 cod_det = rmi.get(RMI_TIPODET);
const int tip_det = cod_det == "3" ? 3 : atoi(cache().get("%DET", cod_det, "I0"));
if (tip_det == 3)
segnala_movimento(mov, em_passaggi_interni);
real rmi_imponibile = rmi.get_real(RMI_IMPONIBILE);
real rmi_imposta = rmi.get_real(RMI_IMPOSTA);
if (natura_operazione == 4 && rmi_imposta.is_zero()) // se l'imposta non è specificata sullo scontrino ...
rmi_imposta = ci.scorpora(rmi_imponibile); // ... scorporo il lordo
tot_imponibile += rmi_imponibile;
tot_imposta += rmi_imposta;
if (tipope == "SE")
{
const TBill zio(rmi);
const TRectype& rec = cache().get(LF_PCON, zio.string());
if (rec.get_int(PCN_RICSER) == 1) // 0=Altro; 1=Servizi; 2=Merce
ser_imponibile += rmi_imponibile;
else
mer_imponibile += rmi_imponibile;
}
}
}
const long numreg = mov.get_long(MOV_NUMREG);
// Registro tutti i dati del cliente e gli importi
falleg.zero();
switch (em)
{
case em_normale:
{
TString8 key; key << tipocf << '|' << codcf;
const TRectype& clifo = cache().get(LF_CLIFO, key);
if (clifo.get_char(CLI_ALLEG) == 'C') // Carta carburanti
falleg.put(ALL_CARBURAN, true);
else
{
if (tipocf == 'C')
{
bool af = false;
if (_partita_IVA.full())
af = _partita_IVA == clifo.get(CLI_PAIV);
else
af = _codice_fiscale == clifo.get(CLI_COFI) && clifo.get(CLI_PAIV).blank(); // Agriturismo
if (af)
{
falleg.put(ALL_AUTOFATT, af);
if (tot_imponibile.is_zero() && !tot_imposta.is_zero())
tot_imponibile = tot_imposta.sign();
}
}
if (mov.get_int(MOV_UPROTIVA) > mov.get_int(MOV_PROTIVA))
falleg.put(ALL_RIEPILOG, true);
}
}
break;
case em_fiscalita_agevolata:
if (abs(tot_imponibile) <= 500)
falleg.put(ALL_IGNORA, em = em_importo_limite); // Ignora importo <= 500 Euro
break; // Non ignorare!
case em_estero:
if (tot_imponibile.is_zero())
falleg.put(ALL_IGNORA, em = em_importo_limite); // Ignora importo nullo
else
{
if (tipocf == 'F') // Considera solo fatture servizi
{
if (ser_imponibile > mer_imponibile)
falleg.put(ALL_SERVIZI, true);
else
falleg.put(ALL_IGNORA, em); // Ignora importazioni di merce
}
}
break;
case em_intra:
if (tipocf == 'C' && !tot_imposta.is_zero())
{
tipope = "FN";
em = em_estero;
break;
}
default:
falleg.put(ALL_IGNORA, em); // Ignora
break;
}
if (mov.get_date(MOV_INVIOFE).ok())
{
falleg.put(ALL_IGNORA, em_inviato);
segnala_movimento(mov, em_inviato);
}
if (em == em_normale || em_intra)
{
if (tipocf == 'F')
{
const TRectype& caus = cache().get(LF_CAUSALI, mov.get(MOV_CODCAUS));
const int reg_spec = caus.get_int(CAU_REGSPIVA);
if (reg_spec == 13 || reg_spec == 50 || reg_spec == 51) // reverse charge
falleg.put(ALL_REVERSE, true);
}
}
if (tipope == "SE")
{
const TAnagrafica anag(mov);
bool good = anag.comune_residenza().full();
if (good)
{
if (anag.fisica())
good = anag.cognome().full() && anag.data_nascita().ok();
else
good = anag.ragione_sociale().full();
}
if (!good)
{
TString8 key; key << tipocf << '|' << codcf;
const TRectype& clifo = cache().get(LF_CLIFO, key);
if (clifo.get_int(CLI_ALLEG) == 9) // Extra CEE con dati anagrafici insufficienti
{
falleg.put(ALL_AUTOFATT, true);
if (tot_imponibile.is_zero() && !tot_imposta.is_zero())
tot_imponibile = tot_imposta.sign();
}
}
}
falleg.put(ALL_ANNO, anno);
falleg.put(ALL_PROGR, numreg);
falleg.put(ALL_TIPOPE, tipope);
falleg.put(ALL_TIPOCF, tipocf);
falleg.put(ALL_CODCF, codcf);
falleg.put(ALL_OCFPI, mov.get(MOV_OCFPI));
falleg.put(ALL_DATAREG, mov.get(MOV_DATAREG));
falleg.put(ALL_NUMDOC, mov.get(MOV_NUMDOC));
falleg.put(ALL_DATADOC, mov.get(MOV_DATADOC));
falleg.put(ALL_NOLEGGIO,mov.get(MOV_NOLEGGIO));
falleg.put(ALL_TIPOIVA, tipo_iva);
falleg.put(ALL_IMPORTO, tot_imponibile);
falleg.put(ALL_IMPOSTA, tot_imposta);
const int err = falleg.rewrite_write();
if (err != NOERR)
{
TString msg;
msg.format(FR("Errore %d di aggiornamento del record %d/%ld sul file %s"),
err, anno, numreg, (const char*)falleg.name());
_log->log(2, msg);
}
return _why;
}
bool TSpesometro_msk::azzera_alleg(TAssoc_array& manuali) const
{
TDate dataini, datafin;
const int anno = get_date_range(dataini, datafin);
if (!delete_box(FR("Si desiderano eliminare le righe dal %s al %s"),
dataini.stringa(), datafin.stringa()))
return false;
TFast_isamfile fast_alleg(LF_ALLEG);
TFast_isamfile fast_mov(LF_MOV);
TString query;
query << "USE " << LF_ALLEG
<< "\nSELECT BETWEEN(DATAREG," << dataini.date2ansi() << ',' << datafin.date2ansi() << ')'
<< "\nJOIN MOV INTO NUMREG==PROGR"
<< "\nFROM ANNO=" << anno
<< "\nTO ANNO=" << anno << " PROGR=" << MANUAL_ROW;
TISAM_recordset alleg(query);
TLocalisamfile& falleg = alleg.cursor()->file();
TRectype& arec = falleg.curr();
TLocalisamfile& fmov = alleg.cursor()->file(LF_MOV);
TRectype& mrec = fmov.curr();
TString msg; msg << TR("Azzeramento ") << falleg.description() << ' ' << anno;
TProgress_monitor pi(alleg.items(), msg, false);
manuali.destroy();
for (bool ok = alleg.move_first(); ok; ok = alleg.move_next())
{
const long progr = arec.get_long(ALL_PROGR);
const long numreg = mrec.get_long(MOV_NUMREG);
const TDate datareg = mrec.get_long(MOV_DATAREG);
const int annoiva = mrec.get_long(MOV_ANNOIVA);
bool kill = numreg != progr || annoiva < anno;
if (!kill)
{
const bool forzata = arec.get_bool(ALL_FORZATURA);
if (forzata)
manuali.add(arec.get(ALL_PROGR));
else
kill = annoiva == anno;
}
if (kill)
falleg.remove(); // Riga generata dalla vecchia versione
pi.add_status();
}
return !manuali.empty();
}
// Cerca l'ultimo numero di riga immesso manualmente
TRecnotype TSpesometro_msk::last_user_progr() const
{
const int anno = get_int(F_ANNO);
TRecnotype progr = MANUAL_ROW;
TString query;
query << "USE " << LF_ALLEG
<< "\nFROM " << ALL_ANNO << '=' << anno << ' ' << ALL_PROGR << '=' << MANUAL_ROW
<< "\nTO " << ALL_ANNO << '=' << anno;
TISAM_recordset alleg(query);
if (alleg.move_last())
progr = alleg.get(ALL_PROGR).as_int();
return progr;
}
TRecnotype TSpesometro_msk::nuovo_progr() const
{
TRecnotype progr = last_user_progr();
TSheet_field& righe = sfield(F_RIGHE);
const int items = righe.items();
if (items > 0)
{
const int col = righe.cid2index(A_RIGA);
for (int i = items-1; i >= 0; i--)
{
const TRecnotype sheet_progr = atol(righe.cell(i,col));
if (sheet_progr > progr)
progr = sheet_progr;
}
}
return progr+1;
}
static int sort_alleg(const TSortable& s1, const TSortable& s2, void* jolly)
{
const TRectype& a1 = (const TRectype&)s1;
const TRectype& a2 = (const TRectype&)s2;
const TDate d1 = a1.get(ALL_DATAREG);
const TDate d2 = a2.get(ALL_DATAREG);
int cmp = d1 - d2;
return cmp;
}
TRecnotype TSpesometro_msk::genera_alleg()
{
const int anno = get_int(F_ANNO);
TString str_pi;
str_pi << TR("Movimenti");
str_pi << ' ' << anno;
_log = new TLog_report(str_pi);
TAssoc_array manuali;
azzera_alleg(manuali);
TRecnotype nprog = 1;
if (anno >= 2012) // Dummy test for bracing TFast_isamfiles
{
TFast_isamfile falleg(LF_ALLEG);
TFast_isamfile fmov(LF_MOV);
const TDate dal(1,1,anno);
const TDate al(31,12,anno);
TString query;
query << "USE MOV KEY 3 SELECT (BETWEEN(DATAREG,"
<< dal.date2ansi() << ',' << al.date2ansi() << "))&&(REG!=\"\")"
<< "\nFROM TIPO=C\nTO TIPO=F";
TISAM_recordset mov(query);
TRectype& mov_rec = mov.cursor()->curr();
const TRecnotype items = mov.items();
TProgress_monitor pi(items, str_pi);
for (bool ok = mov.move_first(); ok; ok = mov.move_next())
{
_why = em_normale;
const TDate datafe = mov_rec.get(MOV_INVIOFE);
if (datafe.ok()) // Non elaborare i movimenti già inviati in definitivo!
{
segnala_movimento(mov_rec, em_inviato);
continue;
}
const TString& key = mov_rec.get(MOV_NUMREG);
if (manuali.is_key(key))
{
manuali.remove(key);
continue;
}
elabora_movimento(mov_rec, falleg);
if (!pi.add_status())
break;
}
}
_log->preview();
delete _log;
_log = NULL;
return nprog;
}
// Analizza tutti i movimenti dell'anno dell'attività corrente e genera i record rilevanti
bool TSpesometro_msk::elabora_alleg()
{
if (!check_fields()) // Controlla che l'anno sia valido
return false;
const TRecnotype prog = genera_alleg();
return prog > 1;
}
bool TSpesometro_msk::send_nota_variazione(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const
{
const real imp = alleg.get_real(ALL_IMPORTO);
operaz.set(11, imp > ZERO ? "ND" : "NC");
return true;
}
bool TSpesometro_msk::send_fatt(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const
{
return true;
}
bool TSpesometro_msk::send_estero(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const
{
const char tipocf = alleg.get_char(ALL_TIPOCF);
const bool is_nota = fe_is_nota_variazione(alleg);
if (is_nota) // Le istruzioni dicono di ignorarla, ma Sirio non ha ancora deciso
send_nota_variazione(alleg, anag, operaz); // Imposta solamente il campo 11 a ND o NC
const char cayman = anag.is_black_list(alleg.get_date(ALL_DATAREG));
const bool servizi = tipocf == 'F' && alleg.get_bool(ALL_SERVIZI);
if (servizi && alleg.get_bool(ALL_AUTOFATT))
{
// Trasforma la fattura da non residente ad autofattura
operaz.set(0, "FR");
// Azzera campi anagrafici e sostituiscili con quelli del dichiarante
const long codditta = prefix().get_codditta();
const TAnagrafica ditta(LF_NDITTE, codditta);
for (int f = 14; f <= 26; f++)
operaz.set(f, "");
save_anagr(ditta, operaz);
return true;
}
// I flag 27,28,29 sono obbligatori e mutuamente esclusivi
if (cayman > ' ') // Residente in paese a fiscalità agevolata (o San Marino)
{
const char str[2] = { cayman, '\0' }; // Convert char to string
operaz.set(27, str);
}
else
{
if (servizi)
operaz.set(29, true); // Acquisto servizi all'estero
else
operaz.set(28, true); // Residente all'estero
}
const char* sez = "BL30";
if (cayman > ' ')
{
if (is_nota)
sez = "BL50";
else
{
if (alleg.get_int(ALL_TIPOIVA) == 4) // Non esposta
sez = "BL41";
}
}
operaz.set(30, sez); // Tipologia imponibile BL
return true;
}
void TSpesometro_msk::save_anagr(const TAnagrafica& anag, TSpesometro_set& operaz) const
{
// Partita IVA e Codice fiscale sono alternativi
const TString& piva = anag.partita_IVA();
if (piva.full())
{
if (piva[0] >= '8' && piva.len() == 11 && anag.italiano()) // Ente pubblico!
operaz.set(2, piva); // In realtà trattasi di codice fiscale speciale!
else
operaz.set(1, piva);
}
else
operaz.set( 2, anag.codice_fiscale());
if (anag.fisica())
{
operaz.set(14, anag.cognome());
operaz.set(15, anag.nome());
operaz.set(16, anag.data_nascita());
operaz.set(17, anag.comune_nascita());
operaz.set(18, anag.provincia_nascita());
operaz.set(19, anag.stato_estero_UNICO());
operaz.set(20, anag.comune_residenza());
operaz.set(21, anag.indirizzo_residenza());
}
else
{
operaz.set(22, anag.ragione_sociale());
operaz.set(23, anag.comune_residenza());
operaz.set(24, anag.stato_estero_UNICO());
operaz.set(25, anag.indirizzo_residenza());
operaz.set(26, piva);
}
}
bool TSpesometro_msk::send_rec(const TRectype& alleg, TSpesometro_set& operaz)
{
bool done = false;
const real importo = abs(alleg.get_real(ALL_IMPORTO));
const real imposta = abs(alleg.get_real(ALL_IMPOSTA));
if (importo.is_zero() && imposta.is_zero())
return false; // should never happen
const TAnagrafica anag(alleg);
if (!anag.ok())
return false; // should never happen
const char tipocf = alleg.get_char(ALL_TIPOCF);
const TString4 tipo = alleg.get(ALL_TIPOPE);
operaz.new_rec(tipo);
operaz.set(31, alleg.get_int(ALL_ATTAGG)); // Provoca nascita dei 34 campi vuoti precedenti
operaz.set(32, alleg.get_int(ALL_PASAGG));
operaz.set(33, alleg.get_bool(ALL_RIEPILOG));
operaz.set(34, alleg.get_bool(ALL_CARBURAN));
operaz.set( 3, alleg.get_int(ALL_TIPOIVA) == 4); // IVA non esposta in fattura
operaz.set( 4, alleg.get(ALL_NOLEGGIO)); // Noleggio
operaz.set( 5, alleg.get_bool(ALL_AUTOFATT)); // Autofattura
operaz.set( 6, alleg.get_bool(ALL_REVERSE)); // Reverse charge
operaz.set( 7, alleg.get(ALL_DATADOC));
operaz.set( 8, alleg.get(ALL_DATAREG));
operaz.set( 9, alleg.get(ALL_NUMDOC));
operaz.set(10, tipocf == 'F' ? "A" : "C"); // Acquisto o Cessione
operaz.set(12, importo);
operaz.set(13, imposta);
save_anagr(anag, operaz);
if (anag.estero())
done = send_estero(alleg, anag, operaz);
else
{
if (fe_is_nota_variazione(alleg))
done = send_nota_variazione(alleg, anag, operaz);
else
done = send_fatt(alleg, anag, operaz);
}
return done;
}
bool TSpesometro_msk::recall_alleg() const
{
TDate dal, al;
const int anno = get_date_range(dal, al);
if (!delete_box(FR("Si desidera annullare l'invio definitivo dal %s al %s?"),
dal.stringa(), al.stringa()))
return false;
TFast_isamfile mov(LF_MOV);
TString query;
query << "USE MOV KEY 2";
query << "\nFROM DATAREG=" << dal;
query << "\nTO DATAREG=" << al;
TISAM_recordset recset(query);
TLocalisamfile& file = recset.cursor()->file();
TString msg;
msg << TR("Aggiornamento movimenti di prima nota dal ")
<< dal.stringa() << TR(" al ") << al.stringa();
TProgress_monitor pi(recset.items(), msg);
for (bool ok = recset.move_first(); ok; ok = recset.move_next())
{
if (file.get_date(MOV_INVIOFE).ok())
{
file.zero(MOV_INVIOFE);
file.rewrite();
}
if (!pi.add_status())
break;
}
return true;
}
void TSpesometro_msk::build_outname(TFilename& n) const
{
TDate dal, al;
const int anno = get_date_range(dal,al);
n = get(F_OUTFOLDER);
if (n.blank())
n.tempdir();
TString80 f;
/*
Eliminata la generazione della blacklist
if (get(F_TIPO) == "BL")
{
const int dm = dal.month(), am = al.month();
if (dm == am)
{
TString16 m = itom(dal.month()); m.cut(3);
f.format("BlackList%05ld%s%04d", prefix().get_codditta(), (const char*)m, anno);
} else
if (am-dm == 2)
{
TString16 m; m << TR("Trim") << itor(am/3);
f.format("BlackList%05ld%s%04d", prefix().get_codditta(), (const char*)m, anno);
}
else
f.format("BlackList%05ld%04d", prefix().get_codditta(), anno);
}
else
*/
f.format("Spesometro%05ld%04d", prefix().get_codditta(), anno);
n.add(f);
n.ext("csv");
}
// Genera file per invio telematico
bool TSpesometro_msk::send_alleg()
{
const TString& tipo = get(F_TIPO);
TDate dal, al;
const int anno = get_date_range(dal, al);
TString query;
query << "USE ALLEG KEY 2\nSELECT ";
/*
Eliminata la generazione della blacklist
if (tipo == "BL")
{
query << "(BETWEEN(DATAREG," << dal.date2ansi() << ',' << al.date2ansi() << "))&&"
<< "(TIPOPE==\"BL\")";
}
else
*/
query << "(TIPOPE!=\"BL\")";
query << "\nFROM " << ALL_ANNO << '=' << anno
<< "\nTO " << ALL_ANNO << '=' << anno;
TISAM_recordset alleg(query);
const TRectype& rec = alleg.cursor()->curr();
const TRecnotype tot_alleg = alleg.items();
bool done = tot_alleg > 0;
if (done)
{
TSpesometro_set recset;
recset.add_header(*this);
TFilename temp; build_outname(temp);
_log = new TLog_report(temp);
TProgress_monitor pi(tot_alleg, temp);
for (bool ok = alleg.move_first(); ok; ok = alleg.move_next())
{
const int ignora = alleg.get(ALL_IGNORA).as_int(); // Non mi fido di "", " " e "0" per questo campo
if (ignora == 0)
send_rec(rec, recset);
if (!pi.add_status())
break;
}
recset.add_footer(*this);
done = recset.save_as(temp);
if (_log->recordset()->items())
_log->preview();
delete _log;
_log = NULL;
}
TFilename tmp = "spesometro/ModuliSirio.jar";
tmp.make_absolute_path();
DIRECTORY old_dir; xvt_fsys_get_dir(&old_dir);
DIRECTORY new_dir; xvt_fsys_convert_str_to_dir(tmp.path(), &new_dir);
xvt_fsys_set_dir(&new_dir);
const bool good = goto_url(tmp);
xvt_sys_sleep(3000);
xvt_fsys_set_dir(&old_dir);
if (!good)
error_box(FR("Impossibile eseguire Java -jar %s"), (const char*)tmp);
if (done && get_bool(F_DEFINITIVO) && yesno_box(TR("Si conferma l'invio definitivo della comunicazione?")))
{
TFast_isamfile mov(LF_MOV);
TProgress_monitor pi(tot_alleg, TR("Aggiornamento movimenti di prima nota"), false);
for (bool ok = alleg.move_first(); ok; ok = alleg.move_next())
{
const int ignora = rec.get_int(ALL_IGNORA);
if (ignora)
continue;
const long numreg = rec.get_long(ALL_PROGR);
if (numreg > 0 && numreg < MANUAL_ROW)
{
mov.put(MOV_NUMREG, numreg);
int err = mov.read(_isequal, _lock);
if (err == NOERR)
{
if (!mov.get_date(MOV_INVIOFE).ok())
{
mov.put(MOV_INVIOFE, al);
err = mov.rewrite();
}
else
mov.reread(_unlock);
}
if (err != NOERR)
{
error_box(FR("Impossibile aggiornare il movimento %ld: errore %d"), numreg, err);
break;
}
}
if (numreg > 0)
{
TLocalisamfile& fall = alleg.cursor()->file();
fall.put(ALL_IGNORA, em_inviato);
fall.rewrite();
}
if (!pi.add_status())
break;
}
}
return done;
}
void TSpesometro_msk::set_dirty(bool d)
{
_sheet_dirty = d;
enable(DLG_SAVEREC, d);
}
void TSpesometro_msk::alleg_sort(TSheet_field& s) const
{
s.sort();
}
void TSpesometro_msk::load_sheet()
{
TWait_cursor hourglass;
const char tipocf = get(F_TIPOCF)[0];
const long codcf = get_long(F_CODCF);
const TString& ocfpi = get(F_OCFPI);
real vendite, acquisti;
TSheet_field& s = sfield(F_RIGHE);
s.hide(); // Nascondo lo sheet per guadagnare un 20% di velocità di caricamento
s.destroy();
_mode = MODE_QUERY;
const TString& tipope = get(F_TIPO);
TDate dal, al;
const int anno = get_date_range(dal, al);
TString limit; limit << ALL_ANNO << '=' << anno;
if (codcf > 0)
limit << ' ' << ALL_TIPOCF << '=' << tipocf << ' ' << ALL_CODCF << '=' << codcf;
TString sel;
if (ocfpi.full())
sel << "&&(" << ALL_OCFPI << "='" << ocfpi << "')";
if (tipope != "**") // Tutto
{
if (tipope == "XX")
{
sel << "&&(STR(IGNORA>0))";
} else
if (tipope == "IN")
{
sel << "&&(STR(IGNORA==9))";
}
else
{
/*
Eliminata la generazione della blacklist
if (tipope == "BL")
sel << "&&(TIPOPE=\"BL\")"; // Black List
else
*/
sel << "&&(TIPOPE!=\"BL\")"; // Spesometro
sel << "&&(STR(IGNORA==0))";
}
}
if (dal.month() != 1 || al.month() != 12)
sel << "&&(BETWEEN(DATAREG," << dal.date2ansi() << ',' << al.date2ansi() << "))";
TString query;
query << "USE " << LF_ALLEG << " KEY 2";
if (sel.full())
{
sel.ltrim(2);
query << " SELECT " << sel;
}
if (limit.full())
query << "\nFROM " << limit << "\nTO " << limit;
TISAM_recordset alleg(query);
const TRecnotype items = alleg.items();
if (items > 0)
{
TString pi_str;
pi_str << TR("Caricamento ") << items << TR(" movimenti ");
if (dal.month() != 1 || al.month() != 12)
{
if (dal.month() == al.month())
pi_str << itom(dal.month()) << ' ';
else
pi_str << itom(dal.month()) << '/' << itom(al.month()) << ' ';
}
pi_str << anno;
TProgress_monitor pi(items, pi_str);
TRectype& curr = alleg.cursor()->curr();
int rec = 0;
for (bool ok = alleg.move_first(); ok; ok = alleg.move_next())
{
if (!pi.addstatus(1))
break;
if (anno <= 2012)
{
const int t = curr.get_int(ALL_TIPOPE);
switch (t)
{
case 1: curr.put(ALL_TIPOPE, "FE"); break;
case 2: curr.put(ALL_TIPOPE, "FR"); break;
default: break;
}
}
if (s.autoload_line(++rec, curr))
{
const real imp = curr.get(ALL_IMPORTO);
if (curr.get_char(ALL_TIPOCF) == 'F')
acquisti += imp;
else
vendite += imp;
}
}
}
//alleg_sort(s);
set(F_ACQUISTI, acquisti);
set(F_VENDITE, vendite);
set(F_TOTALE, real(acquisti+vendite));
s.force_update();
s.show();
set_dirty(false);
if (s.items() > 0)
{
_mode = MODE_MOD;
disable(-1);
}
else
{
_mode = MODE_QUERY;
enable(-1);
}
enable_buttons();
}
bool TSpesometro_msk::save_sheet()
{
if (!check_rows(false))
return false;
bool done = true;
const int anno = get_int(F_ANNO);
TSheet_field& s = sfield(F_RIGHE);
const TRecnotype items = s.items();
if (items > 0)
{
TFast_isamfile alleg(LF_ALLEG);
TRectype& rec = alleg.curr();
TProgress_monitor pi(items, TR("Registrazione righe"), false);
FOR_EACH_SHEET_ROW(s, r, row)
{
alleg.zero();
rec.put(ALL_ANNO, anno);
s.autosave_line(r+1, rec);
const int err = alleg.rewrite_write();
if (err != NOERR)
{
done = cantwrite_box(alleg.name());
break;
}
pi.add_status();
}
}
if (done)
{
set_dirty(false);
}
return done;
}
bool TSpesometro_msk::check_rows(bool show_error)
{
const int anno = get_int(F_ANNO);
bool ok = anno >= 2012;
if (!ok)
{
if (show_error)
check_fields(); // Provoco segnalazione automatica
return false;
}
long codcf = 0L;
TString16 ocfpi;
TSheet_field& s = sfield(F_RIGHE);
FOR_EACH_SHEET_ROW(s, i, row)
{
row->get(s.cid2index(A_CODCF), codcf);
row->get(s.cid2index(A_OCFPI), ocfpi);
if (codcf <= 0L && ocfpi.blank())
{
ok = show_error && error_box(FR("Soggetto mancante alla riga %d"), i+1);
break;
}
}
return ok;
}
bool TSpesometro_msk::save_if_dirty()
{
bool done = true;
if (_sheet_dirty && yesno_box(TR("Si desiderano registrare le modifiche?")))
{
done = check_rows(true);
if (done)
done = save_sheet();
}
return done;
}
int TSpesometro_msk::get_date_range(TDate& dal, TDate& al) const
{
int anno = get_int(F_ANNO);
if (anno < 2012)
{
const TDate oggi(TODAY);
anno = oggi.year();
}
dal = TDate( 1, 1, anno);
al = TDate(31, 12, anno);
return anno;
}
void TSpesometro_msk::enable_buttons()
{
TSheet_field& s = sfield(F_RIGHE);
TDate dal, al;
const int anno = get_date_range(dal, al);
const bool good_year = anno >= 2012;
const bool def = get_bool(F_DEFINITIVO);
const bool full_rows = good_year && !s.empty();
bool one_sent = false; // Ho spedito almeno un movimento in definitivo
if (good_year)
{
TString query;
query << "USE MOV KEY 2 SELECT INVIOFE!=\"\"";
query << "\nFROM DATAREG=" << dal;
query << "\nTO DATAREG=" << al;
TISAM_recordset recset(query);
one_sent = recset.move_first();
}
enable(DLG_CANCEL, full_rows);
enable(DLG_SAVEREC,full_rows && _sheet_dirty);
enable(DLG_EXPORT, full_rows);
enable(DLG_RECALC, !full_rows && good_year && !one_sent);
enable(DLG_ELABORA, good_year && !(one_sent && def));
enable(DLG_DELREC, one_sent);
enable(F_DEFINITIVO, !def);
if (def) reset(F_DEFINITIVO);
TFilename temp; build_outname(temp);
enable(DLG_PREVIEW, temp.exist());
}
bool TSpesometro_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case DLG_OK: // Salva
if (e == fe_button && jolly == 0) // Selezione su maschera principale
{
if (_mode == MODE_QUERY || save_if_dirty())
load_sheet();
return false;
}
break;
case DLG_CANCEL:
if (e == fe_button && jolly == 0)
{
if (_mode != MODE_QUERY && save_if_dirty())
{
TSheet_field& s = sfield(F_RIGHE);
s.destroy();
s.force_update();
_mode = MODE_QUERY;
enable(-1);
enable_buttons();
}
return false;
}
break;
case DLG_LINK: // Ditta
if (e == fe_button)
{
TRectype ndt(LF_NDITTE);
ndt.put(NDT_CODDITTA, prefix().get_codditta());
if (ndt.edit(LF_NDITTE, NULL, "ba4 -2"))
prefix().notify_change(LF_NDITTE);
}
break;
case DLG_SAVEREC:
if (e == fe_button)
save_if_dirty();
break;
case DLG_EXPORT:
if (e == fe_button)
return sfield(F_RIGHE).esporta();
break;
case DLG_RECALC:
if (e == fe_button && check_fields())
{
if (elabora_alleg())
load_sheet();
}
break;
case DLG_ELABORA:
if (e == fe_button && check_fields())
{
const TString& tipo = get(F_TIPO);
if (tipo != "FE" && tipo != "BL")
return error_box("Non è possibile inviare record scartati");
send_alleg();
enable_buttons(); // Disabilita bottone se definitivo
}
break;
case DLG_DELREC:
if (e == fe_button && o.active())
{
if (jolly == 0) // Toolbar principale
{
recall_alleg();
enable_buttons(); // Disabilita bottone
return false;
}
else // Maschera di riga
{
const long progr = o.mask().get_long(A_RIGA);
if (progr >= MANUAL_ROW)
{
TLocalisamfile alleg(LF_ALLEG);
alleg.put(ALL_ANNO, get(F_ANNO));
alleg.put(ALL_PROGR, progr);
const int err = alleg.remove();
if (err != NOERR)
return error_box(FR("Errore di cancellazione: %d"), err);
}
else
return error_box(TR("Riga non cancellabile"));
}
}
break;
case DLG_PREVIEW:
if (e == fe_button)
{
TFilename temp; build_outname(temp);
if (temp.exist())
{
TSpesometro_rep rep(temp);
rep.preview();
}
}
break;
case F_ANNO:
if (e == fe_init || e == fe_modify)
{
int anno = atoi(o.get());
if (anno < 2012)
{
anno = TDate(TODAY).year()-1;
o.set(anno);
}
enable_buttons();
}
break;
case F_OUTFOLDER:
if (e == fe_init && o.empty())
{
TFilename tmp; tmp.tempdir();
o.set(tmp);
}
break;
case F_RIGHE:
if (e == fe_init)
load_sheet(); else
if (e == se_query_modify)
{
TSheet_field& s = (TSheet_field&)o;
TToken_string& row = s.row(jolly);
const TRecnotype progr = row.get_long(0);
s.sheet_mask().enable(DLG_DELREC, progr >= MANUAL_ROW);
s.sheet_mask().enable(DLG_USER, progr < MANUAL_ROW);
} else
if (e == se_notify_modify)
{
set_dirty(true);
enable_buttons();
} else
if (e == se_query_add)
{
if (!check_rows(false))
return false;
} else
if (e == se_notify_add)
{
TSheet_field& s = (TSheet_field&)o;
TToken_string& row = s.row(jolly);
row.add(nuovo_progr(), s.cid2index(A_RIGA));
} else
if (e == se_query_del)
{
TSheet_field& s = (TSheet_field&)o;
TToken_string& row = s.row(jolly);
const TRecnotype progr = row.get_long(0);
return progr >= MANUAL_ROW;
}
break;
case A_CODCF:
case A_OCFPI:
if (e == fe_modify || (e == fe_init && !o.empty()))
{
TMask& m = o.mask();
const TAnagrafica anag(m.get(A_TIPOCF)[0], m.get_long(A_CODCF), m.get(A_OCFPI));
m.set(A_RAGSOC, anag.ragione_sociale());
m.set(A_PAIV, anag.partita_IVA());
m.set(A_COFI, anag.codice_fiscale());
}
break;
case DLG_USER:
if (e == fe_button || e == fe_init)
{
const long numreg = o.mask().get_long(A_RIGA);
const bool enab = (numreg > 0) && (numreg < MANUAL_ROW);
if (e == fe_button && enab)
{
o.disable(); // Tecnica anti doppio click!
TRectype mov(LF_MOV);
mov.put(MOV_NUMREG, numreg);
mov.edit();
o.enable();
}
else
o.enable(enab);
}
break;
default:
break;
}
if (e == fe_modify && jolly == 1 && _mode == MODE_MOD)
{
const short id = o.dlg();
if (id >= A_RIGA && id < A_COFI && id != A_FORZATA)
{
o.mask().set(A_FORZATA, true);
set_dirty();
}
}
return true;
}
///////////////////////////////////////////////////////////
// TSpesometro_app
///////////////////////////////////////////////////////////
class TSpesometro_app : public TSkeleton_application
{
protected:
virtual bool create();
public:
virtual void main_loop();
};
bool TSpesometro_app::create()
{
if (!has_module(F3AUT))
{
const TDate oggi(TODAY);
TString html;
html << "<html><body>"
<< "<h5>Attenzione: Il modulo FE deve essere attivato in congiunzione a F3.</h5>\n"
<< "<p align=justify>Al fine di poter attivare l'utilizzo della Comunicazione Polivalente " << oggi.year() << " "
<< "La preghiamo di contattare <b>Sirio informatica e sistemi</b> al seguente riferimento:</p><br/>"
<< "<ul>"
<< "<li>Casella vocale Hotline Campo: <br /><a href=mailto:hotlinecampo@sirio-is.it>hotlinecampo@sirio-is.it</a> Tel. 02-36583540</li>"
<< "</ul>"
<< "</body></html>";
return warning_box(html);
}
// Controllo preventivo dell'avvenuta conversione del tracciato record
TRectype alleg(LF_ALLEG);
if (alleg.type(ALL_CARBURAN) == _nullfld)
return error_box(TR("Database non convertito per la Comunicazione Polivalente"));
TLocalisamfile mov(LF_MOV);
if (mov.last() == NOERR)
{
const long numreg = mov.get_long(MOV_NUMREG);
while (numreg > MANUAL_ROW)
MANUAL_ROW *= 10;
}
// Teoricamente è possibile visualizzare tutti i movimenti di un anno, per cui allargo il numero riga
TSheet_field::set_line_number_width(7);
return TSkeleton_application::create();
}
void TSpesometro_app::main_loop()
{
TSpesometro_msk msk;
msk.run();
}
///////////////////////////////////////////////////////////
// main
///////////////////////////////////////////////////////////
int fe0100(int argc, char* argv[])
{
TSpesometro_app app;
app.run(argc, argv, TR("Comunicazione Polivalente"));
return 0;
}