Refactor scripts to improve modularity and add transaction handling.
Enhanced `CommonScript` and `PayByPhoneScript` functionalities by restructuring functions for better readability and parameterization (e.g., device-specific inputs). Included a new transaction handling process and database updates for tracking payment details and statuses.
This commit is contained in:
parent
59cef50ad3
commit
8a3c1c5196
@ -94,13 +94,15 @@ bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &pack
|
||||
// adb -s 6edc4a47 shell 'uiautomator dump /sdcard/uidump.xml' && adb -s 6edc4a47 pull /sdcard/uidump.xml step_1.xml && adb -s 6edc4a47 shell 'rm /sdcard/uidump.xml'
|
||||
QString AdbUtils::getScreenDumpAsXml(const QString &deviceId, const int idx) {
|
||||
// TODO убрать логирование в xml файл
|
||||
// "adb -s %1 pull /sdcard/uidump.xml step_%2.xml && "
|
||||
QProcess process;
|
||||
QString xml = QString(
|
||||
"adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && "
|
||||
"adb -s %1 pull /sdcard/uidump.xml step_%2.xml && "
|
||||
|
||||
"adb -s %1 shell 'cat /sdcard/uidump.xml' && "
|
||||
"adb -s %1 shell 'rm /sdcard/uidump.xml'"
|
||||
).arg(deviceId, QString::number(idx));
|
||||
// ).arg(deviceId, QString::number(idx));
|
||||
).arg(deviceId);
|
||||
process.start("sh", {"-c", xml});
|
||||
process.waitForFinished();
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ bool CommonScript::inputPinCode(const QString &deviceId, const QList<Node> &pinc
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommonScript::goToHomeScreen(
|
||||
bool CommonScript::runAppAndGoToHomeScreen(
|
||||
const QString &deviceId,
|
||||
const QString &packageName,
|
||||
const QString &pinCode,
|
||||
@ -85,7 +85,7 @@ bool CommonScript::goToHomeScreen(
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, totalCounter + 1));
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
|
||||
if (xmlScreenParser.isHomeScreen()) {
|
||||
return true;
|
||||
@ -129,29 +129,6 @@ bool CommonScript::goToHomeScreen(
|
||||
}
|
||||
}
|
||||
|
||||
bool CommonScript::runAppAndGoToHomeScreen() {
|
||||
const QString deviceId = "6edc4a47";
|
||||
const QString packageName = "ru.rshb.dbo";
|
||||
const QString pinCode = "1102";
|
||||
const int width = 720;
|
||||
const int height = 1600;
|
||||
|
||||
const QString cardNumber = "7 1 8 3";
|
||||
// В том числе и данные на каком устройстве это делать
|
||||
// TODO тут код работы с БД
|
||||
|
||||
// +7 (964) 181-51-46
|
||||
const QString phoneNumber = "+79641815146";
|
||||
const QString bankName = "Альфа-Банк";
|
||||
const QString paySum = "250";
|
||||
|
||||
xmlScreenParser.test();
|
||||
return false;
|
||||
// выше достаем данные и все прочее
|
||||
|
||||
return goToHomeScreen(deviceId, packageName, pinCode, width, height);
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -163,27 +140,24 @@ bool CommonScript::tryToCloseAllBannersOnHomePage(const QString &deviceId, const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CommonScript::goToAllProducts() {
|
||||
int counter = 100;
|
||||
const QString deviceId = "6edc4a47";
|
||||
const int width = 720;
|
||||
const int height = 1600;
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, counter));
|
||||
bool CommonScript::goToAllProducts(
|
||||
const QString &deviceId,
|
||||
const int width,
|
||||
const int height
|
||||
) {
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, m_counter));
|
||||
if (tryToCloseAllBannersOnHomePage(deviceId, width, height)) {
|
||||
QThread::msleep(500);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++counter));
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
|
||||
if (xmlScreenParser.isHomeScreen()) {
|
||||
// идем на экран "Все продукты"
|
||||
if (Node allCardTitle = xmlScreenParser.findTextNode("Счета и карты"); !allCardTitle.isEmpty()) {
|
||||
if (Node allCardTitle = xmlScreenParser.findTextNode("Счета и карты"); !allCardTitle.isEmpty()) {
|
||||
// 1. Если нет кнопки видимой, свайпаем. Кликаем на "Все продукты"
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
Node allProductsBtn = xmlScreenParser.findButtonNode("Все продукты", false);
|
||||
// Node allProductsBtn = xmlScreenParser.findTextNode("Курсы валют и металлов"); для теста
|
||||
if (allProductsBtn.x() > 0 && allProductsBtn.y() > 0) {
|
||||
qDebug() << "--- All Product in focus";
|
||||
AdbUtils::makeTap(deviceId, allProductsBtn.x(), allProductsBtn.y());
|
||||
QThread::msleep(1000);
|
||||
break;
|
||||
@ -191,7 +165,7 @@ bool CommonScript::goToAllProducts() {
|
||||
AdbUtils::makeSwipe(deviceId,
|
||||
allCardTitle.x(), allCardTitle.y(),
|
||||
allCardTitle.x(), allCardTitle.y() - 200);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++counter));
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
@ -202,15 +176,15 @@ bool CommonScript::goToAllProducts() {
|
||||
}
|
||||
|
||||
QThread::msleep(1000);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++counter));
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
|
||||
} else {
|
||||
// пишем в БД, что не дошли до домашней страницы, и завершаемся
|
||||
// FIXME пишем в БД, что не дошли до домашней страницы, и завершаемся
|
||||
// сохраняем скрин приложения
|
||||
// дделаем алерт
|
||||
}
|
||||
} else {
|
||||
// FIXME
|
||||
qDebug() << "Not home screen...";
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -17,7 +17,11 @@ protected:
|
||||
// static method
|
||||
static bool inputPinCode(const QString &deviceId, const QList<Node> &pincode);
|
||||
|
||||
bool goToAllProducts();
|
||||
bool goToAllProducts(
|
||||
const QString &deviceId,
|
||||
int width,
|
||||
int height
|
||||
);
|
||||
|
||||
Node swipeToButton(
|
||||
const QString &deviceId,
|
||||
@ -25,7 +29,13 @@ protected:
|
||||
int &counter, int width, int height
|
||||
);
|
||||
|
||||
bool runAppAndGoToHomeScreen();
|
||||
bool runAppAndGoToHomeScreen(
|
||||
const QString &deviceId,
|
||||
const QString &packageName,
|
||||
const QString &pinCode,
|
||||
int width,
|
||||
int height
|
||||
);
|
||||
|
||||
bool tryToCloseAllBannersOnHomePage(
|
||||
const QString &deviceId, int width, int height
|
||||
@ -35,10 +45,7 @@ protected:
|
||||
|
||||
bool m_running = true;
|
||||
ScreenXmlParser xmlScreenParser;
|
||||
QString m_packageName;
|
||||
QString m_pinCode;
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
int m_counter = 0;
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
@ -49,9 +56,5 @@ public slots:
|
||||
virtual void stop() final;
|
||||
|
||||
private:
|
||||
// Q_DISABLE_COPY(CommonScript);
|
||||
|
||||
bool goToHomeScreen(
|
||||
const QString &deviceId, const QString &packageName,
|
||||
const QString &pinCode, int width, int height);
|
||||
Q_DISABLE_COPY(CommonScript);
|
||||
};
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
#include "PayByPhoneScript.h"
|
||||
|
||||
#include <QRandomGenerator>
|
||||
#include <QThread>
|
||||
#include <utility>
|
||||
|
||||
#include "DatabaseManager.h"
|
||||
#include "adb/AdbUtils.h"
|
||||
#include "dao/AccountDAO.h"
|
||||
#include "dao/ApplicationDAO.h"
|
||||
#include "dao/DeviceDAO.h"
|
||||
@ -23,6 +26,204 @@ PayByPhoneScript::PayByPhoneScript(
|
||||
|
||||
PayByPhoneScript::~PayByPhoneScript() = default;
|
||||
|
||||
|
||||
void PayByPhoneScript::makePayment(
|
||||
const QString &deviceId,
|
||||
const QString &pinCode,
|
||||
int width,
|
||||
int height
|
||||
) {
|
||||
// Оплата со страницы карты
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
Node payBtn = xmlScreenParser.findButtonNode("Оплатить", false);
|
||||
if (!payBtn.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, payBtn.x(), payBtn.y());
|
||||
QThread::msleep(1000);
|
||||
} else {
|
||||
qWarning() << "--- payBtn not found";
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
// TODO - По номеру карты В РСХБ и другие банки
|
||||
Node payTitle = xmlScreenParser.findTextNode("Платежи и переводы");
|
||||
if (!payTitle.isEmpty() && payTitle.y() < 300) {
|
||||
Node payByPhoneBtn = xmlScreenParser.findButtonNode("По номеру телефона В РСХБ и через", false);
|
||||
if (!payByPhoneBtn.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, payByPhoneBtn.x(), payByPhoneBtn.y());
|
||||
QThread::msleep(1000);
|
||||
} else {
|
||||
qWarning() << "--- payByPhoneBtn not found";
|
||||
}
|
||||
} else {
|
||||
qWarning() << "--- payTitle not found";
|
||||
}
|
||||
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
Node payByPhoneTitle = xmlScreenParser.findTextNode("Перевод по телефону");
|
||||
Node continueBtn = xmlScreenParser.findButtonNode("Продолжить", false);
|
||||
if (!payByPhoneTitle.isEmpty() && payByPhoneTitle.y() < 300 && continueBtn.isEmpty()) {
|
||||
Node inputPhone = xmlScreenParser.findFirstEditText();
|
||||
AdbUtils::makeTap(deviceId, inputPhone.x(), inputPhone.y());
|
||||
QThread::msleep(500);
|
||||
AdbUtils::inputText(deviceId, m_phone);
|
||||
QThread::msleep(1000);
|
||||
} else {
|
||||
qWarning() << "--- payByPhoneTitle not found (no continueBtn)";
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
QString payBankName;
|
||||
payBankName = m_bankName == "Россельхозбанк" ? "Россельхозбанк" : "Другой банк через СБП";
|
||||
Node payOtherBankBtn = xmlScreenParser.findButtonNode(payBankName, false);
|
||||
if (!payOtherBankBtn.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, payOtherBankBtn.x(), payOtherBankBtn.y());
|
||||
QThread::msleep(1000);
|
||||
} else {
|
||||
qWarning() << "--- payOtherBankBtn not found";
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
Node allBanksTitle = xmlScreenParser.findTextNode("Банки участники");
|
||||
if (!allBanksTitle.isEmpty() && allBanksTitle.y() < 300) {
|
||||
Node inputBankName = xmlScreenParser.findFirstEditText();
|
||||
AdbUtils::makeTap(deviceId, inputBankName.x(), inputBankName.y());
|
||||
QThread::msleep(500);
|
||||
AdbUtils::enableAdbIMEKeyboard(deviceId);
|
||||
AdbUtils::inputAdbIMEText(deviceId, m_bankName);
|
||||
AdbUtils::disableAdbIMEKeyboard(deviceId);
|
||||
QThread::msleep(1000);
|
||||
break;
|
||||
} else {
|
||||
qWarning() << "--- allBanksTitle not found, i: " << i;
|
||||
}
|
||||
QThread::msleep(1000);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
Node bankNameListItem = xmlScreenParser.findTextNode(m_bankName);
|
||||
if (!bankNameListItem.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, bankNameListItem.x(), bankNameListItem.y());
|
||||
QThread::msleep(1000);
|
||||
break;
|
||||
} else {
|
||||
qWarning() << "--- bankNameListItem not found, i: " << i;
|
||||
}
|
||||
QThread::msleep(1000);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
|
||||
Node payByPhoneScreenTitle = xmlScreenParser.findTextNode("Перевод по телефону");
|
||||
Node continuePayBtn = xmlScreenParser.findButtonNode("Продолжить", false);
|
||||
if (!payByPhoneScreenTitle.isEmpty() && payByPhoneScreenTitle.y() < 300 && !continuePayBtn.isEmpty()) {
|
||||
Node sumBtn = xmlScreenParser.findButtonNode("0", false);
|
||||
if (!sumBtn.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, sumBtn.x(), sumBtn.y());
|
||||
QThread::msleep(500);
|
||||
AdbUtils::inputText(deviceId, QString::number(m_amount));
|
||||
QThread::msleep(500);
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
Node readyBtn = xmlScreenParser.findTextNode("Готово");
|
||||
if (!readyBtn.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, readyBtn.x(), readyBtn.y());
|
||||
QThread::msleep(500);
|
||||
AdbUtils::makeTap(deviceId, continuePayBtn.x(), continuePayBtn.y());
|
||||
QThread::msleep(1000);
|
||||
} else {
|
||||
qWarning() << "--- readyBtn not found";
|
||||
}
|
||||
} else {
|
||||
qWarning() << "--- sumBtn not found";
|
||||
}
|
||||
} else {
|
||||
qWarning() << "--- payByPhoneScreenTitle not found";
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
// TODO кнопка содержит "Перевести 10 ₽" если будет от 1000 то скорее всвего будет "Перевести 1 000 ₽",
|
||||
// TODO не ясно как форматирование будет, поэтому пока на начало зашьем
|
||||
Node makePayBtn = xmlScreenParser.findButtonNode("Перевести ", true);
|
||||
if (!makePayBtn.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, makePayBtn.x(), makePayBtn.y());
|
||||
QThread::msleep(500);
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
if (const QList<Node> pincode = xmlScreenParser.tryToFindPinCode(pinCode, "Введите код доступа");
|
||||
pincode.size() == 4) {
|
||||
inputPinCode(deviceId, pincode);
|
||||
// После ввода пин-кода, ждем 3с
|
||||
QThread::msleep(3000);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
qWarning() << "--- makePayBtn not found, i: " << i;
|
||||
}
|
||||
QThread::msleep(1000);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
|
||||
bool isPaymentCompleted = false;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
Node moreDetailBtn = xmlScreenParser.findButtonNode("Детали операции", false);
|
||||
if (!moreDetailBtn.isEmpty()) {
|
||||
AdbUtils::makeTap(deviceId, moreDetailBtn.x(), moreDetailBtn.y());
|
||||
QThread::msleep(200);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
|
||||
// TODO считываем все данные по переводу
|
||||
TransactionInfo transaction = xmlScreenParser.parseTransactionInfo(width, height);
|
||||
transaction.accountId = m_account.id;
|
||||
transaction.amount = -m_amount;
|
||||
transaction.type = TransactionType::Phone;
|
||||
if (bool inserted = TransactionDAO::insertTransaction(transaction); !inserted) {
|
||||
// FIXME alert!!
|
||||
qDebug() << "Transaction has not inserted...";
|
||||
}
|
||||
|
||||
// ждем 10 секунд смену статуса
|
||||
for (int k = 0; k < 10; ++k) {
|
||||
Node paymentCompleted = xmlScreenParser.findTextNode("Исполнен", 0, 0, width, height / 2);
|
||||
if (!paymentCompleted.isEmpty()) {
|
||||
isPaymentCompleted = true;
|
||||
transaction.status = TransactionStatus::Complete;
|
||||
if (!TransactionDAO::updateTransactionStatus(transaction.id, transaction.status)) {
|
||||
qDebug() << "Not updated: " << transaction.id;
|
||||
}
|
||||
// TODO обновляем данные
|
||||
break;
|
||||
}
|
||||
|
||||
QThread::msleep(1000);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
transaction.updateTime = QDateTime::currentDateTime();
|
||||
if (!TransactionDAO::updateTransaction(transaction)) {
|
||||
qDebug() << "Not updated: " << transaction.id;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
qWarning() << "--- moreDetailBtn not found, i: " << i;
|
||||
}
|
||||
QThread::msleep(1000);
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||
}
|
||||
|
||||
Node homeBtn = xmlScreenParser.findButtonNode("Вернуться на главную", false);
|
||||
AdbUtils::makeTap(deviceId, homeBtn.x(), homeBtn.y());
|
||||
if (!isPaymentCompleted) {
|
||||
qDebug() << "--- payment not completed";
|
||||
}
|
||||
}
|
||||
|
||||
void PayByPhoneScript::doStart() {
|
||||
const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId);
|
||||
const ApplicationInfo app = ApplicationDAO::getApplicationsByDeviceId(m_account.deviceId, m_account.appName);
|
||||
@ -31,21 +232,30 @@ void PayByPhoneScript::doStart() {
|
||||
qDebug() << "Device or app not found....";
|
||||
return;
|
||||
}
|
||||
m_width = device.screenWidth;
|
||||
m_height = device.screenHeight;
|
||||
m_pinCode = app.pinCode;
|
||||
m_packageName = app.package;
|
||||
|
||||
if (runAppAndGoToHomeScreen()) {
|
||||
if (goToAllProducts()) {
|
||||
QList<AccountInfo> accounts = xmlScreenParser.parseAccountsInfo();
|
||||
for (AccountInfo &account: accounts) {
|
||||
if (runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) {
|
||||
if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) {
|
||||
qDebug() << "======== 1. All products";
|
||||
QList<QPair<AccountInfo, Node> > accounts = xmlScreenParser.parseAccountsInfo();
|
||||
for (auto &[account, node]: accounts) {
|
||||
account.deviceId = m_account.deviceId;
|
||||
account.appName = m_account.appName;
|
||||
if (!AccountDAO::upsertAccount(account)) {
|
||||
qDebug() << "Not updated: " << account.lastNumbers;
|
||||
}
|
||||
}
|
||||
for (auto &[account, node]: accounts) {
|
||||
// FIXME будем считать что числа последние везде уникальные
|
||||
if (m_account.lastNumbers == account.lastNumbers) {
|
||||
qDebug() << "======== 2. Tap by card";
|
||||
AdbUtils::makeTap(device.id, node.x(), node.y());
|
||||
QThread::msleep(1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "======== 3. Make payment";
|
||||
makePayment(device.id, app.pinCode, device.screenWidth, device.screenHeight);
|
||||
} else {
|
||||
qDebug() << "Не смогли открыть 'Все продукты'";
|
||||
}
|
||||
|
||||
@ -24,4 +24,11 @@ private:
|
||||
const QString m_phone;
|
||||
const QString m_bankName;
|
||||
const double m_amount;
|
||||
|
||||
void makePayment(
|
||||
const QString &deviceId,
|
||||
const QString &pinCode,
|
||||
int width,
|
||||
int height
|
||||
);
|
||||
};
|
||||
|
||||
@ -775,19 +775,42 @@ TransactionInfo parseExpandedInfo(const QDomElement &root) {
|
||||
return {};
|
||||
}
|
||||
|
||||
QList<AccountInfo> ScreenXmlParser::parseAccountsInfo() {
|
||||
QList<AccountInfo> accounts;
|
||||
TransactionInfo ScreenXmlParser::parseTransactionInfo(int screenWidth, int screenHeight) {
|
||||
// 1. Распарсить описание транзакции
|
||||
TransactionInfo transaction = parseExpandedInfo(m_xml);
|
||||
// 1. Найти статус: Исполнен | Операция исполнена
|
||||
transaction.status = TransactionStatus::Wait;
|
||||
Node status1 = findTextNode("Исполнен", 0, 0, screenWidth, screenHeight / 2);
|
||||
Node status2 = findTextNode("Операция исполнена", 0, 0, screenWidth, screenHeight / 2);
|
||||
if (!status1.isEmpty() || !status2.isEmpty()) {
|
||||
transaction.status = TransactionStatus::Complete;
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QList<QPair<AccountInfo, Node> > ScreenXmlParser::parseAccountsInfo() {
|
||||
QList<QPair<AccountInfo, Node> > accounts;
|
||||
for (const Node &node: m_nodes) {
|
||||
if (node.text.contains("Номер карты с последними цифрами")) {
|
||||
if (QRegularExpressionMatch match = reCardData.match(node.text); match.hasMatch()) {
|
||||
AccountInfo info;
|
||||
info.lastNumbers = match.captured(1).remove(" ");
|
||||
info.amount = match.captured(2).remove(" ").toFloat();
|
||||
info.description = node.text.mid(0, node.text.indexOf("Номер карты"));
|
||||
info.updateTime = QDateTime::currentDateTime();
|
||||
accounts.append(info);
|
||||
}
|
||||
const QString text = node.text;
|
||||
|
||||
// Проверяем только нужные строки
|
||||
if (!text.contains("Номер карты с последними цифрами")) {
|
||||
continue;
|
||||
}
|
||||
QRegularExpressionMatch match = reCardData.match(text);
|
||||
if (!match.hasMatch()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AccountInfo info;
|
||||
info.lastNumbers = match.captured(1).remove(" ");
|
||||
info.amount = match.captured(2).remove(" ").toFloat();
|
||||
info.description = text.mid(0, text.indexOf("Номер карты"));
|
||||
info.updateTime = QDateTime::currentDateTime();
|
||||
|
||||
accounts.append(qMakePair(info, node));
|
||||
}
|
||||
|
||||
return accounts;
|
||||
@ -814,9 +837,9 @@ void ScreenXmlParser::test() {
|
||||
// Номер карты с последними цифрами
|
||||
QDomElement root = doc.documentElement();
|
||||
parseAndSaveXml(doc.toString());
|
||||
for (const AccountInfo& info : parseAccountsInfo()) {
|
||||
qDebug().noquote().nospace() << convertAccountToString(info);
|
||||
}
|
||||
// for (const AccountInfo &info: parseAccountsInfo()) {
|
||||
// qDebug().noquote().nospace() << convertAccountToString(info);
|
||||
// }
|
||||
// TransactionInfo info = parseExpandedInfo(root);
|
||||
// qDebug().noquote().nospace() << convertTransactionToString(info);
|
||||
// ЕСПП
|
||||
|
||||
@ -19,6 +19,7 @@ public:
|
||||
Node tryToFindSecurityBanner();
|
||||
|
||||
Node findTextNode(const QString &text);
|
||||
|
||||
Node findTextNode(const QString &text, int x1, int y1, int x2, int y2);
|
||||
|
||||
Node findFirstEditText();
|
||||
@ -35,9 +36,12 @@ public:
|
||||
void parseAndSaveXml(const QString &xml);
|
||||
|
||||
TransactionInfo parseTransactionInfoHistory(int screenWidth, int screenHeight);
|
||||
TransactionInfo parseTransactionInfo(int screenWidth, int screenHeight);
|
||||
|
||||
QList<TransactionInfo> parseTodayAndYesterdayHistory();
|
||||
|
||||
QList<AccountInfo> parseAccountsInfo();
|
||||
|
||||
QList<QPair<AccountInfo, Node> > parseAccountsInfo();
|
||||
|
||||
void test();
|
||||
|
||||
|
||||
Binary file not shown.
@ -15,7 +15,8 @@ bool AccountDAO::upsertAccount(const AccountInfo &info) {
|
||||
DO UPDATE SET
|
||||
amount = excluded.amount,
|
||||
update_time = excluded.update_time,
|
||||
status = excluded.status
|
||||
status = excluded.status,
|
||||
description = excluded.description
|
||||
)");
|
||||
|
||||
query.bindValue(":device_id", info.deviceId);
|
||||
|
||||
@ -75,6 +75,48 @@ bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransactionDAO::insertTransaction(const TransactionInfo &info) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
query.prepare(R"(
|
||||
INSERT INTO transactions (
|
||||
account_id, amount, fee, status, phone, type,
|
||||
description, updated_description, short_description, updated_short_description,
|
||||
bank_name, bank_time, name, tr_external_id,
|
||||
update_time, complete_time
|
||||
) VALUES (
|
||||
:account_id, :amount, :fee, :status, :phone, :type,
|
||||
:description, :updated_description, :short_description, :updated_short_description,
|
||||
:bank_name, :bank_time, :name, :tr_external_id,
|
||||
:update_time, :complete_time
|
||||
)
|
||||
)");
|
||||
|
||||
query.bindValue(":account_id", info.accountId);
|
||||
query.bindValue(":amount", info.amount);
|
||||
query.bindValue(":fee", info.fee);
|
||||
query.bindValue(":status", transactionStatusToString(info.status));
|
||||
query.bindValue(":type", transactionTypeToString(info.type));
|
||||
query.bindValue(":phone", info.phone);
|
||||
query.bindValue(":name", info.name);
|
||||
query.bindValue(":description", info.description);
|
||||
query.bindValue(":updated_description", info.updatedDescription);
|
||||
query.bindValue(":short_description", info.shortDescription);
|
||||
query.bindValue(":updated_short_description", info.updatedShortDescription);
|
||||
query.bindValue(":bank_name", info.bankName);
|
||||
query.bindValue(":bank_time", info.bankTime);
|
||||
query.bindValue(":tr_external_id", info.trExternalId);
|
||||
query.bindValue(":update_time", info.updateTime.toString(Qt::ISODate));
|
||||
query.bindValue(":complete_time", info.completeTime.toString(Qt::ISODate));
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при вставке transaction:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransactionDAO::deleteTransaction(const int id) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
query.prepare("DELETE FROM transactions WHERE id = :id");
|
||||
@ -176,6 +218,37 @@ bool TransactionDAO::updateTransaction(const TransactionInfo &info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransactionDAO::updateTransactionStatus(
|
||||
const int id,
|
||||
const TransactionStatus status
|
||||
) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
query.prepare(R"(
|
||||
UPDATE transactions SET
|
||||
status = :status,
|
||||
update_time = :update_time,
|
||||
complete_time = :complete_time
|
||||
WHERE id = :id
|
||||
)");
|
||||
|
||||
query.bindValue(":id", id);
|
||||
query.bindValue(":status", transactionStatusToString(status));
|
||||
QString updateTime;
|
||||
if (status == TransactionStatus::Complete) {
|
||||
updateTime = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||
}
|
||||
query.bindValue(":update_time", updateTime);
|
||||
query.bindValue(":complete_time", QDateTime::currentDateTime().toString(Qt::ISODate));
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при обновлении transaction:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TransactionInfo TransactionDAO::getTransactionById(const int id) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
query.prepare("SELECT * FROM transactions WHERE id = :id");
|
||||
|
||||
@ -5,10 +5,15 @@ class TransactionDAO {
|
||||
public:
|
||||
[[nodiscard]] static bool insertTransactionIfNotExists(const TransactionInfo &info);
|
||||
|
||||
[[nodiscard]] static bool insertTransaction(const TransactionInfo &info);
|
||||
|
||||
[[nodiscard]] static bool deleteTransaction(int id);
|
||||
|
||||
[[nodiscard]] static QList<TransactionInfo> getTransactions(int accountId);
|
||||
|
||||
[[nodiscard]] static bool updateTransaction(const TransactionInfo &info);
|
||||
|
||||
[[nodiscard]] static bool updateTransactionStatus(int id, TransactionStatus status);
|
||||
|
||||
[[nodiscard]] static TransactionInfo getTransactionById(int id);
|
||||
};
|
||||
|
||||
1
main.cpp
1
main.cpp
@ -54,6 +54,7 @@ void setupScriptAutoPaymentAndThread(QCoreApplication &app) {
|
||||
|
||||
const QString phoneNumber = "79641815146";
|
||||
const QString bankName = "Альфа-Банк";
|
||||
// const QString bankName = "Сбербанк";
|
||||
const double ammount = 250;
|
||||
|
||||
AccountInfo account = AccountDAO::findAppAccount(appName, cardNumber);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user