21 const std::string& value) {
23 sqlite3_bind_null(stmt.
get(), column);
30 const std::vector<uint8_t>& value) {
32 sqlite3_bind_null(stmt.
get(), column);
35 sqlite3_bind_blob(stmt.
get(), column, value.data(),
36 static_cast<int>(value.size()), SQLITE_TRANSIENT);
39int nextTransactionDraftPosition(sqlite3* db) {
45 db,
"SELECT COALESCE(MAX(position), -1) + 1 FROM transaction_drafts;");
49 if (stmt.
step() != SQLITE_ROW) {
56void removeTransactionDraftProperties(sqlite3* db,
const std::string&
id) {
58 "WHERE transaction_draft_id = ?;");
67void upsertTransactionDraftProperties(
71 db,
"INSERT OR REPLACE INTO transaction_draft_properties "
72 "(transaction_draft_id, property_position, property_id) VALUES (?, "
78 for (std::size_t propertyIndex = 0; propertyIndex < draft.
propertyIds.size();
80 const auto& propertyId = draft.
propertyIds[propertyIndex];
81 if (propertyId.empty()) {
87 stmt.
bindInt(2,
static_cast<int>(propertyIndex));
93void writeTransactionDraft(
95 const std::shared_ptr<
97 const char* sql,
bool autoPosition) {
102 if (draft->
id.empty()) {
105 if (autoPosition && draft->
position < 0) {
106 draft->
position = nextTransactionDraftPosition(db);
123 bindNullableText(stmt, 10, draft->
actorId);
125 bindNullableText(stmt, 12, draft->
contractId);
137 removeTransactionDraftProperties(db, draft->
id);
138 upsertTransactionDraftProperties(db, *draft);
141std::shared_ptr<core::application::importing::draft::TransactionDraft>
144 std::make_shared<core::application::importing::draft::TransactionDraft>();
160 static_cast<const uint8_t*
>(sqlite3_column_blob(stmt.
get(), 14));
161 const int blobSize = sqlite3_column_bytes(stmt.
get(), 14);
162 if (blob && blobSize > 0) {
174 db,
"SELECT property_id FROM transaction_draft_properties WHERE "
175 "transaction_draft_id = ? ORDER BY property_position;");
177 properties.bindText(1, draft->
id);
178 while (properties.step() == SQLITE_ROW) {
179 draft->
propertyIds.push_back(properties.columnText(0));
189 explicit Impl(std::shared_ptr<SqliteDb>
db) :
db(std::move(
db)) {}
191 std::shared_ptr<SqliteDb>
db;
195 const std::string& dbPath)
199 std::shared_ptr<SqliteDb> db)
200 : pimpl_(std::make_unique<
Impl>(std::move(db))) {
202 throw std::runtime_error(
"db is null");
209 const std::shared_ptr<
211 const auto db = pimpl_->db->handle();
212 writeTransactionDraft(
214 "INSERT INTO transaction_drafts (id, statement_draft_id, position, name, "
215 "booking_date, valuta, amount, actor_text, property_text, actor_id, "
216 "actor_selected, contract_id, contract_selected, metadata, "
217 "proof_image_data, type, allocatable, allocatable_selected, status, "
218 "created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
219 "?, ?, ?, ?, ?, ?, ?, ?);",
224 std::shared_ptr<core::application::importing::draft::TransactionDraft>>
227 std::shared_ptr<core::application::importing::draft::TransactionDraft>>
229 const auto db = pimpl_->db->handle();
233 "SELECT id, statement_draft_id, position, name, booking_date, valuta, "
234 "amount, actor_text, property_text, actor_id, actor_selected, "
235 "contract_id, contract_selected, metadata, proof_image_data, type, "
236 "allocatable, allocatable_selected, status, created_at, updated_at FROM "
237 "transaction_drafts ORDER BY statement_draft_id, position, id;");
242 while (stmt.
step() == SQLITE_ROW) {
243 drafts.push_back(readDraftRow(db, stmt));
250 std::shared_ptr<core::application::importing::draft::TransactionDraft>>
252 const std::string&
id)
const {
253 const auto db = pimpl_->db->handle();
256 "SELECT id, statement_draft_id, position, name, booking_date, valuta, "
257 "amount, actor_text, property_text, actor_id, actor_selected, "
258 "contract_id, contract_selected, metadata, proof_image_data, type, "
259 "allocatable, allocatable_selected, status, created_at, updated_at FROM "
260 "transaction_drafts WHERE id = ? LIMIT 1;");
266 if (stmt.
step() != SQLITE_ROW) {
270 return readDraftRow(db, stmt);
274 const std::string&
id) {
275 const auto db = pimpl_->db->handle();
276 removeTransactionDraftProperties(db,
id);
279 "DELETE FROM transaction_drafts WHERE id = ?;");
288 const std::shared_ptr<
290 const auto db = pimpl_->db->handle();
291 writeTransactionDraft(
293 "UPDATE transaction_drafts SET statement_draft_id = ?2, position = ?3, "
294 "name = ?4, booking_date = ?5, valuta = ?6, amount = ?7, actor_text = "
295 "?8, property_text = ?9, actor_id = ?10, actor_selected = ?11, "
296 "contract_id = ?12, contract_selected = ?13, metadata = ?14, "
297 "proof_image_data = ?15, type = ?16, allocatable = ?17, "
298 "allocatable_selected = ?18, status = ?19, created_at = ?20, updated_at "
299 "= ?21 WHERE id = ?1;",
304 const std::shared_ptr<
306 const auto db = pimpl_->db->handle();
307 writeTransactionDraft(
309 "INSERT OR REPLACE INTO transaction_drafts (id, statement_draft_id, "
310 "position, name, booking_date, valuta, amount, actor_text, "
311 "property_text, actor_id, actor_selected, contract_id, "
312 "contract_selected, metadata, proof_image_data, type, allocatable, "
313 "allocatable_selected, status, created_at, updated_at) VALUES (?, ?, ?, "
314 "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
319 const auto db = pimpl_->db->handle();
322 db,
"DELETE FROM transaction_draft_properties;");
323 if (deleteProperties) {
324 deleteProperties.
step();
Declares the lightweight SQLite connection wrapper.
Declares the SQLite-backed transaction draft repository.
RAII wrapper for sqlite3_stmt* that auto-finalizes on destruction.
Draft transaction model used by import finalization and core application flow.
std::vector< std::shared_ptr< core::application::importing::draft::TransactionDraft > > getTransactionDrafts() const override
Retrieve all transaction drafts.
void updateTransactionDraft(const std::shared_ptr< core::application::importing::draft::TransactionDraft > &draft) override
Update an existing transaction draft.
SqliteTransactionDraftRepository(const std::string &dbPath)
Create a transaction draft repository for the database at the given path.
void upsertTransactionDraft(const std::shared_ptr< core::application::importing::draft::TransactionDraft > &draft) override
Insert or update a transaction draft.
~SqliteTransactionDraftRepository() override
Destroy the repository.
void clearTransactionDrafts() override
Remove all transaction drafts.
void addTransactionDraft(const std::shared_ptr< core::application::importing::draft::TransactionDraft > &draft) override
Insert a new transaction draft.
std::optional< std::shared_ptr< core::application::importing::draft::TransactionDraft > > getTransactionDraftById(const std::string &id) const override
Retrieve a transaction draft by identifier.
void removeTransactionDraft(const std::string &id) override
Remove a transaction draft by identifier.
core::domain::Transaction::Status status
std::vector< uint8_t > proofImageData
std::vector< std::string > propertyIds
std::string statementDraftId
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::string generateUuid()
std::shared_ptr< SqliteDb > db
Impl(std::shared_ptr< SqliteDb > db)