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 Account interface { Insert(userId uuid.UUID, account *types.Account) error Update(userId uuid.UUID, account *types.Account) error GetAll(userId uuid.UUID) ([]*types.Account, error) Get(userId uuid.UUID, id uuid.UUID) (*types.Account, error) Delete(userId uuid.UUID, id uuid.UUID) error } type AccountSqlite struct { db *sqlx.DB } func NewAccountSqlite(db *sqlx.DB) *AccountSqlite { return &AccountSqlite{db: db} } func (db AccountSqlite) Insert(userId uuid.UUID, account *types.Account) error { _, err := db.db.Exec(` INSERT INTO account (id, user_id, name, current_balance, oink_balance, created_at, created_by) VALUES (?,?,?,?,?,?,?)`, account.Id, userId, account.Name, 0, 0, account.CreatedAt, account.CreatedBy) if err != nil { log.Error("account Insert: %v", err) return types.ErrInternal } return nil } func (db AccountSqlite) Update(userId uuid.UUID, account *types.Account) error { r, err := db.db.Exec(` UPDATE account SET name = ?, current_balance = ?, last_transaction = ?, oink_balance = ?, updated_at = ?, updated_by = ? WHERE id = ? AND user_id = ?`, account.Name, account.CurrentBalance, account.LastTransaction, account.OinkBalance, account.UpdatedAt, account.UpdatedBy, account.Id, userId) if err != nil { log.Error("account Update: %v", err) return types.ErrInternal } rows, err := r.RowsAffected() if err != nil { log.Error("account Update: %v", err) return types.ErrInternal } if rows == 0 { log.Info("account Update: not found") return ErrNotFound } return nil } func (db AccountSqlite) GetAll(userId uuid.UUID) ([]*types.Account, error) { accounts := make([]*types.Account, 0) err := db.db.Select(&accounts, ` SELECT id, user_id, name, current_balance, last_transaction, oink_balance, created_at, created_by, updated_at, updated_by FROM account WHERE user_id = ? ORDER BY name`, userId) if err != nil { log.Error("account GetAll: %v", err) return nil, types.ErrInternal } return accounts, nil } func (db AccountSqlite) Get(userId uuid.UUID, id uuid.UUID) (*types.Account, error) { account := &types.Account{} err := db.db.Get(account, ` SELECT id, user_id, name, current_balance, last_transaction, oink_balance, created_at, created_by, updated_at, updated_by FROM account WHERE user_id = ? AND id = ?`, userId, id) if err != nil { if err == sql.ErrNoRows { return nil, ErrNotFound } log.Error("account Get: %v", err) return nil, types.ErrInternal } return account, nil } func (db AccountSqlite) Delete(userId uuid.UUID, id uuid.UUID) error { res, err := db.db.Exec("DELETE FROM account WHERE id = ? and user_id = ?", id, userId) if err != nil { log.Error("account Delete: %v", err) return types.ErrInternal } rows, err := res.RowsAffected() if err != nil { log.Error("account Delete: %v", err) return types.ErrInternal } if rows == 0 { log.Info("account Delete: not found") return ErrNotFound } return nil }