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) ); } }