1
0
forked from BRT/arc
arc/docs/black_tasks.md
trnsmkot 38f33797c5 - Add toggleMaterial logic to NetworkService for enabling/disabling materials via PATCH request.
- Implement `toggleMaterialStatus` in `AccountSettingsWindow` for UI control and threading integration.
- Enhance `MaterialDAO` with numeric validation for `lastNumbers` field to ensure data integrity.
- Update `PayByCardScript` and `PayByPhoneScript` to handle PIN entry if required after payment confirmation.
- Introduce dynamic UI adjustments for material toggling, including a new toggle button and layout refinements.
- Add documentation for task logic in `ozon_tasks.md` and `black_tasks.md`.
- Switch default currency in `GetCardInfoScript` (Black app) from USD to ARS.
2026-03-31 11:40:34 +07:00

14 KiB
Raw Blame History

Black - Логика задач

← Главная | События

Описание логики всех типов задач для банка Black (appCode: black).

Black — аргентинское банковское приложение. Интерфейс на испанском. Валюта: ARS (код 32). Таймзона: America/Argentina/Buenos_Aires (UTC-3).


Общие механизмы (CommonScript)

Запуск приложения (runAppAndGoToHomeScreen)

  1. Убивает приложение если запущено
  2. Запускает приложение
  3. Ждёт 4.5 секунды
  4. Цикл до 10 попыток:
    • Получает XML-дамп экрана
    • Проверяет isHomeScreen() (наличие "Saldo disponible" + content-desc "Inicio")
    • Если экран с PIN-кодом (isPinCodeScreen() — "¿Olvidaste tu PIN?" или "Ingresá tu PIN"):
      • Находит EditText с password=true
      • Тапает для фокуса → ожидание 500мс
      • Вводит PIN через AdbUtils::inputText()
      • Ожидание 3 сек
    • Ожидание 1 сек между попытками
  5. При неудаче — скриншот

Прокрутка к кнопке (swipeToButton)

  • До 10 свайпов вверх
  • После каждого свайпа парсит XML и ищет кнопку
  • Аналогично Ozon

Создание банковского профиля (createBankProfileIfNeeded)

  • Аналогично Ozon (общий код в CommonScript)
  • Валюта по умолчанию: ARS→32

FETCH_PROFILE

Скрипты: Black::LoginAndCheckAccountsScriptBlack::GetProfileInfoScriptBlack::GetCardInfoScript

Цель

Авторизация, сбор профиля (ФИО, телефон, email), получение CVU и баланса.

Шаги LoginAndCheckAccountsScript

  1. Валидация — получение DeviceInfo и BankProfileInfo из БД
  2. Запуск приложенияrunAppAndGoToHomeScreen() с PIN-кодом
  3. Запуск GetProfileInfoScript — синхронно, для сбора профиля
  4. При ошибке: скриншот + лог + обновление комментария в BankProfileDAO

Шаги GetProfileInfoScript

  1. Домашний экран — проверка/перезапуск

  2. Парсинг с домашнего экрана:

    • fullName из parseUserNameFromHomeScreen() — формат "¡Hola!\nИМЯ\ninitials"
    • Баланс из parseBalanceFromHomeScreen() — формат "$1.857,00" → 1857.00
    • Обновление баланса в BankProfileDAO
  3. Навигация в боковое меню:

    • Поиск кнопки "¡Hola!" (аватар)
    • Тап → ожидание 2 сек
    • Ожидание isSideMenu() (5 × 1 сек) — маркеры: "Tu Información" + "Cerrar sesión"
  4. Навигация к профилю:

    • Тап "Tu Información" (content-desc)
    • Ожидание 2.5 сек
    • Ожидание isProfilePage() (5 × 1 сек) — маркер: content-desc "Tu información"
  5. Парсинг профиля:

    • Nombre, Apellido, Email — по hint-атрибутам EditText
    • Свайп вниз → ожидание 1.5 сек
    • Телефон — из hint-атрибута
    • fullName = "nombre apellido" (или fallback на имя с домашнего экрана)
  6. Сохранение: BankProfileDAO::updateProfileInfo(id, fullName, phone, email)

  7. Синхронизация с сервером: createBankProfileIfNeeded()

  8. Отправка аккаунтов: postAccountsData() для аккаунтов без materialId

  9. Завершение — убийство приложения

Шаги GetCardInfoScript (CVU)

  1. Домашний экран — проверка/перезапуск

  2. Парсинг баланса → обновление в БД

  3. Навигация к CVU:

    • Поиск кнопки "Tu CVU" (exact match)
    • Тап → ожидание 2 сек
    • Ожидание isCVUScreen() (5 × 1 сек)
  4. Парсинг CVU:

    • parseCVUNumber() — 22-значный номер после маркера "CVU"
    • lastNumbers = последние 4 цифры CVU
  5. Сохранение в БД:

    • MaterialDAO::upsertAccount() с:
      • cardNumber = полный CVU
      • lastNumbers = CVU[-4:]
      • currency = "USD" (хардкод)
      • description = "CVU"
  6. Отправка материала на сервер: ns.postMaterial() (если есть bankProfileId и нет materialId)

  7. Завершение — убийство приложения

Ответ серверу (при успехе)

{
  "type": "FETCH_PROFILE",
  "material_id": "...",
  "bank_name": "black",
  "data": {
    "bank_account_id": "",
    "amount": 185700,
    "currency": 32
  }
}

FETCH_TRANSACTIONS

Скрипт: Black::GetLastTransactionsScript

Цель

Получение списка последних транзакций из истории операций.

Шаги

  1. Домашний экран — проверка/перезапуск

  2. Навигация к истории транзакций:

    • Поиск кнопки "Ver más" после секции "Tu actividad" через findVerMasAfterTuActividad()
    • Если не найдена — до 5 свайпов вниз (1 сек между свайпами)
    • Тап "Ver más" → ожидание 2 сек
  3. Ожидание загрузки (15 × 1.5 сек):

    • isTransactionLoadingScreen() = "Tu Actividad" есть, но транзакций нет (загрузка)
    • isTransactionListScreen() = "Tu Actividad" + видимые транзакции
    • Если после 15 попыток всё ещё loading → пустой аккаунт (нормально), возврат без ошибки
  4. Парсинг транзакций (parseTransactionItems()):

    • Источник: ImageView ноды с текстом формата:
      Transferencia
      DD de MES de YYYY - HH:MM
      $amount,cents
      
      или (входящие):
      Transferencia externa de ИМЯ
      DD de MES de YYYY - HH:MM
      $amount,cents
      
    • Отрицательные суммы: $-amount (исходящие переводы)
    • Парсинг испанских дат (parseSpanishDate()): enero, febrero, ..., diciembre
  5. Сохранение в БД (для каждой транзакции):

    • bankName = "black"
    • status = Complete
    • timestamp = currentDateTimeUtc()
    • Конвертация времени: парсинг испанской даты → таймзона Buenos Aires
    • TransactionDAO::insertTransactionIfNotExists()
  6. ВозвратgoBack() → ожидание 1 сек

Retry-логика (EventHandler)

Аналогична Ozon:

"Transaction not found" + < 10 мин → повтор через 15 сек
"Transaction not found" + ≥ 10 мин → ошибка

Ответ серверу

{
  "type": "FETCH_TRANSACTIONS",
  "material_id": "...",
  "bank_name": "black",
  "data": [
    {
      "bank_transaction_id": null,
      "amount": 185700,
      "currency": 32,
      "transaction_type": "bank",
      "bank_participator_id": "+5491112345678",
      "status": "completed",
      "extra": { "fee": 0 },
      "created_at": "2025-01-15T14:30:00.000-03:00"
    }
  ]
}

CREATE_TRANSACTION (bank — по CBU/CVU/Alias)

Скрипт: Black::PayByCardScript

Цель

Перевод на CBU, CVU или Alias получателя.

Входные параметры

  • event.phone — CBU/CVU/Alias получателя (поле m_cardNumber)
  • event.amount — сумма перевода
  • m_account — аккаунт-отправитель

Шаги

  1. Домашний экран — проверка/перезапуск

  2. Поиск кнопки оплаты:

    • findNodeByContentDesc("Enviar a\nCBU o alias", contains=true)
    • Если не найдена — до 5 свайпов вниз
    • Тап → ожидание 2 сек
  3. Ввод реквизитов (10 × 1.5 сек ожидание экрана):

    • Экран isPayInputCardNumberScreen() — hint "Ingresar CBU, CVU o Alias"
    • Тап на EditText → ожидание 500мс
    • Ввод CBU/CVU/Alias
    • Тап "Continuar" → ожидание 2 сек
  4. Подтверждение получателя (10 × 1.5 сек):

    • Экран isPayTransferConfirmScreen() — кнопка "Transferir" + поле "Alias:"
    • Тап "Transferir" → ожидание 2 сек
  5. Ввод суммы (10 × 1.5 сек):

    • Экран isPayInputSumScreen() — "Cuánto vas a transferír"
    • Тап на EditText → ожидание 500мс
    • Очистка поля: 20 × keyevent 67 (backspace)
    • Ввод суммы в сентаво: int(amount * 100) → строка
      • Пример: 500.00 → "50000"
    • Проверка: перечитывает поле, если не совпадает — повторяет ввод
    • Тап "Continuar" → ожидание 2 сек
  6. Финальное подтверждение (10 × 1.5 сек):

    • Экран isPayConfirmScreen() — "Vas a transferir \na ИМЯ_ПОЛУЧАТЕЛЯ"
    • Парсинг имени получателя (parseRecipientNameFromConfirm())
    • Тап "Transferir" → ожидание 3 сек
  7. Ввод PIN (если запрошен):

    • isPinCodeScreen()inputPinCode()
    • Ожидание 3 сек
  8. Проверка результата (15 × 2 сек):

    • "Dinero enviado!" → успех:
      • Парсинг bankTime: parsePaySuccessDateTime() → "DD/MM/YY HH:MM"
      • Парсинг ID: parsePaySuccessCoelsaId() → Coelsa transaction ID
      • Скриншот как чек
    • Если снова PIN-экран → повторный ввод PIN
    • Таймаут → ошибка
  9. Сохранение транзакции:

    • amount = -m_amount (отрицательная)
    • fee = 0
    • type = Card, status = Complete
    • name = имя получателя
    • description = "Transferencia a ИМЯ"
    • phone = CBU/CVU/Alias
    • bankTrExternalId = Coelsa ID
    • receiptImage = скриншот
    • TransactionDAO::insertTransaction()

Ответ серверу

{
  "type": "CREATE_TRANSACTION",
  "material_id": "...",
  "bank_name": "black",
  "data": {
    "amount": -50000,
    "currency": 32,
    "transaction_type": "bank",
    "bank_participator_id": "0000003100012345678901",
    "status": "completed",
    "bank_transaction_id": "COELSA-12345",
    "extra": { "fee": 0 },
    "created_at": "2025-01-15T14:30:00.000-03:00"
  }
}

ScreenXmlParser (Black)

Определение экранов

Метод Маркеры
isHomeScreen() "Saldo disponible" + content-desc "Inicio"
isPinCodeScreen() "¿Olvidaste tu PIN?" или "Ingresá tu PIN"
isSideMenu() "Tu Información" + "Cerrar sesión"
isProfilePage() content-desc "Tu información"
isCVUScreen() маркер "CVU"
isTransactionLoadingScreen() "Tu Actividad" без "Transferencia"
isTransactionListScreen() "Tu Actividad" + транзакции
isPayInputCardNumberScreen() EditText с hint "Ingresar CBU, CVU o Alias"
isPayTransferConfirmScreen() "Transferir" + "Alias:" без "Vas a transferir"
isPayInputSumScreen() "Cuánto vas a transferír"
isPayConfirmScreen() "Vas a transferir"
isPaySuccessScreen() "Dinero enviado!"

Парсинг данных

Метод Формат / Логика
parseUserNameFromHomeScreen() "¡Hola!\nИМЯ\ninitials" → ИМЯ
parseBalanceFromHomeScreen() "$1.857,00" → 1857.00 (аргентинский формат)
parseProfileNombre/Apellido/Email/Phone() По hint-атрибутам EditText
parseCVUNumber() 22-значный номер после маркера "CVU"
parseTransactionItems() ImageView ноды с "Transferencia"
parseSpanishDate() "DD de MES de YYYY - HH:MM" → QDateTime
parseRecipientNameFromConfirm() "Vas a transferir \na ИМЯ" → ИМЯ
parsePaySuccessDateTime() "DD/MM/YY HH:MM"
parsePaySuccessCoelsaId() Текст после "Id Coelsa"

Парсинг транзакций

Формат элемента списка (ImageView text):

Transferencia                          // тип
15 de enero de 2025 - 14:30           // дата (испанский)
$1.500,00                             // сумма (положительная = входящая)

или:

Transferencia externa de Juan Perez   // тип + имя отправителя
15 de enero de 2025 - 14:30
$-1.500,00                            // отрицательная = исходящая

Испанские месяцы

Месяц Перевод
enero январь
febrero февраль
marzo март
abril апрель
mayo май
junio июнь
julio июль
agosto август
septiembre сентябрь
octubre октябрь
noviembre ноябрь
diciembre декабрь