15 std::shared_ptr<SqliteDb>
db;
16 std::shared_ptr<core::ports::diagnostics::IErrorReporter>
errorReporter;
20 const std::string& dbPath)
25 const std::string& dbPath,
26 std::shared_ptr<core::ports::diagnostics::IErrorReporter> er)
31 std::shared_ptr<SqliteDb> db)
35 std::shared_ptr<SqliteDb> db,
36 std::shared_ptr<core::ports::diagnostics::IErrorReporter> er)
37 : pimpl_(std::make_unique<
Impl>()) {
39 throw std::runtime_error(
"db is null");
40 pimpl_->db = std::move(db);
41 pimpl_->errorReporter = std::move(er);
48constexpr auto kSelectTx =
49 "SELECT id, name, booking_date, amount, statement_id,"
50 " status, actor_id, allocatable, contract_id, valuta, created_at, "
51 "updated_at FROM transactions";
54 const std::string& value) {
56 sqlite3_bind_null(stmt.
get(), column);
64 "WHERE transaction_id = ?;");
67 s.bindText(1, t.
id());
68 while (s.step() == SQLITE_ROW)
73 auto t = std::make_shared<Transaction>();
86 loadTxProperties(db, *t);
90void insertTxProperties(sqlite3* db,
const Transaction& t) {
92 "(transaction_id, property_id) VALUES (?, ?);");
105void deleteTxProperties(sqlite3* db,
const std::string& txId) {
107 db,
"DELETE FROM transaction_properties WHERE transaction_id = ?;");
117 const std::shared_ptr<Transaction>& transaction) {
118 if (!transaction || transaction->id().empty())
121 "INSERT OR IGNORE INTO transactions"
122 " (id, name, booking_date, amount, statement_id,"
123 " status, actor_id, allocatable, contract_id, "
124 "valuta, created_at, updated_at)"
125 " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
128 stmt.
bindText(1, transaction->id());
129 stmt.
bindText(2, transaction->name());
130 stmt.
bindText(3, transaction->bookingDate());
132 bindNullableText(stmt, 5, transaction->statementId());
133 stmt.
bindInt(6,
static_cast<int>(transaction->status()));
134 bindNullableText(stmt, 7, transaction->actorId());
135 stmt.
bindInt(8, transaction->isAllocatable() ? 1 : 0);
136 bindNullableText(stmt, 9, transaction->contractId());
137 stmt.
bindText(10, transaction->valuta());
138 stmt.
bindText(11, transaction->createdAt());
139 stmt.
bindText(12, transaction->updatedAt());
140 if (stmt.
step() == SQLITE_DONE)
141 insertTxProperties(pimpl_->db->handle(), *transaction);
144std::vector<std::shared_ptr<Transaction>>
146 std::vector<std::shared_ptr<Transaction>> out;
148 std::string(kSelectTx) +
" ORDER BY rowid;");
151 while (stmt.
step() == SQLITE_ROW)
152 out.push_back(readTx(stmt, pimpl_->db->handle()));
156std::optional<std::shared_ptr<Transaction>>
161 pimpl_->db->handle(), std::string(kSelectTx) +
" WHERE id = ? LIMIT 1;");
165 if (stmt.
step() != SQLITE_ROW)
167 return readTx(stmt, pimpl_->db->handle());
173 deleteTxProperties(pimpl_->db->handle(),
id);
175 "DELETE FROM transactions WHERE id = ?;");
183 const std::shared_ptr<Transaction>& transaction) {
184 if (!transaction || transaction->id().empty())
187 pimpl_->db->handle(),
188 "UPDATE transactions SET name=?, booking_date=?, amount=?,"
189 " statement_id=?, status=?, actor_id=?, allocatable=?, contract_id=?, "
190 "valuta=?, created_at=?, updated_at=?"
194 stmt.
bindText(1, transaction->name());
195 stmt.
bindText(2, transaction->bookingDate());
197 bindNullableText(stmt, 4, transaction->statementId());
198 stmt.
bindInt(5,
static_cast<int>(transaction->status()));
199 bindNullableText(stmt, 6, transaction->actorId());
200 stmt.
bindInt(7, transaction->isAllocatable() ? 1 : 0);
201 bindNullableText(stmt, 8, transaction->contractId());
202 stmt.
bindText(9, transaction->valuta());
203 stmt.
bindText(10, transaction->createdAt());
204 stmt.
bindText(11, transaction->updatedAt());
205 stmt.
bindText(12, transaction->id());
207 deleteTxProperties(pimpl_->db->handle(), transaction->id());
208 insertTxProperties(pimpl_->db->handle(), *transaction);
212 const std::shared_ptr<Transaction>& transaction) {
213 if (!transaction || transaction->id().empty())
217 pimpl_->db->handle(),
218 "INSERT INTO transactions (id, name, booking_date, amount, statement_id, "
219 "status, actor_id, allocatable, contract_id, valuta, created_at, "
221 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
222 "ON CONFLICT(id) DO UPDATE SET "
223 "name = excluded.name, booking_date = excluded.booking_date, amount = "
225 "statement_id = excluded.statement_id, status = excluded.status, "
226 "actor_id = excluded.actor_id, allocatable = excluded.allocatable, "
227 "contract_id = excluded.contract_id, valuta = excluded.valuta, "
228 "created_at = excluded.created_at, updated_at = excluded.updated_at;");
233 stmt.
bindText(1, transaction->id());
234 stmt.
bindText(2, transaction->name());
235 stmt.
bindText(3, transaction->bookingDate());
237 bindNullableText(stmt, 5, transaction->statementId());
238 stmt.
bindInt(6,
static_cast<int>(transaction->status()));
239 bindNullableText(stmt, 7, transaction->actorId());
240 stmt.
bindInt(8, transaction->isAllocatable() ? 1 : 0);
241 bindNullableText(stmt, 9, transaction->contractId());
242 stmt.
bindText(10, transaction->valuta());
243 stmt.
bindText(11, transaction->createdAt());
244 stmt.
bindText(12, transaction->updatedAt());
248 deleteTxProperties(pimpl_->db->handle(), transaction->id());
249 insertTxProperties(pimpl_->db->handle(), *transaction);
254 sqlite3_exec(pimpl_->db->handle(),
255 "DELETE FROM transaction_properties; DELETE FROM transactions;",
256 nullptr,
nullptr, &err);
261std::vector<std::shared_ptr<Transaction>>
263 const std::string& contractId)
const {
264 std::vector<std::shared_ptr<Transaction>> out;
266 pimpl_->db->handle(), std::string(kSelectTx) +
" WHERE contract_id = ?;");
270 while (stmt.
step() == SQLITE_ROW)
271 out.push_back(readTx(stmt, pimpl_->db->handle()));
276 const std::string& contractId,
277 const std::vector<std::string>& transactionIds) {
278 if (transactionIds.empty())
280 std::vector<std::string> ids;
281 ids.reserve(transactionIds.size());
282 for (
const auto&
id : transactionIds)
290 std::string sql =
"UPDATE transactions SET contract_id = ? WHERE id IN (";
291 for (
size_t i = 0; i < ids.size(); ++i) {
303 for (
size_t i = 0; i < ids.size(); ++i) {
304 stmt.
bindText(
static_cast<int>(i + 2), ids[i]);
Declares the lightweight SQLite connection wrapper.
Declares a lightweight SQLite transaction guard.
Declares the SQLite-backed transaction repository.
RAII wrapper for sqlite3_stmt* that auto-finalizes on destruction.
Domain model for transactions.
void commit()
Commit the transaction.
void upsertTransaction(const std::shared_ptr< core::domain::Transaction > &transaction) override
Insert or update a transaction.
void updateTransaction(const std::shared_ptr< core::domain::Transaction > &transaction) override
Update an existing transaction.
void clearTransactions() override
Remove all transactions.
void removeTransaction(const std::string &id) override
Remove a transaction by identifier.
~SqliteTransactionRepository() override
Destroy the repository.
std::vector< std::shared_ptr< core::domain::Transaction > > getTransactions() const override
Retrieve all transactions.
void addTransaction(const std::shared_ptr< core::domain::Transaction > &transaction) override
Insert a new transaction.
SqliteTransactionRepository(const std::string &dbPath)
Create a transaction repository for the database at the given path.
std::optional< std::shared_ptr< core::domain::Transaction > > getTransactionById(const std::string &id) const override
Retrieve a transaction by identifier.
std::vector< std::shared_ptr< core::domain::Transaction > > getTransactionsForContract(const std::string &contractId) const override
Retrieve transactions associated with a given contract.
void assignTransactionsToContract(const std::string &contractId, const std::vector< std::string > &transactionIds) override
Assign transactions to a contract.
void setAmount(MoneyAmount value)
Sets the amount from a value object.
void setStatementId(std::string value)
Sets the statement id.
void setActorId(std::string value)
Sets the actor id.
void setName(EntityName value)
Sets the transaction name from a value object.
void setStatus(Status value)
Sets the transaction status.
void setValuta(std::string value)
Sets the valuta text.
void setContractId(std::string value)
Sets the contract id.
const std::string & id() const noexcept
const std::vector< std::string > & propertyIds() const noexcept
void addPropertyId(std::string value)
Adds a property id when it is not already present.
void setCreatedAt(std::string value)
void setBookingDate(BookingDate value)
Sets the booking date from a value object.
void setId(std::string value)
void setUpdatedAt(std::string value)
void setAllocatable(bool value)
Sets the allocatable flag.
std::string columnText(int col) const noexcept
sqlite3_stmt * get() const noexcept
void bindInt(int col, int v) noexcept
double columnDouble(int col) const noexcept
void bindText(int col, const std::string &v) noexcept
int columnInt(int col) const noexcept
void bindDouble(int col, double v) noexcept
std::shared_ptr< core::ports::diagnostics::IErrorReporter > errorReporter
std::shared_ptr< SqliteDb > db