Introduced new logging system with QInstallMessageHandler. Refactored NetworkService for better modularity and added new methods to handle transaction data. Updated database schema and TransactionDAO to support external transaction ID. Cleaned up and streamlined transaction processing in GetLastDaysHistoryScript.
357 lines
13 KiB
C++
357 lines
13 KiB
C++
#include <QSqlQuery>
|
||
#include <QSqlError>
|
||
#include <QVariant>
|
||
|
||
#include "DatabaseManager.h"
|
||
#include "TransactionDAO.h"
|
||
|
||
#include "time/DateUtils.h"
|
||
|
||
bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) {
|
||
QSqlQuery query(DatabaseManager::instance().database());
|
||
|
||
if (info.amount < 0) {
|
||
// Если исходящая, то мы знаем время timestamp
|
||
query.prepare(R"(
|
||
SELECT COUNT(*) FROM transactions
|
||
WHERE account_id = :account_id AND amount = :amount AND timestamp = :timestamp AND type = :type
|
||
)");
|
||
} else {
|
||
query.prepare(R"(
|
||
SELECT COUNT(*) FROM transactions
|
||
WHERE account_id = :account_id AND amount = :amount AND bankTime = :bankTime AND type = :type
|
||
)");
|
||
}
|
||
|
||
query.bindValue(":account_id", info.accountId);
|
||
query.bindValue(":amount", info.amount);
|
||
query.bindValue(":type", transactionTypeToString(info.type));
|
||
query.bindValue(":timestamp", DateUtils::toUtcString(info.timestamp));
|
||
|
||
if (!query.exec() || !query.next()) {
|
||
qWarning() << "Ошибка при проверке существования transaction:" << query.lastError().text();
|
||
return false;
|
||
}
|
||
|
||
if (query.value(0).toInt() > 0) {
|
||
return false; // Уже существует
|
||
}
|
||
|
||
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, 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, :bank_tr_external_id,
|
||
:update_time, :complete_time, :timestamp
|
||
)
|
||
)");
|
||
|
||
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(":bank_tr_external_id", info.bankTrExternalId);
|
||
query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime));
|
||
query.bindValue(":complete_time", DateUtils::toUtcString(info.completeTime));
|
||
|
||
if (!query.exec()) {
|
||
qWarning() << "Ошибка при вставке transaction:" << query.lastError().text();
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
int 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, 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, :bank_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(":bank_tr_external_id", info.bankTrExternalId);
|
||
query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime));
|
||
query.bindValue(":complete_time", DateUtils::toUtcString(info.completeTime));
|
||
|
||
if (!query.exec()) {
|
||
qWarning() << "Ошибка при вставке transaction:" << query.lastError().text();
|
||
return -1;
|
||
}
|
||
|
||
return query.lastInsertId().toInt();
|
||
}
|
||
|
||
bool TransactionDAO::deleteTransaction(const int id) {
|
||
QSqlQuery query(DatabaseManager::instance().database());
|
||
query.prepare("DELETE FROM transactions WHERE id = :id");
|
||
query.bindValue(":id", id);
|
||
return query.exec();
|
||
}
|
||
|
||
|
||
TransactionInfo parseTransaction(const QSqlQuery &query) {
|
||
TransactionInfo tx;
|
||
tx.id = query.value("id").toInt();
|
||
tx.accountId = query.value("account_id").toInt();
|
||
tx.amount = query.value("amount").toDouble();
|
||
tx.fee = query.value("fee").toDouble();
|
||
tx.status = transactionStatusFromString(query.value("status").toString());
|
||
tx.type = transactionTypeFromString(query.value("type").toString());
|
||
tx.phone = query.value("phone").toString();
|
||
tx.name = query.value("name").toString();
|
||
tx.description = query.value("description").toString();
|
||
tx.updatedDescription = query.value("updated_description").toString();
|
||
tx.shortDescription = query.value("short_description").toString();
|
||
tx.updatedShortDescription = query.value("updated_short_description").toString();
|
||
tx.bankName = query.value("bank_name").toString();
|
||
tx.bankTime = query.value("bank_time").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());
|
||
return tx;
|
||
}
|
||
|
||
|
||
QList<TransactionInfo> TransactionDAO::getTransactions(const int accountId) {
|
||
QList<TransactionInfo> list;
|
||
QSqlQuery query(DatabaseManager::instance().database());
|
||
|
||
query.prepare(R"(
|
||
SELECT * FROM transactions
|
||
WHERE account_id = :account_id
|
||
ORDER BY timestamp DESC
|
||
)");
|
||
|
||
query.bindValue(":account_id", accountId);
|
||
|
||
if (!query.exec()) {
|
||
qWarning() << "Ошибка при получении transactions:" << query.lastError().text();
|
||
return list;
|
||
}
|
||
|
||
while (query.next()) {
|
||
list.append(parseTransaction(query));
|
||
}
|
||
|
||
return list;
|
||
}
|
||
|
||
bool TransactionDAO::updateTransaction(const TransactionInfo &info) {
|
||
QSqlQuery query(DatabaseManager::instance().database());
|
||
|
||
qDebug().noquote().nospace() << convertTransactionToString(info);
|
||
|
||
query.prepare(R"(
|
||
UPDATE transactions SET
|
||
amount = :amount,
|
||
fee = :fee,
|
||
status = :status,
|
||
type = :type,
|
||
phone = :phone,
|
||
description = :description,
|
||
updated_description = :updated_description,
|
||
short_description = :short_description,
|
||
updated_short_description = :updated_short_description,
|
||
bank_name = :bank_name,
|
||
bank_time = :bank_time,
|
||
name = :name,
|
||
bank_tr_external_id = :bank_tr_external_id,
|
||
update_time = :update_time,
|
||
complete_time = :complete_time,
|
||
timestamp = :timestamp
|
||
WHERE id = :id
|
||
)");
|
||
|
||
query.bindValue(":id", info.id);
|
||
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(":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));
|
||
|
||
if (!query.exec()) {
|
||
qWarning() << "Ошибка при обновлении transaction:" << query.lastError().text();
|
||
return false;
|
||
}
|
||
|
||
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
|
||
)");
|
||
|
||
// const QString currentTime = now.toString("yyyy-MM-dd HH:mm:ss");
|
||
query.bindValue(":id", id);
|
||
query.bindValue(":status", transactionStatusToString(status));
|
||
query.bindValue(":update_time", DateUtils::toUtcString(DateUtils::getUtcNow()));
|
||
|
||
if (status == TransactionStatus::Complete) {
|
||
query.bindValue(":complete_time", DateUtils::toUtcString(DateUtils::getUtcNow()));
|
||
} else {
|
||
query.bindValue(":complete_time", QVariant(QMetaType(QMetaType::QString)));
|
||
}
|
||
|
||
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");
|
||
query.bindValue(":id", id);
|
||
|
||
|
||
if (!query.exec() || !query.next()) {
|
||
qWarning() << "Ошибка или не найден transaction с id:" << id << query.lastError().text();
|
||
return {};
|
||
}
|
||
return parseTransaction(query);
|
||
}
|
||
|
||
QList<TransactionInfo> TransactionDAO::getTransactionsWithinHours(const int accountId, const int hours) {
|
||
QList<TransactionInfo> list;
|
||
QSqlQuery query(DatabaseManager::instance().database());
|
||
query.prepare(R"(
|
||
SELECT * FROM transactions
|
||
WHERE account_id = :accountId
|
||
AND timestamp >= datetime('now', '-' || :hours || ' hours')
|
||
)");
|
||
query.bindValue(":accountId", accountId);
|
||
query.bindValue(":hours", hours);
|
||
|
||
if (!query.exec()) {
|
||
qWarning() << "Ошибка получения транзакций: " << query.lastError().text();
|
||
return {};
|
||
}
|
||
|
||
while (query.next()) {
|
||
list.append(parseTransaction(query));
|
||
}
|
||
return list;
|
||
}
|
||
|
||
bool TransactionDAO::updateTransaction(
|
||
const int id,
|
||
const TransactionStatus status,
|
||
const QString &oldDesc,
|
||
const QString &newDesc
|
||
) {
|
||
QSqlQuery query(DatabaseManager::instance().database());
|
||
|
||
query.prepare(R"(
|
||
UPDATE transactions SET
|
||
status = :status,
|
||
update_time = :update_time,
|
||
complete_time = :complete_time,
|
||
description = :description,
|
||
updated_description = :updated_description
|
||
WHERE id = :id
|
||
)");
|
||
|
||
query.bindValue(":id", id);
|
||
query.bindValue(":status", transactionStatusToString(status));
|
||
query.bindValue(":update_time", DateUtils::toUtcString(DateUtils::getUtcNow()));
|
||
|
||
if (oldDesc.isEmpty() || oldDesc != newDesc) {
|
||
query.bindValue(":description", newDesc);
|
||
query.bindValue(":updated_description", oldDesc);
|
||
} else {
|
||
query.bindValue(":description", newDesc);
|
||
query.bindValue(":updated_description", "");
|
||
}
|
||
|
||
if (status == TransactionStatus::Complete) {
|
||
query.bindValue(":complete_time", DateUtils::toUtcString(DateUtils::getUtcNow()));
|
||
} else {
|
||
query.bindValue(":complete_time", QVariant(QMetaType(QMetaType::QString)));
|
||
}
|
||
|
||
if (!query.exec()) {
|
||
qWarning() << "Ошибка при обновлении transaction:" << query.lastError().text();
|
||
return false;
|
||
}
|
||
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;
|
||
}
|