campo-sirio/src/ps/ps0430600.cpp
Alessandro Bonazzi 09aab17a34 Patch level : 12.0 no-patch
Files correlati     : ps
Commento            :

Import ordini export bolle Major Flexform
2020-11-25 19:32:22 +01:00

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