You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Labcontrol/src/Lib/receipts_handler.cpp

291 lines
12 KiB
C++

/*
* Copyright 2014-2016 Markus Prasser
*
* This file is part of Labcontrol.
*
* Labcontrol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Labcontrol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory>
#include <QDebug>
#include "receipts_handler.h"
#include "settings.h"
extern std::unique_ptr< lc::Settings > settings;
lc::ReceiptsHandler::ReceiptsHandler( const QString &argZTreeDataTargetPath,
bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName,
QObject *argParent ) :
QObject{ argParent },
anonymousReceiptsPlaceholder{ argAnonymousReceiptsPlaceholder },
dateString{ QDateTime::currentDateTime().toString( "yyMMdd_hhmm" ) },
expectedPaymentFileName{ dateString + ".pay" },
expectedPaymentFilePath{ argZTreeDataTargetPath + "/" + dateString + ".pay" },
latexHeaderName{ argLatexHeaderName },
paymentFile{ expectedPaymentFilePath },
printReceiptsForLocalClients{ argPrintReceiptsForLocalClients },
timer{ new QTimer{ this } },
zTreeDataTargetPath{ argZTreeDataTargetPath }
{
qDebug() << "Expected payment file name is:" << expectedPaymentFilePath;
// Create a QTimer regularly checking if the payment file was created and print it if so
connect( timer, &QTimer::timeout,
this, &ReceiptsHandler::PrintReceipts );
timer->start( 2000 );
}
lc::ReceiptsHandler::ReceiptsHandler( const QString &argZTreeDataTargetPath,
bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName,
const QString &argDateString, QObject *argParent ) :
QObject{ argParent },
anonymousReceiptsPlaceholder{ argAnonymousReceiptsPlaceholder },
dateString{ argDateString },
expectedPaymentFileName{ argDateString + ".pay" },
expectedPaymentFilePath{ argZTreeDataTargetPath + "/" + argDateString + ".pay" },
latexHeaderName{ argLatexHeaderName },
paymentFile{ expectedPaymentFilePath },
printReceiptsForLocalClients{ argPrintReceiptsForLocalClients },
zTreeDataTargetPath{ argZTreeDataTargetPath }
{
qDebug() << "Expected payment file name is:" << expectedPaymentFilePath;
PrintReceipts();
}
void lc::ReceiptsHandler::PrintReceipts() {
// If the payment file exists, print it
if ( paymentFile.exists() ) {
qDebug() << "The payment file has been created and will be printed";
if ( timer ) {
timer->stop();
}
CreateReceiptsFromPaymentFile();
}
}
void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
// Get the data needed for receipts creation from the payment file
QVector<QString> *rawParticipantsData = nullptr;
rawParticipantsData = GetParticipantsDataFromPaymentFile();
for ( int i = 0; i < rawParticipantsData->size(); i++ ) {
qDebug() << "Payment file line" << QString::number( i ) << ":\t" << rawParticipantsData->at( i );
}
// Extract the data of the participant's whose receipts shall be printed
/* The tab separated fields in the payment file are:
* SUBJECT COMPUTER INTERESTED NAME PROFIT SIGNATURE
*/
QVector<paymentEntry_t*> *participants = new QVector<paymentEntry_t*>;
double overall_payoff = 0.0;
for ( QVector<QString>::iterator it = rawParticipantsData->begin(); it != rawParticipantsData->end() - 1; ++it ) {
// Split the lines containing the participants' data into their inidivual parts
QStringList temp_participant_data = it->split('\t', QString::KeepEmptyParts);
qDebug() << temp_participant_data.join( " - " );
if ( !printReceiptsForLocalClients && temp_participant_data.at( 3 ).contains( "local" ) ) {
qDebug() << "Receipt for local client" << temp_participant_data.at( 1 ) << "will not be printed.";
}
else {
// Create a new struct instance for participant data and fill it
paymentEntry_t *participant = new paymentEntry_t;
participant->computer = temp_participant_data.at(1);
participant->name = temp_participant_data.at(3);
participant->payoff = temp_participant_data.at(4).toDouble();
overall_payoff += participant->payoff;
participants->append(participant);
}
}
delete rawParticipantsData;
rawParticipantsData = nullptr;
// Make receipts overview anonymous if requested (at this stage just names are removed, so that the overview still containts the client names
if ( !anonymousReceiptsPlaceholder.isEmpty() ) {
MakeReceiptsAnonymous( participants, false );
}
// Load the LaTeX header
QString *latexText = LoadLatexHeader();
if ( latexText == nullptr ) {
for ( auto s : *participants ) {
delete s;
}
delete participants;
participants = nullptr;
return;
}
// Write the comprehension table
latexText->append( "\n\\COMPREHENSION{\n" );
unsigned short int zeile = 0;
for ( auto s : *participants ) {
latexText->append( expectedPaymentFileName + " & " + s->computer + " & " + s->name + " & " + QString::number( s->payoff, 'f', 2 ) + " \\EUR\\\\\n" );
if ( zeile % 2 == 0 ) {
latexText->append( "\\rowcolor[gray]{0.9}\n" );
}
++zeile;
}
// MISSING: Appending show up entries to the overview
// Make also the clients on the receipts anonymous. This is done as second step, so that the beforehand created overview still contains the clients
if ( !anonymousReceiptsPlaceholder.isEmpty() ) {
MakeReceiptsAnonymous( participants, true );
}
// Add the LaTeX middle sequence
latexText->append( "}{" + QString::number( overall_payoff, 'f', 2 ) + "}\n\n%%Einzelquittungen\n" );
// Write the single receipts
for ( auto s : *participants ) {
if ( s->payoff >= 0 ) {
latexText->append( "\\GAINRECEIPT{" + expectedPaymentFileName + "}{" + s->computer + "}{" + s->name + "}{" + QString::number( s->payoff, 'f', 2 ) + "}\n" );
}
else {
latexText->append( "\\LOSSRECEIPT{" + expectedPaymentFileName + "}{" + s->computer + "}{" + s->name + "}{" + QString::number( s->payoff, 'f', 2 ) + "}\n" );
}
delete s;
}
delete participants;
participants = nullptr;
// Append LaTeX ending
latexText->append( "\\end{document}" );
qDebug() << *latexText;
// Create the tex file
QFile *texFile = new QFile{ zTreeDataTargetPath + "/" + dateString + ".tex" };
qDebug() << "Tex file" << texFile->fileName() << "will be created for receipts printing.";
// Clean up any already existing files
if ( texFile->exists() ) {
if ( !texFile->remove() ) {
QMessageBox messageBox( QMessageBox::Critical, "Tex file removing failed", "There already exists a tex file at '" + texFile->fileName()
+ "' which cannot be removed. The creation of the receipts printout may fail.", QMessageBox::Ok );
messageBox.exec();
}
}
// Create a new file
if ( !texFile->open( QIODevice::Text | QIODevice::WriteOnly ) ) {
QMessageBox messageBox( QMessageBox::Critical, "Tex file creation failed", "The creation of the tex file for receipts printing at '" + texFile->fileName()
+ "' failed. Receipts printing will not work.", QMessageBox::Ok );
messageBox.exec();
return;
}
// Open a QTextStream to write to the file
QTextStream out( texFile );
out << *latexText;
delete latexText;
latexText = nullptr;
receiptsPrinter = new ReceiptsPrinter{ dateString, zTreeDataTargetPath, this };
receiptsPrinter->start();
connect( receiptsPrinter, &ReceiptsPrinter::PrintingFinished,
this, &ReceiptsHandler::DeleteReceiptsPrinterInstance );
connect( receiptsPrinter, &ReceiptsPrinter::ErrorOccurred,
this, &ReceiptsHandler::DisplayMessageBox );
// Clean up
texFile->close();
delete texFile;
}
void lc::ReceiptsHandler::DeleteReceiptsPrinterInstance() {
receiptsPrinter->quit();
receiptsPrinter->wait();
receiptsPrinter->deleteLater();
receiptsPrinter = nullptr;
qDebug() << "Deleted 'ReceiptsPrinter' instance.";
emit PrintingFinished();
}
void lc::ReceiptsHandler::DisplayMessageBox( QString *argErrorMessage, QString *argHeading ) {
QMessageBox messageBox( QMessageBox::Warning, *argHeading, *argErrorMessage, QMessageBox::Ok );
delete argHeading;
delete argErrorMessage;
messageBox.exec();
}
QVector<QString> *lc::ReceiptsHandler::GetParticipantsDataFromPaymentFile() {
// Create the vector to store the single lines of the file
QVector<QString> *participantsData = new QVector<QString>;
// Open the payment file for reading and create a QTextStream
paymentFile.open( QIODevice::ReadOnly | QIODevice::Text );
QTextStream in( &paymentFile );
in.setCodec( "ISO 8859-1" );
// Read the file line by line and store them in the vector
while ( true ) {
QString line = in.readLine();
if ( line.isNull() ) {
break;
}
participantsData->append( line );
}
// Remove the first line, since it is not needed
participantsData->erase( participantsData->begin() );
// Close the file afterwards
paymentFile.close();
return participantsData;
}
QString *lc::ReceiptsHandler::LoadLatexHeader() {
// Prepare all facilities to read the latex header file
QFile latexHeaderFile( settings->lcDataDir + "/" + latexHeaderName + "_header.tex" );
if ( !latexHeaderFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
QMessageBox messageBox{ QMessageBox::Critical, tr( "LaTeX header could not be loaded" ),
tr( "The LaTeX header at '%1/%2_header.tex' could not be loaded. Receipts printing will not work." )
.arg( settings->lcDataDir ).arg( latexHeaderName ), QMessageBox::Ok };
messageBox.exec();
return nullptr;
}
QTextStream in( &latexHeaderFile );
QString *header = nullptr;
header = new QString( in.readAll() );
latexHeaderFile.close();
return header;
}
void lc::ReceiptsHandler::MakeReceiptsAnonymous( QVector<paymentEntry_t*> *argDataVector, bool argAlsoAnonymizeClients ) {
if ( !argAlsoAnonymizeClients ) {
qDebug() << "Names are made anonymous";
for ( QVector< paymentEntry_t* >::iterator it = argDataVector->begin(); it != argDataVector->end(); ++it ) {
( *it )->name = anonymousReceiptsPlaceholder;
}
}
else {
qDebug() << "Clients and names are made anonymous";
for ( QVector< paymentEntry_t* >::iterator it = argDataVector->begin(); it != argDataVector->end(); ++it ) {
( *it )->name = anonymousReceiptsPlaceholder;
( *it )->computer = "\\hspace{1cm}";
}
}
}