Files correlati : ps Commento : Import ordini export bolle Major Flexform
482 lines
17 KiB
C++
482 lines
17 KiB
C++
/************************************************************************************************************************************************
|
|
* Author: Tolla *
|
|
* Date: 12/2016 *
|
|
* Questo programma serve a calcolare tutti i pagamenti fatti da privati in un determinato anno (e nel precedente in caso di fatture arretrate) *
|
|
* per la detrazione dalle tasse delle spese del Cigno. Tutto ciò va fatto perchè non usano la gestione del saldaconto. *
|
|
* Ma non temete! Il sacro e prepotente Campo vi salverà anche questa volta! *
|
|
************************************************************************************************************************************************/
|
|
|
|
#include <automask.h>
|
|
#include <applicat.h>
|
|
#include <progind.h>
|
|
#include <reputils.h>
|
|
#include <config.h>
|
|
|
|
|
|
#include "../cg/cglib.h"
|
|
#include "../mg/mglib.h"
|
|
#include "ps0430600a.h"
|
|
|
|
#include "../ca/calib01.h"
|
|
#include "../ca/commesse.h"
|
|
#include "../ca/movana.h"
|
|
#include "../ca/rmovana.h"
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TClifo
|
|
///////////////////////////////////////////////////////////
|
|
class TClifo : public TObject
|
|
{
|
|
public:
|
|
long codcf; // Codice del cliente
|
|
real p98; // > 0 se trovo un P98 per quel cliente // Viene già inizializzata a 0?
|
|
real importoPagato; // Importo pagato per quest'anno dal cliente
|
|
TString nome; // Nome
|
|
TString cognome; // Cognome
|
|
TString indirizzo; // Indirizzo
|
|
TString citta; // Città
|
|
TString provincia; // Provincia
|
|
TString codF; // Codice Fiscale
|
|
real totale; // Totale pagato durante l'anno
|
|
real p98Ini;
|
|
|
|
TClifo(): codcf(0), p98(ZERO), p98Ini(ZERO), importoPagato(ZERO), nome(""), cognome(""), indirizzo (""), citta(""), provincia(""), codF(""), totale(ZERO){}
|
|
TClifo(long cod, TString nom, TString cog, TString ind, TString cit, TString prov, TString codFisc) : codcf(cod), nome(nom), cognome(cog), indirizzo(ind), citta(cit), provincia(prov), codF(codFisc){}
|
|
virtual ~TClifo(){}
|
|
|
|
TClifo & operator = (const TClifo& r);
|
|
};
|
|
|
|
TClifo& TClifo::operator =(const TClifo& r)
|
|
{
|
|
codcf = r.codcf;
|
|
p98 = r.p98;
|
|
p98Ini = r.p98Ini;
|
|
importoPagato = r.importoPagato;
|
|
nome = r.nome;
|
|
cognome = r.cognome;
|
|
indirizzo = r.indirizzo;
|
|
citta = r.citta;
|
|
provincia = r.provincia;
|
|
codF = r.codF;
|
|
totale = r.totale;
|
|
return *this;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TTessan_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TTessan_mask : public TAutomask
|
|
{
|
|
protected:
|
|
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
|
|
|
public:
|
|
TTessan_mask() : TAutomask("ps0430600a") {set(F_USER_PATH, ini_get_string(CONFIG_DITTA, "Tessera sanitaria", "Percorso"));}
|
|
};
|
|
|
|
bool TTessan_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TTessan_app
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TTessan_app : public TSkeleton_application
|
|
{
|
|
private:
|
|
TToken_string p, p98;
|
|
|
|
protected:
|
|
bool elabPayment(int anno, TString userPath);
|
|
TString toEur(real val);
|
|
bool findErase(TToken_string *tn, long val);
|
|
void splitName(TString ragsoc, TString &nome, TString &cognome);
|
|
void getLocalita(TString cod, TString &comune, TString &provincia);
|
|
public:
|
|
virtual void main_loop();
|
|
};
|
|
|
|
TString TTessan_app::toEur(real val)
|
|
{
|
|
return TString(TCurrency(val).string(true)) << " €";
|
|
}
|
|
|
|
|
|
bool TTessan_app::findErase(TToken_string *tn, long find)
|
|
{
|
|
// La token_string deve essere in ordine decrescente
|
|
tn->restart();
|
|
long val = atoi(tn->get());
|
|
for(int k = 0;k <= tn->items() && val <= find; k++)
|
|
{
|
|
if(val == find)
|
|
{
|
|
for(int j = 0; j < k; j++) tn->destroy(0);
|
|
return true;
|
|
}
|
|
val = atoi(tn->get());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TTessan_app::splitName(TString ragsoc, TString &nome, TString &cognome)
|
|
{
|
|
/* Casi:
|
|
* COGNOME NOME
|
|
* COGNOME NOME
|
|
* Prima cerco più di uno spazio così da mantenere eventuali nomi/cognomi multipli (come GUIDI GIORGI GABRIELLA ANNUNZIATA FILOMENA)
|
|
*/
|
|
int f , l = -1, offset = 2;
|
|
for(int i = 0; i < ragsoc.len(); i++)
|
|
{
|
|
if(ragsoc[i] == ' ' && ragsoc[i + 1] == ' ') l = i;
|
|
}
|
|
if(l == -1)
|
|
{
|
|
f = ragsoc.find(' ');
|
|
cognome = ragsoc.sub(0, f);
|
|
nome = ragsoc.sub(f + 1);
|
|
}
|
|
else
|
|
{
|
|
f = ragsoc.find(" ");
|
|
cognome = ragsoc.sub(0, f);
|
|
nome = ragsoc.sub(l + 2);
|
|
}
|
|
}
|
|
void TTessan_app::getLocalita(TString cod, TString &comune, TString &provincia)
|
|
{
|
|
TRelation com(LF_COMUNI);
|
|
TRectype filCom(com.curr());
|
|
filCom.put("STATO", "");
|
|
filCom.put("COM", cod);
|
|
TCursor curCom(&com, "", 1, &filCom, &filCom);
|
|
curCom.items();
|
|
curCom = 0;
|
|
TRectype rowCom = curCom.curr();
|
|
comune = rowCom.get("DENCOM");
|
|
provincia = rowCom.get("PROVCOM"); // Teoricamente le province saranno sempre di 2 ma non si sa mai
|
|
}
|
|
|
|
bool TTessan_app::elabPayment(int anno, TString userPath)
|
|
{
|
|
// Calcolo tutti i pagamenti da mov con codice P* tranne P099
|
|
TRelation clifo(LF_CLIFO), mov(LF_MOV), rmov(LF_RMOV);
|
|
|
|
// Creo filtro e cursore per i clienti
|
|
TRectype filClifo(clifo.curr());
|
|
filClifo.put("TIPOCF", "C");
|
|
TCursor curClifo(&clifo, "ALLEG = \"6\"", 1, &filClifo, &filClifo);
|
|
|
|
int numCli = curClifo.items();
|
|
|
|
// Mi creo un array di SClifo
|
|
TClifo * clienti = new TClifo[numCli];
|
|
// Mi creo un array dei movimenti che iniziano con P per velocizzare il processo
|
|
//TToken_string p98, p;
|
|
|
|
TProgress_monitor a(numCli, "Caricamento clienti");
|
|
for(curClifo = 0; curClifo.pos() < numCli && !a.is_cancelled(); ++curClifo)
|
|
{
|
|
if (!a.add_status())
|
|
break;
|
|
// Riga cliente attuale
|
|
TRectype rowClifo = curClifo.curr();
|
|
TString nome, cognome, comune, provincia;
|
|
splitName(rowClifo.get("RAGSOC"), nome, cognome);
|
|
getLocalita(rowClifo.get("COMCF"), comune, provincia);
|
|
TClifo cliente(rowClifo.get_long("CODCF"), nome, cognome, (TString)rowClifo.get("INDCF") << " " << rowClifo.get("CIVCF"), comune, provincia, rowClifo.get("COFI"));
|
|
clienti[curClifo.pos()] = cliente;
|
|
}
|
|
|
|
// Creo il cursore di Mov
|
|
// Creo la stringa per i filtri
|
|
TString first("01-01-"),last("31-12-");
|
|
first << anno; last << anno;
|
|
|
|
// Creo i filtri e assegno
|
|
TRectype filFirst(mov.curr()), filLast(mov.curr());
|
|
filFirst.put("DATAREG", first);
|
|
filLast.put("DATAREG", last);
|
|
|
|
// Creo il cursore e conto gli elementi
|
|
TSorted_cursor curMov(&mov, "NUMREG", "", 2, &filFirst, &filLast);
|
|
int numMov = curMov.items();
|
|
|
|
TProgress_monitor b(numMov, "Carico i movimenti");
|
|
|
|
// Azzero le token string
|
|
p.cut(0); p98.cut(0);
|
|
|
|
// Le carico
|
|
for(curMov = 0; curMov.pos() < numMov && !b.is_cancelled(); ++curMov)
|
|
{
|
|
if (!b.add_status())
|
|
break;
|
|
// Movimento attuale
|
|
TRectype rowMov = curMov.curr();
|
|
TString codcaus(rowMov.get("CODCAUS"));
|
|
if(codcaus.starts_with("P") || codcaus == "I03" || codcaus == "I05")
|
|
{
|
|
if(codcaus == "P98")
|
|
p98.add(rowMov.get("NUMREG"));
|
|
else if(codcaus != "P99")
|
|
p.add(rowMov.get("NUMREG"));
|
|
}
|
|
}
|
|
|
|
// Adesso che ho tutti i movimenti prima cerco i vari P98 e li salvo in clienti
|
|
// Filtro
|
|
TRectype filP98Ini(rmov.curr()), filP98Fin(rmov.curr());
|
|
filP98Ini.put("NUMREG", p98.get(0));
|
|
filP98Fin.put("NUMREG", p98.get(p98.items()-1));
|
|
|
|
|
|
TCursor curRMov(&rmov, "", 1, &filP98Ini, &filP98Fin);
|
|
int p98items = curRMov.items();
|
|
int nump98 = 0;
|
|
|
|
TProgress_monitor c(p98items, "Elaboro i movimenti P98");
|
|
|
|
for(curRMov = 0; curRMov.pos() < p98items && !c.is_cancelled() && p98.items() > 0; ++curRMov)
|
|
{
|
|
if(!c.add_status())
|
|
break;
|
|
|
|
// Riga del movimento attuale
|
|
TRectype rowRMov = curRMov.curr();
|
|
// Controllo che è di una persona fisica
|
|
TString cod(rowRMov.get("NUMREG")),rig(rowRMov.get("NUMRIG")),gruppo(rowRMov.get("GRUPPO")), conto(rowRMov.get("CONTO"));
|
|
if(rowRMov.get("GRUPPO") != "2" || rowRMov.get("CONTO") != "1") continue;
|
|
|
|
if(!findErase(&p98, rowRMov.get_long("NUMREG"))) continue;
|
|
|
|
//trovato = false;
|
|
for(int i = 0; i < numCli; i++)
|
|
{
|
|
TClifo cliente = clienti[i];
|
|
if(clienti[i].codcf == rowRMov.get_long("SOTTOCONTO")) // N.B. Teoricamente si fa solo una volta a cliente
|
|
{
|
|
nump98++;
|
|
if(rowRMov.get("SEZIONE") == "D")
|
|
{
|
|
clienti[i].p98 += rowRMov.get_real("IMPORTO"); // Aggiungo a P98 per sapere quanto è dell'anno scorso
|
|
clienti[i].p98Ini += rowRMov.get_real("IMPORTO");
|
|
clienti[i].importoPagato -= rowRMov.get_real("IMPORTO"); // Sottraggo all'importo di quest'anno per vedere quanto è di quest'anno
|
|
}
|
|
else
|
|
{
|
|
clienti[i].importoPagato += rowRMov.get_real("IMPORTO"); // Sommo se è in avere
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Adesso che ho calcolato i P98 analizzo i pagamenti
|
|
// Filtro
|
|
TRectype filPIni(rmov.curr()), filPFin(rmov.curr());
|
|
filPIni.put("NUMREG", p.get(0));
|
|
filPFin.put("NUMREG", p.get(p.items()-1));
|
|
|
|
TCursor curRMovP(&rmov, "", 1, &filPIni, &filPFin);
|
|
int pitems = curRMovP.items();
|
|
|
|
TProgress_monitor d(pitems, "Analizzo i pagamenti di quest'anno");
|
|
|
|
for(curRMovP = 0; curRMovP.pos() < pitems && !d.is_cancelled() && p.items() > 0; ++curRMovP)
|
|
{
|
|
if(!d.add_status())
|
|
break;
|
|
// Riga del movimento attuale
|
|
TRectype rowRMov = curRMovP.curr();
|
|
// Controllo che è di una persona fisica
|
|
if(rowRMov.get("GRUPPO") != "2" || rowRMov.get("CONTO") != "1") continue;
|
|
|
|
if(!findErase(&p, rowRMov.get_long("NUMREG"))) continue;
|
|
|
|
//bool trovato = false;
|
|
for(int i = 0; i < numCli; i++)
|
|
{
|
|
TClifo cliente = clienti[i];
|
|
if(clienti[i].codcf == rowRMov.get_long("SOTTOCONTO"))
|
|
{
|
|
if(rowRMov.get("SEZIONE") == "A")
|
|
{
|
|
clienti[i].importoPagato += rowRMov.get_real("IMPORTO"); // Aggiunto l'importo a quanto è stato pagato quest'anno
|
|
clienti[i].totale += rowRMov.get_real("IMPORTO"); // Calcolo l'importo totale di quell'anno
|
|
}
|
|
else
|
|
{
|
|
clienti[i].importoPagato -= rowRMov.get_real("IMPORTO"); // Sottraggo all'importo di quest'anno per vedere quanto è di quest'anno
|
|
clienti[i].totale -= rowRMov.get_real("IMPORTO"); // Calcolo l'importo totale di quell'anno
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Creo il file di output **********************************************************
|
|
ofstream outputFile;
|
|
outputFile.open(userPath << "tessera_sanitaria.csv");
|
|
// Controllo l'apertura
|
|
if(!outputFile.is_open())
|
|
return false;
|
|
//***********************************************************************************
|
|
|
|
// Inizio a scriverci
|
|
outputFile << "CodiceAnagrafico;CodiceFiscale;Cognome;Nome;Indirizzo;Citta;Provincia;NumeroDocumento;DataDocumento;DataPagamento;Dispositivo;TipoOperazione;NumeroDocumentoOriginale;DataDocumentoOriginale;DispositivoDocumentoOriginale;TipoSpesa;FlagSpesa;Importo;OperazioneEsclusa\n";
|
|
|
|
|
|
int clientsSatisfied = 0; // Numero di clienti con P98 <= 0 (Quindi ho trovato tutte le fatture vecchie)
|
|
|
|
// Creo il cursore di Mov Vecchio
|
|
// Creo la stringa per i filtri
|
|
TString firstOld("01-01-"),lastOld("31-12-");
|
|
firstOld << anno-1; lastOld << anno-1;
|
|
|
|
// Creo i filtri e assegno
|
|
TRectype filFirstOld(mov.curr()), filLastOld(mov.curr());
|
|
filFirstOld.put("DATAREG", firstOld);
|
|
filLastOld.put("DATAREG", lastOld);
|
|
|
|
// Creo il cursore e conto gli elementi
|
|
TSorted_cursor curMovOld(&mov, "DATAREG-", "", 2, &filFirstOld, &filLastOld);
|
|
int numMovOld = curMovOld.items();
|
|
|
|
TProgress_monitor e(numMovOld, (TString)"Aggiungo al file i movimenti del " << anno -1);
|
|
for(curMovOld = 0; curMovOld.pos() < numMovOld && clientsSatisfied < numCli && !e.is_cancelled(); ++curMovOld)
|
|
{
|
|
if(!e.add_status())
|
|
break;
|
|
// Movimento attuale
|
|
TRectype rowMovOld = curMovOld.curr();
|
|
if(rowMovOld.get("TIPO") != "C") continue; // Non riesco a metterlo nel filtro
|
|
if(rowMovOld.get("CODCAUS") != "V01" && rowMovOld.get("CODCAUS") != "V02") continue;
|
|
|
|
for(int i = 0; i < numCli; i++)
|
|
{
|
|
#ifdef DBG
|
|
if (rowMovOld.get_long("CODCF") == clienti[i].codcf && clienti[i].codcf == 1669)
|
|
{
|
|
TString asd = clienti[i].importoPagato.string();
|
|
bool tolla = true;
|
|
}
|
|
#endif // DBG
|
|
if(clienti[i].codcf == rowMovOld.get_long("CODCF") && clienti[i].p98 > 0 && clienti[i].importoPagato > 0) // Trova più spesso il cliente diverso dal codice all'inizio
|
|
{
|
|
// Aggiungo il documento al file
|
|
TString codcfFilled; codcfFilled << rowMovOld.get("CODCF");
|
|
for(int j = codcfFilled.len(); j <= 6; j++) codcfFilled.insert("0",0);
|
|
|
|
real totdoc = rowMovOld.get_real("TOTDOC");
|
|
real importo = clienti[i].p98 - totdoc >= 0 ? totdoc : clienti[i].p98;
|
|
|
|
outputFile << rowMovOld.get("CODCF") << ";" << clienti[i].codF << ";" << clienti[i].cognome << ";" << clienti[i].nome << ";" << clienti[i].indirizzo << ";" << clienti[i].citta << ";" << clienti[i].provincia << ";" << rowMovOld.get("NUMDOC") << ";" << rowMovOld.get("DATADOC") << ";" << rowMovOld.get("DATAREG") << ";1;I;;;;AA;;" << toEur(importo) << ";\n";
|
|
|
|
clienti[i].p98 -= totdoc;
|
|
|
|
// Se ha trovato tutti i documenti incremento la variabile sentinella
|
|
if(clienti[i].p98 <= 0) clientsSatisfied ++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Creo il cursore di Mov Nuovo
|
|
// Creo la stringa per i filtri
|
|
TString firstNew("01-01-"),lastNew("31-12-");
|
|
firstNew << anno; lastNew << anno;
|
|
|
|
// Creo i filtri e assegno
|
|
TRectype filFirstNew(mov.curr()), filLastNew(mov.curr());
|
|
filFirstNew.put("DATAREG", firstNew);
|
|
filLastNew.put("DATAREG", lastNew);
|
|
|
|
// Creo il cursore e conto gli elementi
|
|
TSorted_cursor curMovNew(&mov, "DATAREG", "", 2, &filFirstNew, &filLastNew);
|
|
//TCursor curMov(&mov, "", 3, &filFirst, &filLast);
|
|
int numMovNew = curMovNew.items();
|
|
|
|
TProgress_monitor f(numMovNew, (TString)"Aggiungo al file i movimenti del " << anno);
|
|
|
|
for(curMovNew = 0; curMovNew.pos() < numMovNew && clientsSatisfied < numCli && !f.is_cancelled(); ++curMovNew)
|
|
{
|
|
if(!f.add_status())
|
|
break;
|
|
// Movimento attuale
|
|
TRectype rowMovNew = curMovNew.curr();
|
|
if(rowMovNew.get("TIPO") != "C") continue; // Non riesco a metterlo nel filtro
|
|
if(rowMovNew.get("CODCAUS") != "V01" && rowMovNew.get("CODCAUS") != "V02") continue;
|
|
|
|
for(int i = 0; i < numCli; i++)
|
|
{
|
|
if(rowMovNew.get_long("CODCF") == clienti[i].codcf && clienti[i].importoPagato >= 0)
|
|
{
|
|
// Sottraggo quanto ha pagato
|
|
// Scrivo su file
|
|
TString codcfFilled; codcfFilled << rowMovNew.get("CODCF");
|
|
for(int j = codcfFilled.len(); j <= 6; j++) codcfFilled.insert("0",0);
|
|
|
|
real totdoc = rowMovNew.get_real("TOTDOC");
|
|
real importo = clienti[i].importoPagato - totdoc >= 0 ? totdoc : clienti[i].importoPagato;
|
|
|
|
outputFile << rowMovNew.get("CODCF") << ";" << clienti[i].codF << ";" << clienti[i].cognome << ";" << clienti[i].nome << ";" << clienti[i].indirizzo << ";" << clienti[i].citta << ";" << clienti[i].provincia << ";" << rowMovNew.get("NUMDOC") << ";" << rowMovNew.get("DATADOC") << ";" << rowMovNew.get("DATAREG") << ";1;I;;;;AA;;" << toEur(importo) << ";\n";
|
|
|
|
clienti[i].importoPagato -= totdoc;
|
|
|
|
//outputFile << rowMovNew.get("DATADOC") << ";" << rowMovNew.get("NUMDOC") << ";" << toEur(rowMovNew.get_real("TOTDOC")) << ";" << toEur(clienti[i].importoPagato) << ";" << "001 002 " << codcfFilled << ";" << rowMovNew.get("CODCF") << ";" << clienti[i].nome << ";" << clienti[i].codF << "\n";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
outputFile.close();
|
|
/*
|
|
// Creo il file di output test **********************************************************
|
|
ofstream outTest;
|
|
outTest.open("C:\\Users\\mtollari\\Desktop\\test_sanitaria.csv");
|
|
// Controllo l'apertura
|
|
if(!outTest.is_open()) return false;
|
|
//***************************************************************************************
|
|
outTest << "Cod.;Totale;p98 Iniziale;p98;importo pagato;\n";
|
|
for(int i = 0; i < numCli; i++)
|
|
{
|
|
//if(clienti[i].totale <= 0) continue;
|
|
outTest << clienti[i].codcf << ";" << toEur(clienti[i].totale) << ";" << toEur(clienti[i].p98Ini) << ";" << toEur(clienti[i].p98) << ";" << toEur(clienti[i].importoPagato) << ";\n" ;
|
|
}
|
|
outTest.close();
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
|
|
void TTessan_app::main_loop()
|
|
{
|
|
TTessan_mask m;
|
|
while (m.run() == K_ENTER)
|
|
{
|
|
TString path(m.get(F_USER_PATH));
|
|
ini_set_string(CONFIG_DITTA, "Tessera sanitaria", "Percorso",path);
|
|
if(elabPayment(m.get_int(F_ANNO), path))
|
|
message_box("File creato!");
|
|
else
|
|
message_box("Creazione file non riuscita");
|
|
}
|
|
}
|
|
|
|
int ps0430600(int argc, char* argv[])
|
|
{
|
|
TTessan_app a;
|
|
a.run(argc, argv, TR("Sistema tessera sanitaria"));
|
|
return 0;
|
|
}
|