From d0330a509a12f8a5ecbf6aa2091c07d762e9b68f Mon Sep 17 00:00:00 2001 From: slava Date: Sat, 18 Apr 2026 17:27:12 +0700 Subject: [PATCH] Refine transaction amount parsing and improve banner closing in Ozon scripts: - Handle fractional amounts during transaction parsing in mock server. - Add support for closing Google Play update banners in `Ozon` homepage handling logic. --- android/ozon/CommonScript.cpp | 28 +++++++++++++++------ tests/mock_server/gen_fetch_transactions.py | 22 ++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/android/ozon/CommonScript.cpp b/android/ozon/CommonScript.cpp index 89eb98e..9e2c8ce 100644 --- a/android/ozon/CommonScript.cpp +++ b/android/ozon/CommonScript.cpp @@ -200,14 +200,28 @@ bool CommonScript::runAppAndGoToHomeScreen( } bool CommonScript::tryToCloseAllBannersOnHomePage(const QString &deviceId, const int width, const int height) { - Node closeBannerOrDialogNode = xmlScreenParser.tryToFindBannerOrDialog(width, height); - if (closeBannerOrDialogNode.x() != -1 && closeBannerOrDialogNode.y() != -1) { - AdbUtils::makeTap(deviceId, closeBannerOrDialogNode.x(), closeBannerOrDialogNode.y()); - return true; - } + bool closedAny = false; + for (int i = 0; i < 5; ++i) { + bool closedThis = false; - // TODO тут все другие банеры попробовать закрыть - return false; + // Баннер Google Play "Доступно обновление" — появляется поверх Ozon при возврате на домашнюю + if (Node gpNode = xmlScreenParser.tryToFindGooglePlayBanner(width, height); !gpNode.isEmpty()) { + qDebug() << "[tryToCloseAllBannersOnHomePage] Google Play update banner detected, closing..."; + AdbUtils::makeTap(deviceId, gpNode.x(), gpNode.y()); + QThread::msleep(1500); + closedThis = true; + } else if (Node closeBannerOrDialogNode = xmlScreenParser.tryToFindBannerOrDialog(width, height); + closeBannerOrDialogNode.x() != -1 && closeBannerOrDialogNode.y() != -1) { + AdbUtils::makeTap(deviceId, closeBannerOrDialogNode.x(), closeBannerOrDialogNode.y()); + QThread::msleep(500); + closedThis = true; + } + + if (!closedThis) break; + closedAny = true; + xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + } + return closedAny; } bool CommonScript::goToAllProducts( diff --git a/tests/mock_server/gen_fetch_transactions.py b/tests/mock_server/gen_fetch_transactions.py index e1a3de1..300a184 100755 --- a/tests/mock_server/gen_fetch_transactions.py +++ b/tests/mock_server/gen_fetch_transactions.py @@ -226,11 +226,12 @@ def parse_ozon_rows(xml): continue if "Расход" in text or "Доход" in text: continue - am = re.search(r"([+\-−])\s*(\d[\d\s\u202f]*)", text) + am = re.search(r"([+\-−])\s*(\d[\d\s\u202f]*(?:[,.]\d{1,2})?)", text) if not am: continue sign = -1 if am.group(1) in ("-", "−") else 1 - amount = sign * int(re.sub(r"[\s\u202f]", "", am.group(2))) + raw = re.sub(r"[\s\u202f]", "", am.group(2)).replace(",", ".") + amount = sign * (float(raw) if "." in raw else int(raw)) rows.append({"text": text, "cx": (x1+x2)//2, "cy": cy, "amount": amount}) rows.sort(key=lambda r: r["cy"]) return rows @@ -275,7 +276,7 @@ def parse_dushanbe_rows(xml): for p in parts: p = p.strip() try: - amount = int(float(p)) + amount = float(p.replace(",", ".")) except ValueError: pass if re.match(r"^\s*\d{1,2}:\d{2}(:\d{2})?\s*$", p): @@ -306,7 +307,14 @@ def extract_dushanbe_detail(xml): def short_label(amount, time_str): sign = "plus" if amount >= 0 else "minus" t = time_str.replace(":", "") if time_str else "unk" - return f"{sign}_{abs(amount)}_{t}" + a = abs(amount) + if isinstance(a, float): + rub = int(a) + kop = int(round((a - rub) * 100)) + amt = f"{rub}_{kop:02d}" if kop else f"{rub}" + else: + amt = f"{a}" + return f"{sign}_{amt}_{t}" def collect_tasks(serial, bank, mid, device_tz, kopecks, prefix): @@ -416,7 +424,7 @@ def collect_tasks(serial, bank, mid, device_tz, kopecks, prefix): while label in seen: label += "_2" seen.add(label) tasks.append({"bank_name": bank, "material_id": mid, "type": "FETCH_TRANSACTIONS", - "body": {"amount": row["amount"] * kopecks, "created_at": cat}, + "body": {"amount": int(round(row["amount"] * kopecks)), "created_at": cat}, "_tag": f"{prefix}_{task_num:02d}_{label}"}) # Помечаем даты как завершённые: все даты кроме последней на экране @@ -477,7 +485,7 @@ def collect_tasks(serial, bank, mid, device_tz, kopecks, prefix): if not date_s or not time_s: print(" SKIP"); continue - amount = int(float(amt_s)) if amt_s else (row["amount"] or 0) + amount = float(amt_s.replace(",", ".")) if amt_s else (row["amount"] or 0) fmt = "%d.%m.%Y %H:%M:%S" if len(time_s) > 5 else "%d.%m.%Y %H:%M" # Душанбе показывает время в Asia/Dushanbe (UTC+5), не в таймзоне устройства dushanbe_tz = timezone(timedelta(hours=5)) @@ -494,7 +502,7 @@ def collect_tasks(serial, bank, mid, device_tz, kopecks, prefix): while label in seen: label += "_2" seen.add(label) tasks.append({"bank_name": bank, "material_id": mid, "type": "FETCH_TRANSACTIONS", - "body": {"amount": amount * kopecks, "created_at": cat}, + "body": {"amount": int(round(amount * kopecks)), "created_at": cat}, "_tag": f"{prefix}_{task_num:02d}_{label}"}) scroll_count += 1