package db import ( "database/sql" "spend-sparrow/log" "spend-sparrow/types" "github.com/google/uuid" "github.com/jmoiron/sqlx" ) // While it may be duplicated to check for userId in the database access, it serves as a security layer type TreasureChest interface { Insert(userId uuid.UUID, treasureChest *types.TreasureChest) error Update(userId uuid.UUID, treasureChest *types.TreasureChest) error GetAll(userId uuid.UUID) ([]*types.TreasureChest, error) GetAllByParentId(userId uuid.UUID, parentId uuid.UUID) ([]*types.TreasureChest, error) Get(userId uuid.UUID, id uuid.UUID) (*types.TreasureChest, error) Delete(userId uuid.UUID, id uuid.UUID) error } type TreasureChestSqlite struct { db *sqlx.DB } func NewTreasureChestSqlite(db *sqlx.DB) *TreasureChestSqlite { return &TreasureChestSqlite{db: db} } func (db TreasureChestSqlite) Insert(userId uuid.UUID, treasureChest *types.TreasureChest) error { _, err := db.db.Exec(` INSERT INTO treasure_chest (id, parent_id, user_id, name, current_balance, created_at, created_by) VALUES (?,?,?,?,?,?,?)`, treasureChest.Id, treasureChest.ParentId, userId, treasureChest.Name, 0, treasureChest.CreatedAt, treasureChest.CreatedBy) if err != nil { log.Error("treasureChest Insert: %v", err) return types.ErrInternal } return nil } func (db TreasureChestSqlite) Update(userId uuid.UUID, treasureChest *types.TreasureChest) error { r, err := db.db.Exec(` UPDATE treasure_chest SET parent_id = ?, name = ?, current_balance = ?, updated_at = ?, updated_by = ? WHERE id = ? AND user_id = ?`, treasureChest.ParentId, treasureChest.Name, treasureChest.CurrentBalance, treasureChest.UpdatedAt, treasureChest.UpdatedBy, treasureChest.Id, userId) if err != nil { log.Error("treasureChest Update: %v", err) return types.ErrInternal } rows, err := r.RowsAffected() if err != nil { log.Error("treasureChest Update: %v", err) return types.ErrInternal } if rows == 0 { log.Info("treasureChest Update: not found") return ErrNotFound } return nil } func (db TreasureChestSqlite) GetAll(userId uuid.UUID) ([]*types.TreasureChest, error) { treasureChests := make([]*types.TreasureChest, 0) err := db.db.Select(&treasureChests, ` SELECT id, parent_id, user_id, name, current_balance, created_at, created_by, updated_at, updated_by FROM treasure_chest WHERE user_id = ? ORDER BY name`, userId) if err != nil { log.Error("treasureChest GetAll: %v", err) return nil, types.ErrInternal } return treasureChests, nil } func (db TreasureChestSqlite) GetAllByParentId(userId uuid.UUID, parentId uuid.UUID) ([]*types.TreasureChest, error) { treasureChests := make([]*types.TreasureChest, 0) err := db.db.Select(&treasureChests, ` SELECT id, parent_id, user_id, name, current_balance, created_at, created_by, updated_at, updated_by FROM treasure_chest WHERE user_id = ? AND parent_id = ? ORDER BY name`, userId, parentId) if err != nil { log.Error("treasureChest GetAll: %v", err) return nil, types.ErrInternal } return treasureChests, nil } func (db TreasureChestSqlite) Get(userId uuid.UUID, id uuid.UUID) (*types.TreasureChest, error) { treasureChest := &types.TreasureChest{} err := db.db.Get(treasureChest, ` SELECT id, parent_id, user_id, name, current_balance, created_at, created_by, updated_at, updated_by FROM treasure_chest WHERE user_id = ? AND id = ?`, userId, id) if err != nil { if err == sql.ErrNoRows { return nil, ErrNotFound } log.Error("treasureChest Get: %v", err) return nil, types.ErrInternal } return treasureChest, nil } func (db TreasureChestSqlite) Delete(userId uuid.UUID, id uuid.UUID) error { res, err := db.db.Exec("DELETE FROM treasure_chest WHERE id = ? and user_id = ?", id, userId) if err != nil { log.Error("treasureChest Delete: %v", err) return types.ErrInternal } rows, err := res.RowsAffected() if err != nil { log.Error("treasureChest Delete: %v", err) return types.ErrInternal } if rows == 0 { log.Info("treasureChest Delete: not found") return ErrNotFound } return nil }