Patch level : 12.0 no-patch

Files correlati     : 
Commento            : 
Sviluppo personalizzazione Cigno ps0430600 per la creazione di un file .csv con le informazioni dei pagamenti di tutti i clienti.
Il programma legge dalla tabella movimenti e genera un file con tutte le fatture che potrebbero essere state pagate dell'anno in corso e del precedente in base ai movimenti Pxx.
Questa personalizzazione è stata fatta in quanto Il Cigno non possiede il modulo "Saldaconto".

git-svn-id: svn://10.65.10.50/branches/R_10_00@23416 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
mtollari 2016-12-06 14:02:05 +00:00
parent 630d4a7d63
commit 0deaa7ba31
6 changed files with 449 additions and 3 deletions

View File

@ -37,10 +37,10 @@
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\exe\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\obj\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\exe\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\obj\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -160,6 +160,7 @@
<ClCompile Include="..\src\ps\ps0430300.cpp" />
<ClCompile Include="..\src\ps\ps0430400.cpp" />
<ClCompile Include="..\src\ps\ps0430500.cpp" />
<ClCompile Include="..\src\ps\ps0430600.cpp" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\src\ps\ps0430100a.uml">
@ -190,6 +191,7 @@
<ClInclude Include="..\src\ps\ps0430300a.h" />
<ClInclude Include="..\src\ps\ps0430400a.h" />
<ClInclude Include="..\src\ps\ps0430500a.h" />
<ClInclude Include="..\src\ps\ps0430600a.h" />
</ItemGroup>
<ItemGroup>
<CustomBuildStep Include="..\lib\AgaLib.lib">
@ -216,6 +218,12 @@
<None Include="..\src\ps\ps0430300a.uml" />
<None Include="..\src\ps\ps0430400a.uml" />
<None Include="..\src\ps\ps0430500a.uml" />
<CustomBuild Include="..\src\ps\ps0430600a.uml">
<FileType>Document</FileType>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)%(Filename).msk;%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">msk32 %(FullPath) $(TargetDir)%(Filename).msk</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling mask %(FullPath)...</Message>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -11,6 +11,7 @@ int main(int argc, char** argv)
//case 2: ps0430300(argc, argv); break; // generazione ordini (è or1400 per il cigno)
case 3: ps0430400(argc, argv); break; // Importazione clienti e fatture
case 4: ps0430500(argc, argv); break; // Generazione rimanenze finali
case 5: ps0430600(argc, argv); break; // Calcolo pagamenti per tessera sanitaria
default: ps0430100(argc, argv); break; // Correlazioni articoli utenti
}
return 0;

View File

@ -2,4 +2,5 @@ int ps0430100(int argc, char* argv[]);
int ps0430200(int argc, char* argv[]);
//int ps0430300(int argc, char* argv[]);
int ps0430400(int argc, char* argv[]);
int ps0430500(int argc, char* argv[]);
int ps0430500(int argc, char* argv[]);
int ps0430600(int argc, char* argv[]);

410
src/ps/ps0430600.cpp Normal file
View File

@ -0,0 +1,410 @@
/************************************************************************************************************************************************
* 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/cg2101.h"
#include "../cg/cglib02.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 e cognome del cliente
TString codF; // Codice Fiscale
real totale; // Totale pagato durante l'anno
real p98Ini;
TClifo(): codcf(0), p98(ZERO), p98Ini(ZERO), importoPagato(ZERO), nome(""), codF(""), totale(ZERO){}
TClifo(long cod, TString nome, TString codF) : codcf(cod), nome(nome), codF(codF){}
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;
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);
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;
}
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();
TClifo cliente(rowClifo.get_long("CODCF"), rowClifo.get("RAGSOC"), 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");
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"))
{
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"))
{
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 << "Anno " << anno -1 << "\n\n";
outputFile << "Data Documento;Numero Documento;Importo;Residuo P98;Conto;Codice Cliente;Cognome Nome;Codice Fiscale;\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-", "CODCAUS = 'V01'", 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
for(int i = 0; i < numCli; i++)
{
if(clienti[i].codcf == rowMovOld.get_long("CODCF") && clienti[i].p98 > 0) // Trova più spesso il cliente diverso dal codice all'inizio
{
clienti[i].p98 -= rowMovOld.get_real("TOTDOC");
// Aggiungo il documento al file
TString codcfFilled; codcfFilled << rowMovOld.get("CODCF");
for(int j = codcfFilled.len(); j <= 6; j++) codcfFilled.insert("0",0);
outputFile << rowMovOld.get("DATADOC") << ";" << rowMovOld.get("NUMDOC") << ";" << toEur(rowMovOld.get_real("TOTDOC")) << ";" << toEur(clienti[i].p98) << ";" << "001 002 " << codcfFilled << ";" << rowMovOld.get("CODCF") << ";" << clienti[i].nome << ";" << clienti[i].codF << "\n";
// Se ha trovato tutti i documenti incremento la variabile sentinella
if(clienti[i].p98 <= 0) clientsSatisfied ++;
break;
}
}
}
// Spazio dal 2016
outputFile << "\n\nAnno " << anno << "\n\n";
outputFile << "Data Documento;Numero documento;Importo;Residuo pagamenti;Conto;Codice Cliente;Cognome Nome;Codice Fiscale;\n";
// 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", "CODCAUS = 'V01'", 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
for(int i = 0; i < numCli; i++)
{
if(rowMovNew.get_long("CODCF") == clienti[i].codcf && clienti[i].importoPagato >= 0)
{
// Sottraggo quanto ha pagato
clienti[i].importoPagato -= rowMovNew.get_real("TOTDOC");
// Scrivo su file
TString codcfFilled; codcfFilled << rowMovNew.get("CODCF");
for(int j = codcfFilled.len(); j <= 6; j++) codcfFilled.insert("0",0);
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!");
}
}
int ps0430600(int argc, char* argv[])
{
TTessan_app a;
a.run(argc, argv, TR("Sistema tessera sanitaria"));
return 0;
}

3
src/ps/ps0430600a.h Normal file
View File

@ -0,0 +1,3 @@
#define F_ANNO 101
#define F_USER_PATH 102

23
src/ps/ps0430600a.uml Normal file
View File

@ -0,0 +1,23 @@
#include "ps0430600a.h"
TOOLBAR "" 0 0 0 2
#include <elabar.h>
ENDPAGE
PAGE "Sistema tessera sanitaria" -1 -1 60 9
STRING F_ANNO 260 4
BEGIN
PROMPT 1 0 "ANNO "
CHECKTYPE REQUIRED
END
STRING F_USER_PATH 260 50
BEGIN
PROMPT 1 1 "Percorso "
CHECKTYPE REQUIRED
END
ENDPAGE
ENDMASK