Patch level : 12.0 908

Files correlati     : ve6.exe, li0.exe
Commento            :
- Correzioni fatturazione con dichiarazioni lettere di intento:
- Ricontrolla a caldo il plafond rimanente per ogni lettera
- Ora se e' a cavallo di due lettere mettere il riferimento di entrambe e chiude la prima
- Prima non chiudeva mai le lettere e metteva il riferimento solo alla prima.
- Cambiato il riferimento da riportare sul documento, ora l'agenzia delle entrate vuole il codice dato dal ministero
This commit is contained in:
Simone Palacino 2019-12-12 16:32:13 +01:00
parent 17bd4fcd67
commit 991def6216
5 changed files with 281 additions and 89 deletions

View File

@ -1,85 +1,85 @@
#ifndef __CLIFO_H
#define __CLIFO_H
#define CLI_TIPOCF "TIPOCF"
#define CLI_CODCF "CODCF"
#define CLI_RAGSOC "RAGSOC"
#define CLI_INDCF "INDCF"
#define CLI_CIVCF "CIVCF"
#define CLI_STATOCF "STATOCF"
#define CLI_LOCCF "LOCALITACF"
#define CLI_COMCF "COMCF"
#define CLI_CAPCF "CAPCF"
#define CLI_COFI "COFI"
#define CLI_STATOPAIV "STATOPAIV"
#define CLI_PAIV "PAIV"
#define CLI_TIPOPERS "TIPOPERS"
#define CLI_ALLEG "ALLEG"
#define CLI_CODALLEG "CODALLEG"
#define CLI_GRUPPO "GRUPPO"
#define CLI_CONTO "CONTO"
#define CLI_GRUPPORIC "GRUPPORIC"
#define CLI_CONTORIC "CONTORIC"
#define CLI_SOTTOCRIC "SOTTOCRIC"
#define CLI_TIPOCF "TIPOCF"
#define CLI_CODCF "CODCF"
#define CLI_RAGSOC "RAGSOC"
#define CLI_INDCF "INDCF"
#define CLI_CIVCF "CIVCF"
#define CLI_STATOCF "STATOCF"
#define CLI_LOCCF "LOCALITACF"
#define CLI_COMCF "COMCF"
#define CLI_CAPCF "CAPCF"
#define CLI_COFI "COFI"
#define CLI_STATOPAIV "STATOPAIV"
#define CLI_PAIV "PAIV"
#define CLI_TIPOPERS "TIPOPERS"
#define CLI_ALLEG "ALLEG"
#define CLI_CODALLEG "CODALLEG"
#define CLI_GRUPPO "GRUPPO"
#define CLI_CONTO "CONTO"
#define CLI_GRUPPORIC "GRUPPORIC"
#define CLI_CONTORIC "CONTORIC"
#define CLI_SOTTOCRIC "SOTTOCRIC"
#define CLI_TIPOAPER "TIPOAPER"
#define CLI_TIPOAPER "TIPOAPER"
#define CLI_CODANAGPER "CODANAGPER"
#define CLI_PTEL "PTEL"
#define CLI_TEL "TEL"
#define CLI_PTEL2 "PTEL2"
#define CLI_TEL2 "TEL2"
#define CLI_PTEL3 "PTEL3"
#define CLI_TEL3 "TEL3"
#define CLI_PFAX "PFAX"
#define CLI_FAX "FAX"
#define CLI_PTELEX "PTELEX"
#define CLI_TELEX "TELEX"
#define CLI_BYMAIL "BYMAIL"
#define CLI_DOCMAIL "DOCMAIL"
#define CLI_MAIL "MAIL"
#define CLI_PEC "PEC"
#define CLI_DATANASC "DATANASC"
#define CLI_STATONASC "STATONASC"
#define CLI_COMNASC "COMNASC"
#define CLI_SESSO "SESSO"
#define CLI_SCONTO "SCONTO"
#define CLI_RAGGRB "RAGGRB"
#define CLI_RAGGFT "RAGGFT"
#define CLI_CODVETT1 "CODVETT1"
#define CLI_CODVETT2 "CODVETT2"
#define CLI_CODVETT3 "CODVETT3"
#define CLI_CODCFFATT "CODCFFATT"
#define CLI_DESTIN "DESTIN"
#define CLI_CODAG "CODAG"
#define CLI_CODZONA "CODZONA"
#define CLI_CODSTAT "CODSTAT"
#define CLI_CODABI "CODABI"
#define CLI_CODCAB "CODCAB"
#define CLI_NUMCC "NUMCC"
#define CLI_IBAN "IBAN"
#define CLI_OCCAS "OCCAS"
#define CLI_STATO "STATO"
#define CLI_CODVAL "CODVAL"
#define CLI_CODLIN "CODLIN"
#define CLI_FIDO "FIDO"
#define CLI_CODPAG "CODPAG"
#define CLI_RICALT "RICALT"
#define CLI_OGGETTI "OGGETTI"
#define CLI_SOSPESO "SOSPESO"
#define CLI_DIRTY "DIRTY"
#define CLI_REFERENTE "REFERENTE"
#define CLI_VALINTRA "VALINTRA"
#define CLI_CODCFASS "CODCFASS"
#define CLI_DIPPUBB "DIPPUBB"
#define CLI_ENTE "ENTE"
#define CLI_AUTORIZ "AUTORIZ"
#define CLI_SPLITPAY "SPLITPAY"
#define CLI_PTEL "PTEL"
#define CLI_TEL "TEL"
#define CLI_PTEL2 "PTEL2"
#define CLI_TEL2 "TEL2"
#define CLI_PTEL3 "PTEL3"
#define CLI_TEL3 "TEL3"
#define CLI_PFAX "PFAX"
#define CLI_FAX "FAX"
#define CLI_PTELEX "PTELEX"
#define CLI_TELEX "TELEX"
#define CLI_BYMAIL "BYMAIL"
#define CLI_DOCMAIL "DOCMAIL"
#define CLI_MAIL "MAIL"
#define CLI_PEC "PEC"
#define CLI_DATANASC "DATANASC"
#define CLI_STATONASC "STATONASC"
#define CLI_COMNASC "COMNASC"
#define CLI_SESSO "SESSO"
#define CLI_SCONTO "SCONTO"
#define CLI_RAGGRB "RAGGRB"
#define CLI_RAGGFT "RAGGFT"
#define CLI_CODVETT1 "CODVETT1"
#define CLI_CODVETT2 "CODVETT2"
#define CLI_CODVETT3 "CODVETT3"
#define CLI_CODCFFATT "CODCFFATT"
#define CLI_DESTIN "DESTIN"
#define CLI_CODAG "CODAG"
#define CLI_CODZONA "CODZONA"
#define CLI_CODSTAT "CODSTAT"
#define CLI_CODABI "CODABI"
#define CLI_CODCAB "CODCAB"
#define CLI_NUMCC "NUMCC"
#define CLI_IBAN "IBAN"
#define CLI_OCCAS "OCCAS"
#define CLI_STATO "STATO"
#define CLI_CODVAL "CODVAL"
#define CLI_CODLIN "CODLIN"
#define CLI_FIDO "FIDO"
#define CLI_CODPAG "CODPAG"
#define CLI_RICALT "RICALT"
#define CLI_OGGETTI "OGGETTI"
#define CLI_SOSPESO "SOSPESO"
#define CLI_DIRTY "DIRTY"
#define CLI_REFERENTE "REFERENTE"
#define CLI_VALINTRA "VALINTRA"
#define CLI_CODCFASS "CODCFASS"
#define CLI_DIPPUBB "DIPPUBB"
#define CLI_ENTE "ENTE"
#define CLI_AUTORIZ "AUTORIZ"
#define CLI_SPLITPAY "SPLITPAY"
#define CLI_UTENTE "UTENTE"
#define CLI_DATAAGG "DATAAGG"
#define CLI_UTENTE "UTENTE"
#define CLI_DATAAGG "DATAAGG"
#define CLI_CODFPCUST "CODFPCUST"
#define CLI_DISCUSTFP "DISCUSTFP"
#define CLI_CODFPCUST "CODFPCUST"
#define CLI_DISCUSTFP "DISCUSTFP"
#endif

View File

@ -14,6 +14,9 @@
#define LETINT_DAL "DAL"
#define LETINT_AL "AL"
#define LETINT_STAMPATO "STAMPATO"
#define LETINT_INVIATO "INVIATO"
#define LETINT_INVIATO "INVIATO"
#define LETINT_PROTINTF "PROTINTF"
#define LETINT_PROTINTS "PROTINTS"
#define LETINT_CHIUSA "CHIUSA"
#endif

View File

@ -1,11 +1,14 @@
#include "lilib01.h"
#include <recarray.h>
#include "letint.h"
#include "sqlset.h"
#include <utility.h>
#include <progind.h>
#define SOLUZIONE_UNICA 1
#define FINO_A_PLAFOND 2
class TSQL_recordset;
const TString make_key(const int anno, const int numplaf)
{
static TString key;
@ -881,3 +884,155 @@ bool popola_plafond(TLista_documenti & din, const TDate& data_elab)
return ok;
}
void scrivi_plafond(TLista_documenti & din, const TDate& data_elab)
{
std::map<int, TLi_manager*> plafonds; // Mappa di clienti-plafond: il plafond e' l'insieme delle lettere
TProgress_monitor m_doc(din.items(), "Generazione plafond nelle fatture");
for (int i = 0; i < din.items(); i++)
{
if (!m_doc.add_status())
return;
// Per ogni fattura richiamo il plafond dell'intestatario e faccio le mie elaborazioni
if (plafonds.find(din[i].codcf()) == plafonds.end())
{
TLi_manager* plaf = new TLi_manager(din[i].tipocf(), din[i].codcf(), data_elab);
plafonds.insert(std::pair<int, TLi_manager*>(din[i].codcf(), plaf));
}
TLi_manager& this_pla = *plafonds[din[i].codcf()]; // Forget about optimization!
if (!this_pla.has_valid_plafond())
continue;
// Prima di tutto guardo se il documento ha righe esenti, altrimenti vado avanti
real esenz_this_doc = ZERO;
TAssoc_array tab_iva = din[i].tabella_iva(true);
for (TRiepilogo_iva * totali = (TRiepilogo_iva *)tab_iva.get(); totali != NULL; totali = (TRiepilogo_iva *)tab_iva.get())
{
if (this_pla.check_iva(totali->cod_iva().codice()))
esenz_this_doc += cache().get("%TIP", din[i].tipo().codice()).get_bool("B7") ? -totali->imp_orig() : totali->imp_orig();
}
if (esenz_this_doc.is_zero())
continue;
// Non mi fido di cosa e' stato scritto sui documenti, ricontrollo a caldo che le lettere siano ancora aperte (ogni volta... lo so...)
// Prendo tutti i documenti, prendo tutte le righe di esenzione e le vado a sottrarre alla prima lettera. Se la supero guardo se ce ne sono altre.
// Se sto dentro sono a posto e so che sto usando ancora quella dichiarazione, se invece la supero e non c'e' un'altra ho sforato il plafond.
TLocalisamfile lint(LF_LETINT);
TSQL_recordset rec_lint("");
TString sql; sql << "SELECT * FROM LETINT WHERE ANNO=" << din[i].anno() << " AND CODCLI=" << din[i].clifor().codice();
rec_lint.set(sql);
int n_letint = rec_lint.items();
if (n_letint > 0)
rec_lint.move_next();
lint.put(LETINT_ANNO, din[i].anno());
lint.put(LETINT_NUMPROT, rec_lint.get(rec_lint.find_column(LETINT_NUMPROT)).as_string());
lint.read();
bool ok = true;
TSQL_recordset docs("");
TToken_string tipi, stati;
create_tipi_stati(tipi, stati);
sql.cut(0) << "SELECT * FROM DOC\n"
"WHERE ANNO=" << din[i].anno() << " AND TIPOCF='" << din[i].clifor().tipo() << "' AND CODCF=" << din[i].clifor().codice() << " AND (";
sql << "CODNUM='" << tipi.get(0) << "' AND STATO=" << stati.get(0);
for(int z = 1; z < tipi.items(); ++z)
sql << " OR CODNUM='" << tipi.get(z) << "' AND STATO=" << stati.get(z);
sql << ")\nORDER BY NDOC";
docs.set(sql);
real valore = rec_lint.get(rec_lint.find_column(LETINT_IMPORTO)).as_real();
for (bool ok_d = docs.move_next(); ok_d; ok_d = docs.move_next())
{
int ndoc = docs.get(docs.find_column(DOC_NDOC)).as_int();
const char* codnum = docs.get(docs.find_column(DOC_CODNUM)).as_string();
TDocumento p_doc('D', din[i].anno(), codnum, ndoc);
// Calcolo quanto plafond sta utilizzando
real esenzione = ZERO;
// Calcolo quant'e' l'importo di esenzione sommando tutte le righe che hanno il codice esenzione iva per plafond
tab_iva.destroy();
tab_iva = p_doc.tabella_iva(true);
for (TRiepilogo_iva * totali = (TRiepilogo_iva *)tab_iva.get(); totali != NULL; totali = (TRiepilogo_iva *)tab_iva.get())
{
if (this_pla.check_iva(totali->cod_iva().codice()))
esenzione += cache().get("%TIP", p_doc.tipo().codice()).get_bool("B7") ? -totali->imp_orig() : totali->imp_orig();
}
if(!p_doc.is_nota_credito())
valore -= esenzione;
else
valore += esenzione;
if(valore < ZERO)
{
lint.put(LETINT_CHIUSA, "X"); // Chiudo
lint.write();
lint.rewrite();
real resto = ZERO;
if (rec_lint.move_next()) // Passo alla successiva se c'e'
{
lint.put(LETINT_ANNO, din[i].anno()); // Dopo la move
lint.put(LETINT_NUMPROT, rec_lint.get(rec_lint.find_column(LETINT_NUMPROT)).as_string());
lint.read();
resto = -valore;
valore = rec_lint.get(rec_lint.find_column(LETINT_IMPORTO)).as_real() - resto;
}
else if(valore < ZERO)
{
ok = false;
break;
}
}
}
if(!ok)
message_box("Attenzione c'e' almeno un documento che sfora il plafond per questo cliente: %d", din[i].clifor().codice());
// Scrivo sul documento le lettere di intento utilizzate e l'importo di ciascuna
// N._riferimento_lettera1|anno1|importo_usato1,N._riferimento_lettera2|anno2|importo_usato2,...
TToken_string used("", ',');
TToken_string single_used("", '|');
if (valore.not_zero())
{
// Guardo se ci sta tutto nella prima lettera o devo usare anche la successiva
single_used.add(TString(lint.get(LETINT_PROTINTF)) << " " << lint.get(LETINT_PROTINTS));
single_used.add(lint.get(LETINT_ANNO));
real this_letint_importo = lint.get_real(LETINT_IMPORTO);
real resto = valore - esenz_this_doc;
single_used.add(resto >= ZERO ? esenz_this_doc : valore);
used.add(single_used); // Aggiungo primo riferimento
single_used = "";
if (valore < esenz_this_doc)
{
lint.put(LETINT_CHIUSA, "X"); // Chiudo
lint.write();
lint.rewrite();
if (rec_lint.move_next()) // Se sforo la prima guardo se c'e' un'altra lettera altrimenti ho sforato veramente
{
lint.put(LETINT_ANNO, din[i].anno());
lint.put(LETINT_NUMPROT, rec_lint.get(rec_lint.find_column(LETINT_NUMPROT)).as_string());
lint.read();
single_used.add(TString(lint.get(LETINT_PROTINTF)) << " " << lint.get(LETINT_PROTINTS));
single_used.add(lint.get(LETINT_ANNO));
if (lint.get_real(LETINT_IMPORTO) < -resto)
message_box("Errore... impossibile inserire ulteriori lettere di intento per questo documento.");
if (lint.get_real(LETINT_IMPORTO) == -resto)
{
lint.put(LETINT_CHIUSA, "X"); // Chiudo
lint.write();
lint.rewrite();
}
single_used.add(-resto);
used.add(single_used);
}
else
message_box("Attenzione c'e' un documento che sfora il plafond per questo cliente:\n%d, %s", din[i].clifor().codice(), din[i].clifor().get(CLI_RAGSOC));
}
else if (valore == esenz_this_doc) // Se uguale chiudo la lettera
{
lint.put(LETINT_CHIUSA, "X");
lint.write();
lint.rewrite();
}
}
din[i].put("PLAFOND", used);
}
for (auto it = plafonds.begin(); it != plafonds.end(); ++it)
delete it->second;
}

View File

@ -104,6 +104,7 @@ public:
static void create_tipi_stati(TToken_string& tipi, TToken_string& stati);
bool genera_li_storico(const TDate& data_ini);
bool popola_plafond(TLista_documenti& din, const TDate& data_elab);
void scrivi_plafond(TLista_documenti& din, const TDate& data_elab);
#endif

View File

@ -6,6 +6,7 @@
#include "ve6200.h"
#include "ve6200a.h"
#include "../li/lilib01.h"
#include "../li/lilib01.cpp"
#include <doc.h>
@ -37,21 +38,53 @@ bool TFatturazione_bolle_app::process(TProgress_monitor& iw, TElaborazione & eld
iw.set_text(msg); // Messaggio sul cliente
do_events(); // Attende visualizzazione
// Una volta che di documenti sono elaborati ci scrivo sopra il valore del plafond
if (!popola_plafond(dout, data_elab))
{
return error_box("Errore durante la generazione del plafond, le fatture non son state create");
}
int err = dout.write(); // Scrive documenti di output
if (err == NOERR)
// Test Plafond
TToken_string tipi, stati;
create_tipi_stati(tipi, stati);
int clifo = din[0].clifor().codice();
TDate aData(TODAY);
TLi_manager currentCli('C', clifo, aData); // Inizializzo l'oggetto per la gestione del plafond
real plafond, res_plafond, tot_fat;
if (currentCli.has_valid_plafond())
{
err = din.rewrite(); // Aggiorna stato dei documenti di input
if (err != NOERR)
ok = error_box("Errore %d durante la scrittura dei documenti raggruppati!", err);
plafond = currentCli.get_plafond();
res_plafond = plafond - currentCli.elab_util(tipi, stati, aData);
for (int i = 0; i < din.items(); ++i)
tot_fat += din[i].totale_doc();
TLog_report lerr;
if (tot_fat > res_plafond)
{
bool plur = din.items() > 1;
TString err;
err << "Errore durante la generazione del plafond:\n" <<
(plur ? "I documenti da elaborare superano" : "Il documento da elaborare supera") << " il plafond per questo cliente.\n"
"Plafond rimanente: %s\n" <<
(plur ? "Totale fatture: %s\n" : "Totale fattura: %s\n") <<
(plur ? "Le fatture non sono state create." : "La fattura non e' stata creata.");
return error_box(err, res_plafond.string(), tot_fat.string());
}
// Una volta che di documenti sono elaborati ci scrivo sopra il valore del plafond
scrivi_plafond(dout, data_elab);
//if (!popola_plafond(dout, data_elab))
//{
// return error_box("Errore durante la generazione del plafond, le fatture non son state create");
//}
int err = dout.write(); // Scrive documenti di output
if (err == NOERR)
{
err = din.rewrite(); // Aggiorna stato dei documenti di input
if (err != NOERR)
ok = error_box("Errore %d durante la scrittura dei documenti raggruppati!", err);
}
else
ok = error_box("Errore %d durante l'aggiornamento dei documenti da raggruppare!", err);
}
else
ok = error_box("Errore %d durante l'aggiornamento dei documenti da raggruppare!", err);
}
return ok;
}