Implement Event Type Handling and Status Updates
Added handling for event types (Balance, Phone) and respective processing logic in EventHandler. Introduced support for tracking and updating event statuses both locally and through network APIs. Enhanced data integrity and clarity by expanding the EventInfo model and associated database management.
This commit is contained in:
parent
4fe6e399bc
commit
6e9b7c2b6e
@ -100,6 +100,7 @@ bool CommonScript::runAppAndGoToHomeScreen(
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Проверяем, что это экран ввода пин-кода
|
||||
if (!findAndInputPincode) {
|
||||
if (const QList<Node> pincode = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН");
|
||||
@ -212,6 +213,7 @@ void CommonScript::postAccountsData(const QList<QPair<AccountInfo, Node> > &acco
|
||||
obj["lastNumbers"] = account.lastNumbers;
|
||||
obj["amount"] = account.amount;
|
||||
obj["description"] = account.description;
|
||||
obj["status"] = accountStatusToString(account.status);
|
||||
|
||||
list.append(obj);
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "DatabaseManager.h"
|
||||
#include "adb/AdbUtils.h"
|
||||
#include "dao/AccountDAO.h"
|
||||
#include "dao/ApplicationDAO.h"
|
||||
#include "dao/DeviceDAO.h"
|
||||
#include "dao/TransactionDAO.h"
|
||||
#include "db/DeviceInfo.h"
|
||||
@ -83,59 +84,6 @@ QString formatPrice(const double value) {
|
||||
return QString("%1 %2").arg(sign, formatted);
|
||||
}
|
||||
|
||||
// bool GetLastDaysHistoryScript::openAndSaveDitailInfo(TransactionInfo &transaction, int width, int height) {
|
||||
// QString text = QString("%1 %2").arg(transaction.shortDescription, formatPrice(transaction.amount));
|
||||
//
|
||||
// Node trButton = swipeToButton(m_account.deviceId, text, m_counter, width, height);
|
||||
// if (!trButton.isEmpty()) {
|
||||
// AdbUtils::makeTap(m_account.deviceId, trButton.x(), trButton.y());
|
||||
// QThread::msleep(500);
|
||||
//
|
||||
// xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
|
||||
//
|
||||
// Node moreDetailBtn = xmlScreenParser.findButtonNode("Детали операции", false);
|
||||
// if (!moreDetailBtn.isEmpty()) {
|
||||
// AdbUtils::makeTap(m_account.deviceId, moreDetailBtn.x(), moreDetailBtn.y());
|
||||
// QThread::msleep(200);
|
||||
// xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
|
||||
// TransactionInfo info = xmlScreenParser.parseTransactionInfoHistory(width, height);
|
||||
//
|
||||
// if (transaction.id == -1) {
|
||||
// info.accountId = m_account.id;
|
||||
// info.shortDescription = transaction.shortDescription;
|
||||
// info.amount = transaction.amount;
|
||||
// info.type = info.phone.isEmpty() ? TransactionType::Card : TransactionType::Phone;
|
||||
// info.updateTime = DateUtils::getUtcNow();
|
||||
// if (info.status == TransactionStatus::Complete) {
|
||||
// info.completeTime = DateUtils::getUtcNow();
|
||||
// }
|
||||
// if (TransactionDAO::insertTransaction(info) == -1) {
|
||||
// qWarning() << "--- insertTransaction failed";
|
||||
// }
|
||||
// } else {
|
||||
// transaction.status = info.status;
|
||||
// transaction.description = info.description;
|
||||
// if (transaction.trExternalId.isEmpty()) {
|
||||
// transaction.trExternalId = info.trExternalId;
|
||||
// }
|
||||
// transaction.updateTime = DateUtils::getUtcNow();
|
||||
// if (transaction.status == TransactionStatus::Complete && !transaction.completeTime.isValid()) {
|
||||
// transaction.completeTime = DateUtils::getUtcNow();
|
||||
// }
|
||||
// if (!TransactionDAO::updateTransaction(transaction)) {
|
||||
// qWarning() << "--- updateTransaction failed";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// AdbUtils::goBack(m_account.deviceId);
|
||||
// QThread::msleep(200);
|
||||
// } else {
|
||||
// qWarning() << "--- trButton not found..........";
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
bool GetLastDaysHistoryScript::saveAndPostNewTransactionData(
|
||||
const AccountInfo &account,
|
||||
const TransactionInfo &transaction
|
||||
@ -178,14 +126,32 @@ bool GetLastDaysHistoryScript::updateAndPostTransactionData(
|
||||
}
|
||||
|
||||
void GetLastDaysHistoryScript::doStart() {
|
||||
|
||||
// берем все транзакции из БД
|
||||
QList<TransactionInfo> localTransactions = TransactionDAO::getTransactionsWithinHours(m_account.id, 48);
|
||||
const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId);
|
||||
const ApplicationInfo app = ApplicationDAO::getApplication(m_account.deviceId, m_account.appCode);
|
||||
|
||||
if (!xmlScreenParser.isHomeScreen()) {
|
||||
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) {
|
||||
m_error = "Не смогли дойти до домашней страницы";
|
||||
qCritical() << m_error;
|
||||
emit finishedWithResult(m_error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
|
||||
Node closeBannerOrDialogNode = xmlScreenParser.tryToFindBannerOrDialog(device.screenWidth, device.screenHeight);
|
||||
if (closeBannerOrDialogNode.x() != -1 && closeBannerOrDialogNode.y() != -1) {
|
||||
AdbUtils::makeTap(device.id, closeBannerOrDialogNode.x(), closeBannerOrDialogNode.y());
|
||||
QThread::msleep(500);
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
|
||||
|
||||
if (xmlScreenParser.isHomeScreen()) {
|
||||
if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) {
|
||||
QList<TransactionInfo> localTransactions = TransactionDAO::getTransactionsWithinHours(m_account.id, 48);
|
||||
|
||||
QList<QPair<AccountInfo, Node> > accounts = xmlScreenParser.parseAccountsInfo();
|
||||
for (auto &[account, node]: accounts) {
|
||||
account.deviceId = m_account.deviceId;
|
||||
@ -204,10 +170,17 @@ void GetLastDaysHistoryScript::doStart() {
|
||||
AdbUtils::makeTap(m_account.deviceId, actionBtn.x(), actionBtn.y());
|
||||
QThread::msleep(200);
|
||||
} else {
|
||||
qWarning() << "--- actionBtn not found";
|
||||
m_error = "All action btn not found";
|
||||
qCritical() << m_error;
|
||||
emit finishedWithResult(m_error);
|
||||
return;
|
||||
}
|
||||
Node reportButton = swipeToButton(m_account.deviceId, "Выписка", m_counter, device.screenWidth,
|
||||
device.screenHeight);
|
||||
Node reportButton = swipeToButton(
|
||||
m_account.deviceId,
|
||||
"Выписка",
|
||||
m_counter, device.screenWidth,
|
||||
device.screenHeight
|
||||
);
|
||||
|
||||
if (!reportButton.isEmpty()) {
|
||||
AdbUtils::makeTap(m_account.deviceId, reportButton.x(), reportButton.y());
|
||||
@ -236,7 +209,10 @@ void GetLastDaysHistoryScript::doStart() {
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
|
||||
}
|
||||
} else {
|
||||
qWarning() << "--- reportTitle not found";
|
||||
m_error = "All action - report title not found";
|
||||
qCritical() << m_error;
|
||||
emit finishedWithResult(m_error);
|
||||
return;
|
||||
}
|
||||
|
||||
// все поддвержденные
|
||||
@ -362,7 +338,6 @@ void GetLastDaysHistoryScript::doStart() {
|
||||
}
|
||||
}
|
||||
if (!updated) {
|
||||
qDebug() << "--- insert: " << transaction.description;
|
||||
if (!saveAndPostNewTransactionData(m_account, transaction)) {
|
||||
qDebug() << "--- saveAndPostNewTransactionData failed";
|
||||
}
|
||||
@ -375,6 +350,9 @@ void GetLastDaysHistoryScript::doStart() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qDebug() << "--- home screen not found";
|
||||
m_error = "GetLastDaysHistoryScript - home screen not found";
|
||||
qWarning() << m_error;
|
||||
emit finishedWithResult(m_error);
|
||||
}
|
||||
emit finishedWithResult(m_error);
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ protected:
|
||||
|
||||
private:
|
||||
const AccountInfo m_account;
|
||||
QString m_error;
|
||||
|
||||
bool saveAndPostNewTransactionData(const AccountInfo &account, const TransactionInfo &transaction);
|
||||
|
||||
|
||||
@ -21,20 +21,23 @@ void LoginAndCheckAccountsScript::doStart() {
|
||||
const ApplicationInfo app = ApplicationDAO::getApplication(m_deviceId, m_appCode);
|
||||
|
||||
if (device.id.isEmpty() || app.id == -1) {
|
||||
qCritical() << "Device or app not found: " << m_deviceId << " " << m_appCode;
|
||||
emit finished();
|
||||
m_error = "Device or app not found: " + m_deviceId + " " + m_appCode;
|
||||
qCritical() << m_error;
|
||||
emit finishedWithResult(m_error);
|
||||
return;
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||
|
||||
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) {
|
||||
qWarning() << "Cant open the home screen: " << m_deviceId << " " << m_appCode;
|
||||
m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode;
|
||||
qWarning() << m_error;
|
||||
if (!ApplicationDAO::updatePinCodeStatus(app.id, "no", "Не прошла проверка [дата]")) {
|
||||
qWarning() << "Cant update the pincode: " << m_deviceId << " " << m_appCode;
|
||||
}
|
||||
|
||||
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||
emit finished();
|
||||
emit finishedWithResult(m_error);
|
||||
return;
|
||||
} else {
|
||||
if (!ApplicationDAO::updatePinCodeStatus(app.id, "yes", "")) {
|
||||
@ -46,7 +49,8 @@ void LoginAndCheckAccountsScript::doStart() {
|
||||
account.deviceId = m_deviceId;
|
||||
account.appCode = m_appCode;
|
||||
if (!AccountDAO::upsertAccount(account)) {
|
||||
qDebug() << "Not updated: " << account.lastNumbers;
|
||||
m_error = "Not updated: " + account.lastNumbers;
|
||||
qCritical() << m_error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,5 +61,5 @@ void LoginAndCheckAccountsScript::doStart() {
|
||||
}
|
||||
|
||||
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||
emit finished();
|
||||
emit finishedWithResult(m_error);
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ public:
|
||||
|
||||
explicit LoginAndCheckAccountsScript(
|
||||
QString deviceId,
|
||||
QString aooCode,
|
||||
QString appCode,
|
||||
QObject *parent = nullptr
|
||||
);
|
||||
|
||||
@ -19,4 +19,5 @@ protected:
|
||||
private:
|
||||
const QString m_deviceId;
|
||||
const QString m_appCode;
|
||||
QString m_error;
|
||||
};
|
||||
@ -296,6 +296,7 @@ void PayByPhoneScript::doStart() {
|
||||
for (auto &[account, node]: accounts) {
|
||||
account.deviceId = m_account.deviceId;
|
||||
account.appCode = m_account.appCode;
|
||||
account.status = account.amount > 0 ? AccountStatus::Active : AccountStatus::Blocked;
|
||||
if (!AccountDAO::upsertAccount(account)) {
|
||||
qDebug() << "Not updated: " << account.lastNumbers;
|
||||
}
|
||||
|
||||
@ -48,7 +48,8 @@ Node ScreenXmlParser::tryToFindBannerOrDialog(const int width, const int height)
|
||||
return node;
|
||||
}
|
||||
// Если нашли пустую кнпоку
|
||||
if (node.className == "android.widget.Button" && node.clickable && node.text.isEmpty()) {
|
||||
if (node.className == "android.widget.Button" && node.clickable
|
||||
&& node.text.isEmpty() && node.contentDesc.isEmpty()) {
|
||||
// <node class="android.widget.Button" package="ru.rshb.dbo" clickable="true" bounds="[630,142][691,205]"/>
|
||||
if (node.x() > width / 2 && node.y() < width / 2) {
|
||||
return node;
|
||||
@ -82,6 +83,21 @@ Node ScreenXmlParser::tryToFindSecurityBanner() {
|
||||
return {};
|
||||
}
|
||||
|
||||
Node ScreenXmlParser::tryToFindSelectBottomSheet() {
|
||||
Node closeBtn;
|
||||
for (const Node &node: m_nodes) {
|
||||
if ((node.text.trimmed() == "Отмена" || node.text.trimmed() == "Отложить") && node.className ==
|
||||
"android.widget.Button") {
|
||||
closeBtn = node;
|
||||
}
|
||||
}
|
||||
// Не нужно проверять все, если хотя бы одна координата есть
|
||||
if (!closeBtn.isEmpty()) {
|
||||
return closeBtn;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Node ScreenXmlParser::findTextNode(const QString &text) {
|
||||
for (const Node &node: m_nodes) {
|
||||
if (node.className == "android.widget.TextView" && node.text.trimmed() == text) {
|
||||
@ -220,6 +236,10 @@ void ScreenXmlParser::parseAndSaveXml(const QString &xml) {
|
||||
node.text = reader.attributes().value("text").toString();
|
||||
}
|
||||
|
||||
if (reader.attributes().hasAttribute("content-desc")) {
|
||||
node.contentDesc = reader.attributes().value("content-desc").toString();
|
||||
}
|
||||
|
||||
if (reader.attributes().hasAttribute("class")) {
|
||||
node.className = reader.attributes().value("class").toString();
|
||||
}
|
||||
|
||||
@ -18,6 +18,8 @@ public:
|
||||
|
||||
Node tryToFindSecurityBanner();
|
||||
|
||||
Node tryToFindSelectBottomSheet();
|
||||
|
||||
Node findTextNode(const QString &text);
|
||||
|
||||
Node findTextNode(const QString &text, int x1, int y1, int x2, int y2);
|
||||
|
||||
@ -18,8 +18,10 @@ android_package_name=ar.com.santander.rio.mbanking
|
||||
|
||||
|
||||
[net]
|
||||
appInfoUpdate="http://localhost:9999/api/v1/app/update"
|
||||
appInfoUpdate=http://localhost:9999/api/v1/device/update
|
||||
accountUpdate=http://localhost:9999/api/v1/account/update
|
||||
paymentsGet=http://localhost:9999/api/v1/payments
|
||||
transactionUpdate=http://localhost:9999/api/v1/transaction/update
|
||||
transactionInsert=http://localhost:9999/api/v1/transaction/insert
|
||||
appStatusUpdate=http://localhost:9999/api/v1/application/update
|
||||
eventStatusUpdate=http://localhost:9999/api/v1/event/update
|
||||
Binary file not shown.
@ -21,7 +21,7 @@ public:
|
||||
const QString &comment
|
||||
);
|
||||
|
||||
[[nodiscard]] static ApplicationInfo getApplication(const QString &deviceId, const QString &appName);
|
||||
[[nodiscard]] static ApplicationInfo getApplication(const QString &deviceId, const QString &appCode);
|
||||
|
||||
[[nodiscard]] static QList<ApplicationInfo> getApplicationsByDeviceId(const QString &deviceId);
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ 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").toInt();
|
||||
event.accountId = query.value("account_id").toInt();
|
||||
event.deviceId = query.value("device_id").toString();
|
||||
@ -27,13 +28,14 @@ int EventDAO::insertEvent(const EventInfo &event) {
|
||||
|
||||
query.prepare(R"(
|
||||
INSERT INTO events (
|
||||
status, external_id, account_id, amount, phone, bank_name, timestamp, device_id
|
||||
status, external_id, account_id, amount, phone, bank_name, timestamp, device_id, type
|
||||
) VALUES (
|
||||
:status, :external_id, :account_id, :amount, :phone, :bank_name, :timestamp, :device_id
|
||||
:status, :external_id, :account_id, :amount, :phone, :bank_name, :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);
|
||||
@ -104,7 +106,7 @@ QList<EventInfo> EventDAO::getAllEvents(const EventStatus &status) {
|
||||
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
query.prepare(R"(
|
||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp
|
||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp, type
|
||||
FROM events
|
||||
WHERE status = :status
|
||||
)");
|
||||
@ -125,7 +127,7 @@ QList<EventInfo> EventDAO::getAllEvents(const EventStatus &status) {
|
||||
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, update_time, complete_time, timestamp
|
||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp, type
|
||||
FROM events
|
||||
WHERE status = :status AND device_id = :device_id
|
||||
ORDER BY timestamp ASC
|
||||
|
||||
2
main.cpp
2
main.cpp
@ -144,7 +144,7 @@ int main(int argc, char *argv[]) {
|
||||
// 79641815146 - Мама Альфа
|
||||
// 79199196105 - Папа рсхб
|
||||
|
||||
// startNetworkService(app);
|
||||
startNetworkService(app);
|
||||
startDeviceScreener(app);
|
||||
startEventHandler(app);
|
||||
|
||||
|
||||
@ -83,6 +83,7 @@ CREATE TABLE IF NOT EXISTS events
|
||||
comment TEXT,
|
||||
|
||||
status TEXT,
|
||||
type TEXT,
|
||||
|
||||
update_time DATETIME,
|
||||
complete_time DATETIME,
|
||||
|
||||
@ -36,6 +36,7 @@ public:
|
||||
}
|
||||
|
||||
QString text;
|
||||
QString contentDesc;
|
||||
QString resourceId;
|
||||
QString className;
|
||||
bool clickable = false;
|
||||
|
||||
@ -11,9 +11,17 @@ enum class EventStatus {
|
||||
Unknown
|
||||
};
|
||||
|
||||
enum class EventType {
|
||||
Phone,
|
||||
Card,
|
||||
Balance,
|
||||
History,
|
||||
Unknown
|
||||
};
|
||||
|
||||
inline QString eventStatusToString(const EventStatus type) {
|
||||
switch (type) {
|
||||
|
||||
inline QString eventStatusToString(const EventStatus status) {
|
||||
switch (status) {
|
||||
case EventStatus::Wait: return "wait";
|
||||
case EventStatus::Error: return "error";
|
||||
case EventStatus::Complete: return "complete";
|
||||
@ -30,6 +38,24 @@ inline EventStatus eventStatusFromString(const QString &str) {
|
||||
return EventStatus::Unknown;
|
||||
}
|
||||
|
||||
inline QString eventTypeToString(const EventType type) {
|
||||
switch (type) {
|
||||
case EventType::Phone: return "phone";
|
||||
case EventType::Card: return "card";
|
||||
case EventType::Balance: return "balance";
|
||||
case EventType::History: return "history";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
inline EventType eventTypeFromString(const QString &str) {
|
||||
if (str == "phone") return EventType::Phone;
|
||||
if (str == "card") return EventType::Card;
|
||||
if (str == "balance") return EventType::Balance;
|
||||
if (str == "history") return EventType::History;
|
||||
return EventType::Unknown;
|
||||
}
|
||||
|
||||
struct EventInfo {
|
||||
int id = -1;
|
||||
int externalId = -1;
|
||||
@ -42,6 +68,7 @@ struct EventInfo {
|
||||
QString comment;
|
||||
|
||||
EventStatus status = EventStatus::Unknown;
|
||||
EventType type = EventType::Unknown;
|
||||
|
||||
QDateTime updateTime;
|
||||
QDateTime completeTime;
|
||||
|
||||
@ -126,7 +126,7 @@ void DeviceScreener::start() {
|
||||
}
|
||||
|
||||
if (!deviceInfos.empty()) {
|
||||
// postDevicesData(deviceInfos); FIXME
|
||||
postDevicesData(deviceInfos);
|
||||
}
|
||||
|
||||
if (!DeviceDAO::markDevicesOfflineExcept(onlineIds)) {
|
||||
|
||||
@ -1,13 +1,19 @@
|
||||
#include "EventHandler.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QMap>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include "dao/AccountDAO.h"
|
||||
#include "dao/ApplicationDAO.h"
|
||||
#include "dao/DeviceDAO.h"
|
||||
#include "dao/EventDAO.h"
|
||||
#include "db/ApplicationInfo.h"
|
||||
#include "net/NetworkService.h"
|
||||
#include "rshb/CommonScript.h"
|
||||
#include "rshb/GetLastDaysHistoryScript.h"
|
||||
#include "rshb/LoginAndCheckAccountsScript.h"
|
||||
#include "rshb/PayByPhoneScript.h"
|
||||
|
||||
EventHandler::EventHandler(QObject *parent) : QObject(parent) {
|
||||
@ -44,51 +50,50 @@ void EventHandler::checkAndRestart() {
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::startThreadForKey(const QString &key) {
|
||||
const EventInfo event = EventDAO::getFirstWaitEventByDeviceId(key);
|
||||
if (event.id == -1) {
|
||||
return;
|
||||
}
|
||||
if (!EventDAO::updateEvent(event.id, EventStatus::InProgress, "")) {
|
||||
qCritical() << "Cant update event: " << event.id;
|
||||
return;
|
||||
void sendEventStatus(const QString &deviceId, const int externalId, const int eventId, const QString &status,
|
||||
const QString &error) {
|
||||
QJsonObject obj;
|
||||
obj["id"] = externalId;
|
||||
obj["externalId"] = eventId;
|
||||
obj["status"] = status;
|
||||
obj["error"] = error;
|
||||
|
||||
auto *paymentThread = new QThread;
|
||||
auto *networkService = new NetworkService;
|
||||
networkService->moveToThread(paymentThread);
|
||||
networkService->setDeviceId(deviceId);
|
||||
networkService->setPayload(QJsonDocument(obj).toJson());
|
||||
QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::postEventStatus);
|
||||
QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit);
|
||||
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||
QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater);
|
||||
paymentThread->start();
|
||||
}
|
||||
|
||||
qDebug() << "Thread for key" << key << "running";
|
||||
// FIXME пока это только оплата,
|
||||
const AccountInfo account = AccountDAO::getAccountById(event.accountId);
|
||||
const auto thr = new QThread(this);
|
||||
auto *worker = new PayByPhoneScript(account, event.phone, event.bankName, event.amount);
|
||||
|
||||
worker->moveToThread(thr);
|
||||
connect(thr, &QThread::started, worker, &PayByPhoneScript::start);
|
||||
connect(worker, &PayByPhoneScript::finished, thr, &QThread::quit);
|
||||
connect(worker, &PayByPhoneScript::finished, worker, &QObject::deleteLater);
|
||||
connect(thr, &QThread::finished, thr, &QObject::deleteLater);
|
||||
|
||||
const int eventId = event.id;
|
||||
// При нормальном завершении — перезапустить новый поток
|
||||
// connect(worker, &PayByPhoneScript::finished, this,
|
||||
// [this, key, eventId]() {
|
||||
// if (!EventDAO::updateEvent(eventId, EventStatus::Complete, "")) {
|
||||
// qCritical() << "Cant update event: " << eventId;
|
||||
// }
|
||||
// if (const auto tm = m_timers.take(key)) {
|
||||
// tm->stop();
|
||||
// tm->deleteLater();
|
||||
// }
|
||||
// m_threads.remove(key);
|
||||
// });
|
||||
|
||||
connect(worker, &PayByPhoneScript::finishedWithResult, this,
|
||||
[this, key, eventId](const QString &result) {
|
||||
void EventHandler::updateEventThread(const QString &key, const EventInfo &event, const QString &result) {
|
||||
if (!result.isEmpty()) {
|
||||
if (!EventDAO::updateEvent(eventId, EventStatus::Error, result)) {
|
||||
qCritical() << "Cant update event: " << eventId;
|
||||
if (!EventDAO::updateEvent(event.id, EventStatus::Error, result)) {
|
||||
qCritical() << "Cant update event: " << event.id;
|
||||
} else {
|
||||
sendEventStatus(
|
||||
event.deviceId,
|
||||
event.externalId,
|
||||
event.id,
|
||||
eventStatusToString(EventStatus::Error),
|
||||
result
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!EventDAO::updateEvent(eventId, EventStatus::Complete, "")) {
|
||||
qCritical() << "Cant update event: " << eventId;
|
||||
if (!EventDAO::updateEvent(event.id, EventStatus::Complete, "")) {
|
||||
qCritical() << "Cant update event: " << event.id;
|
||||
} else {
|
||||
sendEventStatus(
|
||||
event.deviceId,
|
||||
event.externalId,
|
||||
event.id,
|
||||
eventStatusToString(EventStatus::Complete),
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +102,58 @@ void EventHandler::startThreadForKey(const QString &key) {
|
||||
tm->deleteLater();
|
||||
}
|
||||
m_threads.remove(key);
|
||||
});
|
||||
}
|
||||
|
||||
void EventHandler::startThreadForKey(const QString &key) {
|
||||
const EventInfo event = EventDAO::getFirstWaitEventByDeviceId(key);
|
||||
if (event.id == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const AccountInfo account = AccountDAO::getAccountById(event.accountId);
|
||||
const ApplicationInfo app = ApplicationDAO::getApplication(event.deviceId, account.appCode);
|
||||
if (app.status != "active") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EventDAO::updateEvent(event.id, EventStatus::InProgress, "")) {
|
||||
qCritical() << "Cant update event: " << event.id;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto thr = new QThread(this);
|
||||
// qDebug() << "Start thread for key" << eventTypeToString(event.type);
|
||||
if (event.type == EventType::Balance) {
|
||||
auto *worker = new GetLastDaysHistoryScript(account);
|
||||
worker->moveToThread(thr);
|
||||
|
||||
connect(thr, &QThread::started, worker, &GetLastDaysHistoryScript::start);
|
||||
connect(worker, &GetLastDaysHistoryScript::finished, thr, &QThread::quit);
|
||||
connect(worker, &GetLastDaysHistoryScript::finished, worker, &QObject::deleteLater);
|
||||
connect(thr, &QThread::finished, thr, &QObject::deleteLater);
|
||||
|
||||
connect(worker, &GetLastDaysHistoryScript::finishedWithResult, this,
|
||||
[this, key, event](const QString &result) {
|
||||
updateEventThread(key, event, result);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (event.type == EventType::Phone) {
|
||||
auto *worker = new PayByPhoneScript(account, event.phone, event.bankName, event.amount);
|
||||
worker->moveToThread(thr);
|
||||
|
||||
connect(thr, &QThread::started, worker, &PayByPhoneScript::start);
|
||||
connect(worker, &PayByPhoneScript::finished, thr, &QThread::quit);
|
||||
connect(worker, &PayByPhoneScript::finished, worker, &QObject::deleteLater);
|
||||
connect(thr, &QThread::finished, thr, &QObject::deleteLater);
|
||||
|
||||
connect(worker, &PayByPhoneScript::finishedWithResult, this,
|
||||
[this, key, event](const QString &result) {
|
||||
updateEventThread(key, event, result);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Таймер на 5 минут — если не успел finish(), убить и перезапустить
|
||||
const auto timer = new QTimer(this);
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "db/EventInfo.h"
|
||||
|
||||
class EventHandler final : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@ -32,5 +34,7 @@ private:
|
||||
|
||||
void clearAll();
|
||||
|
||||
void updateEventThread(const QString &key, const EventInfo &event, const QString &result);
|
||||
|
||||
void startThreadForKey(const QString &key);
|
||||
};
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include <QTimeZone>
|
||||
|
||||
#include "dao/AccountDAO.h"
|
||||
#include "dao/ApplicationDAO.h"
|
||||
#include "dao/DeviceDAO.h"
|
||||
#include "dao/EventDAO.h"
|
||||
#include "dao/TransactionDAO.h"
|
||||
#include "db/EventInfo.h"
|
||||
@ -20,7 +22,9 @@ NetworkService::NetworkService(QObject *parent) : QObject(parent) {
|
||||
m_urlAccountUpdate = settings.value("net/accountUpdate").toString();
|
||||
m_urlPaymentsGet = settings.value("net/paymentsGet").toString();
|
||||
m_urlTransactionUpdate = settings.value("net/transactionUpdate").toString();
|
||||
m_urlAppStatusUpdate = settings.value("net/appStatusUpdate").toString();
|
||||
m_urlTransactionInsert = settings.value("net/transactionInsert").toString();
|
||||
m_urlEventStatusUpdate = settings.value("net/eventStatusUpdate").toString();
|
||||
m_manager = new QNetworkAccessManager(this);
|
||||
m_desktopId = "DT88bokcwQ";
|
||||
}
|
||||
@ -145,6 +149,7 @@ void NetworkService::getPayments() {
|
||||
QJsonObject obj = item.toObject();
|
||||
EventInfo eventInfo;
|
||||
eventInfo.status = EventStatus::Wait;
|
||||
eventInfo.type = eventTypeFromString(obj["type"].toString());
|
||||
eventInfo.externalId = obj["id"].toInt();
|
||||
eventInfo.timestamp = QDateTime::fromMSecsSinceEpoch(obj["timestamp"].toDouble(), QTimeZone::utc());
|
||||
eventInfo.amount = obj["amount"].toDouble();
|
||||
@ -169,6 +174,33 @@ void NetworkService::getPayments() {
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkService::postAppStatus() {
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
|
||||
addFormMetadata(multiPart, m_json);
|
||||
addFormField(multiPart, "desktopUniqueName", m_desktopId);
|
||||
addFormField(multiPart, "androidUniqueName", m_deviceId);
|
||||
|
||||
const bool isSuccess = post(multiPart, m_urlAppStatusUpdate).toBool();
|
||||
if (!isSuccess) {
|
||||
qCritical() << "Cant post data: postAppStatus";
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void NetworkService::postEventStatus() {
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
|
||||
addFormMetadata(multiPart, m_json);
|
||||
|
||||
const bool isSuccess = post(multiPart, m_urlEventStatusUpdate).toBool();
|
||||
if (!isSuccess) {
|
||||
qCritical() << "Cant post data: postEventStatus";
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void NetworkService::updateTransactionData() {
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
@ -205,6 +237,38 @@ void NetworkService::insertTransactionData() {
|
||||
}
|
||||
|
||||
void NetworkService::start() {
|
||||
QList<DeviceInfo> devices = DeviceDAO::getAllDevices(true);
|
||||
for (DeviceInfo &device: devices) {
|
||||
QList<ApplicationInfo> applications = ApplicationDAO::getApplicationsByDeviceId(device.id);
|
||||
for (ApplicationInfo &app: applications) {
|
||||
if (app.pinCodeChecked) {
|
||||
QList<AccountInfo> accounts = AccountDAO::getAccounts(device.id, app.code);
|
||||
QJsonArray list;
|
||||
|
||||
for (const AccountInfo &account: accounts) {
|
||||
QJsonObject obj;
|
||||
obj["appName"] = account.appCode;
|
||||
obj["lastNumbers"] = account.lastNumbers;
|
||||
obj["amount"] = account.amount;
|
||||
obj["description"] = account.description;
|
||||
obj["status"] = accountStatusToString(account.status);
|
||||
list.append(obj);
|
||||
}
|
||||
|
||||
auto *paymentThread = new QThread;
|
||||
auto *networkService = new NetworkService;
|
||||
networkService->setDeviceId(device.id);
|
||||
networkService->setPayload(QJsonDocument(list).toJson());
|
||||
networkService->moveToThread(paymentThread);
|
||||
QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::postAccountsData);
|
||||
QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit);
|
||||
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||
QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater);
|
||||
paymentThread->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QTimer *poller = new QTimer(this);
|
||||
poller->setInterval(1000);
|
||||
connect(poller, &QTimer::timeout, this, &NetworkService::getPayments);
|
||||
|
||||
@ -25,6 +25,10 @@ public slots:
|
||||
|
||||
void getPayments();
|
||||
|
||||
void postAppStatus();
|
||||
|
||||
void postEventStatus();
|
||||
|
||||
void insertTransactionData();
|
||||
|
||||
void updateTransactionData();
|
||||
@ -45,7 +49,9 @@ private:
|
||||
QString m_urlAccountUpdate;
|
||||
QString m_urlPaymentsGet;
|
||||
QString m_urlTransactionUpdate;
|
||||
QString m_urlAppStatusUpdate;
|
||||
QString m_urlTransactionInsert;
|
||||
QString m_urlEventStatusUpdate;
|
||||
|
||||
QNetworkAccessManager *m_manager;
|
||||
|
||||
|
||||
@ -11,12 +11,15 @@
|
||||
#include <QMessageBox>
|
||||
#include <QLabel>
|
||||
#include <QDialog>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "dao/ApplicationDAO.h"
|
||||
#include "db/ApplicationInfo.h"
|
||||
#include "common/PaddedItemDelegate.h"
|
||||
#include "device/EditBankDialog.h"
|
||||
#include "net/NetworkService.h"
|
||||
#include "rshb/LoginAndCheckAccountsScript.h"
|
||||
#include "widget/common/CollapsibleSection.h"
|
||||
|
||||
@ -54,6 +57,23 @@ void BankSettingsWindow::startCheckPinCode(const QString &appCode) {
|
||||
thread->start();
|
||||
}
|
||||
|
||||
void sendAppStatus(const QString &deviceId, const QString &code, const QString &status) {
|
||||
QJsonObject obj;
|
||||
obj["code"] = code;
|
||||
obj["status"] = status;
|
||||
|
||||
auto *paymentThread = new QThread;
|
||||
auto *networkService = new NetworkService;
|
||||
networkService->moveToThread(paymentThread);
|
||||
networkService->setDeviceId(deviceId);
|
||||
networkService->setPayload(QJsonDocument(obj).toJson());
|
||||
QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::postAppStatus);
|
||||
QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit);
|
||||
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||
QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater);
|
||||
paymentThread->start();
|
||||
}
|
||||
|
||||
void BankSettingsWindow::reloadContent(QTableWidget *tableWidget) {
|
||||
QList<ApplicationInfo> applications = ApplicationDAO::getApplicationsByDeviceId(m_deviceId);
|
||||
|
||||
@ -173,6 +193,7 @@ void BankSettingsWindow::reloadContent(QTableWidget *tableWidget) {
|
||||
if (!ApplicationDAO::update(app.id, app.pinCode, app.comment, "off")) {
|
||||
qDebug() << "Cant update bank data";
|
||||
} else {
|
||||
sendAppStatus(app.deviceId, app.code, "off");
|
||||
tableWidget->clearContents();
|
||||
reloadContent(tableWidget);
|
||||
tableWidget->resizeRowsToContents();
|
||||
@ -201,6 +222,7 @@ void BankSettingsWindow::reloadContent(QTableWidget *tableWidget) {
|
||||
if (!ApplicationDAO::update(app.id, pinCode, comment, on ? "active" : "off")) {
|
||||
qDebug() << "Cant update bank data";
|
||||
} else {
|
||||
sendAppStatus(app.deviceId, app.code, on ? "active" : "off");
|
||||
tableWidget->clearContents();
|
||||
reloadContent(tableWidget);
|
||||
tableWidget->resizeRowsToContents();
|
||||
|
||||
@ -8,10 +8,14 @@
|
||||
#include <QPointer>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QGraphicsScene>
|
||||
#include <QJsonObject>
|
||||
#include <QMessageBox>
|
||||
#include <QThread>
|
||||
|
||||
#include "bank/BankSettingsWindow.h"
|
||||
#include "dao/ApplicationDAO.h"
|
||||
#include "db/ApplicationInfo.h"
|
||||
#include "net/NetworkService.h"
|
||||
|
||||
|
||||
QString getColorByStatus(const ApplicationInfo &app) {
|
||||
@ -30,6 +34,23 @@ QString getColorByStatus(const ApplicationInfo &app) {
|
||||
}
|
||||
}
|
||||
|
||||
void sendBankStatus(const QString &deviceId, const QString &code, const QString &status) {
|
||||
QJsonObject obj;
|
||||
obj["code"] = code;
|
||||
obj["status"] = status;
|
||||
|
||||
auto *paymentThread = new QThread;
|
||||
auto *networkService = new NetworkService;
|
||||
networkService->moveToThread(paymentThread);
|
||||
networkService->setDeviceId(deviceId);
|
||||
networkService->setPayload(QJsonDocument(obj).toJson());
|
||||
QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::postAppStatus);
|
||||
QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit);
|
||||
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||
QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater);
|
||||
paymentThread->start();
|
||||
}
|
||||
|
||||
void DeviceWidget::buildBankRow(const ApplicationInfo &app, QWidget *rowWidget, QWidget *parent) {
|
||||
rowWidget->setContentsMargins(0, 0, 0, 0);
|
||||
rowWidget->setStyleSheet(
|
||||
@ -104,6 +125,7 @@ void DeviceWidget::buildBankRow(const ApplicationInfo &app, QWidget *rowWidget,
|
||||
if (!ApplicationDAO::update(app.id, app.pinCode, app.comment, newStatus)) {
|
||||
qDebug() << "Cant update bank data";
|
||||
} else {
|
||||
sendBankStatus(app.deviceId, app.code, newStatus);
|
||||
}
|
||||
} else {
|
||||
// просто закрыли — ничего не делаем
|
||||
|
||||
Loading…
Reference in New Issue
Block a user