Replaced `PayByPhoneScript` with `GetLastDaysHistoryScript` in `main.cpp`. Introduced enhanced date/time utilities and improved database timestamp handling with `DateUtils`. Refactored `TransactionDAO` methods to separate parsing logic and added support for retrieving recent transactions within specified hours. Added the `GetLastDaysHistoryScript` class to parse and save recent transaction history.
295 lines
11 KiB
C++
295 lines
11 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, 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,
|
||
: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(":tr_external_id", info.trExternalId);
|
||
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, 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", 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.trExternalId = query.value("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,
|
||
tr_external_id = :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(":tr_external_id", info.trExternalId);
|
||
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;
|
||
}
|