#include "GetLastTransactionsScript.h" #include #include #include "adb/AdbUtils.h" #include "dao/AccountDAO.h" #include "dao/ApplicationDAO.h" #include "dao/DeviceDAO.h" #include "dao/TransactionDAO.h" #include "AppLogger.h" namespace Black { GetLastTransactionsScript::GetLastTransactionsScript( QString deviceId, QString appCode, QObject *parent ) : CommonScript(parent), m_deviceId(std::move(deviceId)), m_appCode(std::move(appCode)) { } GetLastTransactionsScript::~GetLastTransactionsScript() = default; void GetLastTransactionsScript::doStart() { const DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId); const ApplicationInfo app = ApplicationDAO::getApplication(m_deviceId, m_appCode); if (device.id.isEmpty() || app.id == -1) { 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 (!xmlScreenParser.isHomeScreen()) { qDebug() << "[Black::GetLastTransactions] Not on home screen, restarting app..."; if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) { m_error = "Cannot reach home screen: " + m_deviceId; qWarning() << m_error; AppLogger::log("black/GetLastTransactions", m_deviceId, m_error, AdbUtils::captureScreenshotBytes(m_deviceId), "FETCH_TRANSACTIONS"); AdbUtils::tryToKillApplication(m_deviceId, app.package); emit finishedWithResult(m_error); return; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); } // Тапаем "Ver más" рядом с "Tu actividad" для перехода на экран транзакций Node verMasBtn = xmlScreenParser.findVerMasAfterTuActividad(); if (verMasBtn.isEmpty()) { // Попробуем проскроллить вниз чтобы увидеть "Tu actividad" + "Ver más" for (int i = 0; i < 5; ++i) { const int x = device.screenWidth / 2; const int offset = device.screenHeight / 4; AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - offset, x, offset); QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); verMasBtn = xmlScreenParser.findVerMasAfterTuActividad(); if (!verMasBtn.isEmpty()) break; } } if (verMasBtn.isEmpty()) { m_error = "Button 'Ver más' not found: " + m_deviceId; qWarning() << m_error; emit finishedWithResult(m_error); return; } qDebug() << "[Black::GetLastTransactions] Tapping 'Ver más' at" << verMasBtn.x() << verMasBtn.y(); AdbUtils::makeTap(m_deviceId, verMasBtn.x(), verMasBtn.y()); QThread::msleep(2000); // Ждём загрузки экрана транзакций // Сперва появляется экран загрузки (Tu Actividad без транзакций), // затем подгружаются транзакции bool loaded = false; for (int attempt = 0; attempt < 15; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); if (xmlScreenParser.isTransactionListScreen()) { loaded = true; break; } if (xmlScreenParser.isTransactionLoadingScreen()) { qDebug() << "[Black::GetLastTransactions] Loading screen detected, waiting for transactions, attempt" << attempt + 1 << "/ 15"; } else { qDebug() << "[Black::GetLastTransactions] Waiting for transaction screen, attempt" << attempt + 1 << "/ 15"; } QThread::msleep(1500); } if (!loaded) { // Проверяем: если экран загрузки есть, но транзакций нет — это нормально (пустой аккаунт) if (xmlScreenParser.isTransactionLoadingScreen()) { qDebug() << "[Black::GetLastTransactions] No transactions found (empty account)"; AdbUtils::goBack(m_deviceId); QThread::msleep(1000); emit finishedWithResult(m_error); return; } m_error = "Transaction list screen not loaded: " + m_deviceId; qWarning() << m_error; emit finishedWithResult(m_error); return; } // Находим accountId для сохранения транзакций int accountId = -1; const QList accounts = AccountDAO::getAccounts(m_deviceId, m_appCode); if (!accounts.isEmpty()) { accountId = accounts.first().id; qDebug() << "[Black::GetLastTransactions] Using accountId:" << accountId; } else { qWarning() << "[Black::GetLastTransactions] No account found for" << m_deviceId << m_appCode; } // Берём все транзакции что видны на экране const QTimeZone argTz("America/Argentina/Buenos_Aires"); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); QList pageItems = xmlScreenParser.parseTransactionItems(); qDebug() << "[Black::GetLastTransactions] Found" << pageItems.size() << "transactions on screen"; for (const TransactionInfo &tx : pageItems) { TransactionInfo saveTx = tx; saveTx.bankName = "black"; saveTx.status = TransactionStatus::Complete; saveTx.timestamp = QDateTime::currentDateTimeUtc(); // Парсим дату из bankTime: "21 de febrero de 2026 - 09:39" QDateTime parsed = xmlScreenParser.parseSpanishDate(saveTx.bankTime); if (parsed.isValid()) { parsed.setTimeZone(argTz); saveTx.completeTime = parsed; } qDebug() << "[Black::GetLastTransactions]" << "date:" << saveTx.bankTime << "desc:" << saveTx.description << "name:" << saveTx.name << "amount:" << (saveTx.amount >= 0 ? "+" : "") + QString::number(saveTx.amount, 'f', 2); // Сохраняем в БД if (accountId != -1) { saveTx.accountId = accountId; if (TransactionDAO::insertTransactionIfNotExists(saveTx)) { qDebug() << "[Black::GetLastTransactions] Saved transaction to DB"; } } } qDebug() << "[Black::GetLastTransactions] Total transactions:" << pageItems.size(); // Возвращаемся на домашний экран AdbUtils::goBack(m_deviceId); QThread::msleep(1000); emit finishedWithResult(m_error); } } // namespace Black