From 89ea2ac53adc514da454d85587b8184884f7ff3d Mon Sep 17 00:00:00 2001 From: slava Date: Wed, 21 May 2025 20:18:53 +0700 Subject: [PATCH] Add event handling and improved account management Introduced a new "events" table and corresponding EventDAO for managing event data. Enhanced account handling with device ID and partial card number support. Added a NetworkService method to fetch payments from an API and store them as events. --- android/rshb/PayByPhoneScript.cpp | 7 -- database/app_data.db | Bin 2621440 -> 2621440 bytes database/dao/AccountDAO.cpp | 49 ++++++-------- database/dao/AccountDAO.h | 6 +- database/dao/EventDAO.cpp | 108 ++++++++++++++++++++++++++++++ database/dao/EventDAO.h | 15 +++++ main.cpp | 26 +++++-- migrations.sql | 19 ++++++ models/db/EventInfo.h | 44 ++++++++++++ services/net/NetworkService.cpp | 83 +++++++++++++++++++++++ services/net/NetworkService.h | 3 + 11 files changed, 318 insertions(+), 42 deletions(-) create mode 100644 database/dao/EventDAO.cpp create mode 100644 database/dao/EventDAO.h create mode 100644 models/db/EventInfo.h diff --git a/android/rshb/PayByPhoneScript.cpp b/android/rshb/PayByPhoneScript.cpp index d5ea7d7..d0e8be6 100644 --- a/android/rshb/PayByPhoneScript.cpp +++ b/android/rshb/PayByPhoneScript.cpp @@ -244,13 +244,6 @@ void PayByPhoneScript::doStart() { const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId); const ApplicationInfo app = ApplicationDAO::getApplicationsByDeviceId(m_account.deviceId, m_account.appName); - for (TransactionInfo &transaction: TransactionDAO::getTransactions(m_account.id)) { - // postNewTransactionData(m_account, transaction); - updateTransactionData(m_account, transaction.id, transaction.status, transaction.updatedDescription, transaction.description); - } - - emit finishedWithResult(m_error); - return; if (device.id.isEmpty() || app.id.isEmpty()) { qDebug() << "Device or app not found...."; return; diff --git a/database/app_data.db b/database/app_data.db index 4e83f5503a864c27d2fa383bfc8da0fd59b7bc7b..ba7d920d5e94d50a06f2250a820cb7bcd21b7025 100644 GIT binary patch delta 871 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 diff --git a/database/dao/AccountDAO.cpp b/database/dao/AccountDAO.cpp index aff69a0..45af597 100644 --- a/database/dao/AccountDAO.cpp +++ b/database/dao/AccountDAO.cpp @@ -44,6 +44,20 @@ bool AccountDAO::deleteAccount(const int id) { return query.exec(); } +AccountInfo parseAccount(const QSqlQuery &query) { + AccountInfo acc; + acc.id = query.value("id").toInt(); + acc.deviceId = query.value("device_id").toString(); + acc.appName = query.value("app_name").toString(); + acc.lastNumbers = query.value("last_numbers").toString(); + acc.numbers = query.value("numbers").toString(); + acc.amount = query.value("amount").toDouble(); + acc.updateTime = DateUtils::fromUtcString(query.value("update_time").toString()); + acc.status = accountStatusFromString(query.value("status").toString()); + acc.description = query.value("description").toString(); + return acc; +} + QList AccountDAO::getAccounts(const QString &deviceId, const QString &appName) { QList accounts; QSqlQuery query(DatabaseManager::instance().database()); @@ -63,36 +77,12 @@ QList AccountDAO::getAccounts(const QString &deviceId, const QStrin } while (query.next()) { - AccountInfo acc; - acc.id = query.value("id").toInt(); - acc.deviceId = query.value("device_id").toString(); - acc.appName = query.value("app_name").toString(); - acc.numbers = query.value("numbers").toString(); - acc.lastNumbers = query.value("last_numbers").toString(); - acc.amount = query.value("amount").toDouble(); - acc.updateTime = DateUtils::fromUtcString(query.value("update_time").toString()); - acc.status = accountStatusFromString(query.value("status").toString()); - acc.description = query.value("description").toString(); - accounts.append(acc); + accounts.append(parseAccount(query)); } return accounts; } -AccountInfo parseAccount(const QSqlQuery &query) { - AccountInfo acc; - acc.id = query.value("id").toInt(); - acc.deviceId = query.value("device_id").toString(); - acc.appName = query.value("app_name").toString(); - acc.lastNumbers = query.value("last_numbers").toString(); - acc.numbers = query.value("numbers").toString(); - acc.amount = query.value("amount").toDouble(); - acc.updateTime = DateUtils::fromUtcString(query.value("update_time").toString()); - acc.status = accountStatusFromString(query.value("status").toString()); - acc.description = query.value("description").toString(); - return acc; -} - AccountInfo AccountDAO::getAccountById(const int accountId) { QSqlQuery query(DatabaseManager::instance().database()); @@ -116,18 +106,19 @@ AccountInfo AccountDAO::getAccountById(const int accountId) { return {}; } -AccountInfo AccountDAO::findAppAccount(const QString &appName, const QString &cardNumber) { +AccountInfo AccountDAO::findAppAccount(const QString &deviceId, const QString &appName, const QString &lastNumber) { QSqlQuery query(DatabaseManager::instance().database()); query.prepare(R"( SELECT id, device_id, app_name, numbers, last_numbers, amount, update_time, status, description FROM accounts - WHERE app_name = :app_name AND numbers = :numbers + WHERE app_name = :appName AND last_numbers = :lastNumber AND device_id = :deviceId LIMIT 1 )"); - query.bindValue(":app_name", appName); - query.bindValue(":numbers", cardNumber); + query.bindValue(":deviceId", deviceId); + query.bindValue(":appName", appName); + query.bindValue(":lastNumber", lastNumber); if (!query.exec()) { qWarning() << "Ошибка при получении account по ID:" << query.lastError().text(); diff --git a/database/dao/AccountDAO.h b/database/dao/AccountDAO.h index ba6eefb..705f469 100644 --- a/database/dao/AccountDAO.h +++ b/database/dao/AccountDAO.h @@ -11,5 +11,9 @@ public: [[nodiscard]] static AccountInfo getAccountById(int accountId); - [[nodiscard]] static AccountInfo findAppAccount(const QString &appName, const QString &cardNumber); + [[nodiscard]] static AccountInfo findAppAccount( + const QString &deviceId, + const QString &appName, + const QString &lastNumber + ); }; diff --git a/database/dao/EventDAO.cpp b/database/dao/EventDAO.cpp new file mode 100644 index 0000000..82c2540 --- /dev/null +++ b/database/dao/EventDAO.cpp @@ -0,0 +1,108 @@ +#include "EventDAO.h" + +#include +#include + +#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.externalId = query.value("external_id").toInt(); + event.accountId = query.value("account_id").toInt(); + event.amount = query.value("amount").toDouble(); + event.phone = query.value("phone").toString(); + event.bankName = query.value("bank_name").toString(); + 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, timestamp + ) VALUES ( + :status, :external_id, :account_id, :amount, :phone, :bank_name, :timestamp + ) + )"); + + query.bindValue(":status", eventStatusToString(event.status)); + query.bindValue(":external_id", event.externalId); + query.bindValue(":account_id", event.accountId); + query.bindValue(":amount", event.amount); + query.bindValue(":phone", event.phone); + query.bindValue(":bank_name", event.bankName); + query.bindValue(":timestamp", DateUtils::toUtcString(DateUtils::getUtcNow())); + + if (!query.exec()) { + qWarning() << "Ошибка при вставке event:" << query.lastError().text(); + return -1; + } + + return query.lastInsertId().toInt(); +} + +bool EventDAO::updateEvent( + const int id, + const EventStatus &status +) { + QSqlQuery query(DatabaseManager::instance().database()); + + query.prepare(R"( + UPDATE events SET + status = :status, + update_time = :update_time, + complete_time = :complete_time + WHERE id = :id + )"); + + query.bindValue(":id", id); + query.bindValue(":status", eventStatusToString(status)); + + if (status == EventStatus::Wait) { + query.bindValue(":update_time", DateUtils::toUtcString(DateUtils::getUtcNow())); + } else { + query.bindValue(":update_time", QVariant(QMetaType(QMetaType::QString))); + } + + if (status == EventStatus::Complete) { + query.bindValue(":complete_time", DateUtils::toUtcString(DateUtils::getUtcNow())); + } else { + query.bindValue(":complete_time", QVariant(QMetaType(QMetaType::QString))); + } + + if (!query.exec()) { + qWarning() << "Ошибка при обновлении event:" << query.lastError().text(); + return false; + } + return true; +} + +QList EventDAO::getAllEvents(const EventStatus &status) { + QList events; + + QSqlQuery query(DatabaseManager::instance().database()); + query.prepare(R"( + SELECT id, account_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp + FROM events + WHERE status = :status + )"); + query.bindValue(":status", eventStatusToString(status)); + + if (!query.exec()) { + qWarning() << "Ошибка при получении списка устройств:" << query.lastError().text(); + return events; + } + + while (query.next()) { + events.append(parseEvent(query)); + } + + return events; +} diff --git a/database/dao/EventDAO.h b/database/dao/EventDAO.h new file mode 100644 index 0000000..9e4982b --- /dev/null +++ b/database/dao/EventDAO.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +class EventDAO { +public: + [[nodiscard]] static int insertEvent(const EventInfo &event); + + [[nodiscard]] static bool updateEvent( + int id, + const EventStatus &status + ); + + [[nodiscard]] static QList getAllEvents(const EventStatus &status); +}; diff --git a/main.cpp b/main.cpp index a49c93a..82388d9 100644 --- a/main.cpp +++ b/main.cpp @@ -16,6 +16,7 @@ #include #include +#include "net/NetworkService.h" #include "rshb/GetLastDaysHistoryScript.h" #include "rshb/HomeScreenScript.h" #include "rshb/PayByPhoneScript.h" @@ -52,8 +53,9 @@ void setupWorkerAndThread(QCoreApplication &app) { void setupWorkerAndThreadHistory(QCoreApplication &app) { const QString appName = "rshb"; - const QString cardNumber = "2200380317107183"; - AccountInfo account = AccountDAO::findAppAccount(appName, cardNumber); + const QString lastNumber = "7183"; + const QString deviceId = "6edc4a47"; + AccountInfo account = AccountDAO::findAppAccount(deviceId, appName, lastNumber); auto *thread = new QThread; auto *deviceScreenerWorker = new GetLastDaysHistoryScript(account); @@ -72,14 +74,15 @@ void setupWorkerAndThreadHistory(QCoreApplication &app) { void setupScriptAutoPaymentAndThread(QCoreApplication &app) { const QString appName = "rshb"; - const QString cardNumber = "2200380317107183"; + const QString lastNumber = "7183"; const QString phoneNumber = "79641815146"; + const QString deviceId = "6edc4a47"; const QString bankName = "Альфа-Банк"; // const QString bankName = "Сбербанк"; const double amount = 320; - const AccountInfo account = AccountDAO::findAppAccount(appName, cardNumber); + const AccountInfo account = AccountDAO::findAppAccount(deviceId, appName, lastNumber); if (account.id != -1) { // Функция для подключения потоков к завершению приложения auto connectStopOnQuit = [&](QObject *worker, QThread *thread) { @@ -193,7 +196,20 @@ int main(int argc, char *argv[]) { // Устанавливаем свой обработчик qInstallMessageHandler(messageHandler); - setupScriptAutoPaymentAndThread(app); + + auto *thread = new QThread; + auto *worker = new NetworkService; + + // FIXME доставить десктоп ид из настроеек + worker->setDeviceData("DT88bokcwQ", ""); + worker->moveToThread(thread); + QObject::connect(thread, &QThread::started, worker, &NetworkService::getPayments); + QObject::connect(worker, &NetworkService::finished, thread, &QThread::quit); + QObject::connect(worker, &NetworkService::finished, worker, &QObject::deleteLater); + QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); + + // setupScriptAutoPaymentAndThread(app); // setupWorkerAndThread(app); MainWindow window; diff --git a/migrations.sql b/migrations.sql index 2d55758..987561f 100644 --- a/migrations.sql +++ b/migrations.sql @@ -67,4 +67,23 @@ CREATE TABLE IF NOT EXISTS transactions complete_time DATETIME, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (account_id) REFERENCES accounts (id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS events +( + id INTEGER PRIMARY KEY AUTOINCREMENT, + account_id INTEGER, + external_id INTEGER, + + amount REAL, + phone TEXT, + bank_name TEXT, + + status TEXT, + + update_time DATETIME, + complete_time DATETIME, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (account_id) REFERENCES accounts (id) ON DELETE CASCADE, + UNIQUE (external_id) ); \ No newline at end of file diff --git a/models/db/EventInfo.h b/models/db/EventInfo.h new file mode 100644 index 0000000..6973f25 --- /dev/null +++ b/models/db/EventInfo.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +enum class EventStatus { + Wait, + InProgress, + Complete, + Unknown +}; + + +inline QString eventStatusToString(const EventStatus type) { + switch (type) { + case EventStatus::Wait: return "wait"; + case EventStatus::Complete: return "complete"; + case EventStatus::InProgress: return "iPprogress"; + default: return "unknown"; + } +} + +inline EventStatus eventStatusFromString(const QString &str) { + if (str == "wait") return EventStatus::Wait; + if (str == "complete") return EventStatus::Complete; + if (str == "iPprogress") return EventStatus::InProgress; + return EventStatus::Unknown; +} + +struct EventInfo { + int id = -1; + int externalId = -1; + int accountId = -1; + + double amount = 0; + QString phone; + QString bankName; + + EventStatus status = EventStatus::Unknown; + + QDateTime updateTime; + QDateTime completeTime; + QDateTime timestamp; +}; \ No newline at end of file diff --git a/services/net/NetworkService.cpp b/services/net/NetworkService.cpp index 2647c8a..0239fc2 100644 --- a/services/net/NetworkService.cpp +++ b/services/net/NetworkService.cpp @@ -1,11 +1,16 @@ #include "NetworkService.h" #include +#include #include #include #include +#include +#include "dao/AccountDAO.h" +#include "dao/EventDAO.h" #include "dao/TransactionDAO.h" +#include "db/EventInfo.h" NetworkService::NetworkService(QObject *parent) : QObject(parent) { } @@ -69,6 +74,47 @@ QJsonValue NetworkService::post(QHttpMultiPart *multiPart, const QString &path) return result; } + +QJsonArray NetworkService::get(const QString &path, const QMap ¶ms) { + QNetworkAccessManager manager; // создаём внутри потока + + QUrl url(path); + QUrlQuery query; + for (auto it = params.constBegin(); it != params.constEnd(); ++it) { + query.addQueryItem(it.key(), it.value()); + } + url.setQuery(query); + + const QNetworkRequest request(url); + QNetworkReply *reply = manager.get(request); + + QEventLoop loop; + connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + connect(reply, &QNetworkReply::errorOccurred, [&loop](QNetworkReply::NetworkError) { + loop.quit(); + }); + loop.exec(); // <- здесь и запускается event-loop потока + + QJsonArray result; + if (reply->error() == QNetworkReply::NoError) { + const QByteArray raw = reply->readAll(); + QJsonParseError err; + const QJsonDocument doc = QJsonDocument::fromJson(raw, &err); + if (err.error == QJsonParseError::NoError && doc.isObject()) { + const QJsonObject root = doc.object(); + if (root.value("success").toBool()) { + result = root.value("data").toArray(); + } else { + qWarning() << "Ошибка:" << root; + } + } + } else { + qWarning() << "Ошибка:" << reply->errorString(); + } + reply->deleteLater(); + return result; +} + void NetworkService::postAccountsData() { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); @@ -83,6 +129,43 @@ void NetworkService::postAccountsData() { emit finished(); } +void NetworkService::getPayments() { + QMap params; + params["desktopUniqueName"] = m_desktopId; + const QJsonArray data = get("http://localhost:9999/api/v1/payments", params); + + for (QJsonValue item: data) { + QJsonObject obj = item.toObject(); + EventInfo eventInfo; + eventInfo.status = EventStatus::Wait; + eventInfo.externalId = obj["id"].toInt(); + eventInfo.amount = obj["amount"].toDouble(); + eventInfo.bankName = obj["bankName"].toString(); + eventInfo.phone = obj["phone"].toString(); + + QString deviceId = obj["deviceId"].toString(); + QString appName = obj["appName"].toString(); + QString lastNumbers = obj["lastNumbers"].toString(); + AccountInfo account = AccountDAO::findAppAccount(deviceId, appName, lastNumbers); + + eventInfo.accountId = account.id; + + + int id = EventDAO::insertEvent(eventInfo); + if (id == -1) { + qDebug() << "Cant insert event"; + } else { + if (!EventDAO::updateEvent(id, EventStatus::Wait)) { + qDebug() << "Cant update event"; + } + } + } + + + emit finished(); +} + + void NetworkService::updateTransactionData() { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); diff --git a/services/net/NetworkService.h b/services/net/NetworkService.h index c70d24c..41f35bd 100644 --- a/services/net/NetworkService.h +++ b/services/net/NetworkService.h @@ -23,6 +23,7 @@ public: public slots: void postAccountsData(); + void getPayments(); void insertTransactionData(); @@ -42,4 +43,6 @@ private: QJsonValue post(QHttpMultiPart *multiPart, const QString &path); + + QJsonArray get(const QString &path, const QMap ¶ms); };