327 lines
9.5 KiB
Go
327 lines
9.5 KiB
Go
package trash
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"rijig/model"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type TrashRepositoryInterface interface {
|
|
CreateTrashCategory(ctx context.Context, category *model.TrashCategory) error
|
|
CreateTrashCategoryWithDetails(ctx context.Context, category *model.TrashCategory, details []model.TrashDetail) error
|
|
UpdateTrashCategory(ctx context.Context, id string, updates map[string]interface{}) error
|
|
GetAllTrashCategories(ctx context.Context) ([]model.TrashCategory, error)
|
|
GetAllTrashCategoriesWithDetails(ctx context.Context) ([]model.TrashCategory, error)
|
|
GetTrashCategoryByID(ctx context.Context, id string) (*model.TrashCategory, error)
|
|
GetTrashCategoryByIDWithDetails(ctx context.Context, id string) (*model.TrashCategory, error)
|
|
DeleteTrashCategory(ctx context.Context, id string) error
|
|
|
|
CreateTrashDetail(ctx context.Context, detail *model.TrashDetail) error
|
|
AddTrashDetailToCategory(ctx context.Context, categoryID string, detail *model.TrashDetail) error
|
|
UpdateTrashDetail(ctx context.Context, id string, updates map[string]interface{}) error
|
|
GetTrashDetailsByCategory(ctx context.Context, categoryID string) ([]model.TrashDetail, error)
|
|
GetTrashDetailByID(ctx context.Context, id string) (*model.TrashDetail, error)
|
|
DeleteTrashDetail(ctx context.Context, id string) error
|
|
|
|
CheckTrashCategoryExists(ctx context.Context, id string) (bool, error)
|
|
CheckTrashDetailExists(ctx context.Context, id string) (bool, error)
|
|
GetMaxStepOrderByCategory(ctx context.Context, categoryID string) (int, error)
|
|
}
|
|
|
|
type TrashRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewTrashRepository(db *gorm.DB) TrashRepositoryInterface {
|
|
return &TrashRepository{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
func (r *TrashRepository) CreateTrashCategory(ctx context.Context, category *model.TrashCategory) error {
|
|
if err := r.db.WithContext(ctx).Create(category).Error; err != nil {
|
|
return fmt.Errorf("failed to create trash category: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *TrashRepository) CreateTrashCategoryWithDetails(ctx context.Context, category *model.TrashCategory, details []model.TrashDetail) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
|
|
if err := tx.Create(category).Error; err != nil {
|
|
return fmt.Errorf("failed to create trash category: %w", err)
|
|
}
|
|
|
|
if len(details) > 0 {
|
|
|
|
for i := range details {
|
|
details[i].TrashCategoryID = category.ID
|
|
|
|
if details[i].StepOrder == 0 {
|
|
details[i].StepOrder = i + 1
|
|
}
|
|
}
|
|
|
|
if err := tx.Create(&details).Error; err != nil {
|
|
return fmt.Errorf("failed to create trash details: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (r *TrashRepository) UpdateTrashCategory(ctx context.Context, id string, updates map[string]interface{}) error {
|
|
|
|
exists, err := r.CheckTrashCategoryExists(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return errors.New("trash category not found")
|
|
}
|
|
|
|
updates["updated_at"] = time.Now()
|
|
|
|
result := r.db.WithContext(ctx).Model(&model.TrashCategory{}).Where("id = ?", id).Updates(updates)
|
|
if result.Error != nil {
|
|
return fmt.Errorf("failed to update trash category: %w", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.New("no rows affected during update")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *TrashRepository) GetAllTrashCategories(ctx context.Context) ([]model.TrashCategory, error) {
|
|
var categories []model.TrashCategory
|
|
|
|
if err := r.db.WithContext(ctx).Find(&categories).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get trash categories: %w", err)
|
|
}
|
|
|
|
return categories, nil
|
|
}
|
|
|
|
func (r *TrashRepository) GetAllTrashCategoriesWithDetails(ctx context.Context) ([]model.TrashCategory, error) {
|
|
var categories []model.TrashCategory
|
|
|
|
if err := r.db.WithContext(ctx).Preload("Details", func(db *gorm.DB) *gorm.DB {
|
|
return db.Order("step_order ASC")
|
|
}).Find(&categories).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get trash categories with details: %w", err)
|
|
}
|
|
|
|
return categories, nil
|
|
}
|
|
|
|
func (r *TrashRepository) GetTrashCategoryByID(ctx context.Context, id string) (*model.TrashCategory, error) {
|
|
var category model.TrashCategory
|
|
|
|
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&category).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, errors.New("trash category not found")
|
|
}
|
|
return nil, fmt.Errorf("failed to get trash category: %w", err)
|
|
}
|
|
|
|
return &category, nil
|
|
}
|
|
|
|
func (r *TrashRepository) GetTrashCategoryByIDWithDetails(ctx context.Context, id string) (*model.TrashCategory, error) {
|
|
var category model.TrashCategory
|
|
|
|
if err := r.db.WithContext(ctx).Preload("Details", func(db *gorm.DB) *gorm.DB {
|
|
return db.Order("step_order ASC")
|
|
}).Where("id = ?", id).First(&category).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, errors.New("trash category not found")
|
|
}
|
|
return nil, fmt.Errorf("failed to get trash category with details: %w", err)
|
|
}
|
|
|
|
return &category, nil
|
|
}
|
|
|
|
func (r *TrashRepository) DeleteTrashCategory(ctx context.Context, id string) error {
|
|
|
|
exists, err := r.CheckTrashCategoryExists(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return errors.New("trash category not found")
|
|
}
|
|
|
|
result := r.db.WithContext(ctx).Delete(&model.TrashCategory{ID: id})
|
|
if result.Error != nil {
|
|
return fmt.Errorf("failed to delete trash category: %w", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.New("no rows affected during deletion")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *TrashRepository) CreateTrashDetail(ctx context.Context, detail *model.TrashDetail) error {
|
|
|
|
exists, err := r.CheckTrashCategoryExists(ctx, detail.TrashCategoryID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return errors.New("trash category not found")
|
|
}
|
|
|
|
if detail.StepOrder == 0 {
|
|
maxOrder, err := r.GetMaxStepOrderByCategory(ctx, detail.TrashCategoryID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
detail.StepOrder = maxOrder + 1
|
|
}
|
|
|
|
if err := r.db.WithContext(ctx).Create(detail).Error; err != nil {
|
|
return fmt.Errorf("failed to create trash detail: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *TrashRepository) AddTrashDetailToCategory(ctx context.Context, categoryID string, detail *model.TrashDetail) error {
|
|
|
|
exists, err := r.CheckTrashCategoryExists(ctx, categoryID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return errors.New("trash category not found")
|
|
}
|
|
|
|
detail.TrashCategoryID = categoryID
|
|
|
|
if detail.StepOrder == 0 {
|
|
maxOrder, err := r.GetMaxStepOrderByCategory(ctx, categoryID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
detail.StepOrder = maxOrder + 1
|
|
}
|
|
|
|
if err := r.db.WithContext(ctx).Create(detail).Error; err != nil {
|
|
return fmt.Errorf("failed to add trash detail to category: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *TrashRepository) UpdateTrashDetail(ctx context.Context, id string, updates map[string]interface{}) error {
|
|
|
|
exists, err := r.CheckTrashDetailExists(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return errors.New("trash detail not found")
|
|
}
|
|
|
|
updates["updated_at"] = time.Now()
|
|
|
|
result := r.db.WithContext(ctx).Model(&model.TrashDetail{}).Where("id = ?", id).Updates(updates)
|
|
if result.Error != nil {
|
|
return fmt.Errorf("failed to update trash detail: %w", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.New("no rows affected during update")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *TrashRepository) GetTrashDetailsByCategory(ctx context.Context, categoryID string) ([]model.TrashDetail, error) {
|
|
var details []model.TrashDetail
|
|
|
|
if err := r.db.WithContext(ctx).Where("trash_category_id = ?", categoryID).Order("step_order ASC").Find(&details).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get trash details: %w", err)
|
|
}
|
|
|
|
return details, nil
|
|
}
|
|
|
|
func (r *TrashRepository) GetTrashDetailByID(ctx context.Context, id string) (*model.TrashDetail, error) {
|
|
var detail model.TrashDetail
|
|
|
|
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&detail).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, errors.New("trash detail not found")
|
|
}
|
|
return nil, fmt.Errorf("failed to get trash detail: %w", err)
|
|
}
|
|
|
|
return &detail, nil
|
|
}
|
|
|
|
func (r *TrashRepository) DeleteTrashDetail(ctx context.Context, id string) error {
|
|
|
|
exists, err := r.CheckTrashDetailExists(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return errors.New("trash detail not found")
|
|
}
|
|
|
|
result := r.db.WithContext(ctx).Delete(&model.TrashDetail{ID: id})
|
|
if result.Error != nil {
|
|
return fmt.Errorf("failed to delete trash detail: %w", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.New("no rows affected during deletion")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *TrashRepository) CheckTrashCategoryExists(ctx context.Context, id string) (bool, error) {
|
|
var count int64
|
|
|
|
if err := r.db.WithContext(ctx).Model(&model.TrashCategory{}).Where("id = ?", id).Count(&count).Error; err != nil {
|
|
return false, fmt.Errorf("failed to check trash category existence: %w", err)
|
|
}
|
|
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (r *TrashRepository) CheckTrashDetailExists(ctx context.Context, id string) (bool, error) {
|
|
var count int64
|
|
|
|
if err := r.db.WithContext(ctx).Model(&model.TrashDetail{}).Where("id = ?", id).Count(&count).Error; err != nil {
|
|
return false, fmt.Errorf("failed to check trash detail existence: %w", err)
|
|
}
|
|
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (r *TrashRepository) GetMaxStepOrderByCategory(ctx context.Context, categoryID string) (int, error) {
|
|
var maxOrder int
|
|
|
|
if err := r.db.WithContext(ctx).Model(&model.TrashDetail{}).
|
|
Where("trash_category_id = ?", categoryID).
|
|
Select("COALESCE(MAX(step_order), 0)").
|
|
Scan(&maxOrder).Error; err != nil {
|
|
return 0, fmt.Errorf("failed to get max step order: %w", err)
|
|
}
|
|
|
|
return maxOrder, nil
|
|
}
|