226 lines
4.9 KiB
Go
226 lines
4.9 KiB
Go
package merch
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
"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 UpdateMerchDTO, 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 UpdateMerchDTO, 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
|
|
}
|
|
|
|
switch payload.Origin {
|
|
case "surugaya":
|
|
if err := r.upsertOrigin(&Surugaya{
|
|
MerchUuid: payload.MerchUuid,
|
|
Link: payload.Link,
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
case "mandarake":
|
|
if err := r.upsertOrigin(&Mandarake{
|
|
MerchUuid: payload.MerchUuid,
|
|
Link: payload.Link,
|
|
}); 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
|
|
}
|
|
|
|
func (r *Repo) upsertOrigin(model any) error {
|
|
return r.db.Clauses(clause.OnConflict{
|
|
Columns: []clause.Column{{Name: "merch_uuid"}},
|
|
DoUpdates: clause.AssignmentColumns([]string{"link"}),
|
|
}).Create(model).Error
|
|
}
|