package repository import ( "context" "github.com/Caknoooo/go-gin-clean-starter/database/entities" "github.com/Caknoooo/go-gin-clean-starter/modules/client/query" "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" ) type ( ClientRepository interface { Create(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) GetById(ctx context.Context, tx *gorm.DB, clientId string) (entities.M_Client, error) GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.M_Client, error) GetAll(ctx context.Context, filter query.ClientFilter) ([]entities.M_Client, int64, error) Update(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) Delete(ctx context.Context, tx *gorm.DB, clientId string) error AssignMenusToClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error RemoveMenusFromClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error } clientRepository struct { db *gorm.DB } ) func (r *clientRepository) GetAll(ctx context.Context, filter query.ClientFilter) ([]entities.M_Client, int64, error) { var clients []entities.M_Client var total int64 db := r.db.Model(&entities.M_Client{}) db = query.ApplyClientFilters(db, filter) // Hitung total data if err := db.Count(&total).Error; err != nil { return nil, 0, err } // Ambil data dengan pagination dan preload menus err := db. Preload("Menus"). Limit(filter.PerPage). Offset(filter.Page). Find(&clients).Error return clients, total, err } func (r *clientRepository) Create(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) { if tx == nil { tx = r.db } if client.ID == uuid.Nil { client.ID = uuid.New() } if err := tx.WithContext(ctx).Create(&client).Error; err != nil { return entities.M_Client{}, err } return client, nil } func (r *clientRepository) GetById(ctx context.Context, tx *gorm.DB, clientId string) (entities.M_Client, error) { if tx == nil { tx = r.db } var client entities.M_Client if err := tx.WithContext(ctx). Preload("Menus"). First(&client, "id = ?", clientId).Error; err != nil { return entities.M_Client{}, err } return client, nil } func (r *clientRepository) GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.M_Client, error) { if tx == nil { tx = r.db } var client entities.M_Client if err := tx.WithContext(ctx).Where("name = ?", name).First(&client).Error; err != nil { return entities.M_Client{}, err } return client, nil } func (r *clientRepository) Update(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Updates(&client).Error; err != nil { return entities.M_Client{}, err } return client, nil } func (r *clientRepository) Delete(ctx context.Context, tx *gorm.DB, clientId string) error { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Delete(&entities.M_Client{}, "id = ?", clientId).Error; err != nil { return err } return nil } // AssignMenusToClient implements MenuRepository. func (c *clientRepository) AssignMenusToClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error { if tx == nil { tx = c.db } var menuClients []entities.M_Menu_Client for _, menuId := range menuIds { menuClient := entities.M_Menu_Client{} if err := menuClient.MenuID.UnmarshalText([]byte(menuId)); err != nil { return err } if err := menuClient.ClientID.UnmarshalText([]byte(clientId)); err != nil { return err } menuClients = append(menuClients, menuClient) } // Use Create with OnConflict to ignore duplicates if err := tx.WithContext(ctx).Clauses( // Only insert if not exists (Postgres syntax, adjust if needed) clause.OnConflict{DoNothing: true}, ).Create(&menuClients).Error; err != nil { return err } return nil } // RemoveMenusFromClient implements MenuRepository. func (c *clientRepository) RemoveMenusFromClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error { if tx == nil { tx = c.db } if err := tx.WithContext(ctx). Where("menu_id IN ? AND client_id = ?", menuIds, clientId). Delete(&entities.M_Menu_Client{}).Error; err != nil { return err } return nil } func NewClientRepository(db *gorm.DB) ClientRepository { return &clientRepository{db: db} }