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(
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();

View File

@ -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;
};

View File

@ -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);

View File

@ -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;
};

View File

@ -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);

View File

@ -3,8 +3,7 @@
#include <QDateTime>
#include <QMetaObject>
#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",

View File

@ -90,6 +90,20 @@ AccountSettingsWindow::AccountSettingsWindow(
const QString comment = dlg.secondValue();
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")) {
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<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);
tableWidget->resizeColumnsToContents();
}

View File

@ -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<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)) {
qDebug() << "Cant update bank data";
} else {