1
0
forked from BRT/arc
arc/android/rshb/GetLastDaysHistoryScript.cpp
trnsmkot 0a31b4d717 Implement Event Type Handling and Status Updates
Added handling for event types (Balance, Phone) and respective processing logic in EventHandler. Introduced support for tracking and updating event statuses both locally and through network APIs. Enhanced data integrity and clarity by expanding the EventInfo model and associated database management.
2025-06-03 22:02:29 +07:00

359 lines
17 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "GetLastDaysHistoryScript.h"
#include <QJsonObject>
#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"
#include "dao/TransactionDAO.h"
#include "db/DeviceInfo.h"
#include "net/NetworkService.h"
#include "time/DateUtils.h"
GetLastDaysHistoryScript::GetLastDaysHistoryScript(
AccountInfo account,
QObject *parent
) : CommonScript(parent),
m_account(std::move(account)) {
}
GetLastDaysHistoryScript::~GetLastDaysHistoryScript() = default;
QList<TransactionInfo> findSavedTransaction(
const QList<TransactionInfo> &transactions,
const TransactionInfo &parsed
) {
QList<TransactionInfo> txs;
const QDateTime dateTime = QDateTime::fromString(parsed.bankTime, "dd.MM.yyyy"); // Московское время
for (const TransactionInfo &info: transactions) {
QDateTime timestamp = info.timestamp;
QString description = parsed.description;
// если тот же день
if (dateTime.date() == timestamp.date() && parsed.amount == info.amount) {
// Перевод Надежда Юрьевна К** в Альфа-Банк через СБП, по номеру телефона +79641815...
if (description.contains("Перевод")) {
if (description.contains(info.name)) {
txs.append(info);
}
} else {
// Перевод по карте
if (description == info.description) {
txs.append(info);
}
}
}
}
return txs;
}
int countSimilar(const TransactionInfo &transaction, const QList<TransactionInfo> &transactions) {
int count = 0;
for (const TransactionInfo &info: transactions) {
if (info.amount == transaction.amount
&& info.description == transaction.description
&& info.bankTime == transaction.bankTime) {
++count;
}
}
return count;
}
QString formatPrice(const double value) {
QString sign = value < 0 ? "Минус" : "Плюс";
const auto intValue = static_cast<qint64>(std::abs(value)); // округление до целого
QString number = QString::number(intValue);
QString formatted;
int count = 0;
for (int i = number.length() - 1; i >= 0; --i) {
formatted.prepend(number[i]);
++count;
if (count % 3 == 0 && i != 0) {
formatted.prepend(' ');
}
}
return QString("%1 %2").arg(sign, formatted);
}
bool GetLastDaysHistoryScript::saveAndPostNewTransactionData(
const AccountInfo &account,
const TransactionInfo &transaction
) {
TransactionInfo tr;
tr.accountId = account.id;
tr.description = transaction.description;
tr.bankTime = transaction.bankTime;
tr.bankName = transaction.bankName;
tr.amount = transaction.amount;
tr.phone = transaction.phone;
tr.updateTime = DateUtils::getUtcNow();
tr.fee = transaction.fee;
tr.name = transaction.name;
tr.bankTrExternalId = transaction.bankTrExternalId;
tr.status = TransactionStatus::Complete;
tr.type = transaction.description.startsWith("Перевод") ? TransactionType::Phone : TransactionType::Card;
tr.completeTime = DateUtils::getUtcNow();
tr.id = TransactionDAO::insertTransaction(tr);
if (tr.id == -1) {
return false;
}
postNewTransactionData(account, tr);
return true;
}
bool GetLastDaysHistoryScript::updateAndPostTransactionData(
const AccountInfo &account,
const int transactionId,
const TransactionStatus status,
const QString &oldDesc,
const QString &newDesc
) {
if (TransactionDAO::updateTransaction(transactionId, status, oldDesc, newDesc)) {
updateTransactionData(account, transactionId, status, oldDesc, newDesc);
return true;
}
return false;
}
void GetLastDaysHistoryScript::doStart() {
// берем все транзакции из БД
const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId);
const ApplicationInfo app = ApplicationDAO::getApplication(m_account.deviceId, m_account.appCode);
if (!xmlScreenParser.isHomeScreen()) {
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) {
m_error = "Не смогли дойти до домашней страницы";
qCritical() << m_error;
emit finishedWithResult(m_error);
return;
}
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
Node closeBannerOrDialogNode = xmlScreenParser.tryToFindBannerOrDialog(device.screenWidth, device.screenHeight);
if (closeBannerOrDialogNode.x() != -1 && closeBannerOrDialogNode.y() != -1) {
AdbUtils::makeTap(device.id, closeBannerOrDialogNode.x(), closeBannerOrDialogNode.y());
QThread::msleep(500);
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
if (xmlScreenParser.isHomeScreen()) {
if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) {
QList<TransactionInfo> localTransactions = TransactionDAO::getTransactionsWithinHours(m_account.id, 48);
QList<QPair<AccountInfo, Node> > accounts = xmlScreenParser.parseAccountsInfo();
for (auto &[account, node]: accounts) {
account.deviceId = m_account.deviceId;
account.appCode = m_account.appCode;
if (!AccountDAO::upsertAccount(account)) {
qDebug() << "Not updated: " << account.lastNumbers;
}
}
postAccountsData(accounts);
findAndTapOnAccount(device.id, m_account.lastNumbers);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
Node actionBtn = xmlScreenParser.findButtonNode("Действия", false);
if (!actionBtn.isEmpty()) {
AdbUtils::makeTap(m_account.deviceId, actionBtn.x(), actionBtn.y());
QThread::msleep(200);
} else {
m_error = "All action btn not found";
qCritical() << m_error;
emit finishedWithResult(m_error);
return;
}
Node reportButton = swipeToButton(
m_account.deviceId,
"Выписка",
m_counter, device.screenWidth,
device.screenHeight
);
if (!reportButton.isEmpty()) {
AdbUtils::makeTap(m_account.deviceId, reportButton.x(), reportButton.y());
QThread::msleep(1000);
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
Node reportTitle = xmlScreenParser.findTextNode("Выписка");
if (!reportTitle.isEmpty() && reportTitle.y() < 300) {
QDate beforeYesterday = DateUtils::getMoscowNow().date().addDays(-2);
QString beforeYesterdayTitle = beforeYesterday.toString("dd.MM.yyyy");
for (int i = 0; i < 5; ++i) {
Node byDayTitle = xmlScreenParser.findTextNode(beforeYesterdayTitle);
if (!byDayTitle.isEmpty()) {
qWarning() << "--- beforeYesterdayTitle found!";
break;
}
AdbUtils::makeSwipe(
m_account.deviceId,
device.screenWidth / 2, device.screenHeight / 4 * 3,
device.screenWidth / 2, device.screenHeight / 4
);
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
}
} else {
m_error = "All action - report title not found";
qCritical() << m_error;
emit finishedWithResult(m_error);
return;
}
// все поддвержденные
QList<TransactionInfo> parsedTransactions = xmlScreenParser.parseTodayAndYesterdayReportHistory();
QSet<int> parsedTransactionIds;
for (const TransactionInfo &transaction: parsedTransactions) {
bool updated = false;
for (const TransactionInfo &saved: localTransactions) {
if (parsedTransactionIds.contains(saved.id)) {
continue;
}
QDate sDate = QDateTime::fromString(saved.bankTime, "dd.MM.yyyy HH:mm:ss").date();
if (!sDate.isValid()) {
sDate = QDateTime::fromString(saved.bankTime, "dd.MM.yyyy").date();
}
QDate pDate = QDateTime::fromString(transaction.bankTime, "dd.MM.yyyy HH:mm:ss").date();
if (!pDate.isValid()) {
pDate = QDateTime::fromString(transaction.bankTime, "dd.MM.yyyy").date();
}
// Если сумма и дата совпадают
if (saved.amount == transaction.amount && sDate == pDate) {
if (transaction.description.startsWith("Перевод")) {
// Перевод по номеру
if (saved.bankName == transaction.bankName && saved.phone == transaction.phone) {
parsedTransactionIds.insert(saved.id);
updated = true;
if (saved.status != TransactionStatus::Complete || saved.description.isEmpty()) {
if (!TransactionDAO::updateTransaction(
saved.id,
TransactionStatus::Complete,
saved.description,
transaction.description
)) {
qDebug().noquote().nospace() << "--- updated+phone failed" <<
convertTransactionToString(transaction);;
}
}
break;
}
} else {
// перевод по карте
// перезаписать saved.description -> updatedDescription если не равны
if (!saved.description.isEmpty()) {
if (saved.description == transaction.description) {
// описания совпадают
if (saved.status != TransactionStatus::Complete) {
if (!TransactionDAO::updateTransaction(
saved.id,
TransactionStatus::Complete,
saved.description,
transaction.description
)) {
qDebug().noquote().nospace() << "--- updated+card[description same] failed"
<<
convertTransactionToString(transaction);;
}
}
parsedTransactionIds.insert(saved.id);
updated = true;
break;
} else {
// описания не совпадают, то пробуем найти такое же, если не находим то это новая
bool findWithSameName = false;
for (const TransactionInfo &saved2: localTransactions) {
if (saved2.description == transaction.description && !parsedTransactionIds.
contains(
saved2.id)) {
// мы нашли с одинаковым описанием и еще не обработанную
if (saved2.status != TransactionStatus::Complete) {
if (!TransactionDAO::updateTransaction(
saved2.id,
TransactionStatus::Complete,
saved2.description,
transaction.description
)) {
qDebug().noquote().nospace() <<
"--- updated+card2[description same] failed"
<<
convertTransactionToString(transaction);;
}
}
parsedTransactionIds.insert(saved2.id);
updated = true;
findWithSameName = true;
break;
}
}
if (!findWithSameName) {
// обновляем описание
if (!TransactionDAO::updateTransaction(
saved.id,
TransactionStatus::Complete,
saved.description,
transaction.description
)) {
qDebug().noquote().nospace() <<
"--- updated+card2+new desc[description same] failed" <<
convertTransactionToString(transaction);;
}
}
parsedTransactionIds.insert(saved.id);
updated = true;
break;
}
} else {
// пустой описание
if (!TransactionDAO::updateTransaction(
saved.id,
TransactionStatus::Complete,
saved.description,
transaction.description
)) {
qDebug().noquote().nospace() <<
"--- updated+card[empty description]" <<
convertTransactionToString(transaction);;
}
parsedTransactionIds.insert(saved.id);
updated = true;
break;
}
}
}
}
if (!updated) {
if (!saveAndPostNewTransactionData(m_account, transaction)) {
qDebug() << "--- saveAndPostNewTransactionData failed";
}
}
// Если это перевод
// Если совпадает по сумме + телефон + банк дата (без времени) + банк
// Если по карте, мы знаем ток дату + сумма
}
}
} else {
m_error = "GetLastDaysHistoryScript - home screen not found";
qWarning() << m_error;
emit finishedWithResult(m_error);
}
emit finishedWithResult(m_error);
}