diff --git a/internal/server/http/entities/treecluster.go b/internal/server/http/entities/treecluster.go index 03f77199..b08763d8 100644 --- a/internal/server/http/entities/treecluster.go +++ b/internal/server/http/entities/treecluster.go @@ -27,7 +27,7 @@ type TreeClusterResponse struct { Archived bool `json:"archived"` Latitude *float64 `json:"latitude"` Longitude *float64 `json:"longitude"` - Trees []*TreeResponse `json:"trees,omitempty" validate:"optional"` + Trees []*TreeResponse `json:"trees" validate:"optional"` SoilCondition TreeSoilCondition `json:"soil_condition"` Name string `json:"name"` } // @Name TreeCluster diff --git a/internal/service/domain/region/region_test.go b/internal/service/domain/region/region_test.go new file mode 100644 index 00000000..11d5ecd0 --- /dev/null +++ b/internal/service/domain/region/region_test.go @@ -0,0 +1,104 @@ +package region + +import ( + "context" + "testing" + + "github.com/green-ecolution/green-ecolution-backend/internal/entities" + "github.com/green-ecolution/green-ecolution-backend/internal/storage" + storageMock "github.com/green-ecolution/green-ecolution-backend/internal/storage/_mock" + "github.com/stretchr/testify/assert" +) + +func TestRegionService_GetAll(t *testing.T) { + t.Run("should return all regions", func(t *testing.T) { + // given + repo := storageMock.NewMockRegionRepository(t) + svc := NewRegionService(repo) + + expectedRegions := []*entities.Region{ + {ID: 1, Name: "Region A"}, + {ID: 2, Name: "Region B"}, + } + + // when + repo.EXPECT().GetAll(context.Background()).Return(expectedRegions, nil) + regions, err := svc.GetAll(context.Background()) + + // then + assert.NoError(t, err) + assert.Equal(t, expectedRegions, regions) + }) + + t.Run("should return error when repository fails", func(t *testing.T) { + // given + repo := storageMock.NewMockRegionRepository(t) + svc := NewRegionService(repo) + + repo.EXPECT().GetAll(context.Background()).Return(nil, storage.ErrRegionNotFound) + regions, err := svc.GetAll(context.Background()) + + // then + assert.Error(t, err) + assert.Equal(t, storage.ErrRegionNotFound, err) + assert.Nil(t, regions) + }) +} + +func TestRegionService_GetByID(t *testing.T) { + t.Run("should return region when found", func(t *testing.T) { + // given + repo := storageMock.NewMockRegionRepository(t) + svc := NewRegionService(repo) + + expectedRegion := &entities.Region{ID: 1, Name: "Region A"} + + // when + repo.EXPECT().GetByID(context.Background(), int32(1)).Return(expectedRegion, nil) + region, err := svc.GetByID(context.Background(), 1) + + // then + assert.NoError(t, err) + assert.Equal(t, expectedRegion, region) + }) + + t.Run("should return error when region not found", func(t *testing.T) { + // given + repo := storageMock.NewMockRegionRepository(t) + svc := NewRegionService(repo) + + // when + repo.EXPECT().GetByID(context.Background(), int32(3)).Return(nil, storage.ErrRegionNotFound) + region, err := svc.GetByID(context.Background(), 3) + + // then + assert.Error(t, err) + assert.Nil(t, region) + }) +} + +func TestReady(t *testing.T) { + t.Run("should return true if the service is ready", func(t *testing.T) { + // given + repo := storageMock.NewMockRegionRepository(t) + svc := NewRegionService(repo) + + // when + ready := svc.Ready() + + // then + assert.True(t, ready) + }) + + t.Run("should return false if the service is not ready", func(t *testing.T) { + // given + svc := NewRegionService(nil) + + // when + ready := svc.Ready() + + // then + assert.False(t, ready) + }) +} + diff --git a/internal/service/domain/treecluster/geo_locator.go b/internal/service/domain/treecluster/geo_locator.go index c94170ee..c290564c 100644 --- a/internal/service/domain/treecluster/geo_locator.go +++ b/internal/service/domain/treecluster/geo_locator.go @@ -35,7 +35,24 @@ func (s *GeoClusterLocator) UpdateCluster(ctx context.Context, clusterID *int32) return err } - treeIDs := utils.Map(cluster.Trees, func(t *entities.Tree) int32 { + if len(cluster.Trees) == 0 { + return s.removeClusterCoords(ctx, *clusterID) + } + + return s.setClusterCoords(ctx, *clusterID, cluster.Trees) +} + +func (s *GeoClusterLocator) removeClusterCoords(ctx context.Context, clusterID int32) error { + _, err := s.clusterRepo.Update(ctx, clusterID, + treecluster.WithLatitude(nil), + treecluster.WithLongitude(nil), + treecluster.WithRegion(nil), + ) + return err +} + +func (s *GeoClusterLocator) setClusterCoords(ctx context.Context, clusterID int32, trees []*entities.Tree) error { + treeIDs := utils.Map(trees, func(t *entities.Tree) int32 { return t.ID }) @@ -49,7 +66,7 @@ func (s *GeoClusterLocator) UpdateCluster(ctx context.Context, clusterID *int32) return err } - _, err = s.clusterRepo.Update(ctx, *clusterID, + _, err = s.clusterRepo.Update(ctx, clusterID, treecluster.WithLatitude(&lat), treecluster.WithLongitude(&long), treecluster.WithRegion(region), diff --git a/internal/storage/postgres/region/get.go b/internal/storage/postgres/region/get.go index 741bfd38..c71a5d8e 100644 --- a/internal/storage/postgres/region/get.go +++ b/internal/storage/postgres/region/get.go @@ -12,10 +12,8 @@ import ( func (r *RegionRepository) GetAll(ctx context.Context) ([]*entities.Region, error) { rows, err := r.store.GetAllRegions(ctx) if err != nil { - fmt.Printf("error: %v\n", err) return nil, err } - fmt.Printf("rows: %v\n", rows) return r.mapper.FromSqlList(rows), nil } diff --git a/internal/storage/postgres/treecluster/update.go b/internal/storage/postgres/treecluster/update.go index 7634ed3b..7b2c3548 100644 --- a/internal/storage/postgres/treecluster/update.go +++ b/internal/storage/postgres/treecluster/update.go @@ -44,15 +44,15 @@ func (r *TreeClusterRepository) updateEntity(ctx context.Context, tc *entities.T Name: tc.Name, } + if err := r.store.UnlinkTreeClusterID(ctx, &tc.ID); err != nil { + return err + } + if len(tc.Trees) > 0 { treeIDs := utils.Map(tc.Trees, func(t *entities.Tree) int32 { return t.ID }) - if err := r.store.UnlinkTreeClusterID(ctx, &tc.ID); err != nil { - return err - } - if err := r.LinkTreesToCluster(ctx, tc.ID, treeIDs); err != nil { return err }