package seriessetmaster import ( "gorm.io/gorm" ) type Repository interface { FindAllSeries(search string) ([]SeriesSetMaster, error) FindAllSets(search string, parentID uint) ([]SeriesSetMaster, error) FindByID(id uint) (*SeriesSetMaster, error) FindBySetCode(setCode string) (*SeriesSetMaster, error) FindCardImagesBySetID(setID uint) ([]string, error) Create(m *SeriesSetMaster) error CreateSet(m *SeriesSetMaster) error Update(m *SeriesSetMaster) error UpdateSet(m *SeriesSetMaster, oldParentID *uint) error DeleteCascade(m *SeriesSetMaster) error RecalculateSeriesStats(seriesID uint) error RecalculateSetStats(setID uint) error } type repository struct { db *gorm.DB } func NewRepository(db *gorm.DB) Repository { return &repository{db: db} } func (r *repository) FindAllSeries(search string) ([]SeriesSetMaster, error) { var list []SeriesSetMaster query := r.db.Model(&SeriesSetMaster{}). Select("id", "parent_id", "series_name", "image", "expansion_count", "card_count", "created_at", "updated_at", "created_by", "updated_by"). Where("parent_id IS NULL") if search != "" { pattern := "%" + search + "%" query = query.Where("series_name ILIKE ?", pattern) } err := query.Order("id ASC").Preload("Children").Find(&list).Error if err != nil { return nil, err } return list, nil } func (r *repository) FindAllSets(search string, parentID uint) ([]SeriesSetMaster, error) { var list []SeriesSetMaster query := r.db.Model(&SeriesSetMaster{}). Select("id", "parent_id", "set_code", "set_name", "series_name", "image", "logo", "release_date", "total_cards", "created_at", "updated_at", "created_by", "updated_by"). Where("parent_id IS NOT NULL") if parentID > 0 { query = query.Where("parent_id = ?", parentID) } if search != "" { pattern := "%" + search + "%" query = query.Where("set_name ILIKE ? OR set_code ILIKE ? OR series_name ILIKE ?", pattern, pattern, pattern) } err := query.Order("id ASC").Find(&list).Error if err != nil { return nil, err } return list, nil } func (r *repository) FindByID(id uint) (*SeriesSetMaster, error) { var m SeriesSetMaster err := r.db.Select("id", "parent_id", "set_code", "set_name", "series_name", "image", "logo", "release_date", "total_cards", "expansion_count", "card_count", "created_at", "updated_at", "created_by", "updated_by"). Preload("Children"). First(&m, id).Error if err != nil { return nil, err } return &m, nil } func (r *repository) FindBySetCode(setCode string) (*SeriesSetMaster, error) { var m SeriesSetMaster err := r.db.Select("id", "parent_id", "set_code", "set_name", "series_name", "image", "logo", "release_date", "total_cards", "expansion_count", "card_count", "created_at", "updated_at", "created_by", "updated_by"). Where("set_code = ? AND parent_id IS NOT NULL", setCode). First(&m).Error if err != nil { return nil, err } return &m, nil } func (r *repository) FindCardImagesBySetID(setID uint) ([]string, error) { var images []string err := r.db.Table("card_masters").Select("image").Where("id_set = ? AND image != ''", setID).Pluck("image", &images).Error return images, err } func (r *repository) Create(m *SeriesSetMaster) error { return r.db.Create(m).Error } func (r *repository) CreateSet(m *SeriesSetMaster) error { return r.db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(m).Error; err != nil { return err } if m.ParentID != nil { return r.RecalculateSeriesStatsTx(tx, *m.ParentID) } return nil }) } func (r *repository) Update(m *SeriesSetMaster) error { return r.db.Save(m).Error } func (r *repository) UpdateSet(m *SeriesSetMaster, oldParentID *uint) error { return r.db.Transaction(func(tx *gorm.DB) error { if err := tx.Save(m).Error; err != nil { return err } if m.ParentID != nil { if err := r.RecalculateSeriesStatsTx(tx, *m.ParentID); err != nil { return err } } if oldParentID != nil && (m.ParentID == nil || *oldParentID != *m.ParentID) { if err := r.RecalculateSeriesStatsTx(tx, *oldParentID); err != nil { return err } } return nil }) } func (r *repository) DeleteCascade(m *SeriesSetMaster) error { return r.db.Transaction(func(tx *gorm.DB) error { parentID := m.ParentID if m.ParentID == nil { if err := tx.Table("card_masters").Where("id_set IN (SELECT id FROM series_set_masters WHERE parent_id = ?)", m.ID).Delete(nil).Error; err != nil { return err } if err := tx.Where("parent_id = ?", m.ID).Delete(&SeriesSetMaster{}).Error; err != nil { return err } if err := tx.Delete(&SeriesSetMaster{}, m.ID).Error; err != nil { return err } } else { if err := tx.Table("card_masters").Where("id_set = ?", m.ID).Delete(nil).Error; err != nil { return err } if err := tx.Delete(&SeriesSetMaster{}, m.ID).Error; err != nil { return err } if parentID != nil { if err := r.RecalculateSeriesStatsTx(tx, *parentID); err != nil { return err } } } return nil }) } func (r *repository) RecalculateSeriesStats(seriesID uint) error { return r.RecalculateSeriesStatsTx(r.db, seriesID) } func (r *repository) RecalculateSeriesStatsTx(tx *gorm.DB, seriesID uint) error { if seriesID == 0 { return nil } var expansionCount int64 if err := tx.Model(&SeriesSetMaster{}).Where("parent_id = ?", seriesID).Count(&expansionCount).Error; err != nil { return err } var cardCount int64 if err := tx.Table("card_masters"). Where("id_set IN (SELECT id FROM series_set_masters WHERE parent_id = ?)", seriesID). Count(&cardCount).Error; err != nil { return err } return tx.Model(&SeriesSetMaster{}). Where("id = ? AND parent_id IS NULL", seriesID). Updates(map[string]interface{}{ "expansion_count": int(expansionCount), "card_count": int(cardCount), }).Error } func (r *repository) RecalculateSetStats(setID uint) error { return r.RecalculateSetStatsTx(r.db, setID) } func (r *repository) RecalculateSetStatsTx(tx *gorm.DB, setID uint) error { if setID == 0 { return nil } var set SeriesSetMaster if err := tx.Select("id", "parent_id").First(&set, setID).Error; err != nil { return err } var totalCards int64 if err := tx.Table("card_masters").Where("id_set = ?", setID).Count(&totalCards).Error; err != nil { return err } if err := tx.Model(&SeriesSetMaster{}).Where("id = ?", setID).Update("total_cards", int(totalCards)).Error; err != nil { return err } if set.ParentID != nil { return r.RecalculateSeriesStatsTx(tx, *set.ParentID) } return nil }