Files
SimpleAccount/SqlOpr.cpp
2026-02-27 12:29:27 +08:00

496 lines
14 KiB
C++

#include "SqlOpr.h"
#include <QFile>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QVariant>
ACTSqlOpr::~ACTSqlOpr()
{
if (db_.isOpen()) {
db_.close();
}
}
bool ACTSqlOpr::OpenDb(const std::string& path)
{
dbPath_ = path;
db_ = QSqlDatabase::addDatabase("QSQLITE", "account_connection");
db_.setDatabaseName(QString::fromStdString(path));
if (!db_.open()) {
lastErr_ = fmt::format("无法打开数据库:{}", db_.lastError().text().toStdString());
return false;
}
if (!generateDefaultTB()) {
return false;
}
return true;
}
bool ACTSqlOpr::UpdateAccount(AccountRecord& record)
{
QSqlQuery query(db_);
query.prepare("UPDATE account_records SET money = ?, pay_type = ?, dt = ?, "
"thing = ?, classify = ?, remark = ?, addition_file = ? WHERE id = ?");
query.addBindValue(record.money);
query.addBindValue(QString::fromStdString(record.payType));
query.addBindValue(QString::fromStdString(record.dt));
query.addBindValue(QString::fromStdString(record.thing));
query.addBindValue(QString::fromStdString(record.classify));
query.addBindValue(QString::fromStdString(record.remark));
query.addBindValue(QString::fromStdString(record.additionFile));
query.addBindValue(record.id);
if (!query.exec()) {
lastErr_ = fmt::format("执行更新失败: {}", query.lastError().text().toStdString());
return false;
}
return true;
}
QSqlDatabase& ACTSqlOpr::GetDb()
{
return db_;
}
const std::string& ACTSqlOpr::GetLastErr()
{
return lastErr_;
}
bool ACTSqlOpr::AppendAccount(AccountRecord& record)
{
QSqlQuery query(db_);
query.prepare("INSERT INTO account_records "
"(money, pay_type, dt, thing, classify, remark, addition_file) "
"VALUES (?, ?, ?, ?, ?, ?, ?)");
query.addBindValue(record.money);
query.addBindValue(QString::fromStdString(record.payType));
query.addBindValue(QString::fromStdString(record.dt));
query.addBindValue(QString::fromStdString(record.thing));
query.addBindValue(QString::fromStdString(record.classify));
query.addBindValue(QString::fromStdString(record.remark));
query.addBindValue(QString::fromStdString(record.additionFile));
if (!query.exec()) {
lastErr_ = fmt::format("执行插入失败: {}", query.lastError().text().toStdString());
return false;
}
record.id = query.lastInsertId().toInt();
return true;
}
bool ACTSqlOpr::DeleteAccount(int32_t id)
{
QSqlQuery query(db_);
query.prepare("DELETE FROM account_records WHERE id = ?");
query.addBindValue(id);
if (!query.exec()) {
lastErr_ = fmt::format("执行删除失败: {}", query.lastError().text().toStdString());
return false;
}
return true;
}
bool ACTSqlOpr::GetAccountList(AccountRecordList& ret)
{
QSqlQuery query(db_);
query.prepare("SELECT id, money, pay_type, dt, thing, classify, remark, addition_file "
"FROM account_records ORDER BY dt DESC");
if (!query.exec()) {
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
return false;
}
ret.clear();
while (query.next()) {
AccountRecord record;
record.id = query.value(0).toInt();
record.money = query.value(1).toInt();
record.payType = query.value(2).toString().toStdString();
record.dt = query.value(3).toString().toStdString();
record.thing = query.value(4).toString().toStdString();
record.classify = query.value(5).toString().toStdString();
record.remark = query.value(6).toString().toStdString();
record.additionFile = query.value(7).toString().toStdString();
ret.push_back(record);
}
return true;
}
bool ACTSqlOpr::generateDefaultTB()
{
QSqlQuery query(db_);
QString sql = "CREATE TABLE IF NOT EXISTS account_records ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"money INTEGER NOT NULL, "
"pay_type TEXT NOT NULL, "
"dt TEXT NOT NULL, "
"thing TEXT, "
"classify TEXT, "
"remark TEXT, "
"addition_file TEXT)";
if (!query.exec(sql)) {
lastErr_ = fmt::format("创建表失败: {}", query.lastError().text().toStdString());
return false;
}
return true;
}
ACTSqlOpr::ACTSqlOpr()
{
}
ComSqlOpr::ComSqlOpr(QSqlDatabase& db) : db_(db)
{
generateDefaultTB();
CheckContent();
}
bool ComSqlOpr::GetClassifyList(ClassifyRecordList& ret)
{
QSqlQuery query(db_);
query.prepare("SELECT id, key, value, type, mark FROM common_records WHERE key = '分类'");
if (!query.exec()) {
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
return false;
}
ret.clear();
while (query.next()) {
CommonRecord record;
record.id = query.value(0).toInt();
record.key = query.value(1).toString().toStdString();
record.value = query.value(2).toString().toStdString();
record.type = query.value(3).toString().toStdString();
record.mark = query.value(4).toString().toStdString();
ret.push_back(record);
}
return true;
}
bool ComSqlOpr::GetItem(CommonRecord& ret, const std::string& key)
{
QSqlQuery query(db_);
query.prepare("SELECT id, key, value, type, mark FROM common_records "
"WHERE key = ? ORDER BY id DESC LIMIT 1");
query.addBindValue(QString::fromStdString(key));
if (!query.exec()) {
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
return false;
}
if (query.next()) {
ret.id = query.value(0).toInt();
ret.key = query.value(1).toString().toStdString();
ret.value = query.value(2).toString().toStdString();
ret.type = query.value(3).toString().toStdString();
ret.mark = query.value(4).toString().toStdString();
return true;
}
lastErr_ = fmt::format("未找到key为'{}'的记录", key);
return false;
}
bool ComSqlOpr::UpdateItem(CommonRecord& ret)
{
if (ret.id <= 0) {
lastErr_ = "无效的记录ID";
return false;
}
QSqlQuery query(db_);
query.prepare("UPDATE common_records SET "
"key = ?, value = ?, type = ?, mark = ? "
"WHERE id = ?");
query.addBindValue(QString::fromStdString(ret.key));
query.addBindValue(QString::fromStdString(ret.value));
query.addBindValue(QString::fromStdString(ret.type));
query.addBindValue(QString::fromStdString(ret.mark));
query.addBindValue(ret.id);
if (!query.exec()) {
lastErr_ = fmt::format("更新失败: {}", query.lastError().text().toStdString());
return false;
}
return true;
}
bool ComSqlOpr::InserItem(CommonRecord& ret)
{
QSqlQuery query(db_);
query.prepare("INSERT INTO common_records (key, value, type, mark) "
"VALUES (?, ?, ?, ?)");
query.addBindValue(QString::fromStdString(ret.key));
query.addBindValue(QString::fromStdString(ret.value));
query.addBindValue(QString::fromStdString(ret.type));
query.addBindValue(QString::fromStdString(ret.mark));
if (!query.exec()) {
lastErr_ = fmt::format("插入失败: {}", query.lastError().text().toStdString());
return false;
}
ret.id = query.lastInsertId().toInt();
return true;
}
bool ComSqlOpr::DeleteItem(const std::string& value)
{
QSqlQuery query(db_);
query.prepare("DELETE FROM common_records WHERE value = ? and key = '分类'");
query.addBindValue(QString::fromStdString(value));
if (!query.exec()) {
lastErr_ = fmt::format("删除失败: {}", query.lastError().text().toStdString());
return false;
}
if (query.numRowsAffected() == 0) {
lastErr_ = fmt::format("未找到value为'{}'的记录", value);
return false;
}
return true;
}
bool ComSqlOpr::CheckContent()
{
if (!db_.transaction()) {
lastErr_ = fmt::format("开始事务失败: {}", db_.lastError().text().toStdString());
return false;
}
const std::vector<std::tuple<std::string, std::string>> defaultCategories = {{"分类", "默认"}};
for (const auto& [key, val] : defaultCategories) {
if (!CheckAndInsert(key, val, "", "")) {
db_.rollback();
return false;
}
}
if (!db_.commit()) {
lastErr_ = fmt::format("提交事务失败: {}", db_.lastError().text().toStdString());
return false;
}
return true;
}
bool ComSqlOpr::CheckClassifyExist(const std::string& value)
{
QSqlQuery query(db_);
query.prepare("SELECT 1 FROM common_records WHERE value = ? and key = '分类'");
query.addBindValue(QString::fromStdString(value));
if (!query.exec()) {
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
return false;
}
return query.next();
}
const std::string& ComSqlOpr::GetLastErr()
{
return lastErr_;
}
bool ComSqlOpr::CheckAndInsert(const std::string& key, const std::string& value, const std::string& type, const std::string& mark)
{
QSqlQuery query(db_);
query.prepare("SELECT 1 FROM common_records WHERE key = ? LIMIT 1");
query.addBindValue(QString::fromStdString(key));
if (!query.exec()) {
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
return false;
}
if (query.next()) {
return true; // 记录已存在
}
query.prepare("INSERT INTO common_records (key, value, type, mark) VALUES (?, ?, ?, ?)");
query.addBindValue(QString::fromStdString(key));
query.addBindValue(QString::fromStdString(value));
query.addBindValue(QString::fromStdString(type));
query.addBindValue(QString::fromStdString(mark));
if (!query.exec()) {
lastErr_ = fmt::format("插入失败: {}", query.lastError().text().toStdString());
return false;
}
return true;
}
bool ComSqlOpr::generateDefaultTB()
{
QSqlQuery query(db_);
QString sql = "CREATE TABLE IF NOT EXISTS common_records ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"key TEXT NOT NULL, "
"value TEXT, "
"type TEXT, "
"mark TEXT)";
if (!query.exec(sql)) {
lastErr_ = fmt::format("创建表失败: {}", query.lastError().text().toStdString());
return false;
}
return true;
}
RepaySqlOpr::RepaySqlOpr(QSqlDatabase& db) : db_(db)
{
generateDefaultTB();
}
bool RepaySqlOpr::GetRepayResult(RepayRecordList& ret, int32_t accID)
{
ret.clear();
lastErr_.clear();
if (!db_.isOpen()) {
lastErr_ = "Database is not open";
return false;
}
QSqlQuery query(db_);
query.prepare("SELECT id, accID, money, dt, remark FROM repay_record WHERE accID = :accID");
query.bindValue(":accID", accID);
if (!query.exec()) {
lastErr_ = query.lastError().text().toStdString();
return false;
}
while (query.next()) {
RepayRecord record;
record.id = query.value("id").toInt();
record.accID = query.value("accID").toInt();
record.money = query.value("money").toInt();
record.dt = query.value("dt").toString().toStdString();
record.remark = query.value("remark").toString().toStdString();
ret.push_back(record);
}
return true;
}
bool RepaySqlOpr::InsertRepayRecord(RepayRecord& ret)
{
lastErr_.clear();
if (!db_.isOpen()) {
lastErr_ = "Database is not open";
return false;
}
QSqlQuery query(db_);
query.prepare("INSERT INTO repay_record (accID, money, dt, remark) "
"VALUES (:accID, :money, :dt, :remark)");
query.bindValue(":accID", ret.accID);
query.bindValue(":money", ret.money);
query.bindValue(":dt", QString::fromStdString(ret.dt));
query.bindValue(":remark", QString::fromStdString(ret.remark));
if (!query.exec()) {
lastErr_ = query.lastError().text().toStdString();
return false;
}
// Get the auto-generated id
ret.id = query.lastInsertId().toInt();
return true;
}
bool RepaySqlOpr::updateRepayRecord(RepayRecord& ret)
{
lastErr_.clear();
if (!db_.isOpen()) {
lastErr_ = "Database is not open";
return false;
}
QSqlQuery query(db_);
query.prepare("UPDATE repay_record SET accID = :accID, money = :money, "
"dt = :dt, remark = :remark WHERE id = :id");
query.bindValue(":accID", ret.accID);
query.bindValue(":money", ret.money);
query.bindValue(":dt", QString::fromStdString(ret.dt));
query.bindValue(":remark", QString::fromStdString(ret.remark));
query.bindValue(":id", ret.id);
if (!query.exec()) {
lastErr_ = query.lastError().text().toStdString();
return false;
}
return query.numRowsAffected() > 0;
}
bool RepaySqlOpr::deleteRepayRecord(int32_t id)
{
lastErr_.clear();
if (!db_.isOpen()) {
lastErr_ = "Database is not open";
return false;
}
QSqlQuery query(db_);
query.prepare("DELETE FROM repay_record WHERE id = :id");
query.bindValue(":id", id);
if (!query.exec()) {
lastErr_ = query.lastError().text().toStdString();
return false;
}
return query.numRowsAffected() > 0;
}
const std::string& RepaySqlOpr::GetLastErr()
{
return lastErr_;
}
bool RepaySqlOpr::generateDefaultTB()
{
lastErr_.clear();
if (!db_.isOpen()) {
lastErr_ = "Database is not open";
return false;
}
QSqlQuery query(db_);
QString createTable = "CREATE TABLE IF NOT EXISTS repay_record ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"accID INTEGER NOT NULL, "
"money INTEGER NOT NULL, "
"dt TEXT NOT NULL, "
"remark TEXT)";
if (!query.exec(createTable)) {
lastErr_ = query.lastError().text().toStdString();
return false;
}
return true;
}