137 lines
3.6 KiB
Go
137 lines
3.6 KiB
Go
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 Transaction interface {
|
|
Insert(userId uuid.UUID, transaction *types.Transaction) error
|
|
Update(userId uuid.UUID, transaction *types.Transaction) error
|
|
GetAll(userId uuid.UUID) ([]*types.Transaction, error)
|
|
Get(userId uuid.UUID, id uuid.UUID) (*types.Transaction, error)
|
|
Delete(userId uuid.UUID, id uuid.UUID) error
|
|
}
|
|
|
|
type TransactionSqlite struct {
|
|
db *sqlx.DB
|
|
}
|
|
|
|
func NewTransactionSqlite(db *sqlx.DB) *TransactionSqlite {
|
|
return &TransactionSqlite{db: db}
|
|
}
|
|
|
|
func (db TransactionSqlite) Insert(userId uuid.UUID, transaction *types.Transaction) error {
|
|
|
|
_, err := db.db.Exec(`
|
|
INSERT INTO transaction (id, user_id, account_id, treasure_chest_id, internal, value, timestamp, note, created_at, created_by)
|
|
VALUES (?,?,?,?,?,?,?,?,?,?)`, transaction.Id, userId, transaction.AccountId, transaction.TreasureChestId, transaction.Internal, transaction.Value, transaction.Timestamp, transaction.Note, transaction.CreatedAt, transaction.CreatedBy)
|
|
if err != nil {
|
|
log.Error("transaction Insert: %v", err)
|
|
return types.ErrInternal
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (db TransactionSqlite) Update(userId uuid.UUID, transaction *types.Transaction) error {
|
|
|
|
r, err := db.db.Exec(`
|
|
UPDATE transaction
|
|
SET
|
|
account_id = ?,
|
|
treasure_chest_id = ?,
|
|
internal = ?,
|
|
value = ?,
|
|
timestamp = ?,
|
|
note = ?,
|
|
updated_at = ?,
|
|
updated_by = ?
|
|
WHERE id = ?
|
|
AND user_id = ?`, transaction.AccountId, transaction.TreasureChestId, transaction.Internal, transaction.Value, transaction.Timestamp, transaction.UpdatedBy, transaction.Id, userId)
|
|
if err != nil {
|
|
log.Error("transaction Update: %v", err)
|
|
return types.ErrInternal
|
|
}
|
|
rows, err := r.RowsAffected()
|
|
if err != nil {
|
|
log.Error("transaction Update: %v", err)
|
|
return types.ErrInternal
|
|
}
|
|
|
|
if rows == 0 {
|
|
log.Info("transaction Update: not found")
|
|
return ErrNotFound
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (db TransactionSqlite) GetAll(userId uuid.UUID) ([]*types.Transaction, error) {
|
|
|
|
transactions := make([]*types.Transaction, 0)
|
|
err := db.db.Select(&transactions, `
|
|
SELECT
|
|
id, user_id,
|
|
account_id, treasure_chest_id, internal, value, timestamp, note,
|
|
created_at, created_by, updated_at, updated_by
|
|
FROM transaction
|
|
WHERE user_id = ?
|
|
ORDER BY name`, userId)
|
|
if err != nil {
|
|
log.Error("transaction GetAll: %v", err)
|
|
return nil, types.ErrInternal
|
|
}
|
|
|
|
return transactions, nil
|
|
}
|
|
|
|
func (db TransactionSqlite) Get(userId uuid.UUID, id uuid.UUID) (*types.Transaction, error) {
|
|
|
|
transaction := &types.Transaction{}
|
|
err := db.db.Get(transaction, `
|
|
SELECT
|
|
id, user_id,
|
|
account_id, treasure_chest_id, internal, value, timestamp, note,
|
|
created_at, created_by, updated_at, updated_by
|
|
FROM transaction
|
|
WHERE user_id = ?
|
|
AND id = ?`, userId, id)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, ErrNotFound
|
|
}
|
|
log.Error("transaction Get: %v", err)
|
|
return nil, types.ErrInternal
|
|
}
|
|
|
|
return transaction, nil
|
|
}
|
|
|
|
func (db TransactionSqlite) Delete(userId uuid.UUID, id uuid.UUID) error {
|
|
|
|
res, err := db.db.Exec("DELETE FROM transaction WHERE id = ? and user_id = ?", id, userId)
|
|
if err != nil {
|
|
log.Error("transaction Delete: %v", err)
|
|
return types.ErrInternal
|
|
}
|
|
|
|
rows, err := res.RowsAffected()
|
|
if err != nil {
|
|
log.Error("transaction Delete: %v", err)
|
|
return types.ErrInternal
|
|
}
|
|
|
|
if rows == 0 {
|
|
log.Info("transaction Delete: not found")
|
|
return ErrNotFound
|
|
}
|
|
|
|
return nil
|
|
}
|