2024-09-19 19:12:23 +00:00
|
|
|
module transaction.data_impl_sqlite;
|
|
|
|
|
|
|
|
import handy_httpd.components.optional;
|
|
|
|
import std.datetime;
|
|
|
|
import d2sqlite3;
|
|
|
|
|
|
|
|
import transaction.model;
|
|
|
|
import transaction.data;
|
|
|
|
import util.sqlite;
|
|
|
|
import util.money;
|
|
|
|
|
|
|
|
class SqliteTransactionVendorRepository : TransactionVendorRepository {
|
|
|
|
private Database db;
|
|
|
|
this(Database db) {
|
|
|
|
this.db = db;
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional!TransactionVendor findById(ulong id) {
|
|
|
|
return util.sqlite.findById(db, "transaction_vendor", &parseVendor, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionVendor[] findAll() {
|
|
|
|
return util.sqlite.findAll(
|
|
|
|
db,
|
|
|
|
"SELECT * FROM transaction_vendor ORDER BY name ASC",
|
|
|
|
&parseVendor
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool existsByName(string name) {
|
|
|
|
return util.sqlite.exists(db, "SELECT id FROM transaction_vendor WHERE name = ?", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionVendor insert(string name, string description) {
|
|
|
|
util.sqlite.update(
|
|
|
|
db,
|
|
|
|
"INSERT INTO transaction_vendor (name, description) VALUES (?, ?)",
|
|
|
|
name, description
|
|
|
|
);
|
|
|
|
ulong id = db.lastInsertRowid();
|
|
|
|
return findById(id).orElseThrow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void deleteById(ulong id) {
|
|
|
|
util.sqlite.deleteById(db, "transaction_vendor", id);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionVendor updateById(ulong id, string name, string description) {
|
|
|
|
util.sqlite.update(
|
|
|
|
db,
|
|
|
|
"UPDATE transaction_vendor SET name = ?, description = ? WHERE id = ?",
|
|
|
|
name, description, id
|
|
|
|
);
|
|
|
|
return findById(id).orElseThrow();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static TransactionVendor parseVendor(Row row) {
|
|
|
|
return TransactionVendor(
|
|
|
|
row.peek!ulong(0),
|
|
|
|
row.peek!string(1),
|
|
|
|
row.peek!string(2)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class SqliteTransactionCategoryRepository : TransactionCategoryRepository {
|
|
|
|
private Database db;
|
|
|
|
this(Database db) {
|
|
|
|
this.db = db;
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional!TransactionCategory findById(ulong id) {
|
|
|
|
return util.sqlite.findById(db, "transaction_category", &parseCategory, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionCategory[] findAllByParentId(Optional!ulong parentId) {
|
|
|
|
if (parentId) {
|
|
|
|
return util.sqlite.findAll(
|
|
|
|
db,
|
|
|
|
"SELECT * FROM transaction_category WHERE parent_id = ? ORDER BY name ASC",
|
|
|
|
&parseCategory,
|
|
|
|
parentId.value
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return util.sqlite.findAll(
|
|
|
|
db,
|
|
|
|
"SELECT * FROM transaction_category WHERE parent_id IS NULL ORDER BY name ASC",
|
|
|
|
&parseCategory
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionCategory insert(Optional!ulong parentId, string name, string description, string color) {
|
|
|
|
util.sqlite.update(
|
|
|
|
db,
|
|
|
|
"INSERT INTO transaction_category
|
|
|
|
(parent_id, name, description, color)
|
|
|
|
VALUES (?, ?, ?, ?)",
|
|
|
|
parentId.asNullable(), name, description, color
|
|
|
|
);
|
|
|
|
ulong id = db.lastInsertRowid();
|
|
|
|
return findById(id).orElseThrow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void deleteById(ulong id) {
|
|
|
|
util.sqlite.deleteById(db, "transaction_category", id);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionCategory updateById(ulong id, string name, string description, string color) {
|
|
|
|
util.sqlite.update(
|
|
|
|
db,
|
|
|
|
"UPDATE transaction_category
|
|
|
|
SET name = ?, description = ?, color = ?
|
|
|
|
WHERE id = ?",
|
|
|
|
name, description, color, id
|
|
|
|
);
|
|
|
|
return findById(id).orElseThrow();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static TransactionCategory parseCategory(Row row) {
|
|
|
|
import std.typecons;
|
|
|
|
return TransactionCategory(
|
|
|
|
row.peek!ulong(0),
|
|
|
|
Optional!ulong.of(row.peek!(Nullable!ulong)(1)),
|
|
|
|
row.peek!string(2),
|
|
|
|
row.peek!string(3),
|
|
|
|
row.peek!string(4)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class SqliteTransactionTagRepository : TransactionTagRepository {
|
|
|
|
private Database db;
|
|
|
|
this(Database db) {
|
|
|
|
this.db = db;
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional!TransactionTag findById(ulong id) {
|
|
|
|
return findOne(db, "SELECT * FROM transaction_tag WHERE id = ?", &parseTag, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional!TransactionTag findByName(string name) {
|
|
|
|
return findOne(db, "SELECT * FROM transaction_tag WHERE name = ?", &parseTag, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionTag[] findAll() {
|
|
|
|
return util.sqlite.findAll(
|
|
|
|
db,
|
|
|
|
"SELECT * FROM transaction_tag ORDER BY name ASC",
|
|
|
|
&parseTag
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransactionTag insert(string name) {
|
|
|
|
auto existingTag = findByName(name);
|
|
|
|
if (existingTag) {
|
|
|
|
return existingTag.value;
|
|
|
|
}
|
|
|
|
util.sqlite.update(
|
|
|
|
db,
|
|
|
|
"INSERT INTO transaction_tag (name) VALUES (?)",
|
|
|
|
name
|
|
|
|
);
|
|
|
|
ulong id = db.lastInsertRowid();
|
|
|
|
return findById(id).orElseThrow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void deleteById(ulong id) {
|
|
|
|
util.sqlite.update(
|
|
|
|
db,
|
|
|
|
"DELETE FROM transaction_tag WHERE id = ?",
|
|
|
|
id
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static TransactionTag parseTag(Row row) {
|
|
|
|
return TransactionTag(
|
|
|
|
row.peek!ulong(0),
|
|
|
|
row.peek!string(1)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2024-09-27 15:35:08 +00:00
|
|
|
|
|
|
|
class SqliteTransactionRepository : TransactionRepository {
|
|
|
|
private const TABLE_NAME = "\"transaction\"";
|
|
|
|
private Database db;
|
|
|
|
this(Database db) {
|
|
|
|
this.db = db;
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional!Transaction findById(ulong id) {
|
|
|
|
return util.sqlite.findById(db, TABLE_NAME, &parseTransaction, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
Transaction insert(
|
|
|
|
SysTime timestamp,
|
|
|
|
SysTime addedAt,
|
|
|
|
ulong amount,
|
|
|
|
Currency currency,
|
|
|
|
string description,
|
|
|
|
Optional!ulong vendorId,
|
|
|
|
Optional!ulong categoryId
|
|
|
|
) {
|
|
|
|
util.sqlite.update(
|
|
|
|
db,
|
|
|
|
"INSERT INTO " ~ TABLE_NAME ~ "
|
|
|
|
(timestamp, added_at, amount, currency, description, vendor_id, category_id)
|
|
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
|
|
timestamp.toISOExtString(),
|
|
|
|
addedAt.toISOExtString(),
|
|
|
|
amount,
|
|
|
|
currency.code,
|
|
|
|
description,
|
|
|
|
vendorId.asNullable,
|
|
|
|
categoryId.asNullable
|
|
|
|
);
|
|
|
|
ulong id = db.lastInsertRowid();
|
|
|
|
return findById(id).orElseThrow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void deleteById(ulong id) {
|
|
|
|
util.sqlite.deleteById(db, TABLE_NAME, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Transaction parseTransaction(Row row) {
|
|
|
|
import std.typecons : Nullable;
|
|
|
|
return Transaction(
|
|
|
|
row.peek!ulong(0),
|
|
|
|
SysTime.fromISOExtString(row.peek!string(1)),
|
|
|
|
SysTime.fromISOExtString(row.peek!string(2)),
|
|
|
|
row.peek!ulong(3),
|
|
|
|
Currency.ofCode(row.peek!(string, PeekMode.slice)(4)),
|
|
|
|
row.peek!string(5),
|
|
|
|
Optional!(ulong).of(row.peek!(Nullable!ulong)(6)),
|
|
|
|
Optional!(ulong).of(row.peek!(Nullable!ulong)(7))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|