Add database schema and DAO implementation for accounts and transactions
Introduced tables for devices, accounts, and transactions in the schema, along with associated models. Implemented DAO methods for CRUD operations, including upsert functionality for accounts and deduplication for transactions. These changes enable structured management of account and transaction data.
This commit is contained in:
parent
d56b91425c
commit
d21e7f4048
74
database/dao/AccountDAO.cpp
Normal file
74
database/dao/AccountDAO.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include "AccountDAO.h"
|
||||
|
||||
#include "AccountInfo.h"
|
||||
#include "DatabaseManager.h"
|
||||
|
||||
bool AccountDAO::upsertAccount(const AccountInfo &info) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
query.prepare(R"(
|
||||
INSERT INTO accounts (device_id, app_name, card_name, amount, update_time, status)
|
||||
VALUES (:device_id, :app_name, :card_name, :amount, :update_time, :status)
|
||||
ON CONFLICT(device_id, app_name, card_name)
|
||||
DO UPDATE SET
|
||||
amount = excluded.amount,
|
||||
update_time = excluded.update_time,
|
||||
status = excluded.status
|
||||
)");
|
||||
|
||||
query.bindValue(":device_id", info.deviceId);
|
||||
query.bindValue(":app_name", info.appName);
|
||||
query.bindValue(":card_name", info.cardName);
|
||||
query.bindValue(":amount", info.amount);
|
||||
query.bindValue(":update_time", info.updateTime.toString(Qt::ISODate));
|
||||
query.bindValue(":status", info.status);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при вставке/обновлении account:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AccountDAO::deleteAccount(const int id) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
query.prepare("DELETE FROM accounts WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
return query.exec();
|
||||
}
|
||||
|
||||
QList<AccountInfo> AccountDAO::getAccounts(const QString &deviceId, const QString &appName) {
|
||||
QList<AccountInfo> accounts;
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
query.prepare(R"(
|
||||
SELECT id, device_id, app_name, card_name, amount, update_time, status
|
||||
FROM accounts
|
||||
WHERE device_id = :device_id AND app_name = :app_name
|
||||
)");
|
||||
|
||||
query.bindValue(":device_id", deviceId);
|
||||
query.bindValue(":app_name", appName);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при получении accounts:" << query.lastError().text();
|
||||
return accounts;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
AccountInfo acc;
|
||||
acc.id = query.value("id").toInt();
|
||||
acc.deviceId = query.value("device_id").toString();
|
||||
acc.appName = query.value("app_name").toString();
|
||||
acc.cardName = query.value("card_name").toString();
|
||||
acc.amount = query.value("amount").toDouble();
|
||||
acc.updateTime = QDateTime::fromString(query.value("update_time").toString(), Qt::ISODate);
|
||||
acc.status = query.value("status").toString();
|
||||
accounts.append(acc);
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
11
database/dao/AccountDAO.h
Normal file
11
database/dao/AccountDAO.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "AccountInfo.h"
|
||||
|
||||
class AccountDAO {
|
||||
public:
|
||||
[[nodiscard]] static bool upsertAccount(const AccountInfo &info);
|
||||
|
||||
[[nodiscard]] static bool deleteAccount(int id);
|
||||
|
||||
[[nodiscard]] static QList<AccountInfo> getAccounts(const QString &deviceId, const QString &appName);
|
||||
};
|
||||
82
database/dao/TransactionDAO.cpp
Normal file
82
database/dao/TransactionDAO.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
|
||||
#include "DatabaseManager.h"
|
||||
#include "TransactionDAO.h"
|
||||
|
||||
bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
query.prepare(R"(
|
||||
SELECT COUNT(*) FROM transactions
|
||||
WHERE account_id = :account_id AND amount = :amount AND timestamp = :timestamp
|
||||
)");
|
||||
|
||||
query.bindValue(":account_id", info.accountId);
|
||||
query.bindValue(":amount", info.amount);
|
||||
query.bindValue(":timestamp", info.timestamp.toString(Qt::ISODate));
|
||||
|
||||
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, description, timestamp)
|
||||
VALUES (:account_id, :amount, :description, :timestamp)
|
||||
)");
|
||||
|
||||
query.bindValue(":account_id", info.accountId);
|
||||
query.bindValue(":amount", info.amount);
|
||||
query.bindValue(":description", info.description);
|
||||
query.bindValue(":timestamp", info.timestamp.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");
|
||||
query.bindValue(":id", id);
|
||||
return query.exec();
|
||||
}
|
||||
|
||||
QList<TransactionInfo> TransactionDAO::getTransactions(const int accountId) {
|
||||
QList<TransactionInfo> list;
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
query.prepare(R"(
|
||||
SELECT id, account_id, amount, description, timestamp
|
||||
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()) {
|
||||
TransactionInfo tx;
|
||||
tx.id = query.value("id").toInt();
|
||||
tx.accountId = query.value("account_id").toInt();
|
||||
tx.amount = query.value("amount").toDouble();
|
||||
tx.description = query.value("description").toString();
|
||||
tx.timestamp = QDateTime::fromString(query.value("timestamp").toString(), Qt::ISODate);
|
||||
list.append(tx);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
11
database/dao/TransactionDAO.h
Normal file
11
database/dao/TransactionDAO.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "TransactionInfo.h"
|
||||
|
||||
class TransactionDAO {
|
||||
public:
|
||||
[[nodiscard]] static bool insertTransactionIfNotExists(const TransactionInfo &info);
|
||||
|
||||
[[nodiscard]] static bool deleteTransaction(int id);
|
||||
|
||||
[[nodiscard]] static QList<TransactionInfo> getTransactions(int accountId);
|
||||
};
|
||||
37
migrations.sql
Normal file
37
migrations.sql
Normal file
@ -0,0 +1,37 @@
|
||||
CREATE TABLE IF NOT EXISTS devices
|
||||
(
|
||||
id TEXT PRIMARY KEY,
|
||||
status TEXT,
|
||||
name TEXT,
|
||||
android TEXT,
|
||||
screen_width INTEGER,
|
||||
screen_height INTEGER,
|
||||
battery INTEGER,
|
||||
update_time DATETIME,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
image BLOB
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS accounts
|
||||
(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
device_id TEXT,
|
||||
app_name TEXT,
|
||||
card_name TEXT,
|
||||
amount REAL,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
status TEXT,
|
||||
FOREIGN KEY (device_id) REFERENCES devices (id) ON DELETE CASCADE,
|
||||
UNIQUE (device_id, app_name, card_name)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS transactions
|
||||
(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER,
|
||||
amount REAL,
|
||||
description TEXT,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (account_id) REFERENCES accounts (id) ON DELETE CASCADE,
|
||||
UNIQUE (amount, timestamp)
|
||||
);
|
||||
13
models/AccountInfo.h
Normal file
13
models/AccountInfo.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
struct AccountInfo {
|
||||
int id;
|
||||
QString deviceId;
|
||||
QString appName;
|
||||
QString cardName;
|
||||
double amount;
|
||||
QDateTime updateTime;
|
||||
QString status;
|
||||
};
|
||||
11
models/TransactionInfo.h
Normal file
11
models/TransactionInfo.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
struct TransactionInfo {
|
||||
int id;
|
||||
int accountId;
|
||||
double amount;
|
||||
QString description;
|
||||
QDateTime timestamp;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user