/* * 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 . */ #include #include #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 *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 *participants = new QVector; double overall_payoff = 0.0; for ( QVector::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 *lc::ReceiptsHandler::GetParticipantsDataFromPaymentFile() { // Create the vector to store the single lines of the file QVector *participantsData = new QVector; // 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 *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}"; } } }