Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 203 additions & 0 deletions apps/api/data/mock/tag_repository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/api/data/mysql/migrations/000045_create_tags.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS `tags`;
10 changes: 10 additions & 0 deletions apps/api/data/mysql/migrations/000045_create_tags.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS `tags` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`color` VARCHAR(20) NOT NULL DEFAULT 'gray',
`is_highlighted` TINYINT(1) NOT NULL DEFAULT 0,
`sort_order` INT NOT NULL DEFAULT 0,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uq_tags_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE `variants`
DROP COLUMN `image_url`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE `variants`
ADD COLUMN `image_url` VARCHAR(255) NULL AFTER `recipe`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS `variant_tags`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS `variant_tags` (
`variant_id` BIGINT NOT NULL,
`tag_id` BIGINT NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`variant_id`, `tag_id`),
KEY `idx_variant_tags_tag_id` (`tag_id`),
CONSTRAINT `fk_variant_tags_variant` FOREIGN KEY (`variant_id`) REFERENCES `variants` (`id`),
CONSTRAINT `fk_variant_tags_tag` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
20 changes: 20 additions & 0 deletions apps/api/data/mysql/tag_entity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package mysql

import "time"

type Tag struct {
Id int64
Name string
Color string
IsHighlighted bool
SortOrder int
VariantCount int64 `gorm:"->"`
CreatedAt time.Time
}

type VariantTag struct {
VariantId int64 `gorm:"primaryKey"`
TagId int64 `gorm:"primaryKey"`
Tag Tag
CreatedAt time.Time
}
109 changes: 109 additions & 0 deletions apps/api/data/mysql/tag_repo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package mysql

import (
"apps/api/domain"
"context"

"gorm.io/gorm"
"gorm.io/gorm/clause"
)

func NewTagRepository(db *gorm.DB) domain.TagRepository {
return Repository{db: db}
}

func selectTagsWithVariantCount(db *gorm.DB) *gorm.DB {
return db.Table("tags").Select("tags.*, (SELECT COUNT(*) FROM variant_tags JOIN variants ON variants.id = variant_tags.variant_id WHERE variant_tags.tag_id = tags.id AND variants.deleted_at IS NULL) AS variant_count")
}

func (repo Repository) GetTagList(ctx context.Context) ([]domain.Tag, *domain.Error) {
db := GetDbFromCtx(ctx, repo.db)
var tags []Tag
result := selectTagsWithVariantCount(db).Order("sort_order ASC, name ASC").Find(&tags)
return ToTagListDomain(tags), ToErrorCtx(ctx, result.Error, "GetTagList")
}

func (repo Repository) GetTagById(ctx context.Context, id int64) (domain.Tag, *domain.Error) {
db := GetDbFromCtx(ctx, repo.db)
var tag Tag
result := selectTagsWithVariantCount(db).Where("tags.id = ?", id).First(&tag)
return ToTagDomain(tag), ToErrorCtx(ctx, result.Error, "GetTagById")
}

func (repo Repository) CreateTag(ctx context.Context, tag domain.Tag) (domain.Tag, *domain.Error) {
db := GetDbFromCtx(ctx, repo.db)
tagPayload := ToTagDB(tag)
result := db.Table("tags").Create(&tagPayload)
return ToTagDomain(tagPayload), ToErrorCtx(ctx, result.Error, "CreateTag")
}

func (repo Repository) UpdateTagById(ctx context.Context, tag domain.Tag, id int64) (domain.Tag, *domain.Error) {
db := GetDbFromCtx(ctx, repo.db)
tagPayload := ToTagDB(tag)
result := db.Table("tags").Where("id = ?", id).
Select("name", "color", "is_highlighted", "sort_order").
Updates(&tagPayload)
if result.Error != nil {
return domain.Tag{}, ToErrorCtx(ctx, result.Error, "UpdateTagById")
}

var updatedTag Tag
fetchResult := selectTagsWithVariantCount(db).Where("tags.id = ?", id).First(&updatedTag)
return ToTagDomain(updatedTag), ToErrorCtx(ctx, fetchResult.Error, "UpdateTagById")
}

func (repo Repository) DeleteTagById(ctx context.Context, id int64) *domain.Error {
db := GetDbFromCtx(ctx, repo.db)
result := db.Table("tags").Where("id = ?", id).Delete(&Tag{})
return ToErrorCtx(ctx, result.Error, "DeleteTagById")
}

func (repo Repository) GetTagVariantIds(ctx context.Context, tagId int64) ([]int64, *domain.Error) {
db := GetDbFromCtx(ctx, repo.db)
variantIds := []int64{}
result := db.Table("variant_tags").Where("tag_id = ?", tagId).Order("variant_id ASC").Pluck("variant_id", &variantIds)
return variantIds, ToErrorCtx(ctx, result.Error, "GetTagVariantIds")
}

func (repo Repository) GetVariantTagIds(ctx context.Context, variantId int64) ([]int64, *domain.Error) {
db := GetDbFromCtx(ctx, repo.db)
tagIds := []int64{}
result := db.Table("variant_tags").Where("variant_id = ?", variantId).Order("tag_id ASC").Pluck("tag_id", &tagIds)
return tagIds, ToErrorCtx(ctx, result.Error, "GetVariantTagIds")
}

func (repo Repository) GetLiveVariantIds(ctx context.Context, variantIds []int64) ([]int64, *domain.Error) {
liveVariantIds := []int64{}
if len(variantIds) == 0 {
return liveVariantIds, nil
}

db := GetDbFromCtx(ctx, repo.db)
result := db.Table("variants").Where("id IN ? AND deleted_at IS NULL", variantIds).Pluck("id", &liveVariantIds)
return liveVariantIds, ToErrorCtx(ctx, result.Error, "GetLiveVariantIds")
}

func (repo Repository) InsertVariantTags(ctx context.Context, pairs []domain.VariantTagPair) *domain.Error {
if len(pairs) == 0 {
return nil
}

db := GetDbFromCtx(ctx, repo.db)
payload := ToVariantTagPairsDB(pairs)
result := db.Table("variant_tags").Clauses(clause.OnConflict{DoNothing: true}).Create(&payload)
return ToErrorCtx(ctx, result.Error, "InsertVariantTags")
}

func (repo Repository) DeleteVariantTags(ctx context.Context, pairs []domain.VariantTagPair) *domain.Error {
if len(pairs) == 0 {
return nil
}

db := GetDbFromCtx(ctx, repo.db)
tuples := [][]interface{}{}
for _, pair := range pairs {
tuples = append(tuples, []interface{}{pair.VariantId, pair.TagId})
}
result := db.Table("variant_tags").Where("(variant_id, tag_id) IN ?", tuples).Delete(&VariantTag{})
return ToErrorCtx(ctx, result.Error, "DeleteVariantTags")
}
Loading
Loading