package cardmaster import ( "gorm.io/gorm" ) type Repository interface { FindAllPaginated(page, limit int, query ListCardMasterQuery) ([]CardMaster, int64, error) FindByID(id uint) (*CardMaster, error) Create(c *CardMaster) error Update(c *CardMaster, oldIDSet uint) error Delete(id uint, idSet uint) error } type repository struct { db *gorm.DB } func NewRepository(db *gorm.DB) Repository { return &repository{db: db} } func (r *repository) FindAllPaginated(page, limit int, queryParams ListCardMasterQuery) ([]CardMaster, int64, error) { var list []CardMaster var total int64 query := r.db.Model(&CardMaster{}). Select( "id", "id_set", "name", "number", "image", "stage", "element", "element_image", "evolves_from", "illustrator", "regulation", "rarity", "id_price_charting_eng", "link_price_charting_eng", "id_price_charting_jpn", "link_price_charting_jpn", "hp", "attacks", "abilities", "battle", "evolution_line", "pokedex_info", "effects", "created_at", "updated_at", "created_by", "updated_by", ) if queryParams.IDSet > 0 { query = query.Where("id_set = ?", queryParams.IDSet) } if queryParams.Element != "" { query = query.Where("element ILIKE ?", queryParams.Element) } if queryParams.Rarity != "" { query = query.Where("rarity ILIKE ?", queryParams.Rarity) } if queryParams.Stage != "" { query = query.Where("stage ILIKE ?", queryParams.Stage) } if queryParams.Search != "" { pattern := "%" + queryParams.Search + "%" query = query.Where("name ILIKE ? OR number ILIKE ? OR illustrator ILIKE ?", pattern, pattern, pattern) } if err := query.Count(&total).Error; err != nil { return nil, 0, err } offset := (page - 1) * limit err := query.Order("id ASC").Limit(limit).Offset(offset).Find(&list).Error if err != nil { return nil, 0, err } return list, total, nil } func (r *repository) FindByID(id uint) (*CardMaster, error) { var c CardMaster err := r.db.Select( "id", "id_set", "name", "number", "image", "stage", "element", "element_image", "evolves_from", "illustrator", "regulation", "rarity", "id_price_charting_eng", "link_price_charting_eng", "id_price_charting_jpn", "link_price_charting_jpn", "hp", "attacks", "abilities", "battle", "evolution_line", "pokedex_info", "effects", "created_at", "updated_at", "created_by", "updated_by", ).First(&c, id).Error if err != nil { return nil, err } return &c, nil } func (r *repository) Create(c *CardMaster) error { return r.db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(c).Error; err != nil { return err } if c.IDSet > 0 { recalculateSetAndSeriesStatsTx(tx, c.IDSet) } return nil }) } func (r *repository) Update(c *CardMaster, oldIDSet uint) error { return r.db.Transaction(func(tx *gorm.DB) error { if err := tx.Save(c).Error; err != nil { return err } if c.IDSet > 0 { recalculateSetAndSeriesStatsTx(tx, c.IDSet) } if oldIDSet > 0 && oldIDSet != c.IDSet { recalculateSetAndSeriesStatsTx(tx, oldIDSet) } return nil }) } func (r *repository) Delete(id uint, idSet uint) error { return r.db.Transaction(func(tx *gorm.DB) error { if err := tx.Delete(&CardMaster{}, id).Error; err != nil { return err } if idSet > 0 { recalculateSetAndSeriesStatsTx(tx, idSet) } return nil }) } func recalculateSetAndSeriesStatsTx(tx *gorm.DB, setID uint) { if setID == 0 { return } type seriesSetRef struct { ID uint ParentID *uint } var set seriesSetRef if err := tx.Table("series_set_masters").Select("id", "parent_id").Where("id = ?", setID).First(&set).Error; err != nil { return } var totalCards int64 _ = tx.Table("card_masters").Where("id_set = ?", setID).Count(&totalCards).Error _ = tx.Table("series_set_masters").Where("id = ?", setID).Update("total_cards", int(totalCards)).Error if set.ParentID != nil { var expansionCount int64 _ = tx.Table("series_set_masters").Where("parent_id = ?", *set.ParentID).Count(&expansionCount).Error var cardCount int64 _ = tx.Table("card_masters"). Where("id_set IN (SELECT id FROM series_set_masters WHERE parent_id = ?)", *set.ParentID). Count(&cardCount).Error _ = tx.Table("series_set_masters"). Where("id = ? AND parent_id IS NULL", *set.ParentID). Updates(map[string]interface{}{ "expansion_count": int(expansionCount), "card_count": int(cardCount), }).Error } }