feat: implement account service and db
This commit is contained in:
145
db/account.go
Normal file
145
db/account.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"spend-sparrow/log"
|
||||
"spend-sparrow/types"
|
||||
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Account interface {
|
||||
Insert(account *types.Account) error
|
||||
Update(account *types.Account) error
|
||||
GetAll(groupId uuid.UUID) ([]*types.Account, error)
|
||||
Get(groupId uuid.UUID, id uuid.UUID) (*types.Account, error)
|
||||
Delete(id uuid.UUID) error
|
||||
}
|
||||
|
||||
type AccountSqlite struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewAccountSqlite(db *sql.DB) *AccountSqlite {
|
||||
return &AccountSqlite{db: db}
|
||||
}
|
||||
|
||||
func (db AccountSqlite) Insert(account *types.Account) error {
|
||||
|
||||
_, err := db.db.Exec(`
|
||||
INSERT INTO account (id, group_id, name, current_balance, oink_balance, created_at, created_by)
|
||||
VALUES (?,?,?,?,?,?,?)`, account.Id, account.GroupId, 0, 0, account.CreatedAt, account.CreatedBy)
|
||||
if err != nil {
|
||||
log.Error("Error inserting account: %v", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db AccountSqlite) Update(account *types.Account) error {
|
||||
|
||||
_, err := db.db.Exec(`
|
||||
UPDATE account
|
||||
name = ?,
|
||||
current_balance = ?,
|
||||
last_transaction = ?,
|
||||
oink_balance = ?,
|
||||
updated_at = ?,
|
||||
updated_by = ?,
|
||||
WHERE id = ?
|
||||
AND group_id = ?`, account.Name, account.CurrentBalance, account.LastTransaction, account.OinkBalance, account.UpdatedAt, account.UpdatedBy, account.Id, account.GroupId)
|
||||
if err != nil {
|
||||
log.Error("Error updating account: %v", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db AccountSqlite) GetAll(groupId uuid.UUID) ([]*types.Account, error) {
|
||||
|
||||
rows, err := db.db.Query(`
|
||||
SELECT
|
||||
id, name,
|
||||
current_balance, last_transaction, oink_balance,
|
||||
created_at, created_by, updated_at, updated_by
|
||||
FROM account
|
||||
WHERE group_id = ?
|
||||
ORDER BY name`, groupId)
|
||||
if err != nil {
|
||||
log.Error("Could not getAll accounts: %v", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
var accounts = make([]*types.Account, 0)
|
||||
for rows.Next() {
|
||||
|
||||
account, err := scanAccount(rows)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
accounts = append(accounts, account)
|
||||
}
|
||||
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
func (db AccountSqlite) Get(groupId uuid.UUID, id uuid.UUID) (*types.Account, error) {
|
||||
|
||||
rows, err := db.db.Query(`
|
||||
SELECT
|
||||
id, name,
|
||||
current_balance, last_transaction, oink_balance,
|
||||
created_at, created_by, updated_at, updated_by
|
||||
FROM account
|
||||
WHERE group_id = ?
|
||||
AND id = ?`, groupId, id)
|
||||
if err != nil {
|
||||
log.Error("Could not get accounts: %v", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
if !rows.Next() {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
return scanAccount(rows)
|
||||
}
|
||||
|
||||
func scanAccount(rows *sql.Rows) (*types.Account, error) {
|
||||
var (
|
||||
account types.Account
|
||||
)
|
||||
|
||||
err := rows.Scan(&account.Id, &account.Name, &account.CurrentBalance, &account.LastTransaction, &account.OinkBalance, &account.CreatedAt, &account.CreatedBy, &account.UpdatedAt, &account.UpdatedBy)
|
||||
if err != nil {
|
||||
log.Error("Could not scan account: %v", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
return &account, nil
|
||||
}
|
||||
|
||||
func (db AccountSqlite) Delete(id uuid.UUID) error {
|
||||
|
||||
res, err := db.db.Exec("DELETE FROM account WHERE id = ?", id)
|
||||
if err != nil {
|
||||
log.Error("Error deleting account: %v", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
log.Error("Error deleting account, getting rows affected: %v", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
if rows == 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -5,18 +5,12 @@ import (
|
||||
"spend-sparrow/types"
|
||||
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("value not found")
|
||||
ErrAlreadyExists = errors.New("row already exists")
|
||||
)
|
||||
|
||||
type Auth interface {
|
||||
InsertUser(user *types.User) error
|
||||
UpdateUser(user *types.User) error
|
||||
|
||||
@@ -12,6 +12,11 @@ import (
|
||||
_ "github.com/golang-migrate/migrate/v4/source/file"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("The value does not exist.")
|
||||
ErrAlreadyExists = errors.New("row already exists")
|
||||
)
|
||||
|
||||
func RunMigrations(db *sql.DB, pathPrefix string) error {
|
||||
driver, err := sqlite3.WithInstance(db, &sqlite3.Config{})
|
||||
if err != nil {
|
||||
@@ -38,4 +43,3 @@ func RunMigrations(db *sql.DB, pathPrefix string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
119
db/workout.go
119
db/workout.go
@@ -1,119 +0,0 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"spend-sparrow/log"
|
||||
"spend-sparrow/types"
|
||||
|
||||
"database/sql"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrWorkoutNotExists = errors.New("Workout does not exist")
|
||||
)
|
||||
|
||||
type WorkoutDb interface {
|
||||
InsertWorkout(userId uuid.UUID, workout *WorkoutInsert) (*Workout, error)
|
||||
GetWorkouts(userId uuid.UUID) ([]Workout, error)
|
||||
DeleteWorkout(userId uuid.UUID, rowId int) error
|
||||
}
|
||||
|
||||
type WorkoutDbSqlite struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewWorkoutDbSqlite(db *sql.DB) *WorkoutDbSqlite {
|
||||
return &WorkoutDbSqlite{db: db}
|
||||
}
|
||||
|
||||
type WorkoutInsert struct {
|
||||
Date time.Time
|
||||
Type string
|
||||
Sets int
|
||||
Reps int
|
||||
}
|
||||
|
||||
type Workout struct {
|
||||
RowId int
|
||||
Date time.Time
|
||||
Type string
|
||||
Sets int
|
||||
Reps int
|
||||
}
|
||||
|
||||
func NewWorkoutInsert(date time.Time, workoutType string, sets int, reps int) *WorkoutInsert {
|
||||
return &WorkoutInsert{Date: date, Type: workoutType, Sets: sets, Reps: reps}
|
||||
}
|
||||
|
||||
func NewWorkoutFromInsert(rowId int, workoutInsert *WorkoutInsert) *Workout {
|
||||
return &Workout{RowId: rowId, Date: workoutInsert.Date, Type: workoutInsert.Type, Sets: workoutInsert.Sets, Reps: workoutInsert.Reps}
|
||||
}
|
||||
|
||||
func (db WorkoutDbSqlite) InsertWorkout(userId uuid.UUID, workout *WorkoutInsert) (*Workout, error) {
|
||||
var rowId int
|
||||
err := db.db.QueryRow(`
|
||||
INSERT INTO workout (user_id, date, type, sets, reps)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
RETURNING rowid`, userId, workout.Date, workout.Type, workout.Sets, workout.Reps).Scan(&rowId)
|
||||
if err != nil {
|
||||
log.Error("Error inserting workout: %v", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
return NewWorkoutFromInsert(rowId, workout), nil
|
||||
}
|
||||
|
||||
func (db WorkoutDbSqlite) GetWorkouts(userId uuid.UUID) ([]Workout, error) {
|
||||
|
||||
rows, err := db.db.Query("SELECT rowid, date, type, sets, reps FROM workout WHERE user_id = ? ORDER BY date desc", userId)
|
||||
if err != nil {
|
||||
log.Error("Could not get workouts: %v", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
var workouts = make([]Workout, 0)
|
||||
for rows.Next() {
|
||||
var (
|
||||
workout Workout
|
||||
date string
|
||||
)
|
||||
|
||||
err = rows.Scan(&workout.RowId, &date, &workout.Type, &workout.Sets, &workout.Reps)
|
||||
if err != nil {
|
||||
log.Error("Could not scan workout: %v", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
workout.Date, err = time.Parse("2006-01-02 15:04:05-07:00", date)
|
||||
if err != nil {
|
||||
log.Error("Could not parse date: %v", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
workouts = append(workouts, workout)
|
||||
}
|
||||
|
||||
return workouts, nil
|
||||
}
|
||||
|
||||
func (db WorkoutDbSqlite) DeleteWorkout(userId uuid.UUID, rowId int) error {
|
||||
|
||||
res, err := db.db.Exec("DELETE FROM workout WHERE user_id = ? AND rowid = ?", userId, rowId)
|
||||
if err != nil {
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
if rows == 0 {
|
||||
return ErrWorkoutNotExists
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user