1
0
forked from BRT/arc

- 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.
This commit is contained in:
slava 2026-03-31 14:07:23 +07:00
parent a6509b5653
commit 8d0eae8ec0
8 changed files with 91 additions and 38 deletions

View File

@ -13,10 +13,12 @@ namespace Black {
LoginAndCheckAccountsScript::LoginAndCheckAccountsScript( LoginAndCheckAccountsScript::LoginAndCheckAccountsScript(
QString deviceId, QString deviceId,
QString appCode, QString appCode,
QObject *parent QObject *parent,
bool pinCheckOnly
) : CommonScript(parent), ) : CommonScript(parent),
m_deviceId(std::move(deviceId)), m_deviceId(std::move(deviceId)),
m_appCode(std::move(appCode)) { m_appCode(std::move(appCode)),
m_pinCheckOnly(pinCheckOnly) {
} }
LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default; LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default;
@ -39,8 +41,7 @@ void LoginAndCheckAccountsScript::doStart() {
m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode; m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode;
qWarning() << m_error; qWarning() << m_error;
AppLogger::log("black/LoginAndCheck", m_deviceId, m_error, AppLogger::log("black/LoginAndCheck", m_deviceId, m_error,
AdbUtils::captureScreenshotBytes(m_deviceId), AdbUtils::captureScreenshotBytes(m_deviceId), "FETCH_PROFILE");
"FETCH_PROFILE");
BankProfileDAO::updateComment(app.id, BankProfileDAO::updateComment(app.id,
"Не прошла проверка " + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss")); "Не прошла проверка " + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss"));
@ -49,6 +50,12 @@ void LoginAndCheckAccountsScript::doStart() {
return; return;
} }
if (m_pinCheckOnly) {
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
return;
}
// Проверяем профиль и аккаунты (приложение уже на home screen) // Проверяем профиль и аккаунты (приложение уже на home screen)
GetProfileInfoScript profileScript(m_deviceId, m_appCode); GetProfileInfoScript profileScript(m_deviceId, m_appCode);
profileScript.start(); profileScript.start();

View File

@ -12,7 +12,8 @@ public:
explicit LoginAndCheckAccountsScript( explicit LoginAndCheckAccountsScript(
QString deviceId, QString deviceId,
QString appCode, QString appCode,
QObject *parent = nullptr QObject *parent = nullptr,
bool pinCheckOnly = false
); );
protected: protected:
@ -21,6 +22,7 @@ protected:
private: private:
QString m_deviceId; QString m_deviceId;
const QString m_appCode; const QString m_appCode;
const bool m_pinCheckOnly;
QString m_error; QString m_error;
}; };

View File

@ -15,11 +15,13 @@ LoginAndCheckAccountsScript::LoginAndCheckAccountsScript(
QString deviceId, QString deviceId,
QString appCode, QString appCode,
QObject *parent, QObject *parent,
bool fetchProfileOnly bool fetchProfileOnly,
bool pinCheckOnly
) : CommonScript(parent), ) : CommonScript(parent),
m_deviceId(std::move(deviceId)), m_deviceId(std::move(deviceId)),
m_appCode(std::move(appCode)), m_appCode(std::move(appCode)),
m_fetchProfileOnly(fetchProfileOnly) { m_fetchProfileOnly(fetchProfileOnly),
m_pinCheckOnly(pinCheckOnly) {
} }
LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default; LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default;
@ -43,8 +45,7 @@ void LoginAndCheckAccountsScript::doStart() {
m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode; m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode;
qWarning() << m_error; qWarning() << m_error;
AppLogger::log("ozon/LoginAndCheck", m_deviceId, m_error, AppLogger::log("ozon/LoginAndCheck", m_deviceId, m_error,
AdbUtils::captureScreenshotBytes(m_deviceId), AdbUtils::captureScreenshotBytes(m_deviceId), "FETCH_PROFILE");
"FETCH_PROFILE");
BankProfileDAO::updateComment(app.id, BankProfileDAO::updateComment(app.id,
"Не прошла проверка " + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss")); "Не прошла проверка " + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss"));
@ -52,6 +53,12 @@ void LoginAndCheckAccountsScript::doStart() {
emit finishedWithResult(m_error); emit finishedWithResult(m_error);
return; return;
} else { } else {
if (m_pinCheckOnly) {
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
return;
}
// Создаём bank profile если ещё не создан // Создаём bank profile если ещё не создан
createBankProfileIfNeeded(device.id, m_appCode); createBankProfileIfNeeded(device.id, m_appCode);

View File

@ -13,7 +13,8 @@ public:
QString deviceId, QString deviceId,
QString appCode, QString appCode,
QObject *parent = nullptr, QObject *parent = nullptr,
bool fetchProfileOnly = false bool fetchProfileOnly = false,
bool pinCheckOnly = false
); );
protected: protected:
@ -23,6 +24,7 @@ private:
QString m_deviceId; QString m_deviceId;
const QString m_appCode; const QString m_appCode;
const bool m_fetchProfileOnly; const bool m_fetchProfileOnly;
const bool m_pinCheckOnly;
QString m_error; QString m_error;
}; };

View File

@ -191,16 +191,9 @@ void DatabaseManager::initSchema() {
nspk_name TEXT nspk_name TEXT
))"); ))");
q.exec(R"(CREATE TABLE IF NOT EXISTS app_logs ( // Таблица app_logs больше не используется — логи пишутся в general_logs
id INTEGER PRIMARY KEY AUTOINCREMENT, // Удаляем если существует (миграция)
source TEXT NOT NULL DEFAULT '', q.exec("DROP TABLE IF EXISTS app_logs");
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)");
q.exec(R"(CREATE TABLE IF NOT EXISTS general_logs ( q.exec(R"(CREATE TABLE IF NOT EXISTS general_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT, 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"; 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 (завершённые/ошибочные) // events (завершённые/ошибочные)
q.prepare("DELETE FROM events WHERE timestamp < :cutoff AND status IN ('complete', 'error')"); q.prepare("DELETE FROM events WHERE timestamp < :cutoff AND status IN ('complete', 'error')");
q.bindValue(":cutoff", cutoff); q.bindValue(":cutoff", cutoff);

View File

@ -3,8 +3,7 @@
#include <QDateTime> #include <QDateTime>
#include <QMetaObject> #include <QMetaObject>
#include "dao/AppLogDAO.h" #include "dao/GeneralLogDAO.h"
#include "db/AppLogEntry.h"
#include "net/NetworkService.h" #include "net/NetworkService.h"
NetworkService *AppLogger::s_networkService = nullptr; NetworkService *AppLogger::s_networkService = nullptr;
@ -16,13 +15,10 @@ void AppLogger::setNetworkService(NetworkService *service) {
void AppLogger::log(const QString &source, const QString &deviceId, void AppLogger::log(const QString &source, const QString &deviceId,
const QString &message, const QByteArray &screenshot, const QString &message, const QByteArray &screenshot,
const QString &event) { const QString &event) {
AppLogEntry entry; const QString fullMessage = deviceId.isEmpty()
entry.source = source; ? message
entry.deviceId = deviceId; : QString("[%1] %2").arg(deviceId, message);
entry.message = message; GeneralLogDAO::insert("WARNING", source, fullMessage, screenshot);
entry.screenshot = screenshot;
entry.timestamp = QDateTime::currentDateTimeUtc();
AppLogDAO::insert(entry);
if (s_networkService) { if (s_networkService) {
QMetaObject::invokeMethod(s_networkService, "postMonitoringLog", QMetaObject::invokeMethod(s_networkService, "postMonitoringLog",

View File

@ -90,6 +90,20 @@ AccountSettingsWindow::AccountSettingsWindow(
const QString comment = dlg.secondValue(); const QString comment = dlg.secondValue();
bool on = dlg.toggled(); bool on = dlg.toggled();
// Если включаем профиль — проверяем что есть хотя бы одна активная карта
if (on) {
const QList<MaterialInfo> 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")) { if (!BankProfileDAO::update(m_applicationInfo.id, pinCode, comment, on ? "active" : "off")) {
qDebug() << "Cant update bank data"; qDebug() << "Cant update bank data";
} else { } else {
@ -358,8 +372,10 @@ void AccountSettingsWindow::startCheckPinCode(const QString &appCode) {
} }
}; };
const bool pinCheckOnly = !m_applicationInfo.bankProfileId.isEmpty();
if (appCode == "ozon") { 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); worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Ozon::LoginAndCheckAccountsScript::start); connect(thread, &QThread::started, worker, &Ozon::LoginAndCheckAccountsScript::start);
connect(worker, &Ozon::LoginAndCheckAccountsScript::finishedWithResult, worker, onResult); 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(worker, &Ozon::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater);
connect(thread, &QThread::finished, thread, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater);
} else if (appCode == "black") { } 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); worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Black::LoginAndCheckAccountsScript::start); connect(thread, &QThread::started, worker, &Black::LoginAndCheckAccountsScript::start);
connect(worker, &Black::LoginAndCheckAccountsScript::finishedWithResult, worker, onResult); connect(worker, &Black::LoginAndCheckAccountsScript::finishedWithResult, worker, onResult);
@ -518,6 +534,29 @@ void AccountSettingsWindow::toggleMaterialStatus(const MaterialInfo &account, QT
thread->start(); thread->start();
} }
// Если выключили материал — проверяем остались ли активные
if (isActive) {
const QList<MaterialInfo> 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("Статус: <span style='color:red;'>Неактивен</span>") +
QString(", пин-код: ") + (m_applicationInfo.pinCodeChecked
? "<span style='color:green;'>Проверен</span>"
: "<span style='color:red;'>Не проверен</span>");
m_statusLabel->setText(status);
QMessageBox::information(this, "Профиль выключен",
"Все карты выключены — банковский профиль автоматически деактивирован.");
}
}
reloadContent(tableWidget); reloadContent(tableWidget);
tableWidget->resizeColumnsToContents(); tableWidget->resizeColumnsToContents();
} }

View File

@ -16,6 +16,7 @@
#include "bank/BankSettingsWindow.h" #include "bank/BankSettingsWindow.h"
#include "DeviceSettingsWindow.h" #include "DeviceSettingsWindow.h"
#include "dao/BankProfileDAO.h" #include "dao/BankProfileDAO.h"
#include "dao/MaterialDAO.h"
#include "dao/DeviceDAO.h" #include "dao/DeviceDAO.h"
#include "dao/EventDAO.h" #include "dao/EventDAO.h"
#include "db/BankProfileInfo.h" #include "db/BankProfileInfo.h"
@ -172,6 +173,19 @@ void DeviceWidget::buildBankRow(const BankProfileInfo &app, QWidget *rowWidget,
msgBox.exec(); msgBox.exec();
if (msgBox.clickedButton() == confirmBtn) { if (msgBox.clickedButton() == confirmBtn) {
// При включении — проверяем что есть хотя бы одна активная карта
if (newStatus == "active") {
const QList<MaterialInfo> 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)) { if (!BankProfileDAO::update(app.id, app.pinCode, app.comment, newStatus)) {
qDebug() << "Cant update bank data"; qDebug() << "Cant update bank data";
} else { } else {