Initial commit
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
#include "refund_generator.h"
|
||||
|
||||
#include "create_refund_request.h"
|
||||
#include "refunds_repository.h"
|
||||
#include "repository_manager.h"
|
||||
#include "repository_result.h"
|
||||
#include "schema_metadata.h"
|
||||
#include "session_dto.h"
|
||||
#include "sessions_repository.h"
|
||||
#include "ticket_dto.h"
|
||||
#include "tickets_repository.h"
|
||||
#include <QRandomGenerator>
|
||||
|
||||
RefundGenerator::RefundGenerator(const QPair<double, double> &refundRatioRange,
|
||||
const QPair<qint64, qint64> &dayRange,
|
||||
const QPair<QTime, QTime> &timeRange)
|
||||
: BaseGenerator("Refund"), DateTimeGenerator(dayRange, timeRange),
|
||||
refundRatioRange_(refundRatioRange) {
|
||||
auto &[lowest, highest] = refundRatioRange_;
|
||||
if (lowest > highest) {
|
||||
qCritical() << "Lowest refund ratio is greater than the highest refund, "
|
||||
"values will be swapped";
|
||||
std::swap(lowest, highest);
|
||||
}
|
||||
|
||||
initializeRepositories(); // First
|
||||
initializeTicketIdToCacheValueMap(); // After initializing
|
||||
// repositories
|
||||
initializeRemainingCapacity(); // After initializing ticketIdToCacheValue
|
||||
}
|
||||
|
||||
void RefundGenerator::initializeRepositories() {
|
||||
RepositoryManager &repositoryManager = RepositoryManager::instance();
|
||||
SchemaMetadata metadata = SchemaMetadata::defaultSchema();
|
||||
|
||||
ticketsRepository_ = repositoryManager.getRepositoryAs<TicketsRepository>(
|
||||
metadata.repositoryTableName("tickets"));
|
||||
refundsRepository_ = repositoryManager.getRepositoryAs<RefundsRepository>(
|
||||
metadata.repositoryTableName("refunds"));
|
||||
sessionsRepository_ = repositoryManager.getRepositoryAs<SessionsRepository>(
|
||||
metadata.repositoryTableName("sessions"));
|
||||
|
||||
if (!bool(ticketsRepository_ && refundsRepository_ && sessionsRepository_)) {
|
||||
qFatal() << "Failed to initialize repositories";
|
||||
}
|
||||
}
|
||||
|
||||
void RefundGenerator::initializeTicketIdToCacheValueMap() {
|
||||
QVector<SessionDTO> sessions;
|
||||
RepositoryResult resultGetAllSessions =
|
||||
sessionsRepository_->getAllSessions(sessions);
|
||||
if (!resultGetAllSessions.success) {
|
||||
qFatal() << "Failed to retrieve sessions";
|
||||
}
|
||||
|
||||
QMap<qint32 /* sessionId */,
|
||||
QPair<QDateTime /* beginAt */, double /* ticketPrice */>>
|
||||
sessionIdToBeginAtAndTicketPrice;
|
||||
|
||||
for (const SessionDTO &session : sessions) {
|
||||
sessionIdToBeginAtAndTicketPrice[session.sessionId()] =
|
||||
qMakePair(session.beginAt(), session.ticketPrice());
|
||||
}
|
||||
|
||||
QVector<TicketDTO> tickets;
|
||||
RepositoryResult resultGetAllTickets =
|
||||
ticketsRepository_->getAllTickets(tickets);
|
||||
|
||||
if (!resultGetAllTickets.success) {
|
||||
qFatal() << "Failed to retrieve tickets";
|
||||
}
|
||||
|
||||
for (const auto &ticket : tickets) {
|
||||
const auto &[beginAt, ticketPrice] =
|
||||
sessionIdToBeginAtAndTicketPrice[ticket.sessionId()];
|
||||
CacheValue cacheValue{beginAt, ticket.soldAt(), ticketPrice};
|
||||
|
||||
if (calculateDurationMs(cacheValue) < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ticketIdToCacheValue_[ticket.ticketId()] = cacheValue;
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
RefundGenerator::createFailureMessage(const QString &errorMessage) const {
|
||||
const QString dateTimeFormat = "yyyy-MM-dd hh:mm:ss.zzz";
|
||||
QString additionalInfo =
|
||||
QString("Additional info: Ticket id: %1 Refund amount: %2 Sold at: %3 "
|
||||
"Refund at: %4 Begin at: %5")
|
||||
.arg(reservationContext_.ticketId)
|
||||
.arg(reservationContext_.refundAmount)
|
||||
.arg(reservationContext_.soldAt.toString(dateTimeFormat))
|
||||
.arg(reservationContext_.refundAt.toString(dateTimeFormat))
|
||||
.arg(reservationContext_.beginAt.toString(dateTimeFormat));
|
||||
QString failureMessage = "Failure:\n\t%1\n\tError message: %2";
|
||||
return failureMessage.arg(additionalInfo).arg(errorMessage);
|
||||
}
|
||||
|
||||
QString RefundGenerator::createSuccessMessage() const {
|
||||
return QString("Success: EId: %1 RAm: %2 RAt: %3")
|
||||
.arg(reservationContext_.ticketId)
|
||||
.arg(reservationContext_.refundAmount)
|
||||
.arg(reservationContext_.refundAt.toString("yyyy-MM-dd hh:mm:ss"));
|
||||
}
|
||||
|
||||
qsizetype RefundGenerator::calculateRemainingCapacity() const {
|
||||
return remainingCapacity_;
|
||||
}
|
||||
|
||||
RepositoryResult RefundGenerator::createRecord() {
|
||||
CreateRefundRequest request;
|
||||
request.setRefundAmount(reservationContext_.refundAmount);
|
||||
request.setRefundAt(reservationContext_.refundAt);
|
||||
request.setTicketId(reservationContext_.ticketId);
|
||||
|
||||
RepositoryResult result = refundsRepository_->createRefund(request);
|
||||
|
||||
if (result.success) {
|
||||
--remainingCapacity_;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RefundGenerator::prepareData() {
|
||||
if (ticketIdToCacheValue_.isEmpty()) {
|
||||
qInfo() << "No tickets to refund";
|
||||
return false;
|
||||
}
|
||||
|
||||
qsizetype ticketIdIndex = bounded<qsizetype>(0, ticketIdToCacheValue_.size());
|
||||
auto ticketIdIt = ticketIdToCacheValue_.cbegin();
|
||||
std::advance(ticketIdIt, ticketIdIndex);
|
||||
|
||||
qint32 ticketId = ticketIdIt.key();
|
||||
CacheValue cacheValue = ticketIdIt.value();
|
||||
|
||||
constexpr qint32 fiveMinutesMs = 5 * 1000 * 60;
|
||||
qint64 deltaBoundMs = calculateDurationMs(cacheValue) / 2;
|
||||
if (deltaBoundMs > fiveMinutesMs) {
|
||||
deltaBoundMs = fiveMinutesMs;
|
||||
}
|
||||
|
||||
const QDateTime refundAt =
|
||||
// SoldAt < RefundAt < BeginAt
|
||||
// SoldAt + n minute <= RefundAt <= BeginAt - n minute
|
||||
generate(cacheValue.soldAt.addMSecs(+deltaBoundMs),
|
||||
cacheValue.beginAt.addMSecs(-deltaBoundMs));
|
||||
|
||||
const auto [refundRatioLowest, refundRatioHighest] = refundRatioRange_;
|
||||
int lowest = refundRatioLowest * 100;
|
||||
int highest = refundRatioHighest * 100;
|
||||
int numerator = bounded(lowest, highest);
|
||||
double refundAmount = std::floor(numerator * cacheValue.ticketPrice) / 100.0;
|
||||
|
||||
ReservationContext context{cacheValue.beginAt, refundAt, cacheValue.soldAt,
|
||||
refundAmount, ticketId};
|
||||
reservationContext_ = std::move(context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RefundGenerator::clearStaleData() {
|
||||
qint32 ticketId = reservationContext_.ticketId;
|
||||
ticketIdToCacheValue_.remove(ticketId);
|
||||
}
|
||||
Reference in New Issue
Block a user