api/internal/api/merch/repository.go
2025-09-26 20:16:21 +03:00

225 lines
4.9 KiB
Go

package merch
import (
"database/sql"
"errors"
"gorm.io/gorm"
"time"
)
type Repo struct {
db *gorm.DB
}
func NewRepo(db *gorm.DB) *Repo {
return &Repo{
db: db,
}
}
type repository interface {
addMerch(bundle merchBundle) error
getSingleMerch(userUuid, merchUuid string) (merchBundle, error)
getAllMerch(userUuid string) ([]ListResponse, error)
updateMerch(payload MerchDTO, userUuid string) error
deleteMerch(userUuid, merchUuid string) error
getAllUserMerch(userUuid string) ([]Merch, error)
prices
}
type prices interface {
getPricesWithDays(userUuid string, period time.Time) ([]Price, error)
getDistinctPrices(userUuid, merchUuid string, period time.Time) (prices []Price, err error)
}
func (r *Repo) addMerch(bundle merchBundle) error {
if err := r.db.Model(&Merch{}).Create(bundle.Merch).Error; err != nil {
return err
}
if err := r.db.Model(&Surugaya{}).Create(bundle.Surugaya).Error; err != nil {
return err
}
if err := r.db.Model(&Mandarake{}).Create(bundle.Mandarake).Error; err != nil {
return err
}
return nil
}
func (r *Repo) getSingleMerch(userUuid, merchUuid string) (merchBundle, error) {
var merch Merch
if err := r.db.
Where("user_uuid = ?", userUuid).
Where("merch_uuid = ?", merchUuid).
Where("deleted_at IS NULL").
First(&merch).Error; err != nil {
return merchBundle{}, err
}
var surugaya Surugaya
if err := r.db.
Where("merch_uuid = ?", merchUuid).
First(&surugaya).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return merchBundle{}, err
}
}
var mandarake Mandarake
if err := r.db.
Where("merch_uuid = ?", merchUuid).
First(&mandarake).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return merchBundle{}, err
}
}
return merchBundle{
Merch: &merch,
Surugaya: &surugaya,
Mandarake: &mandarake,
}, nil
}
func (r *Repo) getAllMerch(userUuid string) ([]ListResponse, error) {
var list []ListResponse
if err := r.db.Model(&Merch{}).
Where("user_uuid = ?", userUuid).
Where("deleted_at IS NULL").
Find(&list).Error; err != nil {
return nil, err
}
return list, nil
}
func (r *Repo) updateMerch(payload MerchDTO, userUuid string) error {
m := make(map[string]any)
m["name"] = payload.Name
m["updated_at"] = sql.NullTime{
Time: time.Now(),
Valid: true,
}
if err := r.db.
Model(&Merch{}).
Where("user_uuid = ?", userUuid).
Where("merch_uuid = ?", payload.MerchUuid).
Updates(m).Error; err != nil {
return err
}
// surugaya
fields := make(map[string]any, 2)
if payload.OriginSurugaya.Link != "" {
fields["link"] = payload.OriginSurugaya.Link
}
if len(fields) > 0 {
if err := r.db.
Model(&Surugaya{}).
Where("merch_uuid = ?", payload.MerchUuid).
Updates(fields).Error; err != nil {
return err
}
}
// mandarake
if payload.OriginMandarake.Link != "" {
if err := r.db.
Model(&Mandarake{}).
Where("merch_uuid = ?", payload.MerchUuid).
Update("link", payload.OriginMandarake.Link).Error; err != nil {
return err
}
}
return nil
}
func (r *Repo) deleteMerch(userUuid, merchUuid string) error {
now := time.Now().UTC()
if err := r.db.
Model(&Merch{}).
Where("user_uuid = ?", userUuid).
Where("merch_uuid = ?", merchUuid).
Update("deleted_at", now).Error; err != nil {
return err
}
if err := r.db.
Model(&Surugaya{}).
Where("merch_uuid = ?", merchUuid).
Update("deleted_at", now).Error; err != nil {
return err
}
if err := r.db.
Model(&Mandarake{}).
Where("merch_uuid = ?", merchUuid).
Update("deleted_at", now).Error; err != nil {
return err
}
return nil
}
func (r *Repo) getAllUserMerch(userUuid string) (merchList []Merch, err error) {
err = r.db.Model(&Merch{}).
Where("user_uuid = ?", userUuid).
Where("deleted_at IS NULL").
Find(&merchList).Error
if err != nil {
return nil, err
}
return merchList, nil
}
func (r *Repo) getPricesWithDays(userUuid string, period time.Time) (prices []Price, err error) {
err = r.db.Raw(`
SELECT p.created_at, p.merch_uuid, p.price, p.origin
FROM prices AS p
JOIN merch AS m ON m.merch_uuid = p.merch_uuid
WHERE m.user_uuid = ?
AND p.created_at > ?
AND p.deleted_at IS NULL
AND m.deleted_at IS NULL
ORDER BY p.created_at DESC
`, userUuid, period).Scan(&prices).Error
if err != nil {
return nil, err
}
return prices, nil
}
func (r *Repo) getDistinctPrices(userUuid, merchUuid string, period time.Time) (prices []Price, err error) {
err = r.db.Raw(`
SELECT price, created_at, origin
FROM (
SELECT DISTINCT ON (price) price, created_at, origin
FROM prices
WHERE merch_uuid = ?
AND created_at > ?
AND deleted_at IS NULL
AND EXISTS (
SELECT 1
FROM merch
WHERE merch_uuid = ?
AND user_uuid = ?
)
) AS up
ORDER BY created_at;`, merchUuid, period, merchUuid, userUuid).Scan(&prices).Error
if err != nil {
return nil, err
}
return prices, nil
}