package repository import ( "context" "errors" "gitlab.com/mbugroup/lti-api.git/internal/common/repository" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gorm.io/gorm" ) type NonstockRepository interface { repository.BaseRepository[entity.Nonstock] NameExists(ctx context.Context, name string, excludeID *uint) (bool, error) SyncSuppliersDiff(ctx context.Context, tx *gorm.DB, nonstockID uint, suppliers []entity.NonstockSupplier) error UomExists(ctx context.Context, uomID uint) (bool, error) GetSuppliersByIDs(ctx context.Context, supplierIDs []uint) ([]entity.Supplier, error) SyncFlags(ctx context.Context, tx *gorm.DB, nonstockID uint, flags []string) error DeleteFlags(ctx context.Context, tx *gorm.DB, nonstockID uint) error GetFlags(ctx context.Context, nonstockID uint) ([]entity.Flag, error) IdExists(ctx context.Context, id uint) (bool, error) IsNonstockAssociatedWithSupplier(ctx context.Context, nonstockID uint, supplierID uint64) (bool, error) } type NonstockRepositoryImpl struct { *repository.BaseRepositoryImpl[entity.Nonstock] } func NewNonstockRepository(db *gorm.DB) NonstockRepository { return &NonstockRepositoryImpl{ BaseRepositoryImpl: repository.NewBaseRepository[entity.Nonstock](db), } } func (r *NonstockRepositoryImpl) NameExists(ctx context.Context, name string, excludeID *uint) (bool, error) { return repository.ExistsByName[entity.Nonstock](ctx, r.DB(), name, excludeID) } func (r *NonstockRepositoryImpl) IdExists(ctx context.Context, id uint) (bool, error) { return repository.Exists[entity.Nonstock](ctx, r.DB(), id) } func (r *NonstockRepositoryImpl) SyncSuppliersDiff(ctx context.Context, tx *gorm.DB, nonstockID uint, suppliers []entity.NonstockSupplier) error { db := tx if db == nil { db = r.DB() } if suppliers == nil { return db.WithContext(ctx). Where("nonstock_id = ?", nonstockID). Delete(&entity.NonstockSupplier{}). Error } var existing []entity.NonstockSupplier if err := db.WithContext(ctx). Where("nonstock_id = ?", nonstockID). Find(&existing). Error; err != nil { return err } existingMap := make(map[uint]entity.NonstockSupplier, len(existing)) for _, rel := range existing { existingMap[rel.SupplierId] = rel } incomingMap := make(map[uint]struct{}, len(suppliers)) for _, rel := range suppliers { incomingMap[rel.SupplierId] = struct{}{} if existingRel, exists := existingMap[rel.SupplierId]; exists { if existingRel.Price != rel.Price { if err := db.WithContext(ctx). Model(&entity.NonstockSupplier{}). Where("nonstock_id = ? AND supplier_id = ?", nonstockID, rel.SupplierId). Update("price", rel.Price). Error; err != nil { return err } } continue } record := entity.NonstockSupplier{ NonstockId: nonstockID, SupplierId: rel.SupplierId, Price: rel.Price, } if err := db.WithContext(ctx).Create(&record).Error; err != nil { return err } } for _, rel := range existing { if _, keep := incomingMap[rel.SupplierId]; !keep { if err := db.WithContext(ctx). Where("nonstock_id = ? AND supplier_id = ?", nonstockID, rel.SupplierId). Delete(&entity.NonstockSupplier{}). Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { continue } return err } } } return nil } func (r *NonstockRepositoryImpl) UomExists(ctx context.Context, uomID uint) (bool, error) { var count int64 if err := r.DB().WithContext(ctx). Model(&entity.Uom{}). Where("id = ?", uomID). Count(&count). Error; err != nil { return false, err } return count > 0, nil } func (r *NonstockRepositoryImpl) GetSuppliersByIDs(ctx context.Context, supplierIDs []uint) ([]entity.Supplier, error) { if len(supplierIDs) == 0 { return nil, nil } var suppliers []entity.Supplier if err := r.DB().WithContext(ctx). Select("id", "category"). Where("id IN ?", supplierIDs). Find(&suppliers). Error; err != nil { return nil, err } return suppliers, nil } func (r *NonstockRepositoryImpl) SyncFlags(ctx context.Context, tx *gorm.DB, nonstockID uint, flags []string) error { db := tx if db == nil { db = r.DB() } // Hapus flags lama terlebih dahulu if err := db.WithContext(ctx). Where("flagable_id = ? AND flagable_type = ?", nonstockID, entity.FlagableTypeNonstock). Delete(&entity.Flag{}). Error; err != nil { return err } // Insert flags baru jika ada if len(flags) > 0 { newFlags := make([]entity.Flag, len(flags)) for i, f := range flags { newFlags[i] = entity.Flag{ Name: f, FlagableID: nonstockID, FlagableType: entity.FlagableTypeNonstock, } } if err := db.WithContext(ctx).Create(&newFlags).Error; err != nil { return err } } return nil } func (r *NonstockRepositoryImpl) DeleteFlags(ctx context.Context, tx *gorm.DB, nonstockID uint) error { db := tx if db == nil { db = r.DB() } return db.WithContext(ctx). Where("flagable_id = ? AND flagable_type = ?", nonstockID, entity.FlagableTypeNonstock). Delete(&entity.Flag{}). Error } func (r *NonstockRepositoryImpl) GetFlags(ctx context.Context, nonstockID uint) ([]entity.Flag, error) { var flags []entity.Flag if err := r.DB().WithContext(ctx). Where("flagable_id = ? AND flagable_type = ?", nonstockID, entity.FlagableTypeNonstock). Find(&flags). Error; err != nil { return nil, err } return flags, nil } func (r *NonstockRepositoryImpl) IsNonstockAssociatedWithSupplier(ctx context.Context, nonstockID uint, supplierID uint64) (bool, error) { var count int64 if err := r.DB().WithContext(ctx). Model(&entity.NonstockSupplier{}). Where("nonstock_id = ? AND supplier_id = ?", nonstockID, supplierID). Count(&count). Error; err != nil { return false, err } return count > 0, nil }