diff --git a/android/rshb/CommonScript.cpp b/android/rshb/CommonScript.cpp index 09791f2..8aae5a9 100644 --- a/android/rshb/CommonScript.cpp +++ b/android/rshb/CommonScript.cpp @@ -1,8 +1,12 @@ #include "CommonScript.h" + +#include +#include #include #include #include "adb/AdbUtils.h" +#include "net/NetworkService.h" CommonScript::CommonScript(QObject *parent) : QObject(parent) { @@ -205,6 +209,95 @@ bool CommonScript::findAndTapOnAccount(const QString &deviceId, const QString &a } +void CommonScript::postAccountsData(const QList > &accounts) { + if (accounts.isEmpty()) { + return; + } + + auto *thread = new QThread; + auto *worker = new NetworkService; + + QJsonArray list; + for (const QPair &pair: accounts) { + QJsonObject obj; + AccountInfo account = pair.first; + obj["appName"] = account.appName; + obj["lastNumbers"] = account.lastNumbers; + obj["amount"] = account.amount; + obj["description"] = account.description; + + list.append(obj); + } + // FIXME доставить десктоп ид из настроеек + worker->setDeviceData("DT88bokcwQ", accounts.first().first.deviceId); + worker->setPayload(QJsonDocument(list).toJson()); + worker->moveToThread(thread); + connect(thread, &QThread::started, worker, &NetworkService::postAccountsData); + connect(worker, &NetworkService::finished, thread, &QThread::quit); + connect(worker, &NetworkService::finished, worker, &QObject::deleteLater); + connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); +} + +void CommonScript::postNewTransactionData(const AccountInfo &account, const TransactionInfo &transaction) { + auto *thread = new QThread; + auto *worker = new NetworkService; + + QJsonObject obj; + obj["id"] = transaction.id; + obj["amount"] = transaction.amount; + obj["name"] = transaction.name; + obj["fee"] = transaction.fee; + obj["status"] = transactionStatusToString(transaction.status); + obj["type"] = transactionTypeToString(transaction.type); + obj["phone"] = transaction.phone; + obj["description"] = transaction.description; + obj["updatedDescription"] = transaction.updatedDescription; + obj["bankName"] = transaction.bankName; + obj["bankTime"] = transaction.bankTime; + obj["bankTransactionId"] = transaction.bankTrExternalId; + + // FIXME доставить десктоп ид из настроеек + worker->setDeviceData("DT88bokcwQ", account.deviceId); + worker->addExtra("lastNumbers", account.lastNumbers); + worker->addExtra("transactionId", transaction.id); + worker->setPayload(QJsonDocument(obj).toJson()); + worker->moveToThread(thread); + connect(thread, &QThread::started, worker, &NetworkService::insertTransactionData); + connect(worker, &NetworkService::finished, thread, &QThread::quit); + connect(worker, &NetworkService::finished, worker, &QObject::deleteLater); + connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); +} + +void CommonScript::updateTransactionData( + const AccountInfo &account, + const int transactionId, + const TransactionStatus status, + const QString &oldDesc, + const QString &newDesc +) { + auto *thread = new QThread; + auto *worker = new NetworkService; + + QJsonObject obj; + obj["id"] = transactionId; + obj["status"] = transactionStatusToString(status); + obj["description"] = newDesc; + obj["updatedDescription"] = oldDesc; + + // FIXME доставить десктоп ид из настроеек + worker->setDeviceData("DT88bokcwQ", account.deviceId); + worker->addExtra("lastNumbers", account.lastNumbers); + worker->setPayload(QJsonDocument(obj).toJson()); + worker->moveToThread(thread); + connect(thread, &QThread::started, worker, &NetworkService::updateTransactionData); + connect(worker, &NetworkService::finished, thread, &QThread::quit); + connect(worker, &NetworkService::finished, worker, &QObject::deleteLater); + connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); +} + void CommonScript::stop() { m_running = false; } diff --git a/android/rshb/CommonScript.h b/android/rshb/CommonScript.h index 9982bc6..94876fe 100644 --- a/android/rshb/CommonScript.h +++ b/android/rshb/CommonScript.h @@ -25,6 +25,18 @@ protected: bool findAndTapOnAccount(const QString &deviceId, const QString &accountNumbers); + void postAccountsData(const QList > &accounts); + + void postNewTransactionData(const AccountInfo &account, const TransactionInfo &transaction); + + void updateTransactionData( + const AccountInfo &account, + int transactionId, + TransactionStatus status, + const QString &oldDesc, + const QString &newDesc + ); + Node swipeToButton( const QString &deviceId, const QString &text, @@ -49,6 +61,7 @@ protected: signals: void finished(); + void finishedWithResult(const QString &result); public slots: diff --git a/android/rshb/GetLastDaysHistoryScript.cpp b/android/rshb/GetLastDaysHistoryScript.cpp index 6898cdc..7637e3f 100644 --- a/android/rshb/GetLastDaysHistoryScript.cpp +++ b/android/rshb/GetLastDaysHistoryScript.cpp @@ -1,6 +1,5 @@ #include "GetLastDaysHistoryScript.h" -#include #include #include #include @@ -84,89 +83,104 @@ QString formatPrice(const double value) { return QString("%1 %2").arg(sign, formatted); } -bool GetLastDaysHistoryScript::openAndSaveDitailInfo(TransactionInfo &transaction, int width, int height) { - QString text = QString("%1 %2").arg(transaction.shortDescription, formatPrice(transaction.amount)); +// bool GetLastDaysHistoryScript::openAndSaveDitailInfo(TransactionInfo &transaction, int width, int height) { +// QString text = QString("%1 %2").arg(transaction.shortDescription, formatPrice(transaction.amount)); +// +// Node trButton = swipeToButton(m_account.deviceId, text, m_counter, width, height); +// if (!trButton.isEmpty()) { +// AdbUtils::makeTap(m_account.deviceId, trButton.x(), trButton.y()); +// QThread::msleep(500); +// +// xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter)); +// +// Node moreDetailBtn = xmlScreenParser.findButtonNode("Детали операции", false); +// if (!moreDetailBtn.isEmpty()) { +// AdbUtils::makeTap(m_account.deviceId, moreDetailBtn.x(), moreDetailBtn.y()); +// QThread::msleep(200); +// xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter)); +// TransactionInfo info = xmlScreenParser.parseTransactionInfoHistory(width, height); +// +// if (transaction.id == -1) { +// info.accountId = m_account.id; +// info.shortDescription = transaction.shortDescription; +// info.amount = transaction.amount; +// info.type = info.phone.isEmpty() ? TransactionType::Card : TransactionType::Phone; +// info.updateTime = DateUtils::getUtcNow(); +// if (info.status == TransactionStatus::Complete) { +// info.completeTime = DateUtils::getUtcNow(); +// } +// if (TransactionDAO::insertTransaction(info) == -1) { +// qWarning() << "--- insertTransaction failed"; +// } +// } else { +// transaction.status = info.status; +// transaction.description = info.description; +// if (transaction.trExternalId.isEmpty()) { +// transaction.trExternalId = info.trExternalId; +// } +// transaction.updateTime = DateUtils::getUtcNow(); +// if (transaction.status == TransactionStatus::Complete && !transaction.completeTime.isValid()) { +// transaction.completeTime = DateUtils::getUtcNow(); +// } +// if (!TransactionDAO::updateTransaction(transaction)) { +// qWarning() << "--- updateTransaction failed"; +// } +// } +// } +// +// AdbUtils::goBack(m_account.deviceId); +// QThread::msleep(200); +// } else { +// qWarning() << "--- trButton not found.........."; +// } +// return false; +// } - Node trButton = swipeToButton(m_account.deviceId, text, m_counter, width, height); - if (!trButton.isEmpty()) { - AdbUtils::makeTap(m_account.deviceId, trButton.x(), trButton.y()); - QThread::msleep(500); +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); - xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter)); + if (tr.id == -1) { + return false; + } + postNewTransactionData(account, tr); + return true; +} - Node moreDetailBtn = xmlScreenParser.findButtonNode("Детали операции", false); - if (!moreDetailBtn.isEmpty()) { - AdbUtils::makeTap(m_account.deviceId, moreDetailBtn.x(), moreDetailBtn.y()); - QThread::msleep(200); - xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter)); - TransactionInfo info = xmlScreenParser.parseTransactionInfoHistory(width, height); - - if (transaction.id == -1) { - info.accountId = m_account.id; - info.shortDescription = transaction.shortDescription; - info.amount = transaction.amount; - info.type = info.phone.isEmpty() ? TransactionType::Card : TransactionType::Phone; - info.updateTime = DateUtils::getUtcNow(); - if (info.status == TransactionStatus::Complete) { - info.completeTime = DateUtils::getUtcNow(); - } - if (TransactionDAO::insertTransaction(info) == -1) { - qWarning() << "--- insertTransaction failed"; - } - } else { - transaction.status = info.status; - transaction.description = info.description; - if (transaction.trExternalId.isEmpty()) { - transaction.trExternalId = info.trExternalId; - } - transaction.updateTime = DateUtils::getUtcNow(); - if (transaction.status == TransactionStatus::Complete && !transaction.completeTime.isValid()) { - transaction.completeTime = DateUtils::getUtcNow(); - } - if (!TransactionDAO::updateTransaction(transaction)) { - qWarning() << "--- updateTransaction failed"; - } - } - } - - AdbUtils::goBack(m_account.deviceId); - QThread::msleep(200); - } else { - qWarning() << "--- trButton not found.........."; +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 postAccountsData(const QList > &accounts) { - if (accounts.isEmpty()) { - return; - } - - auto *thread = new QThread; - auto *worker = new NetworkService; - - QJsonArray list; - for (const QPair &pair: accounts) { - QJsonObject obj; - AccountInfo account = pair.first; - obj["appName"] = account.appName; - obj["lastNumbers"] = account.lastNumbers; - obj["amount"] = account.amount; - obj["description"] = account.description; - - list.append(obj); - } - worker->setDeviceData("DT88bokcwQ", accounts.first().first.deviceId); - worker->setPayload(QJsonDocument(list).toJson()); - worker->moveToThread(thread); - QObject::connect(thread, &QThread::started, worker, &NetworkService::postAccountsData); - QObject::connect(worker, &NetworkService::finished, thread, &QThread::quit); - QObject::connect(worker, &NetworkService::finished, worker, &QObject::deleteLater); - QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); - thread->start(); -} - void GetLastDaysHistoryScript::doStart() { + + return; + // берем все транзакции из БД QList localTransactions = TransactionDAO::getTransactionsWithinHours(m_account.id, 48); const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId); @@ -230,8 +244,6 @@ void GetLastDaysHistoryScript::doStart() { // все поддвержденные QList parsedTransactions = xmlScreenParser.parseTodayAndYesterdayReportHistory(); QSet parsedTransactionIds; - qDebug() << "--- parsedTransactions: " << parsedTransactions.length(); - qDebug() << "--- localTransactions: " << localTransactions.length(); for (const TransactionInfo &transaction: parsedTransactions) { bool updated = false; @@ -353,25 +365,8 @@ void GetLastDaysHistoryScript::doStart() { } if (!updated) { qDebug() << "--- insert: " << transaction.description; - // не нашлась транзакция - TransactionInfo tr; - tr.accountId = m_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.trExternalId = transaction.trExternalId; - tr.status = TransactionStatus::Complete; - tr.type = transaction.description.startsWith("Перевод") - ? TransactionType::Phone - : TransactionType::Card; - tr.completeTime = DateUtils::getUtcNow(); - if (TransactionDAO::insertTransaction(tr) == -1) { - qDebug() << "--- not inserted: " << transaction.description; + if (!saveAndPostNewTransactionData(m_account, transaction)) { + qDebug() << "--- saveAndPostNewTransactionData failed"; } } diff --git a/android/rshb/GetLastDaysHistoryScript.h b/android/rshb/GetLastDaysHistoryScript.h index 4ab370b..9538e64 100644 --- a/android/rshb/GetLastDaysHistoryScript.h +++ b/android/rshb/GetLastDaysHistoryScript.h @@ -18,5 +18,13 @@ protected: private: const AccountInfo m_account; - bool openAndSaveDitailInfo(TransactionInfo &transaction, int width, int height); + bool saveAndPostNewTransactionData(const AccountInfo &account, const TransactionInfo &transaction); + + bool updateAndPostTransactionData( + const AccountInfo &account, + int transactionId, + TransactionStatus status, + const QString &oldDesc, + const QString &newDesc + ); }; diff --git a/android/rshb/PayByPhoneScript.cpp b/android/rshb/PayByPhoneScript.cpp index d0e8be6..d5ea7d7 100644 --- a/android/rshb/PayByPhoneScript.cpp +++ b/android/rshb/PayByPhoneScript.cpp @@ -244,6 +244,13 @@ void PayByPhoneScript::doStart() { const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId); const ApplicationInfo app = ApplicationDAO::getApplicationsByDeviceId(m_account.deviceId, m_account.appName); + for (TransactionInfo &transaction: TransactionDAO::getTransactions(m_account.id)) { + // postNewTransactionData(m_account, transaction); + updateTransactionData(m_account, transaction.id, transaction.status, transaction.updatedDescription, transaction.description); + } + + emit finishedWithResult(m_error); + return; if (device.id.isEmpty() || app.id.isEmpty()) { qDebug() << "Device or app not found...."; return; diff --git a/android/rshb/ScreenXmlParser.cpp b/android/rshb/ScreenXmlParser.cpp index 0a58a3e..8e9cecc 100644 --- a/android/rshb/ScreenXmlParser.cpp +++ b/android/rshb/ScreenXmlParser.cpp @@ -339,9 +339,9 @@ void parseTransferInfo(const QString &text, TransactionInfo &info) { } if (const auto m = reSbpId.match(text); m.hasMatch()) { - info.trExternalId = m.captured(1); + info.bankTrExternalId = m.captured(1); } else if (const auto m1 = reIdAlt.match(text); m1.hasMatch()) { - info.trExternalId = m1.captured(1); + info.bankTrExternalId = m1.captured(1); } if (const auto m = reDate.match(text); m.hasMatch()) { @@ -864,7 +864,7 @@ TransactionInfo parseExpandedInfo(const QDomElement &root) { break; case 10: ee = findSubElement(infoElement, "1"); - transaction.trExternalId = findSubInfo(ee, "1"); + transaction.bankTrExternalId = findSubInfo(ee, "1"); break; default: break; diff --git a/database/app_data.db b/database/app_data.db index 39452c3..4e83f55 100644 Binary files a/database/app_data.db and b/database/app_data.db differ diff --git a/database/dao/TransactionDAO.cpp b/database/dao/TransactionDAO.cpp index a089185..f449344 100644 --- a/database/dao/TransactionDAO.cpp +++ b/database/dao/TransactionDAO.cpp @@ -41,12 +41,12 @@ bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) { 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, + bank_name, bank_time, name, bank_tr_external_id, update_time, complete_time, timestamp ) VALUES ( :account_id, :amount, :fee, :status, :phone, :type, :description, :updated_description, :short_description, :updated_short_description, - :bank_name, :bank_time, :name, :tr_external_id, + :bank_name, :bank_time, :name, :bank_tr_external_id, :update_time, :complete_time, :timestamp ) )"); @@ -64,7 +64,7 @@ bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) { 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(":bank_tr_external_id", info.bankTrExternalId); query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime)); query.bindValue(":complete_time", DateUtils::toUtcString(info.completeTime)); @@ -83,12 +83,12 @@ int TransactionDAO::insertTransaction(const TransactionInfo &info) { 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, + bank_name, bank_time, name, bank_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, + :bank_name, :bank_time, :name, :bank_tr_external_id, :update_time, :complete_time ) )"); @@ -106,7 +106,7 @@ int TransactionDAO::insertTransaction(const TransactionInfo &info) { 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(":bank_tr_external_id", info.bankTrExternalId); query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime)); query.bindValue(":complete_time", DateUtils::toUtcString(info.completeTime)); @@ -142,7 +142,7 @@ TransactionInfo parseTransaction(const QSqlQuery &query) { tx.updatedShortDescription = query.value("updated_short_description").toString(); tx.bankName = query.value("bank_name").toString(); tx.bankTime = query.value("bank_time").toString(); - tx.trExternalId = query.value("tr_external_id").toString(); + tx.bankTrExternalId = query.value("bank_tr_external_id").toString(); tx.updateTime = DateUtils::fromUtcString(query.value("update_time").toString()); tx.completeTime = DateUtils::fromUtcString(query.value("complete_time").toString()); tx.timestamp = DateUtils::fromUtcString(query.value("timestamp").toString()); @@ -193,7 +193,7 @@ bool TransactionDAO::updateTransaction(const TransactionInfo &info) { bank_name = :bank_name, bank_time = :bank_time, name = :name, - tr_external_id = :tr_external_id, + bank_tr_external_id = :bank_tr_external_id, update_time = :update_time, complete_time = :complete_time, timestamp = :timestamp @@ -213,7 +213,7 @@ bool TransactionDAO::updateTransaction(const TransactionInfo &info) { 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(":bank_tr_external_id", info.bankTrExternalId); query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime)); query.bindValue(":complete_time", DateUtils::toUtcString(info.completeTime)); query.bindValue(":timestamp", DateUtils::toUtcString(info.timestamp)); @@ -335,3 +335,22 @@ bool TransactionDAO::updateTransaction( } return true; } + +bool TransactionDAO::updateExternalTransactionId(const int id, const int externalId) { + QSqlQuery query(DatabaseManager::instance().database()); + + query.prepare(R"( + UPDATE transactions SET + external_id = :external_id + WHERE id = :id + )"); + + query.bindValue(":id", id); + query.bindValue(":external_id", externalId); + + if (!query.exec()) { + qWarning() << "Ошибка при обновлении external_id:" << query.lastError().text(); + return false; + } + return true; +} diff --git a/database/dao/TransactionDAO.h b/database/dao/TransactionDAO.h index 5b4ca56..e3636f4 100644 --- a/database/dao/TransactionDAO.h +++ b/database/dao/TransactionDAO.h @@ -25,4 +25,6 @@ public: const QString &oldDesc, const QString &newDesc ); + + [[nodiscard]] static bool updateExternalTransactionId(int id, int externalId); }; diff --git a/main.cpp b/main.cpp index ac57b3f..a49c93a 100644 --- a/main.cpp +++ b/main.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "rshb/GetLastDaysHistoryScript.h" #include "rshb/HomeScreenScript.h" @@ -59,7 +60,8 @@ void setupWorkerAndThreadHistory(QCoreApplication &app) { deviceScreenerWorker->moveToThread(thread); QObject::connect(thread, &QThread::started, deviceScreenerWorker, &GetLastDaysHistoryScript::start); QObject::connect(deviceScreenerWorker, &GetLastDaysHistoryScript::finished, thread, &QThread::quit); - QObject::connect(deviceScreenerWorker, &GetLastDaysHistoryScript::finished, deviceScreenerWorker, &QObject::deleteLater); + QObject::connect(deviceScreenerWorker, &GetLastDaysHistoryScript::finished, deviceScreenerWorker, + &QObject::deleteLater); QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); QObject::connect(&app, &QCoreApplication::aboutToQuit, [=]() { deviceScreenerWorker->stop(); @@ -75,7 +77,7 @@ void setupScriptAutoPaymentAndThread(QCoreApplication &app) { const QString phoneNumber = "79641815146"; const QString bankName = "Альфа-Банк"; // const QString bankName = "Сбербанк"; - const double amount = 520; + const double amount = 320; const AccountInfo account = AccountDAO::findAppAccount(appName, cardNumber); if (account.id != -1) { @@ -104,25 +106,29 @@ void setupScriptAutoPaymentAndThread(QCoreApplication &app) { QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); // Обработка результата первого потока - QObject::connect(scriptWorker, &PayByPhoneScript::finishedWithResult, &app, [account, connectStopOnQuit](const QString &result) { - qDebug() << "Получен результат: [" << result << "]"; + QObject::connect(scriptWorker, &PayByPhoneScript::finishedWithResult, &app, + [account, connectStopOnQuit](const QString &result) { + qDebug() << "Получен результат: [" << result << "]"; - // Создаем второй поток после завершения первого - auto *thread2 = new QThread; - auto *scriptWorker2 = new GetLastDaysHistoryScript(account); - scriptWorker2->moveToThread(thread2); + // Создаем второй поток после завершения первого + auto *thread2 = new QThread; + auto *scriptWorker2 = new GetLastDaysHistoryScript(account); + scriptWorker2->moveToThread(thread2); - // Запуск второго потока - QObject::connect(thread2, &QThread::started, scriptWorker2, &GetLastDaysHistoryScript::start); - QObject::connect(scriptWorker2, &GetLastDaysHistoryScript::finished, thread2, &QThread::quit); - QObject::connect(scriptWorker2, &GetLastDaysHistoryScript::finished, scriptWorker2, &QObject::deleteLater); - QObject::connect(thread2, &QThread::finished, thread2, &QThread::deleteLater); + // Запуск второго потока + QObject::connect(thread2, &QThread::started, scriptWorker2, + &GetLastDaysHistoryScript::start); + QObject::connect(scriptWorker2, &GetLastDaysHistoryScript::finished, thread2, + &QThread::quit); + QObject::connect(scriptWorker2, &GetLastDaysHistoryScript::finished, scriptWorker2, + &QObject::deleteLater); + QObject::connect(thread2, &QThread::finished, thread2, &QThread::deleteLater); - // Остановка второго потока при завершении приложения - connectStopOnQuit(scriptWorker2, thread2); + // Остановка второго потока при завершении приложения + connectStopOnQuit(scriptWorker2, thread2); - thread2->start(); - }); + thread2->start(); + }); // Остановка первого потока при завершении приложения connectStopOnQuit(scriptWorker, thread); @@ -132,12 +138,63 @@ void setupScriptAutoPaymentAndThread(QCoreApplication &app) { } } +static QFile logFile; +static QMutex logMutex; + +void messageHandler( + QtMsgType type, + const QMessageLogContext &context, + const QString &msg +) { + Q_UNUSED(context) // можно раскомментировать, если нужны file/line/function + // Формируем строку с типом и временем + const QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); + QString level; + switch (type) { + case QtDebugMsg: level = "DEBUG"; + break; + case QtInfoMsg: level = "INFO"; + break; + case QtWarningMsg: level = "WARNING"; + break; + case QtCriticalMsg: level = "CRITICAL"; + break; + case QtFatalMsg: level = "FATAL"; + break; + } + + const QString line = QString("%1 [%2] %3\n").arg(timestamp, level, msg); + + // Записываем в файл (потокобезопасно) + { + QMutexLocker locker(&logMutex); + if (logFile.isOpen()) { + QTextStream(&logFile) << line; + logFile.flush(); + } + } + + // По желанию — дублировать в консоль + QByteArray localMsg = line.toLocal8Bit(); + fprintf(stderr, "%s", localMsg.constData()); + + if (type == QtFatalMsg) { + abort(); + } +} int main(int argc, char *argv[]) { QApplication app(argc, argv); - setupWorkerAndThreadHistory(app); - setupWorkerAndThread(app); + logFile.setFileName("application.log"); + if (!logFile.open(QIODevice::Append | QIODevice::Text)) { + qWarning() << "Не удалось открыть лог-файл для записи"; + } + // Устанавливаем свой обработчик + qInstallMessageHandler(messageHandler); + + setupScriptAutoPaymentAndThread(app); + // setupWorkerAndThread(app); MainWindow window; window.show(); diff --git a/migrations.sql b/migrations.sql index e1a190f..2d55758 100644 --- a/migrations.sql +++ b/migrations.sql @@ -45,6 +45,7 @@ CREATE TABLE IF NOT EXISTS transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER, + external_id INTEGER, amount REAL, fee REAL, @@ -60,9 +61,7 @@ CREATE TABLE IF NOT EXISTS transactions bank_name TEXT, bank_time TEXT, - - - tr_external_id TEXT, + bank_tr_external_id TEXT, update_time DATETIME, complete_time DATETIME, diff --git a/models/db/TransactionInfo.h b/models/db/TransactionInfo.h index 35451e2..d4cce91 100644 --- a/models/db/TransactionInfo.h +++ b/models/db/TransactionInfo.h @@ -63,7 +63,7 @@ struct TransactionInfo { QString bankName; QString bankTime; - QString trExternalId; + QString bankTrExternalId; QDateTime updateTime; QDateTime completeTime; @@ -90,7 +90,7 @@ inline QString convertTransactionToString(const TransactionInfo &tx) { if (!tx.bankName.isEmpty()) lines << " bankName: " + tx.bankName; else emptyFields << "bankName"; if (!tx.bankTime.isEmpty()) lines << " bankTime: " + tx.bankTime; else emptyFields << "bankTime"; if (!tx.name.isEmpty()) lines << " name: " + tx.name; else emptyFields << "name"; - if (!tx.trExternalId.isEmpty()) lines << " trExternalId: " + tx.trExternalId; else emptyFields << "trExternalId"; + if (!tx.bankTrExternalId.isEmpty()) lines << " bankTrExternalId: " + tx.bankTrExternalId; else emptyFields << "bankTrExternalId"; if (tx.updateTime.isValid()) lines << " updateTime: " + tx.updateTime.toString(Qt::ISODate); else emptyFields << "updateTime"; if (tx.completeTime.isValid()) lines << " completeTime: " + tx.completeTime.toString(Qt::ISODate); else emptyFields << "completeTime"; if (tx.timestamp.isValid()) lines << " timestamp: " + tx.timestamp.toString(Qt::ISODate); else emptyFields << "timestamp"; diff --git a/services/DeviceScreener.cpp b/services/DeviceScreener.cpp index a971fa4..a3051ea 100644 --- a/services/DeviceScreener.cpp +++ b/services/DeviceScreener.cpp @@ -54,7 +54,7 @@ void postDevicesData(const QList &devices) { } QHttpPart uniquePart; - uniquePart.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="uniqueName")"); + uniquePart.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="desktopUniqueName")"); uniquePart.setBody("DT88bokcwQ"); multiPart->append(uniquePart); diff --git a/services/net/NetworkService.cpp b/services/net/NetworkService.cpp index fd289fc..2647c8a 100644 --- a/services/net/NetworkService.cpp +++ b/services/net/NetworkService.cpp @@ -5,36 +5,38 @@ #include #include +#include "dao/TransactionDAO.h" + NetworkService::NetworkService(QObject *parent) : QObject(parent) { } NetworkService::~NetworkService() = default; +// FIXME доделать работу с экстра +void NetworkService::addExtra(const QString &key, const QVariant &value) { + m_extraData[key] = value; +} -void NetworkService::postAccountsData() { - QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); +void addFormField(QHttpMultiPart *multiPart, const QString &fieldName, const QString &fieldValue) { + QHttpPart formField; + formField.setHeader( + QNetworkRequest::ContentDispositionHeader,QStringLiteral("form-data; name=\"%1\"").arg(fieldName) + ); + formField.setBody(fieldValue.toUtf8()); + multiPart->append(formField); +} +void addFormMetadata(QHttpMultiPart *multiPart, const QByteArray &fieldValue) { QHttpPart jsonPart; jsonPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=UTF-8"); jsonPart.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="metadata")"); - - jsonPart.setBody(m_json); + jsonPart.setBody(fieldValue); multiPart->append(jsonPart); +} - - QHttpPart desktopUniqueName; - desktopUniqueName.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="desktopUniqueName")"); - desktopUniqueName.setBody(m_desktopId.toUtf8()); - multiPart->append(desktopUniqueName); - - - QHttpPart androidUniqueName; - androidUniqueName.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="androidUniqueName")"); - androidUniqueName.setBody(m_deviceId.toUtf8()); - multiPart->append(androidUniqueName); - +QJsonValue NetworkService::post(QHttpMultiPart *multiPart, const QString &path) { QNetworkAccessManager manager; // создаём внутри потока - const QUrl url("http://localhost:9999/api/v1/account/update"); + const QUrl url(path); const QNetworkRequest request(url); QNetworkReply *reply = manager.post(request, multiPart); @@ -47,20 +49,71 @@ void NetworkService::postAccountsData() { }); loop.exec(); // <- здесь и запускается event-loop потока - // обрабатываем результат + QJsonValue result; if (reply->error() == QNetworkReply::NoError) { const QByteArray raw = reply->readAll(); QJsonParseError err; const QJsonDocument doc = QJsonDocument::fromJson(raw, &err); if (err.error == QJsonParseError::NoError && doc.isObject()) { const QJsonObject root = doc.object(); - qDebug() << "Успешный ответ: " << root.value("success").toBool(); + if (root.value("success").toBool()) { + result = root.value("data"); + } else { + qWarning() << "Ошибка:" << root; + } } } else { qWarning() << "Ошибка:" << reply->errorString(); } reply->deleteLater(); + return result; +} +void NetworkService::postAccountsData() { + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + + addFormMetadata(multiPart, m_json); + addFormField(multiPart, "desktopUniqueName", m_desktopId); + addFormField(multiPart, "androidUniqueName", m_deviceId); + const bool isSuccess = post(multiPart, "http://localhost:9999/api/v1/account/update").toBool(); + if (!isSuccess) { + qDebug() << "Cant post accounts data"; + } + + emit finished(); +} + +void NetworkService::updateTransactionData() { + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + + addFormMetadata(multiPart, m_json); + addFormField(multiPart, "desktopUniqueName", m_desktopId); + addFormField(multiPart, "androidUniqueName", m_deviceId); + addFormField(multiPart, "lastNumbers", m_extraData["lastNumbers"].toString()); + + const bool isSuccess = post(multiPart, "http://localhost:9999/api/v1/transaction/update").toBool(); + if (!isSuccess) { + qDebug() << "Cant update transaction"; + } + + emit finished(); +} + +void NetworkService::insertTransactionData() { + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + + addFormMetadata(multiPart, m_json); + addFormField(multiPart, "desktopUniqueName", m_desktopId); + addFormField(multiPart, "androidUniqueName", m_deviceId); + addFormField(multiPart, "lastNumbers", m_extraData["lastNumbers"].toString()); + + const int id = post(multiPart, "http://localhost:9999/api/v1/transaction/insert").toInt(); + if (id > 0) { + const int transactionId = m_extraData["transactionId"].toInt(); + if (!TransactionDAO::updateExternalTransactionId(transactionId, id)) { + qDebug() << "Cant update transaction id"; + } + } emit finished(); } diff --git a/services/net/NetworkService.h b/services/net/NetworkService.h index 4f82d48..c70d24c 100644 --- a/services/net/NetworkService.h +++ b/services/net/NetworkService.h @@ -1,5 +1,7 @@ #pragma once +#include #include +#include class NetworkService final : public QObject { Q_OBJECT @@ -16,9 +18,16 @@ public: m_deviceId = deviceId; } + void addExtra(const QString &key, const QVariant &value); + public slots: void postAccountsData(); + + void insertTransactionData(); + + void updateTransactionData(); + void stop(); signals: @@ -28,5 +37,9 @@ private: QByteArray m_json; QString m_deviceId; QString m_desktopId; + QMap m_extraData = {}; bool m_running = true; + + + QJsonValue post(QHttpMultiPart *multiPart, const QString &path); };