diff --git a/android/adb/AdbUtils.cpp b/android/adb/AdbUtils.cpp index d60ac8e..3f05ddd 100644 --- a/android/adb/AdbUtils.cpp +++ b/android/adb/AdbUtils.cpp @@ -92,21 +92,30 @@ bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &pack // idx - временный лог // adb -s 6edc4a47 shell 'uiautomator dump /sdcard/uidump.xml' && adb -s 6edc4a47 pull /sdcard/uidump.xml step_1.xml && adb -s 6edc4a47 shell 'rm /sdcard/uidump.xml' -QString AdbUtils::getScreenDumpAsXml(const QString &deviceId, const int idx) { +QString AdbUtils::getScreenDumpAsXml(const QString &deviceId, const int idx, const bool screenshot) { // TODO убрать логирование в xml файл // "adb -s %1 pull /sdcard/uidump.xml step_%2.xml && " QProcess process; - QString xml = QString( - "adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && " + QString xml; + if (screenshot) { + xml = QString( + "adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && " + "adb -s %1 pull /sdcard/uidump.xml step_%2.xml && " + "adb -s %1 shell 'cat /sdcard/uidump.xml' && " + "adb -s %1 shell 'rm /sdcard/uidump.xml'" + ).arg(deviceId, QString::number(idx)); + } else { + xml = QString( + "adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && " + "adb -s %1 shell 'cat /sdcard/uidump.xml' && " + "adb -s %1 shell 'rm /sdcard/uidump.xml'" + ).arg(deviceId); + } - "adb -s %1 shell 'cat /sdcard/uidump.xml' && " - "adb -s %1 shell 'rm /sdcard/uidump.xml'" - // ).arg(deviceId, QString::number(idx)); - ).arg(deviceId); process.start("sh", {"-c", xml}); process.waitForFinished(); - if (false) { + if (screenshot) { // TODO делаем скрин, убрать потом // adb -s 6edc4a47 shell 'screencap -p /sdcard/screen.png' && adb -s 6edc4a47 pull /sdcard/screen.png screen_step_1.png && adb -s 6edc4a47 shell 'rm /sdcard/screen.png' QProcess processScreenshot; @@ -136,7 +145,7 @@ bool AdbUtils::takeScreenshot(const QString &deviceId, const QString &name) { QProcess process; QString screenshot = QString( "adb -s %1 shell 'screencap -p /sdcard/screen.png' && " - "adb -s %1 pull /sdcard/screen.png screen_%2.png && " + "adb -s %1 pull /sdcard/screen.png %2.png && " "adb -s %1 shell 'rm /sdcard/screen.png'" ).arg(deviceId, name); process.start("sh", {"-c", screenshot}); @@ -144,6 +153,19 @@ bool AdbUtils::takeScreenshot(const QString &deviceId, const QString &name) { return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; } +bool AdbUtils::takeXmlDump(const QString &deviceId, const QString &name) { + QProcess process; + QString xml = QString( + "adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && " + "adb -s %1 pull /sdcard/uidump.xml %2.xml && " + "adb -s %1 shell 'cat /sdcard/uidump.xml' && " + "adb -s %1 shell 'rm /sdcard/uidump.xml'" + ).arg(deviceId, name); + process.start("sh", {"-c", xml}); + process.waitForFinished(); + return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; +} + bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) { QProcess process; process.start("adb", { @@ -235,7 +257,7 @@ QSet AdbUtils::getListApps(const QString &deviceId) { QSet apps; const QStringList lines = output.split('\n'); - for (int i = 1; i < lines.size(); ++i) { + for (int i = 0; i < lines.size(); ++i) { QString line = lines.at(i).trimmed().replace("package:", ""); if (line.isEmpty()) { diff --git a/android/adb/AdbUtils.h b/android/adb/AdbUtils.h index dd93b73..d3dcd42 100644 --- a/android/adb/AdbUtils.h +++ b/android/adb/AdbUtils.h @@ -17,10 +17,12 @@ public: static bool tryToKillApplication(const QString &deviceId, const QString &packageName); - static QString getScreenDumpAsXml(const QString &deviceId, int idx); + static QString getScreenDumpAsXml(const QString &deviceId, int idx, bool screenshot = false); static bool takeScreenshot(const QString &deviceId, const QString &name); + static bool takeXmlDump(const QString &deviceId, const QString &name); + static bool makeTap(const QString &deviceId, int x, int y); static bool enableAdbIMEKeyboard(const QString &deviceId); diff --git a/android/rshb/CommonScript.cpp b/android/rshb/CommonScript.cpp index 8aae5a9..ecda021 100644 --- a/android/rshb/CommonScript.cpp +++ b/android/rshb/CommonScript.cpp @@ -39,7 +39,7 @@ bool CommonScript::inputPinCode(const QString &deviceId, const QList &pinc for (const Node &node: pincode) { const bool completePincode = AdbUtils::makeTap(deviceId, node.x(), node.y()); if (!completePincode) { - return false; + AdbUtils::makeTap(deviceId, node.x(), node.y()); } QThread::msleep(QRandomGenerator::global()->bounded(100, 901)); } @@ -68,27 +68,16 @@ bool CommonScript::runAppAndGoToHomeScreen( // Даем минимальное время на запуск QThread::msleep(4500); int counter = 0; - int restarted = 0; - int totalCounter = 0; bool findAndInputPincode = false; + while (true) { counter++; - totalCounter++; - // 3 раза уже перезапускали приложение, завершаем попытки - if (restarted > 2) { - AdbUtils::takeScreenshot(deviceId, "3_times_try_start"); + // Если более 10 раз мы пытаемся перейти на домашнюю + if (counter > 10) { + AdbUtils::takeScreenshot(deviceId, "too_many_attempts"); return false; } - - // Если более 30 секунд мы пытаемся перейти на домашнюю, перезапускаем - if (counter > 30) { - AdbUtils::tryToKillApplication(deviceId, packageName); - QThread::msleep(4500); - ++restarted; - counter = 0; - } - xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); if (xmlScreenParser.isHomeScreen()) { @@ -115,6 +104,10 @@ bool CommonScript::runAppAndGoToHomeScreen( if (!findAndInputPincode) { if (const QList pincode = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН"); pincode.size() == 4) { + // чтобы пробудить экран + if (Node textPinCodeNode = xmlScreenParser.findTextNode("Введите ПИН"); !textPinCodeNode.isEmpty()) { + AdbUtils::makeTap(deviceId, textPinCodeNode.x(), textPinCodeNode.y()); + } inputPinCode(deviceId, pincode); // После ввода пин-код нужно сделать задержку, пока подгрузка идет, чтобы снова не спарсить findAndInputPincode = true; @@ -124,12 +117,6 @@ bool CommonScript::runAppAndGoToHomeScreen( } QThread::msleep(1000); - - // Если что-то пойдет не по плану... - if (totalCounter > 100) { - AdbUtils::takeScreenshot(deviceId, "too_many_attempts"); - return false; - } } } @@ -161,7 +148,7 @@ bool CommonScript::goToAllProducts( // 1. Если нет кнопки видимой, свайпаем. Кликаем на "Все продукты" for (int i = 0; i < 5; ++i) { Node allProductsBtn = xmlScreenParser.findButtonNode("Все продукты", false); - if (allProductsBtn.x() > 0 && allProductsBtn.y() > 0) { + if (allProductsBtn.x() > 0 && allProductsBtn.y() > 0 && allProductsBtn.y() < height - 200) { AdbUtils::makeTap(deviceId, allProductsBtn.x(), allProductsBtn.y()); QThread::msleep(1000); break; @@ -221,7 +208,7 @@ void CommonScript::postAccountsData(const QList > &acco for (const QPair &pair: accounts) { QJsonObject obj; AccountInfo account = pair.first; - obj["appName"] = account.appName; + obj["appName"] = account.appCode; obj["lastNumbers"] = account.lastNumbers; obj["amount"] = account.amount; obj["description"] = account.description; @@ -229,7 +216,7 @@ void CommonScript::postAccountsData(const QList > &acco list.append(obj); } // FIXME доставить десктоп ид из настроеек - worker->setDeviceData("DT88bokcwQ", accounts.first().first.deviceId); + worker->setDeviceId(accounts.first().first.deviceId); worker->setPayload(QJsonDocument(list).toJson()); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &NetworkService::postAccountsData); @@ -258,7 +245,7 @@ void CommonScript::postNewTransactionData(const AccountInfo &account, const Tran obj["bankTransactionId"] = transaction.bankTrExternalId; // FIXME доставить десктоп ид из настроеек - worker->setDeviceData("DT88bokcwQ", account.deviceId); + worker->setDeviceId(account.deviceId); worker->addExtra("lastNumbers", account.lastNumbers); worker->addExtra("transactionId", transaction.id); worker->setPayload(QJsonDocument(obj).toJson()); @@ -287,7 +274,7 @@ void CommonScript::updateTransactionData( obj["updatedDescription"] = oldDesc; // FIXME доставить десктоп ид из настроеек - worker->setDeviceData("DT88bokcwQ", account.deviceId); + worker->setDeviceId(account.deviceId); worker->addExtra("lastNumbers", account.lastNumbers); worker->setPayload(QJsonDocument(obj).toJson()); worker->moveToThread(thread); diff --git a/android/rshb/GetLastDaysHistoryScript.cpp b/android/rshb/GetLastDaysHistoryScript.cpp index 7637e3f..12a42c4 100644 --- a/android/rshb/GetLastDaysHistoryScript.cpp +++ b/android/rshb/GetLastDaysHistoryScript.cpp @@ -32,17 +32,17 @@ QList findSavedTransaction( for (const TransactionInfo &info: transactions) { QDateTime timestamp = info.timestamp; - QString shortDescription = parsed.shortDescription; + QString description = parsed.description; // если тот же день if (dateTime.date() == timestamp.date() && parsed.amount == info.amount) { // Перевод Надежда Юрьевна К** в Альфа-Банк через СБП, по номеру телефона +79641815... - if (shortDescription.contains("Перевод")) { - if (shortDescription.contains(info.name)) { + if (description.contains("Перевод")) { + if (description.contains(info.name)) { txs.append(info); } } else { // Перевод по карте - if (shortDescription == info.shortDescription) { + if (description == info.description) { txs.append(info); } } @@ -56,7 +56,7 @@ int countSimilar(const TransactionInfo &transaction, const QList localTransactions = TransactionDAO::getTransactionsWithinHours(m_account.id, 48); const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId); @@ -191,7 +189,7 @@ void GetLastDaysHistoryScript::doStart() { QList > accounts = xmlScreenParser.parseAccountsInfo(); for (auto &[account, node]: accounts) { account.deviceId = m_account.deviceId; - account.appName = m_account.appName; + account.appCode = m_account.appCode; if (!AccountDAO::upsertAccount(account)) { qDebug() << "Not updated: " << account.lastNumbers; } diff --git a/android/rshb/HomeScreenScript.cpp b/android/rshb/HomeScreenScript.cpp index 7a01f94..ff000b3 100644 --- a/android/rshb/HomeScreenScript.cpp +++ b/android/rshb/HomeScreenScript.cpp @@ -185,7 +185,7 @@ void HomeScreenScript::start() { // .. пробуем кликать, но если не кликается ??? QList transactions = xmlScreenParser.parseTodayAndYesterdayHistory(); for (const TransactionInfo &info: transactions) { - QString text = QString("%1 %2").arg(info.shortDescription, getPriceAsString(info.amount)); + QString text = QString("%1 %2").arg(info.description, getPriceAsString(info.amount)); qDebug().noquote().nospace() << convertTransactionToString(info); // Node trButton = xmlScreenParser.findButtonNode(text, true); diff --git a/android/rshb/LoginAndCheckAccountsScript.cpp b/android/rshb/LoginAndCheckAccountsScript.cpp new file mode 100644 index 0000000..d9d9cac --- /dev/null +++ b/android/rshb/LoginAndCheckAccountsScript.cpp @@ -0,0 +1,61 @@ +#include "LoginAndCheckAccountsScript.h" + +#include "adb/AdbUtils.h" +#include "dao/AccountDAO.h" +#include "dao/ApplicationDAO.h" +#include "dao/DeviceDAO.h" + +LoginAndCheckAccountsScript::LoginAndCheckAccountsScript( + QString deviceId, + QString appCode, + QObject *parent +) : CommonScript(parent), + m_deviceId(std::move(deviceId)), m_appCode(std::move(appCode)) { +} + +LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default; + + +void LoginAndCheckAccountsScript::doStart() { + const DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId); + 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(); + 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; + if (!ApplicationDAO::updatePinCodeStatus(app.id, "no", "Не прошла проверка [дата]")) { + qWarning() << "Cant update the pincode: " << m_deviceId << " " << m_appCode; + } + + AdbUtils::tryToKillApplication(m_deviceId, app.package); + emit finished(); + return; + } else { + if (!ApplicationDAO::updatePinCodeStatus(app.id, "yes", "")) { + qWarning() << "Cant update the pincode: " << m_deviceId << " " << m_appCode; + } + if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) { + QList > accounts = xmlScreenParser.parseAccountsInfo(); + for (auto &[account, node]: accounts) { + account.deviceId = m_deviceId; + account.appCode = m_appCode; + if (!AccountDAO::upsertAccount(account)) { + qDebug() << "Not updated: " << account.lastNumbers; + } + } + + postAccountsData(accounts); + } else { + qWarning() << "Cant go to all products: " << m_deviceId << " " << m_appCode; + } + } + + AdbUtils::tryToKillApplication(m_deviceId, app.package); + emit finished(); +} diff --git a/android/rshb/LoginAndCheckAccountsScript.h b/android/rshb/LoginAndCheckAccountsScript.h new file mode 100644 index 0000000..283e811 --- /dev/null +++ b/android/rshb/LoginAndCheckAccountsScript.h @@ -0,0 +1,22 @@ +#pragma once +#include "CommonScript.h" + +class LoginAndCheckAccountsScript final : public CommonScript { + Q_OBJECT + +public: + ~LoginAndCheckAccountsScript() override; + + explicit LoginAndCheckAccountsScript( + QString deviceId, + QString aooCode, + QObject *parent = nullptr + ); + +protected: + void doStart() override; + +private: + const QString m_deviceId; + const QString m_appCode; +}; \ No newline at end of file diff --git a/android/rshb/PayByPhoneScript.cpp b/android/rshb/PayByPhoneScript.cpp index 63bb3b5..e1a209a 100644 --- a/android/rshb/PayByPhoneScript.cpp +++ b/android/rshb/PayByPhoneScript.cpp @@ -40,6 +40,7 @@ void PayByPhoneScript::makePayment( AdbUtils::makeTap(deviceId, payBtn.x(), payBtn.y()); QThread::msleep(1000); } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_pay_btn_not_found"); m_error = "Кнопка 'Оплатить' не нашлась"; qDebug() << m_error; return; @@ -54,11 +55,13 @@ void PayByPhoneScript::makePayment( AdbUtils::makeTap(deviceId, payByPhoneBtn.x(), payByPhoneBtn.y()); QThread::msleep(1000); } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_not_found_pay_by_phone"); m_error = "Не смогли найти пункт 'По номеру телефона В РСХБ и через'"; qDebug() << m_error; return; } } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_cant_go_to_payments"); m_error = "Не смогли перейти на экран 'Платежи и переводы'"; qDebug() << m_error; return; @@ -75,6 +78,7 @@ void PayByPhoneScript::makePayment( AdbUtils::inputText(deviceId, m_phone); QThread::msleep(1000); } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_cant_find_pay_by_phone"); m_error = "Не смогли найти пункт 'Перевод по телефону'"; qDebug() << m_error; return; @@ -87,6 +91,7 @@ void PayByPhoneScript::makePayment( AdbUtils::makeTap(deviceId, payOtherBankBtn.x(), payOtherBankBtn.y()); QThread::msleep(1000); } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_cant_tap_on_bank"); m_error = "Не смогли нажать на первичный выбор банка"; qDebug() << m_error; return; @@ -158,16 +163,19 @@ void PayByPhoneScript::makePayment( AdbUtils::makeTap(deviceId, continuePayBtn.x(), continuePayBtn.y()); QThread::msleep(1000); } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_cant_tap_on_ready"); m_error = "Не смогли нажать 'Готово'"; qDebug() << m_error; return; } } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_cant_tap_on_continue"); m_error = "Не смогли нажать 'Продолжить'"; qDebug() << m_error; return; } } else { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_cant_find_bank_title"); m_error = "Не смогли найти заголовок: " + payByPhoneScreenTitleText; qDebug() << m_error; return; @@ -200,6 +208,7 @@ void PayByPhoneScript::makePayment( } if (!isRshbBank && !inputedPinCode) { + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_cant_input_pin_code"); m_error = "Не смогли ввести пин-код!'"; qDebug() << m_error; return; @@ -245,6 +254,9 @@ void PayByPhoneScript::makePayment( } postNewTransactionData(m_account, transaction); + + AdbUtils::takeScreenshot(deviceId, "pay_by_phone_finish_transactions_" + transaction.id); + AdbUtils::takeXmlDump(deviceId, "pay_by_phone_finish_transactions_" + transaction.id); break; } else { qWarning() << "--- moreDetailBtn not found, i: " << i; @@ -260,7 +272,7 @@ void PayByPhoneScript::makePayment( void PayByPhoneScript::doStart() { const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId); - const ApplicationInfo app = ApplicationDAO::getApplication(m_account.deviceId, m_account.appName); + const ApplicationInfo app = ApplicationDAO::getApplication(m_account.deviceId, m_account.appCode); if (device.id.isEmpty() || app.id == -1) { m_error = "Device or app not found...."; @@ -272,7 +284,7 @@ void PayByPhoneScript::doStart() { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter)); if (!xmlScreenParser.isHomeScreen()) { if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) { - m_error = "Не смогли дойти до домашней страницы...."; + m_error = "Не смогли дойти до домашней страницы"; qDebug() << m_error; emit finishedWithResult(m_error); return; @@ -280,11 +292,10 @@ void PayByPhoneScript::doStart() { } if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) { - qDebug() << "======== 1. All products"; QList > accounts = xmlScreenParser.parseAccountsInfo(); for (auto &[account, node]: accounts) { account.deviceId = m_account.deviceId; - account.appName = m_account.appName; + account.appCode = m_account.appCode; if (!AccountDAO::upsertAccount(account)) { qDebug() << "Not updated: " << account.lastNumbers; } @@ -295,16 +306,27 @@ void PayByPhoneScript::doStart() { for (auto &[account, node]: accounts) { // FIXME будем считать что числа последние везде уникальные if (m_account.lastNumbers == account.lastNumbers) { - qDebug() << "======== 2. Tap by card"; - AdbUtils::makeTap(device.id, node.x(), node.y()); - QThread::msleep(1000); + if (account.amount >= m_amount) { + AdbUtils::makeTap(device.id, node.x(), node.y()); + QThread::msleep(1000); + } else { + AdbUtils::takeScreenshot(device.id, "pay_by_phone_not_enough_money_" + QString::number(m_account.id)); + m_error = "Not enough money, id: " + QString::number(m_account.id) + + ", amount: " + QString::number(account.amount) + + ", trx amount: " + QString::number(m_amount); + qCritical() << m_error; + emit finishedWithResult(m_error); + return; + } break; } } - qDebug() << "======== 3. Make payment"; makePayment(device.id, app.pinCode, device.screenWidth, device.screenHeight); + // AdbUtils::tryToKillApplication(device.id, app.package); TODO - надо ли это??? } else { + AdbUtils::takeScreenshot(device.id, "pay_by_phone_cant_open_all_products_" + QString::number(m_account.id)); + AdbUtils::tryToKillApplication(device.id, app.package); m_error = "Не смогли открыть 'Все продукты'"; qDebug() << m_error; } diff --git a/android/rshb/ScreenXmlParser.cpp b/android/rshb/ScreenXmlParser.cpp index 8e9cecc..0360c91 100644 --- a/android/rshb/ScreenXmlParser.cpp +++ b/android/rshb/ScreenXmlParser.cpp @@ -660,7 +660,7 @@ QList ScreenXmlParser::parseTodayAndYesterdayHistory() { TransactionInfo info; info.amount = amount; info.bankTime = date.toString("dd.MM.yyyy"); - info.shortDescription = shortDesc; + info.description = shortDesc; transactions.append(info); } diff --git a/database/app_data.db b/database/app_data.db index f0468ea..b314354 100644 Binary files a/database/app_data.db and b/database/app_data.db differ diff --git a/database/dao/AccountDAO.cpp b/database/dao/AccountDAO.cpp index c9fc019..39eed50 100644 --- a/database/dao/AccountDAO.cpp +++ b/database/dao/AccountDAO.cpp @@ -21,7 +21,7 @@ bool AccountDAO::upsertAccount(const AccountInfo &info) { )"); query.bindValue(":device_id", info.deviceId); - query.bindValue(":app_name", info.appName); + query.bindValue(":app_name", info.appCode); query.bindValue(":last_numbers", info.lastNumbers); query.bindValue(":amount", info.amount); query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime)); @@ -47,7 +47,7 @@ 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.appCode = query.value("app_name").toString(); acc.lastNumbers = query.value("last_numbers").toString(); acc.amount = query.value("amount").toDouble(); acc.updateTime = DateUtils::fromUtcString(query.value("update_time").toString()); diff --git a/database/dao/ApplicationDAO.cpp b/database/dao/ApplicationDAO.cpp index 2b0eb17..aca2415 100644 --- a/database/dao/ApplicationDAO.cpp +++ b/database/dao/ApplicationDAO.cpp @@ -78,7 +78,6 @@ bool ApplicationDAO::update( )"); query.bindValue(":id", appId); - query.bindValue(":pin_code", pinCode); query.bindValue(":comment", comment); query.bindValue(":pin_code", pinCode); query.bindValue(":status", status); @@ -90,6 +89,32 @@ bool ApplicationDAO::update( return true; } +bool ApplicationDAO::updatePinCodeStatus( + const int &appId, + const QString &pinCodeStatus, + const QString &comment +) { + QSqlQuery query(DatabaseManager::instance().database()); + + query.prepare(R"( + UPDATE applications + SET pin_code_checked = :pin_code_checked, comment = :comment, status = :status + WHERE id = :id + )"); + + query.bindValue(":id", appId); + query.bindValue(":comment", comment); + query.bindValue(":pin_code_checked", pinCodeStatus); + query.bindValue(":status", pinCodeStatus == "yes" ? "active" : "off"); + + if (!query.exec()) { + qWarning() << "Ошибка при обновлении PIN-кода приложения:" << query.lastError().text(); + return false; + } + return true; +} + + ApplicationInfo parseApplication(const QSqlQuery &query) { ApplicationInfo app; app.id = query.value("id").toInt(); diff --git a/database/dao/ApplicationDAO.h b/database/dao/ApplicationDAO.h index 873f92d..73076c6 100644 --- a/database/dao/ApplicationDAO.h +++ b/database/dao/ApplicationDAO.h @@ -8,8 +8,18 @@ public: [[nodiscard]] static bool updatePinCode(const QString &appId, const QString &pinCode); - [[nodiscard]] static bool update(const int &appId, const QString &pinCode, const QString &comment, - const QString &status); + [[nodiscard]] static bool update( + const int &appId, + const QString &pinCode, + const QString &comment, + const QString &status + ); + + [[nodiscard]] static bool updatePinCodeStatus( + const int &appId, + const QString &pinCodeStatus, + const QString &comment + ); [[nodiscard]] static ApplicationInfo getApplication(const QString &deviceId, const QString &appName); diff --git a/database/dao/EventDAO.cpp b/database/dao/EventDAO.cpp index 15645d4..dfd5bed 100644 --- a/database/dao/EventDAO.cpp +++ b/database/dao/EventDAO.cpp @@ -40,7 +40,7 @@ int EventDAO::insertEvent(const EventInfo &event) { query.bindValue(":amount", event.amount); query.bindValue(":phone", event.phone); query.bindValue(":bank_name", event.bankName); - query.bindValue(":timestamp", event.timestamp); + query.bindValue(":timestamp", DateUtils::toUtcString(event.timestamp)); if (!query.exec()) { qCritical() << "Ошибка при вставке event:" << query.lastError().text(); @@ -52,33 +52,46 @@ int EventDAO::insertEvent(const EventInfo &event) { bool EventDAO::updateEvent( const int id, - const EventStatus &status + const EventStatus &status, + const QString &comment ) { 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) { + 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())); - } else { - query.bindValue(":update_time", QVariant(QMetaType(QMetaType::QString))); } 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())); - } else { - query.bindValue(":complete_time", QVariant(QMetaType(QMetaType::QString))); } + 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; diff --git a/database/dao/EventDAO.h b/database/dao/EventDAO.h index 3572a5d..2465cb1 100644 --- a/database/dao/EventDAO.h +++ b/database/dao/EventDAO.h @@ -8,7 +8,8 @@ public: [[nodiscard]] static bool updateEvent( int id, - const EventStatus &status + const EventStatus &status, + const QString &comment ); [[nodiscard]] static QList getAllEvents(const EventStatus &status); diff --git a/database/dao/TransactionDAO.cpp b/database/dao/TransactionDAO.cpp index f449344..f3d325a 100644 --- a/database/dao/TransactionDAO.cpp +++ b/database/dao/TransactionDAO.cpp @@ -40,12 +40,12 @@ bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) { query.prepare(R"( INSERT INTO transactions ( account_id, amount, fee, status, phone, type, - description, updated_description, short_description, updated_short_description, + description, updated_description, bank_name, bank_time, name, bank_tr_external_id, update_time, complete_time, timestamp ) VALUES ( :account_id, :amount, :fee, :status, :phone, :type, - :description, :updated_description, :short_description, :updated_short_description, + :description, :updated_description, :bank_name, :bank_time, :name, :bank_tr_external_id, :update_time, :complete_time, :timestamp ) @@ -60,8 +60,6 @@ bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) { query.bindValue(":name", info.name); query.bindValue(":description", info.description); query.bindValue(":updated_description", info.updatedDescription); - query.bindValue(":short_description", info.shortDescription); - query.bindValue(":updated_short_description", info.updatedShortDescription); query.bindValue(":bank_name", info.bankName); query.bindValue(":bank_time", info.bankTime); query.bindValue(":bank_tr_external_id", info.bankTrExternalId); @@ -82,12 +80,12 @@ int TransactionDAO::insertTransaction(const TransactionInfo &info) { query.prepare(R"( INSERT INTO transactions ( account_id, amount, fee, status, phone, type, - description, updated_description, short_description, updated_short_description, + description, updated_description, bank_name, bank_time, name, bank_tr_external_id, update_time, complete_time ) VALUES ( :account_id, :amount, :fee, :status, :phone, :type, - :description, :updated_description, :short_description, :updated_short_description, + :description, :updated_description, :bank_name, :bank_time, :name, :bank_tr_external_id, :update_time, :complete_time ) @@ -102,8 +100,6 @@ int TransactionDAO::insertTransaction(const TransactionInfo &info) { query.bindValue(":name", info.name); query.bindValue(":description", info.description); query.bindValue(":updated_description", info.updatedDescription); - query.bindValue(":short_description", info.shortDescription); - query.bindValue(":updated_short_description", info.updatedShortDescription); query.bindValue(":bank_name", info.bankName); query.bindValue(":bank_time", info.bankTime); query.bindValue(":bank_tr_external_id", info.bankTrExternalId); @@ -138,8 +134,6 @@ TransactionInfo parseTransaction(const QSqlQuery &query) { tx.name = query.value("name").toString(); tx.description = query.value("description").toString(); tx.updatedDescription = query.value("updated_description").toString(); - tx.shortDescription = query.value("short_description").toString(); - tx.updatedShortDescription = query.value("updated_short_description").toString(); tx.bankName = query.value("bank_name").toString(); tx.bankTime = query.value("bank_time").toString(); tx.bankTrExternalId = query.value("bank_tr_external_id").toString(); @@ -188,8 +182,6 @@ bool TransactionDAO::updateTransaction(const TransactionInfo &info) { phone = :phone, description = :description, updated_description = :updated_description, - short_description = :short_description, - updated_short_description = :updated_short_description, bank_name = :bank_name, bank_time = :bank_time, name = :name, @@ -209,8 +201,6 @@ bool TransactionDAO::updateTransaction(const TransactionInfo &info) { query.bindValue(":name", info.name); query.bindValue(":description", info.description); query.bindValue(":updated_description", info.updatedDescription); - query.bindValue(":short_description", info.shortDescription); - query.bindValue(":updated_short_description", info.updatedShortDescription); query.bindValue(":bank_name", info.bankName); query.bindValue(":bank_time", info.bankTime); query.bindValue(":bank_tr_external_id", info.bankTrExternalId); diff --git a/main.cpp b/main.cpp index e1dba74..834a0cb 100644 --- a/main.cpp +++ b/main.cpp @@ -21,8 +21,8 @@ #include "rshb/HomeScreenScript.h" #include "rshb/PayByPhoneScript.h" -void startDeviceScreener(QCoreApplication &app) { - auto *thread = new QThread; +void startDeviceScreener(const QCoreApplication &app) { + auto *thread = new QThread(); auto *deviceScreenerWorker = new DeviceScreener; // Перемещаем worker в новый поток thread. @@ -51,94 +51,32 @@ void startDeviceScreener(QCoreApplication &app) { thread->start(); } -void setupWorkerAndThreadHistory(QCoreApplication &app) { - const QString appName = "rshb"; - const QString lastNumber = "7183"; - const QString deviceId = "6edc4a47"; - AccountInfo account = AccountDAO::findAppAccount(deviceId, appName, lastNumber); +void startEventHandler(const QCoreApplication &app) { auto *thread = new QThread; - auto *deviceScreenerWorker = new GetLastDaysHistoryScript(account); - - deviceScreenerWorker->moveToThread(thread); - QObject::connect(thread, &QThread::started, deviceScreenerWorker, &GetLastDaysHistoryScript::start); - QObject::connect(deviceScreenerWorker, &GetLastDaysHistoryScript::finished, thread, &QThread::quit); - QObject::connect(deviceScreenerWorker, &GetLastDaysHistoryScript::finished, deviceScreenerWorker, - &QObject::deleteLater); + auto *eventHandler = new EventHandler; + eventHandler->moveToThread(thread); + QObject::connect(thread, &QThread::started, eventHandler, &EventHandler::start); + QObject::connect(eventHandler, &EventHandler::finished, thread, &QThread::quit); + QObject::connect(eventHandler, &EventHandler::finished, eventHandler, &QObject::deleteLater); QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); QObject::connect(&app, &QCoreApplication::aboutToQuit, [=]() { - deviceScreenerWorker->stop(); + eventHandler->stop(); }); - thread->start(); } -void setupScriptAutoPaymentAndThread(QCoreApplication &app) { - const QString appName = "rshb"; - 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(deviceId, appName, lastNumber); - if (account.id != -1) { - // Функция для подключения потоков к завершению приложения - auto connectStopOnQuit = [&](QObject *worker, QThread *thread) { - QObject::connect(&app, &QCoreApplication::aboutToQuit, [=]() { - if (thread->isRunning()) { - qDebug() << "Завершаем поток:" << thread; - thread->quit(); - thread->wait(); // Ожидаем завершения потока - } - worker->deleteLater(); - thread->deleteLater(); - }); - }; - - // Первый поток - auto *thread = new QThread; - auto *scriptWorker = new PayByPhoneScript(account, phoneNumber, bankName, amount); - scriptWorker->moveToThread(thread); - - // Запуск первого потока - QObject::connect(thread, &QThread::started, scriptWorker, &PayByPhoneScript::start); - QObject::connect(scriptWorker, &PayByPhoneScript::finished, thread, &QThread::quit); - QObject::connect(scriptWorker, &PayByPhoneScript::finished, scriptWorker, &QObject::deleteLater); - QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); - - // Обработка результата первого потока - QObject::connect(scriptWorker, &PayByPhoneScript::finishedWithResult, &app, - [account, connectStopOnQuit](const QString &result) { - qDebug() << "Получен результат: [" << result << "]"; - - // Создаем второй поток после завершения первого - auto *thread2 = new QThread; - auto *scriptWorker2 = new GetLastDaysHistoryScript(account); - scriptWorker2->moveToThread(thread2); - - // Запуск второго потока - QObject::connect(thread2, &QThread::started, scriptWorker2, - &GetLastDaysHistoryScript::start); - QObject::connect(scriptWorker2, &GetLastDaysHistoryScript::finished, thread2, - &QThread::quit); - QObject::connect(scriptWorker2, &GetLastDaysHistoryScript::finished, scriptWorker2, - &QObject::deleteLater); - QObject::connect(thread2, &QThread::finished, thread2, &QThread::deleteLater); - - // Остановка второго потока при завершении приложения - connectStopOnQuit(scriptWorker2, thread2); - - thread2->start(); - }); - - // Остановка первого потока при завершении приложения - connectStopOnQuit(scriptWorker, thread); - - // Запуск первого потока - thread->start(); - } +void startNetworkService(const QCoreApplication &app) { + auto *paymentThread = new QThread; + auto *networkService = new NetworkService; + networkService->moveToThread(paymentThread); + QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::start); + QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit); + QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater); + QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater); + QObject::connect(&app, &QCoreApplication::aboutToQuit, [=]() { + networkService->stop(); + }); + paymentThread->start(); } static QFile logFile; @@ -191,7 +129,7 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); // Выбрать стиль Fusion - app.setStyle(QStyleFactory::create("Fusion")); + QApplication::setStyle(QStyleFactory::create("Fusion")); logFile.setFileName("application.log"); if (!logFile.open(QIODevice::Append | QIODevice::Text)) { @@ -199,29 +137,16 @@ int main(int argc, char *argv[]) { } // Устанавливаем свой обработчик qInstallMessageHandler(messageHandler); - // - // auto *thread = new QThread; - // auto *worker = new EventHandler; - // worker->moveToThread(thread); - // QObject::connect(thread, &QThread::started, worker, &EventHandler::start); - // QObject::connect(worker, &EventHandler::finished, thread, &QThread::quit); - // QObject::connect(worker, &EventHandler::finished, worker, &QObject::deleteLater); - // QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); - // thread->start(); - // - // auto *paymentThread = new QThread; - // auto *networkService = new NetworkService; - // - // // FIXME доставить десктоп ид из настроеек - // networkService->setDeviceData("DT88bokcwQ", ""); - // networkService->moveToThread(paymentThread); - // QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::start); - // 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(); - // + + + // 7927296033 - Амир + // 79829976987 - Егор + // 79641815146 - Мама Альфа + // 79199196105 - Папа рсхб + + // startNetworkService(app); startDeviceScreener(app); + startEventHandler(app); MainWindow window; window.show(); diff --git a/migrations.sql b/migrations.sql index d8cc374..7d98723 100644 --- a/migrations.sql +++ b/migrations.sql @@ -80,6 +80,7 @@ CREATE TABLE IF NOT EXISTS events amount REAL, phone TEXT, bank_name TEXT, + comment TEXT, status TEXT, diff --git a/models/db/AccountInfo.h b/models/db/AccountInfo.h index 817bc16..eaf08fc 100644 --- a/models/db/AccountInfo.h +++ b/models/db/AccountInfo.h @@ -24,7 +24,7 @@ inline AccountStatus accountStatusFromString(const QString &str) { struct AccountInfo { int id = -1; QString deviceId; // code - QString appName; + QString appCode; QString lastNumbers; double amount = 0.0; QDateTime updateTime; @@ -40,7 +40,7 @@ inline QString convertAccountToString(const AccountInfo &info) { if (info.id != -1) lines << " id: " + QString::number(info.id); else emptyFields << "id"; if (!info.deviceId.isEmpty()) lines << " deviceId: " + info.deviceId; else emptyFields << "deviceId"; - if (!info.appName.isEmpty()) lines << " appName: " + info.appName; else emptyFields << "appName"; + if (!info.appCode.isEmpty()) lines << " appCode: " + info.appCode; else emptyFields << "appCode"; if (!info.lastNumbers.isEmpty()) lines << " lastNumbers: " + info.lastNumbers; else emptyFields << "lastNumbers"; if (info.amount != 0.0) lines << " amount: " + QString::number(info.amount, 'f', 2); else emptyFields << "amount"; if (info.updateTime.isValid()) lines << " updateTime: " + info.updateTime.toString(Qt::ISODate); else emptyFields << "updateTime"; diff --git a/models/db/EventInfo.h b/models/db/EventInfo.h index 95ce7d9..e202c90 100644 --- a/models/db/EventInfo.h +++ b/models/db/EventInfo.h @@ -7,6 +7,7 @@ enum class EventStatus { Wait, InProgress, Complete, + Error, Unknown }; @@ -14,6 +15,7 @@ enum class EventStatus { inline QString eventStatusToString(const EventStatus type) { switch (type) { case EventStatus::Wait: return "wait"; + case EventStatus::Error: return "error"; case EventStatus::Complete: return "complete"; case EventStatus::InProgress: return "iPprogress"; default: return "unknown"; @@ -21,6 +23,7 @@ inline QString eventStatusToString(const EventStatus type) { } inline EventStatus eventStatusFromString(const QString &str) { + if (str == "error") return EventStatus::Error; if (str == "wait") return EventStatus::Wait; if (str == "complete") return EventStatus::Complete; if (str == "iPprogress") return EventStatus::InProgress; @@ -36,6 +39,7 @@ struct EventInfo { double amount = 0; QString phone; QString bankName; + QString comment; EventStatus status = EventStatus::Unknown; diff --git a/models/db/TransactionInfo.h b/models/db/TransactionInfo.h index d4cce91..ad41ce4 100644 --- a/models/db/TransactionInfo.h +++ b/models/db/TransactionInfo.h @@ -55,8 +55,6 @@ struct TransactionInfo { QString phone; QString name; - QString shortDescription; - QString updatedShortDescription; QString description; QString updatedDescription; @@ -83,8 +81,6 @@ inline QString convertTransactionToString(const TransactionInfo &tx) { if (tx.status != TransactionStatus::Unknown) lines << " status: " + transactionStatusToString(tx.status); else emptyFields << "status"; if (tx.type != TransactionType::Unknown) lines << " type: " + transactionTypeToString(tx.type); else emptyFields << "type"; if (!tx.phone.isEmpty()) lines << " phone: " + tx.phone; else emptyFields << "phone"; - if (!tx.shortDescription.isEmpty()) lines << " shortDescription: " + tx.shortDescription; else emptyFields << "shortDescription"; - if (!tx.updatedShortDescription.isEmpty()) lines << " updatedShortDescription: " + tx.updatedShortDescription; else emptyFields << "updatedShortDescription"; if (!tx.description.isEmpty()) lines << " description: " + tx.description; else emptyFields << "description"; if (!tx.updatedDescription.isEmpty()) lines << " updatedDescription: " + tx.updatedDescription; else emptyFields << "updatedDescription"; if (!tx.bankName.isEmpty()) lines << " bankName: " + tx.bankName; else emptyFields << "bankName"; diff --git a/services/DeviceScreener.cpp b/services/DeviceScreener.cpp index 1b12848..7647727 100644 --- a/services/DeviceScreener.cpp +++ b/services/DeviceScreener.cpp @@ -126,7 +126,7 @@ void DeviceScreener::start() { } if (!deviceInfos.empty()) { - postDevicesData(deviceInfos); + // postDevicesData(deviceInfos); FIXME } if (!DeviceDAO::markDevicesOfflineExcept(onlineIds)) { diff --git a/services/EventHandler.cpp b/services/EventHandler.cpp index 5c709b7..31e7b7b 100644 --- a/services/EventHandler.cpp +++ b/services/EventHandler.cpp @@ -49,7 +49,7 @@ void EventHandler::startThreadForKey(const QString &key) { if (event.id == -1) { return; } - if (!EventDAO::updateEvent(event.id, EventStatus::InProgress)) { + if (!EventDAO::updateEvent(event.id, EventStatus::InProgress, "")) { qCritical() << "Cant update event: " << event.id; return; } @@ -66,10 +66,32 @@ void EventHandler::startThreadForKey(const QString &key) { 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]() { - // qDebug() << "Thread finished for key" << key << "- restarting."; + // 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) { + if (!result.isEmpty()) { + if (!EventDAO::updateEvent(eventId, EventStatus::Error, result)) { + qCritical() << "Cant update event: " << eventId; + } + } else { + if (!EventDAO::updateEvent(eventId, EventStatus::Complete, "")) { + qCritical() << "Cant update event: " << eventId; + } + } + if (const auto tm = m_timers.take(key)) { tm->stop(); tm->deleteLater(); diff --git a/services/net/NetworkService.cpp b/services/net/NetworkService.cpp index 9c18397..5e7382b 100644 --- a/services/net/NetworkService.cpp +++ b/services/net/NetworkService.cpp @@ -22,6 +22,7 @@ NetworkService::NetworkService(QObject *parent) : QObject(parent) { m_urlTransactionUpdate = settings.value("net/transactionUpdate").toString(); m_urlTransactionInsert = settings.value("net/transactionInsert").toString(); m_manager = new QNetworkAccessManager(this); + m_desktopId = "DT88bokcwQ"; } NetworkService::~NetworkService() = default; diff --git a/services/net/NetworkService.h b/services/net/NetworkService.h index 717c3d6..cd89196 100644 --- a/services/net/NetworkService.h +++ b/services/net/NetworkService.h @@ -14,8 +14,7 @@ public: void setPayload(const QByteArray &json) { m_json = json; } - void setDeviceData(const QString &desktopId, const QString &deviceId) { - m_desktopId = desktopId; + void setDeviceId(const QString &deviceId) { m_deviceId = deviceId; } diff --git a/views/bank/BankSettingsWindow.cpp b/views/bank/BankSettingsWindow.cpp index f2f2e49..dc6e6d1 100644 --- a/views/bank/BankSettingsWindow.cpp +++ b/views/bank/BankSettingsWindow.cpp @@ -11,11 +11,13 @@ #include #include #include +#include #include "dao/ApplicationDAO.h" #include "db/ApplicationInfo.h" #include "common/PaddedItemDelegate.h" #include "device/EditBankDialog.h" +#include "rshb/LoginAndCheckAccountsScript.h" #include "widget/common/CollapsibleSection.h" QTableWidgetItem *BankSettingsWindow::createTableWidget(const QString &text) { @@ -30,7 +32,7 @@ QString parseStatus(const ApplicationInfo &app) { } if (app.status == "active") { if (!app.pinCodeChecked) { - return app.pinCode.isEmpty() ? "нет пин-код" : "ин-код не проверен"; + return app.pinCode.isEmpty() ? "нет пин-код" : "пин-код не проверен"; } return "работает"; } else if (app.status == "off") { @@ -40,6 +42,18 @@ QString parseStatus(const ApplicationInfo &app) { } } +void BankSettingsWindow::startCheckPinCode(const QString &appCode) { + const auto thread = new QThread(nullptr); + auto *worker = new LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr); + + worker->moveToThread(thread); + connect(thread, &QThread::started, worker, &LoginAndCheckAccountsScript::start); + connect(worker, &LoginAndCheckAccountsScript::finished, thread, &QThread::quit); + connect(worker, &LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater); + connect(thread, &QThread::finished, thread, &QObject::deleteLater); + thread->start(); +} + void BankSettingsWindow::reloadContent(QTableWidget *tableWidget) { QList applications = ApplicationDAO::getApplicationsByDeviceId(m_deviceId); @@ -121,20 +135,21 @@ void BankSettingsWindow::reloadContent(QTableWidget *tableWidget) { pinCodeBtn->setProperty("btnClass", "pincode"); tableWidget->setCellWidget(k, 5, pinCodeBtn); - connect(pinCodeBtn, &QPushButton::clicked, this, [this,tableWidget, app]() { - QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Проверка пин-код")); - msgBox.setText("Сейчас запустится скрипт проверки пин-код в приложении: " + app.name); + connect(pinCodeBtn, &QPushButton::clicked, this, [this, app]() { + QMessageBox msgBox(this); + msgBox.setWindowTitle(tr("Проверка пин-код")); + msgBox.setText("Сейчас запустится скрипт проверки пин-код в приложении: " + app.name); - QPushButton *deleteBtn = msgBox.addButton(tr("Запустить"), QMessageBox::AcceptRole); - QPushButton *closeBtn = msgBox.addButton(tr("Отмена"), QMessageBox::RejectRole); - msgBox.setDefaultButton(closeBtn); - msgBox.setModal(true); - msgBox.exec(); + QPushButton *deleteBtn = msgBox.addButton(tr("Запустить"), QMessageBox::AcceptRole); + QPushButton *closeBtn = msgBox.addButton(tr("Отмена"), QMessageBox::RejectRole); + msgBox.setDefaultButton(closeBtn); + msgBox.setModal(true); + msgBox.exec(); - if (msgBox.clickedButton() == deleteBtn) { - } - }); + if (msgBox.clickedButton() == deleteBtn) { + startCheckPinCode(app.code); + } + }); } else { if (app.status == "active" && !app.pinCode.isEmpty()) { auto *deleteBtn = new QPushButton(" Отключить ", tableWidget); diff --git a/views/bank/BankSettingsWindow.h b/views/bank/BankSettingsWindow.h index 42cfe0f..98ed616 100644 --- a/views/bank/BankSettingsWindow.h +++ b/views/bank/BankSettingsWindow.h @@ -14,5 +14,7 @@ private: QTableWidgetItem *createTableWidget(const QString &text); + void startCheckPinCode(const QString &appCode); + void reloadContent(QTableWidget *tableWidget); }; diff --git a/views/device/DeviceWidget.cpp b/views/device/DeviceWidget.cpp index ec2ea67..12429ff 100644 --- a/views/device/DeviceWidget.cpp +++ b/views/device/DeviceWidget.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "bank/BankSettingsWindow.h" #include "dao/ApplicationDAO.h" #include "db/ApplicationInfo.h" @@ -64,21 +65,52 @@ void DeviceWidget::buildBankRow(const ApplicationInfo &app, QWidget *rowWidget, const QString color = getColorByStatus(app); circle->setStyleSheet( "margin: 0px;" - "background-color: " +color + "; " + "background-color: " + color + "; " "border-radius: 6px;" ); + // собираем + if (app.install && app.pinCodeChecked && (app.status == "active" || app.status == "off")) { + auto *btn1 = new QPushButton(parent); + bool turnOn = app.pinCodeChecked && app.status == "active"; + QIcon btnIcon( + QCoreApplication::applicationDirPath() + (turnOn ? "/images/turn_off.png" : "/images/turn_on.png")); + btn1->setIcon(btnIcon); + btn1->setIconSize(QSize(16, 16)); + btn1->setFlat(true); + btn1->setStyleSheet( + "margin: 0px;" + "background-color: transparent;" + "border: none;" + ); - // auto *btn1 = new QPushButton(parent); - // bool turnOn = app.pinCodeChecked && app.status == "active"; - // QIcon btnIcon(QCoreApplication::applicationDirPath() + (turnOn ? "/images/turn_off.png" : "/images/turn_on.png")); - // btn1->setIcon(btnIcon); - // btn1->setIconSize(QSize(16, 16)); - // btn1->setFlat(true); - // btn1->setStyleSheet( - // "margin: 0px;" - // "background-color: transparent;" - // "border: none;" - // ); + connect(btn1, &QPushButton::clicked, this, [app]() { + QString newStatus = app.status == "active" ? "off" : "active"; + QMessageBox msgBox(nullptr); + msgBox.setWindowTitle(tr("Подтверждение")); + msgBox.setText( + "Вы уверены, что хотите " + + QString(newStatus == "off" ? "отключить от работы" : "включить") + + " данный банк: " + + app.name + "?"); + + QPushButton *deleteBtn = msgBox.addButton(tr(newStatus == "off" ? "Отключить" : "Включить"), + QMessageBox::AcceptRole); + QPushButton *closeBtn = msgBox.addButton(tr("Отмена"), QMessageBox::RejectRole); + msgBox.setDefaultButton(closeBtn); + msgBox.setModal(true); + msgBox.exec(); + + if (msgBox.clickedButton() == deleteBtn) { + if (!ApplicationDAO::update(app.id, app.pinCode, app.comment, newStatus)) { + qDebug() << "Cant update bank data"; + } else { + } + } else { + // просто закрыли — ничего не делаем + } + }); + hbox->addWidget(btn1); + } auto *btn2 = new QPushButton(parent); QIcon btn2Icon(QCoreApplication::applicationDirPath() + "/images/cogwheel.png"); @@ -108,11 +140,9 @@ void DeviceWidget::buildBankRow(const ApplicationInfo &app, QWidget *rowWidget, setOpenBanksSettings(btn2); - // собираем hbox->addWidget(icon); - hbox->addWidget(label,1); + hbox->addWidget(label, 1); hbox->addWidget(circle); - // hbox->addWidget(btn1); hbox->addWidget(btn2); // hbox->addStretch();