From 8d0eae8ec0320d1ecbea503c3f6dd31261cb234e Mon Sep 17 00:00:00 2001 From: slava Date: Tue, 31 Mar 2026 14:07:23 +0700 Subject: [PATCH] - Remove `app_logs` table and related logic, transitioning to `general_logs`. - Add `pinCheckOnly` parameter in scripts to support conditional account checks. - Prevent activation of bank profiles without active cards in `AccountSettingsWindow` and `DeviceWidget`. - Adjust logging flow in `AppLogger` for unified data handling. --- android/black/LoginAndCheckAccountsScript.cpp | 15 +++++-- android/black/LoginAndCheckAccountsScript.h | 4 +- android/ozon/LoginAndCheckAccountsScript.cpp | 15 +++++-- android/ozon/LoginAndCheckAccountsScript.h | 4 +- database/DatabaseManager.cpp | 20 ++------- services/AppLogger.cpp | 14 +++--- views/bank/AccountSettingsWindow.cpp | 43 ++++++++++++++++++- views/device/DeviceWidget.cpp | 14 ++++++ 8 files changed, 91 insertions(+), 38 deletions(-) diff --git a/android/black/LoginAndCheckAccountsScript.cpp b/android/black/LoginAndCheckAccountsScript.cpp index dd79508..51135bf 100644 --- a/android/black/LoginAndCheckAccountsScript.cpp +++ b/android/black/LoginAndCheckAccountsScript.cpp @@ -13,10 +13,12 @@ namespace Black { LoginAndCheckAccountsScript::LoginAndCheckAccountsScript( QString deviceId, QString appCode, - QObject *parent + QObject *parent, + bool pinCheckOnly ) : CommonScript(parent), m_deviceId(std::move(deviceId)), - m_appCode(std::move(appCode)) { + m_appCode(std::move(appCode)), + m_pinCheckOnly(pinCheckOnly) { } LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default; @@ -39,8 +41,7 @@ void LoginAndCheckAccountsScript::doStart() { m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode; qWarning() << m_error; AppLogger::log("black/LoginAndCheck", m_deviceId, m_error, - AdbUtils::captureScreenshotBytes(m_deviceId), - "FETCH_PROFILE"); + AdbUtils::captureScreenshotBytes(m_deviceId), "FETCH_PROFILE"); BankProfileDAO::updateComment(app.id, "Не прошла проверка " + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss")); @@ -49,6 +50,12 @@ void LoginAndCheckAccountsScript::doStart() { return; } + if (m_pinCheckOnly) { + AdbUtils::tryToKillApplication(m_deviceId, app.package); + emit finishedWithResult(m_error); + return; + } + // Проверяем профиль и аккаунты (приложение уже на home screen) GetProfileInfoScript profileScript(m_deviceId, m_appCode); profileScript.start(); diff --git a/android/black/LoginAndCheckAccountsScript.h b/android/black/LoginAndCheckAccountsScript.h index 6bb0dae..43c327d 100644 --- a/android/black/LoginAndCheckAccountsScript.h +++ b/android/black/LoginAndCheckAccountsScript.h @@ -12,7 +12,8 @@ public: explicit LoginAndCheckAccountsScript( QString deviceId, QString appCode, - QObject *parent = nullptr + QObject *parent = nullptr, + bool pinCheckOnly = false ); protected: @@ -21,6 +22,7 @@ protected: private: QString m_deviceId; const QString m_appCode; + const bool m_pinCheckOnly; QString m_error; }; diff --git a/android/ozon/LoginAndCheckAccountsScript.cpp b/android/ozon/LoginAndCheckAccountsScript.cpp index 45733f6..c7ce4c7 100644 --- a/android/ozon/LoginAndCheckAccountsScript.cpp +++ b/android/ozon/LoginAndCheckAccountsScript.cpp @@ -15,11 +15,13 @@ LoginAndCheckAccountsScript::LoginAndCheckAccountsScript( QString deviceId, QString appCode, QObject *parent, - bool fetchProfileOnly + bool fetchProfileOnly, + bool pinCheckOnly ) : CommonScript(parent), m_deviceId(std::move(deviceId)), m_appCode(std::move(appCode)), - m_fetchProfileOnly(fetchProfileOnly) { + m_fetchProfileOnly(fetchProfileOnly), + m_pinCheckOnly(pinCheckOnly) { } LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default; @@ -43,8 +45,7 @@ void LoginAndCheckAccountsScript::doStart() { m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode; qWarning() << m_error; AppLogger::log("ozon/LoginAndCheck", m_deviceId, m_error, - AdbUtils::captureScreenshotBytes(m_deviceId), - "FETCH_PROFILE"); + AdbUtils::captureScreenshotBytes(m_deviceId), "FETCH_PROFILE"); BankProfileDAO::updateComment(app.id, "Не прошла проверка " + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss")); @@ -52,6 +53,12 @@ void LoginAndCheckAccountsScript::doStart() { emit finishedWithResult(m_error); return; } else { + if (m_pinCheckOnly) { + AdbUtils::tryToKillApplication(m_deviceId, app.package); + emit finishedWithResult(m_error); + return; + } + // Создаём bank profile если ещё не создан createBankProfileIfNeeded(device.id, m_appCode); diff --git a/android/ozon/LoginAndCheckAccountsScript.h b/android/ozon/LoginAndCheckAccountsScript.h index f3a537d..08368cb 100644 --- a/android/ozon/LoginAndCheckAccountsScript.h +++ b/android/ozon/LoginAndCheckAccountsScript.h @@ -13,7 +13,8 @@ public: QString deviceId, QString appCode, QObject *parent = nullptr, - bool fetchProfileOnly = false + bool fetchProfileOnly = false, + bool pinCheckOnly = false ); protected: @@ -23,6 +24,7 @@ private: QString m_deviceId; const QString m_appCode; const bool m_fetchProfileOnly; + const bool m_pinCheckOnly; QString m_error; }; diff --git a/database/DatabaseManager.cpp b/database/DatabaseManager.cpp index 5fa7ec7..6278179 100644 --- a/database/DatabaseManager.cpp +++ b/database/DatabaseManager.cpp @@ -191,16 +191,9 @@ void DatabaseManager::initSchema() { nspk_name TEXT ))"); - q.exec(R"(CREATE TABLE IF NOT EXISTS app_logs ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - source TEXT NOT NULL DEFAULT '', - device_id TEXT NOT NULL DEFAULT '', - message TEXT NOT NULL, - screenshot BLOB, - timestamp TEXT NOT NULL - ))"); - - q.exec("CREATE INDEX IF NOT EXISTS idx_app_logs_ts ON app_logs (id DESC)"); + // Таблица app_logs больше не используется — логи пишутся в general_logs + // Удаляем если существует (миграция) + q.exec("DROP TABLE IF EXISTS app_logs"); q.exec(R"(CREATE TABLE IF NOT EXISTS general_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -239,13 +232,6 @@ void DatabaseManager::cleanupOldData(int days) { qDebug() << "[cleanup] general_logs: deleted" << q.numRowsAffected() << "rows older than" << days << "days"; } - // app_logs - q.prepare("DELETE FROM app_logs WHERE timestamp < :cutoff"); - q.bindValue(":cutoff", cutoff); - if (q.exec()) { - qDebug() << "[cleanup] app_logs: deleted" << q.numRowsAffected() << "rows older than" << days << "days"; - } - // events (завершённые/ошибочные) q.prepare("DELETE FROM events WHERE timestamp < :cutoff AND status IN ('complete', 'error')"); q.bindValue(":cutoff", cutoff); diff --git a/services/AppLogger.cpp b/services/AppLogger.cpp index 286aa2f..d148f40 100644 --- a/services/AppLogger.cpp +++ b/services/AppLogger.cpp @@ -3,8 +3,7 @@ #include #include -#include "dao/AppLogDAO.h" -#include "db/AppLogEntry.h" +#include "dao/GeneralLogDAO.h" #include "net/NetworkService.h" NetworkService *AppLogger::s_networkService = nullptr; @@ -16,13 +15,10 @@ void AppLogger::setNetworkService(NetworkService *service) { void AppLogger::log(const QString &source, const QString &deviceId, const QString &message, const QByteArray &screenshot, const QString &event) { - AppLogEntry entry; - entry.source = source; - entry.deviceId = deviceId; - entry.message = message; - entry.screenshot = screenshot; - entry.timestamp = QDateTime::currentDateTimeUtc(); - AppLogDAO::insert(entry); + const QString fullMessage = deviceId.isEmpty() + ? message + : QString("[%1] %2").arg(deviceId, message); + GeneralLogDAO::insert("WARNING", source, fullMessage, screenshot); if (s_networkService) { QMetaObject::invokeMethod(s_networkService, "postMonitoringLog", diff --git a/views/bank/AccountSettingsWindow.cpp b/views/bank/AccountSettingsWindow.cpp index 23054c0..5ddbecf 100644 --- a/views/bank/AccountSettingsWindow.cpp +++ b/views/bank/AccountSettingsWindow.cpp @@ -90,6 +90,20 @@ AccountSettingsWindow::AccountSettingsWindow( const QString comment = dlg.secondValue(); bool on = dlg.toggled(); + // Если включаем профиль — проверяем что есть хотя бы одна активная карта + if (on) { + const QList materials = MaterialDAO::getAccounts(m_deviceId, m_applicationInfo.code); + bool hasActive = false; + for (const auto &m : materials) { + if (m.status == MaterialStatus::Active) { hasActive = true; break; } + } + if (!hasActive) { + QMessageBox::warning(this, "Невозможно включить", + "Ни одна карта не активна.\nВключите хотя бы одну карту перед включением профиля."); + return; + } + } + if (!BankProfileDAO::update(m_applicationInfo.id, pinCode, comment, on ? "active" : "off")) { qDebug() << "Cant update bank data"; } else { @@ -358,8 +372,10 @@ void AccountSettingsWindow::startCheckPinCode(const QString &appCode) { } }; + const bool pinCheckOnly = !m_applicationInfo.bankProfileId.isEmpty(); + if (appCode == "ozon") { - auto *worker = new Ozon::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr); + auto *worker = new Ozon::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr, false, pinCheckOnly); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &Ozon::LoginAndCheckAccountsScript::start); connect(worker, &Ozon::LoginAndCheckAccountsScript::finishedWithResult, worker, onResult); @@ -367,7 +383,7 @@ void AccountSettingsWindow::startCheckPinCode(const QString &appCode) { connect(worker, &Ozon::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater); } else if (appCode == "black") { - auto *worker = new Black::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr); + auto *worker = new Black::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr, pinCheckOnly); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &Black::LoginAndCheckAccountsScript::start); connect(worker, &Black::LoginAndCheckAccountsScript::finishedWithResult, worker, onResult); @@ -518,6 +534,29 @@ void AccountSettingsWindow::toggleMaterialStatus(const MaterialInfo &account, QT thread->start(); } + // Если выключили материал — проверяем остались ли активные + if (isActive) { + const QList materials = MaterialDAO::getAccounts(m_deviceId, m_applicationInfo.code); + bool hasActive = false; + for (const auto &m : materials) { + if (m.status == MaterialStatus::Active) { hasActive = true; break; } + } + if (!hasActive && m_applicationInfo.status == "active") { + BankProfileDAO::update(m_applicationInfo.id, m_applicationInfo.pinCode, m_applicationInfo.comment, "off"); + m_applicationInfo.status = "off"; + sendAppStatus(m_deviceId, m_applicationInfo.code, "off"); + + const QString status = QString("Статус: Неактивен") + + QString(", пин-код: ") + (m_applicationInfo.pinCodeChecked + ? "Проверен" + : "Не проверен"); + m_statusLabel->setText(status); + + QMessageBox::information(this, "Профиль выключен", + "Все карты выключены — банковский профиль автоматически деактивирован."); + } + } + reloadContent(tableWidget); tableWidget->resizeColumnsToContents(); } diff --git a/views/device/DeviceWidget.cpp b/views/device/DeviceWidget.cpp index 66e03cc..664e805 100644 --- a/views/device/DeviceWidget.cpp +++ b/views/device/DeviceWidget.cpp @@ -16,6 +16,7 @@ #include "bank/BankSettingsWindow.h" #include "DeviceSettingsWindow.h" #include "dao/BankProfileDAO.h" +#include "dao/MaterialDAO.h" #include "dao/DeviceDAO.h" #include "dao/EventDAO.h" #include "db/BankProfileInfo.h" @@ -172,6 +173,19 @@ void DeviceWidget::buildBankRow(const BankProfileInfo &app, QWidget *rowWidget, msgBox.exec(); if (msgBox.clickedButton() == confirmBtn) { + // При включении — проверяем что есть хотя бы одна активная карта + if (newStatus == "active") { + const QList materials = MaterialDAO::getAccounts(app.deviceId, app.code); + bool hasActive = false; + for (const auto &m : materials) { + if (m.status == MaterialStatus::Active) { hasActive = true; break; } + } + if (!hasActive) { + QMessageBox::warning(nullptr, "Невозможно включить", + "Ни одна карта не активна.\nВключите хотя бы одну карту перед включением профиля."); + return; + } + } if (!BankProfileDAO::update(app.id, app.pinCode, app.comment, newStatus)) { qDebug() << "Cant update bank data"; } else {