Files
back-hokm/internal/user/user.go
T

85 lines
2.5 KiB
Go

package user
import (
"context"
"database/sql"
"errors"
"time"
)
// User مدل کاربر.
type User struct {
ID int64 `json:"id"`
Mobile string `json:"mobile"`
FirstName *string `json:"first_name"`
LastName *string `json:"last_name"`
Avatar *string `json:"avatar"`
Coins int64 `json:"coins"`
IsAdmin bool `json:"is_admin"`
CreatedAt time.Time `json:"created_at"`
}
var ErrNotFound = errors.New("user not found")
// Repo دسترسی به جدول users.
type Repo struct{ db *sql.DB }
func NewRepo(db *sql.DB) *Repo { return &Repo{db: db} }
// FindByMobile کاربر را با شماره موبایل پیدا می‌کند.
func (r *Repo) FindByMobile(ctx context.Context, mobile string) (*User, error) {
row := r.db.QueryRowContext(ctx,
`SELECT id, mobile, first_name, last_name, avatar, coins, is_admin, created_at
FROM users WHERE mobile = ?`, mobile)
return scan(row)
}
// FindByID کاربر را با شناسه پیدا می‌کند.
func (r *Repo) FindByID(ctx context.Context, id int64) (*User, error) {
row := r.db.QueryRowContext(ctx,
`SELECT id, mobile, first_name, last_name, avatar, coins, is_admin, created_at
FROM users WHERE id = ?`, id)
return scan(row)
}
// Create کاربر جدید می‌سازد.
func (r *Repo) Create(ctx context.Context, mobile string) (*User, error) {
res, err := r.db.ExecContext(ctx, `INSERT INTO users (mobile) VALUES (?)`, mobile)
if err != nil {
return nil, err
}
id, _ := res.LastInsertId()
return r.FindByID(ctx, id)
}
// UpdateProfile نام نمایشی و آواتار کاربر را تنظیم می‌کند.
func (r *Repo) UpdateProfile(ctx context.Context, id int64, firstName, avatar string) error {
_, err := r.db.ExecContext(ctx,
`UPDATE users SET first_name = ?, avatar = ? WHERE id = ?`,
firstName, avatar, id)
return err
}
// FindOrCreate اگر کاربر نبود می‌سازد (مطابق فلوی login-otp).
func (r *Repo) FindOrCreate(ctx context.Context, mobile string) (*User, error) {
u, err := r.FindByMobile(ctx, mobile)
if errors.Is(err, ErrNotFound) {
return r.Create(ctx, mobile)
}
return u, err
}
func scan(row *sql.Row) (*User, error) {
var u User
var created string
err := row.Scan(&u.ID, &u.Mobile, &u.FirstName, &u.LastName, &u.Avatar, &u.Coins, &u.IsAdmin, &created)
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNotFound
}
if err != nil {
return nil, err
}
u.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", created)
return &u, nil
}