Initial commit
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
#ifndef TICKET_SALES_REPORT_WIDGET_H
|
||||
#define TICKET_SALES_REPORT_WIDGET_H
|
||||
|
||||
#include "ui_ticket_sales_report_widget.h"
|
||||
|
||||
#include <QChartView>
|
||||
#include <QLineSeries>
|
||||
#include <QScatterSeries>
|
||||
#include <functional>
|
||||
|
||||
// Forward declaration
|
||||
class RepositoryResult;
|
||||
class SessionStatisticsDTO;
|
||||
class RepositoriesInterface;
|
||||
class SessionsStatisticsRepository;
|
||||
|
||||
class TicketSalesReportWidget : public QWidget,
|
||||
private Ui::TicketSalesReportWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
class SalesData {
|
||||
private:
|
||||
double refundExpenses_;
|
||||
double salesRevenue_;
|
||||
qint32 refundedTickets_;
|
||||
qint32 soldTickets_;
|
||||
qint32 maximumTickets_;
|
||||
|
||||
public:
|
||||
SalesData();
|
||||
explicit SalesData(double refundExpenses, double salesRevenue,
|
||||
qint32 refundedTickets, qint32 soldTickets,
|
||||
qint32 maximumTickets);
|
||||
|
||||
SalesData &operator+=(const SalesData &other);
|
||||
SalesData operator+(const SalesData &other) const;
|
||||
|
||||
// clang-format off
|
||||
inline double refundExpenses() const { return refundExpenses_; };
|
||||
inline double salesRevenue() const { return salesRevenue_; };
|
||||
inline qint32 refundedTickets() const { return refundedTickets_; };
|
||||
inline qint32 soldTickets() const { return soldTickets_; };
|
||||
inline qint32 maximumTickets() const { return maximumTickets_; };
|
||||
inline void setRefundExpenses(double refundExpenses) { refundExpenses_ = refundExpenses; };
|
||||
inline void setRefundedTickets(qint32 refundedTickets) { refundedTickets_ = refundedTickets; };
|
||||
inline void setSalesRevenue(double salesRevenue) { salesRevenue_ = salesRevenue; };
|
||||
inline void setSoldTickets(qint32 soldTickets) { soldTickets_ = soldTickets; };
|
||||
inline void setMaximumTickets(qint32 maximumTickets) { maximumTickets_ = maximumTickets; };
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
private:
|
||||
using GetSessionsForEntityByIdMethod = std::function<RepositoryResult(
|
||||
qint32 entityId, std::optional<QDateTime> startDate,
|
||||
std::optional<QDateTime> endDate,
|
||||
QVector<SessionStatisticsDTO> &sessions)>;
|
||||
|
||||
private:
|
||||
GetSessionsForEntityByIdMethod sessionsStatisticsMethod_;
|
||||
QChartView *chartView_;
|
||||
QDateTime startRange_, endRange_;
|
||||
QString billetChartTitle_, chartTitle_, seriesName_, yAxisTitle_;
|
||||
SessionsStatisticsRepository *sessionsStatisticsRepository;
|
||||
int columnInfoIndex_;
|
||||
qint32 selectedEntityId_;
|
||||
|
||||
public:
|
||||
explicit TicketSalesReportWidget(QWidget *parent = nullptr);
|
||||
|
||||
void configureReportForGenre();
|
||||
void configureReportForHall();
|
||||
void configureReportForMovie();
|
||||
|
||||
private:
|
||||
void initializeChart();
|
||||
void initializeRepositories();
|
||||
void setupChart();
|
||||
void setupConnections();
|
||||
|
||||
void configureEntityFinder(const QString &databaseTableName,
|
||||
const QString &labelText,
|
||||
const QString &placeholder);
|
||||
|
||||
private slots:
|
||||
void onEntityFinderReseted();
|
||||
void onPushButtonGenerateClicked();
|
||||
void onFieldRetrieved(const QSqlField &field);
|
||||
void onRecordRetrieved(const QSqlRecord &rowValues);
|
||||
|
||||
private:
|
||||
template <typename T, typename SeriesType>
|
||||
SeriesType *
|
||||
createSeriesTemplate(const QMap<QDateTime, SalesData> &accumulatedSalesData,
|
||||
QDateTime &minDate, QDateTime &maxDate,
|
||||
T (SalesData::*getter)() const,
|
||||
const QString &seriesName);
|
||||
|
||||
template <typename T>
|
||||
QAbstractSeries *
|
||||
createLineSeries(const QMap<QDateTime, SalesData> &accumulatedSalesData,
|
||||
QDateTime &minDate, QDateTime &maxDate,
|
||||
T (SalesData::*getter)() const, const QString &seriesName);
|
||||
|
||||
template <typename T>
|
||||
QAbstractSeries *
|
||||
createScatterSeries(const QMap<QDateTime, SalesData> &accumulatedSalesData,
|
||||
QDateTime &minDate, QDateTime &maxDate,
|
||||
T (SalesData::*getter)() const,
|
||||
const QString &seriesName);
|
||||
|
||||
template <typename T>
|
||||
T maxValue(const QMap<QDateTime, SalesData> &data,
|
||||
T (SalesData::*getter)() const);
|
||||
|
||||
private:
|
||||
QMap<QDateTime, TicketSalesReportWidget::SalesData> aggregateByDateTime(
|
||||
const QVector<SessionStatisticsDTO> &sessions,
|
||||
std::function<bool(const SessionStatisticsDTO &)> filter = {});
|
||||
|
||||
QAbstractAxis *createDateTimeAxis(int tickCount, const QString &axisTitle,
|
||||
const QDateTime &minDate,
|
||||
const QDateTime &maxDate) const;
|
||||
|
||||
QAbstractAxis *createValueAxis(int maxValue, const QString &axisTitle) const;
|
||||
|
||||
RepositoryResult retrieveSessions(QVector<SessionStatisticsDTO> &sessions);
|
||||
|
||||
bool dateRange(QDateTime &startOut, QDateTime &endOut);
|
||||
|
||||
bool validateData(const QMap<QDateTime, SalesData> &data) const;
|
||||
|
||||
void createChart(const QMap<QDateTime, SalesData> &data);
|
||||
|
||||
void setupChart(QChart *chart, QAbstractSeries *series, QAbstractAxis *axisX,
|
||||
QAbstractAxis *axisY) const;
|
||||
|
||||
void updateChartView(QChart *chart) const;
|
||||
};
|
||||
|
||||
template <typename T, typename SeriesType>
|
||||
SeriesType *TicketSalesReportWidget::createSeriesTemplate(
|
||||
const QMap<QDateTime, SalesData> &accumulatedSalesData, QDateTime &minDate,
|
||||
QDateTime &maxDate, T (SalesData::*getter)() const,
|
||||
const QString &seriesName) {
|
||||
|
||||
auto *series = new SeriesType();
|
||||
series->setName(seriesName);
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (auto it = accumulatedSalesData.cbegin();
|
||||
it != accumulatedSalesData.cend(); ++it) {
|
||||
const QDateTime &dateTime = it.key();
|
||||
|
||||
series->append(dateTime.toMSecsSinceEpoch(), (it.value().*getter)());
|
||||
|
||||
if (first) {
|
||||
minDate = dateTime;
|
||||
maxDate = dateTime;
|
||||
first = false;
|
||||
} else {
|
||||
if (dateTime < minDate)
|
||||
minDate = dateTime;
|
||||
if (dateTime > maxDate)
|
||||
maxDate = dateTime;
|
||||
}
|
||||
}
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QAbstractSeries *TicketSalesReportWidget::createScatterSeries(
|
||||
const QMap<QDateTime, SalesData> &accumulatedSalesData, QDateTime &minDate,
|
||||
QDateTime &maxDate, T (SalesData::*getter)() const,
|
||||
const QString &seriesName) {
|
||||
|
||||
return createSeriesTemplate<T, QScatterSeries>(accumulatedSalesData, minDate,
|
||||
maxDate, getter, seriesName);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QAbstractSeries *TicketSalesReportWidget::createLineSeries(
|
||||
const QMap<QDateTime, SalesData> &accumulatedSalesData, QDateTime &minDate,
|
||||
QDateTime &maxDate, T (SalesData::*getter)() const,
|
||||
const QString &seriesName) {
|
||||
|
||||
return createSeriesTemplate<T, QLineSeries>(accumulatedSalesData, minDate,
|
||||
maxDate, getter, seriesName);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T TicketSalesReportWidget::maxValue(const QMap<QDateTime, SalesData> &data,
|
||||
T (SalesData::*getter)() const) {
|
||||
if (data.isEmpty()) {
|
||||
return T{};
|
||||
}
|
||||
|
||||
T maxValue = (data.cbegin().value().*getter)();
|
||||
|
||||
for (auto it = data.cbegin(); it != data.cend(); ++it) {
|
||||
maxValue = std::max(maxValue, (it.value().*getter)());
|
||||
}
|
||||
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
#endif // TICKET_SALES_REPORT_WIDGET_H
|
||||
Reference in New Issue
Block a user