1
0
forked from BRT/arc
arc/database/dao/EventDAO.cpp
trnsmkot 04025aa32b Add database migration, DAO enhancements, and OCR-based transaction handling updates
Implemented database migration for adding new fields (`json`, `sent_to_server`) in `events` table. Updated DAO methods to support the new fields and introduced `markSentToServer`. Enhanced Ozon transaction workflows with OCR-based extraction, event error handling improvements, and result reporting. Refactored `EventHandler` for streamlined task processing and stale event cleanup.
2026-03-08 14:20:12 +07:00

227 lines
7.6 KiB
C++

#include "EventDAO.h"
#include <QSqlError>
#include <QSqlQuery>
#include "DatabaseManager.h"
#include "time/DateUtils.h"
EventInfo parseEvent(const QSqlQuery &query) {
EventInfo event;
event.id = query.value("id").toInt();
event.status = eventStatusFromString(query.value("status").toString());
event.type = eventTypeFromString(query.value("type").toString());
event.externalId = query.value("external_id").toString();
event.accountId = query.value("account_id").toInt();
event.deviceId = query.value("device_id").toString();
event.amount = query.value("amount").toDouble();
event.phone = query.value("phone").toString();
event.bankName = query.value("bank_name").toString();
event.comment = query.value("comment").toString();
event.json = query.value("json").toString();
event.sentToServer = query.value("sent_to_server").toBool();
event.timestamp = DateUtils::fromUtcString(query.value("timestamp").toString());
event.updateTime = DateUtils::fromUtcString(query.value("update_time").toString());
event.completeTime = DateUtils::fromUtcString(query.value("complete_time").toString());
return event;
}
int EventDAO::insertEvent(const EventInfo &event) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
INSERT INTO events (
status, external_id, account_id, amount, phone, bank_name, comment, json, timestamp, device_id, type
) VALUES (
:status, :external_id, :account_id, :amount, :phone, :bank_name, :comment, :json, :timestamp, :device_id, :type
)
)");
query.bindValue(":status", eventStatusToString(event.status));
query.bindValue(":type", eventTypeToString(event.type));
query.bindValue(":external_id", event.externalId);
query.bindValue(":account_id", event.accountId);
query.bindValue(":device_id", event.deviceId);
query.bindValue(":amount", event.amount);
query.bindValue(":phone", event.phone);
query.bindValue(":bank_name", event.bankName);
query.bindValue(":comment", event.comment);
query.bindValue(":json", event.json);
query.bindValue(":timestamp", DateUtils::toUtcString(event.timestamp));
if (!query.exec()) {
qCritical() << "Ошибка при вставке event:" << query.lastError().text();
return -1;
}
return query.lastInsertId().toInt();
}
bool EventDAO::updateEvent(
const int id,
const EventStatus &status,
const QString &comment
) {
QSqlQuery query(DatabaseManager::instance().database());
if (status == EventStatus::InProgress) {
query.prepare(R"(
UPDATE events SET
status = :status,
update_time = :update_time
WHERE id = :id
)");
query.bindValue(":update_time", DateUtils::toUtcString(DateUtils::getUtcNow()));
}
if (status == EventStatus::Complete) {
query.prepare(R"(
UPDATE events SET
status = :status,
complete_time = :complete_time
WHERE id = :id
)");
query.bindValue(":complete_time", DateUtils::toUtcString(DateUtils::getUtcNow()));
}
if (status == EventStatus::Error) {
query.prepare(R"(
UPDATE events SET
status = :status,
update_time = :update_time,
comment = :comment
WHERE id = :id
)");
query.bindValue(":update_time", DateUtils::toUtcString(DateUtils::getUtcNow()));
query.bindValue(":comment", comment);
}
query.bindValue(":id", id);
query.bindValue(":status", eventStatusToString(status));
if (!query.exec()) {
qCritical() << "Ошибка при обновлении event:" << query.lastError().text();
return false;
}
return true;
}
bool EventDAO::updateEventAmount(int id, double amount) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare("UPDATE events SET amount = :amount WHERE id = :id");
query.bindValue(":amount", amount);
query.bindValue(":id", id);
if (!query.exec()) {
qCritical() << "Ошибка при обновлении amount event:" << query.lastError().text();
return false;
}
return true;
}
bool EventDAO::markSentToServer(int id) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare("UPDATE events SET sent_to_server = 1 WHERE id = :id");
query.bindValue(":id", id);
if (!query.exec()) {
qWarning() << "Ошибка markSentToServer:" << query.lastError().text();
return false;
}
return true;
}
QList<EventInfo> EventDAO::getAllEvents(const EventStatus &status) {
QList<EventInfo> events;
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
status, type, comment, json, sent_to_server, update_time, complete_time, timestamp
FROM events
WHERE status = :status
)");
query.bindValue(":status", eventStatusToString(status));
if (!query.exec()) {
qWarning() << "Ошибка при получении getAllEvents:" << query.lastError().text();
return events;
}
while (query.next()) {
events.append(parseEvent(query));
}
return events;
}
EventInfo EventDAO::getFirstWaitEventByDeviceId(const QString &key) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
status, type, comment, json, sent_to_server, update_time, complete_time, timestamp
FROM events
WHERE status = :status AND device_id = :device_id
ORDER BY timestamp ASC
LIMIT 1
)");
query.bindValue(":status", eventStatusToString(EventStatus::Wait));
query.bindValue(":device_id", key);
if (!query.exec()) {
qCritical() << "Ошибка при получении getFirstWaitEventByDeviceId:" << query.lastError().text();
return {};
}
while (query.next()) {
return parseEvent(query);
}
return {};
}
QList<EventInfo> EventDAO::getEvents(int page, int pageSize) {
QList<EventInfo> events;
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
status, type, comment, json, sent_to_server, update_time, complete_time, timestamp
FROM events
ORDER BY id DESC
LIMIT :limit OFFSET :offset
)");
query.bindValue(":limit", pageSize);
query.bindValue(":offset", page * pageSize);
if (!query.exec()) {
qWarning() << "Ошибка при получении getEvents:" << query.lastError().text();
return events;
}
while (query.next()) {
events.append(parseEvent(query));
}
return events;
}
int EventDAO::getTotalCount() {
QSqlQuery query(DatabaseManager::instance().database());
query.exec("SELECT COUNT(*) FROM events");
if (query.next()) return query.value(0).toInt();
return 0;
}
bool EventDAO::existsActiveByExternalId(const QString &externalId) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT 1 FROM events
WHERE external_id = :external_id
AND status IN ('wait', 'iPprogress')
LIMIT 1
)");
query.bindValue(":external_id", externalId);
if (!query.exec()) {
qCritical() << "Ошибка при existsActiveByExternalId:" << query.lastError().text();
return false;
}
return query.next();
}