diff --git a/android/ozon/GetLastTransactionsScript.cpp b/android/ozon/GetLastTransactionsScript.cpp index 5192288..3095a8a 100644 --- a/android/ozon/GetLastTransactionsScript.cpp +++ b/android/ozon/GetLastTransactionsScript.cpp @@ -222,6 +222,42 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int << "date(local)=" << searchDate.toString("dd.MM.yyyy"); // ── Шаг 1: скроллим до нужной даты ────────────────────────────── + static const QMap monthMap = { + {"января", 1}, {"февраля", 2}, {"марта", 3}, {"апреля", 4}, + {"мая", 5}, {"июня", 6}, {"июля", 7}, {"августа", 8}, + {"сентября", 9}, {"октября", 10}, {"ноября", 11}, {"декабря", 12} + }; + static const QRegularExpression dateRx(R"((\d{1,2})\s+(\S+),\s+\S+)"); + + auto parseDateHeader = [&](const QString &t) -> QDate { + const QDate today = QDateTime::currentDateTimeUtc().toTimeZone(deviceTz).date(); + if (t.compare("Сегодня", Qt::CaseInsensitive) == 0) return today; + if (t.compare("Вчера", Qt::CaseInsensitive) == 0) return today.addDays(-1); + const auto match = dateRx.match(t); + if (!match.hasMatch()) return {}; + const int day = match.captured(1).toInt(); + const int month = monthMap.value(match.captured(2), 0); + if (month == 0) return {}; + return QDate(searchDate.year(), month, day); + }; + + auto hasDateOnScreen = [&]() -> bool { + for (const Node &node : xmlScreenParser.getNodes()) { + if (node.className != "android.widget.TextView") continue; + if (parseDateHeader(node.text.trimmed()) == searchDate) return true; + } + return false; + }; + + auto hasOlderDateOnScreen = [&]() -> bool { + for (const Node &node : xmlScreenParser.getNodes()) { + if (node.className != "android.widget.TextView") continue; + const QDate d = parseDateHeader(node.text.trimmed()); + if (d.isValid() && d < searchDate) return true; + } + return false; + }; + bool dateFound = false; for (int scroll = 0; scroll < maxScrolls; ++scroll) { if (QThread::currentThread()->isInterruptionRequested()) { @@ -229,57 +265,15 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int return; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); - - // Ищем заголовки дат на экране (формат: "4 января, вс") - static const QMap monthMap = { - {"января", 1}, {"февраля", 2}, {"марта", 3}, {"апреля", 4}, - {"мая", 5}, {"июня", 6}, {"июля", 7}, {"августа", 8}, - {"сентября", 9}, {"октября", 10}, {"ноября", 11}, {"декабря", 12} - }; - - const QDate today = QDateTime::currentDateTimeUtc().toTimeZone(deviceTz).date(); - bool hasOlderDate = false; - for (const Node &node : xmlScreenParser.getNodes()) { - if (node.className != "android.widget.TextView") continue; - const QString t = node.text.trimmed(); - QDate headerDate; - - // Относительные заголовки "Сегодня" / "Вчера" - if (t.compare("Сегодня", Qt::CaseInsensitive) == 0) { - headerDate = today; - } else if (t.compare("Вчера", Qt::CaseInsensitive) == 0) { - headerDate = today.addDays(-1); - } else { - // Абсолютный формат "4 января, вс" - static const QRegularExpression dateRx(R"((\d{1,2})\s+(\S+),\s+\S+)"); - const auto match = dateRx.match(t); - if (!match.hasMatch()) continue; - const int day = match.captured(1).toInt(); - const int month = monthMap.value(match.captured(2), 0); - if (month == 0) continue; - headerDate = QDate(searchDate.year(), month, day); - } - if (!headerDate.isValid()) continue; - - if (headerDate == searchDate) { - dateFound = true; - qDebug() << "[FetchTransactions] Found target date header:" << t; - break; - } - if (headerDate < searchDate) { - hasOlderDate = true; - } + if (hasDateOnScreen()) { + dateFound = true; + qDebug() << "[FetchTransactions] Found target date on screen"; + break; } - - if (dateFound) break; - - if (hasOlderDate) { - // Проскочили мимо нужной даты — её нет в списке + if (hasOlderDateOnScreen()) { qDebug() << "[FetchTransactions] Passed target date, not found in list"; break; } - - // Скроллим вниз AdbUtils::makeSwipe(m_deviceId, device.screenWidth / 2, device.screenHeight - 300, device.screenWidth / 2, 300, 300); QThread::msleep(1500); @@ -293,8 +287,11 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int return; } - // ── Шаг 2: на экране с нужной датой ищем транзакцию по сумме ──── - for (int attempt = 0; attempt < 10; ++attempt) { + // ── Шаг 2: тапаем по кнопкам с нужной суммой, проверяем дату/время в деталях ─ + // Запоминаем уже проверенные (date+time из деталей) чтобы не застревать + QSet checkedDetails; + + for (int attempt = 0; attempt < 15; ++attempt) { if (QThread::currentThread()->isInterruptionRequested()) { m_error = "Interrupted"; return; @@ -302,6 +299,7 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); QList txButtons = xmlScreenParser.findTransactionButtons(20); + bool tapped = false; for (int bi = 0; bi < txButtons.size(); ++bi) { if (QThread::currentThread()->isInterruptionRequested()) { m_error = "Interrupted"; @@ -311,28 +309,9 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int const TransactionInfo parsed = xmlScreenParser.parseTransactionButtonText(txButtons[bi].text); if (qAbs(parsed.amount - m_searchAmount) > 0.01) continue; - // Если кнопка за экраном — скроллим до неё, рассчитывая дистанцию - if (txButtons[bi].y() <= 0 || txButtons[bi].y() >= navBarTop) { - bool scrolledIntoView = false; - for (int s = 0; s < 5; ++s) { - const int btnY = txButtons[bi].y(); - const int x = device.screenWidth / 2; - const int visibleCenter = navBarTop / 2; - // Расстояние от кнопки до центра видимой области + небольшой запас - const int delta = btnY - visibleCenter; - const int fromY = qBound(100, visibleCenter + delta / 2, device.screenHeight - 100); - const int toY = qBound(100, visibleCenter - delta / 2, device.screenHeight - 100); - AdbUtils::makeSwipe(m_deviceId, x, fromY, x, toY, 300); - QThread::msleep(1000); - xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); - txButtons = xmlScreenParser.findTransactionButtons(20); - if (bi < txButtons.size() && txButtons[bi].y() > 0 && txButtons[bi].y() < navBarTop) { - scrolledIntoView = true; - break; - } - } - if (!scrolledIntoView) continue; - } + // Пропускаем кнопки за экраном + const int btnY = txButtons[bi].y(); + if (btnY <= 0 || btnY >= navBarTop) continue; const Node &visibleBtn = txButtons[bi]; qDebug() << "[FetchTransactions] Amount match:" << parsed.amount @@ -341,6 +320,7 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int // Тапаем и ждём деталей AdbUtils::makeTap(m_deviceId, visibleBtn.x(), visibleBtn.y()); QThread::msleep(2000); + tapped = true; TransactionInfo detail; for (int da = 0; da < 10; ++da) { @@ -374,25 +354,34 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int if (!txTime.isValid()) txTime = QDateTime::fromString(dtStr, "dd.MM.yyyy,HH:mm"); if (txTime.isValid()) txTime.setTimeZone(deviceTz); - // Проверяем что дата и время совпадают (±1 час от m_searchTime) - if (txTime.isValid()) { - if (txTime.date() != searchDate) { - qDebug() << "[FetchTransactions] Wrong date:" << dtStr << "expected" << searchDate; + // Пропускаем если уже проверяли эту транзакцию + if (checkedDetails.contains(dtStr)) { + qDebug() << "[FetchTransactions] Already checked:" << dtStr << "- skipping"; + AdbUtils::goBack(m_deviceId); + QThread::msleep(500); + continue; // пробуем следующую кнопку + } + checkedDetails.insert(dtStr); + + // Проверяем дату + if (txTime.isValid() && txTime.date() != searchDate) { + qDebug() << "[FetchTransactions] Wrong date:" << dtStr << "expected" << searchDate; + AdbUtils::goBack(m_deviceId); + QThread::msleep(1000); + continue; + } + + // Проверяем время (±1 час) + if (txTime.isValid() && m_searchTime.isValid()) { + const qint64 diffSecs = qAbs(txTime.toUTC().secsTo(m_searchTime.toUTC())); + if (diffSecs > 3600) { + qDebug() << "[FetchTransactions] Time mismatch:" << dtStr + << "expected" << searchLocal.toString("dd.MM.yyyy, HH:mm") + << "diff=" << diffSecs << "sec"; AdbUtils::goBack(m_deviceId); QThread::msleep(1000); continue; } - if (m_searchTime.isValid()) { - const qint64 diffSecs = qAbs(txTime.toUTC().secsTo(m_searchTime.toUTC())); - if (diffSecs > 3600) { - qDebug() << "[FetchTransactions] Time mismatch:" << dtStr - << "expected" << searchLocal.toString("dd.MM.yyyy, HH:mm") - << "diff=" << diffSecs << "sec"; - AdbUtils::goBack(m_deviceId); - QThread::msleep(1000); - continue; - } - } } // Нашли! @@ -504,10 +493,14 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int return; // успех } - // Скроллим чуть вниз чтобы увидеть больше транзакций за этот день - AdbUtils::makeSwipe(m_deviceId, device.screenWidth / 2, - device.screenHeight - 300, device.screenWidth / 2, 300, 300); - QThread::msleep(1000); + // Скроллим вниз если ни одна кнопка не была нажата или все проверенные не подошли + if (!tapped) { + AdbUtils::makeSwipe(m_deviceId, device.screenWidth / 2, + device.screenHeight * 3 / 4, + device.screenWidth / 2, + device.screenHeight / 4, 300); + QThread::msleep(1000); + } } m_error = "Transaction not found: amount=" + QString::number(m_searchAmount, 'f', 2)