From 6e5bded9e20f4a69388052c5af2c8915a7723f55 Mon Sep 17 00:00:00 2001 From: pahmiudahgede Date: Fri, 13 Dec 2024 08:49:44 +0700 Subject: [PATCH] feat: add feature coverage area API --- config/connection.go | 3 + domain/coveragearea.go | 29 +++++++++ dto/coveragearea.go | 72 +++++++++++++++++++++ internal/api/routes.go | 5 ++ internal/controllers/coveragearea.go | 91 +++++++++++++++++++++++++++ internal/repositories/coveragearea.go | 30 +++++++++ internal/services/coveragearea.go | 18 ++++++ 7 files changed, 248 insertions(+) create mode 100644 domain/coveragearea.go create mode 100644 dto/coveragearea.go create mode 100644 internal/controllers/coveragearea.go create mode 100644 internal/repositories/coveragearea.go create mode 100644 internal/services/coveragearea.go diff --git a/config/connection.go b/config/connection.go index d8f9888..ece1e39 100644 --- a/config/connection.go +++ b/config/connection.go @@ -62,6 +62,9 @@ func InitDatabase() { &domain.TrashCategory{}, &domain.TrashDetail{}, &domain.Banner{}, + &domain.CoverageArea{}, + &domain.CoverageDetail{}, + &domain.LocationSpecific{}, ) if err != nil { log.Fatal("Error: Failed to auto migrate domain:", err) diff --git a/domain/coveragearea.go b/domain/coveragearea.go new file mode 100644 index 0000000..ba2e0b6 --- /dev/null +++ b/domain/coveragearea.go @@ -0,0 +1,29 @@ +package domain + +import "time" + +type CoverageArea struct { + ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"` + Province string `gorm:"not null" json:"province"` + CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"` + UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"` + Details []CoverageDetail `gorm:"foreignKey:CoverageAreaID" json:"coverage_area"` +} + +type CoverageDetail struct { + ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"` + CoverageAreaID string `gorm:"not null" json:"coverage_area_id"` + Province string `gorm:"not null" json:"province"` + District string `gorm:"not null" json:"district"` + CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"` + UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"` + LocationSpecific []LocationSpecific `gorm:"foreignKey:CoverageDetailID" json:"location_specific"` +} + +type LocationSpecific struct { + ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"` + CoverageDetailID string `gorm:"not null" json:"coverage_detail_id"` + Subdistrict string `gorm:"not null" json:"subdistrict"` + CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"` + UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"` +} diff --git a/dto/coveragearea.go b/dto/coveragearea.go new file mode 100644 index 0000000..0083a3e --- /dev/null +++ b/dto/coveragearea.go @@ -0,0 +1,72 @@ +package dto + +type CoverageAreaResponse struct { + ID string `json:"id"` + Province string `json:"province"` +} + +type CoverageAreaWithDistrictsResponse struct { + ID string `json:"id"` + Province string `json:"province"` + CoverageArea []CoverageAreaResponse `json:"coverage_area"` +} + +type CoverageAreaDetailWithLocation struct { + ID string `json:"id"` + Province string `json:"province"` + District string `json:"district"` + LocationSpecific []LocationSpecificResponse `json:"location_specific"` +} + +type CoverageDetailResponse struct { + ID string `json:"id"` + Province string `json:"province"` + District string `json:"district"` + LocationSpecific []LocationSpecificResponse `json:"location_specific"` +} + +type LocationSpecificResponse struct { + ID string `json:"id"` + Subdistrict string `json:"subdistrict"` +} + +func NewCoverageAreaResponse(id, province string) CoverageAreaResponse { + return CoverageAreaResponse{ + ID: id, + Province: province, + } +} + +func NewCoverageDetailResponse(id, province, district string, locationSpecific []LocationSpecificResponse) CoverageDetailResponse { + return CoverageDetailResponse{ + ID: id, + Province: province, + District: district, + LocationSpecific: locationSpecific, + } +} + +func NewLocationSpecificResponse(id, subdistrict string) LocationSpecificResponse { + return LocationSpecificResponse{ + ID: id, + Subdistrict: subdistrict, + } +} + +func NewCoverageAreaWithDistrictsResponse(id, province string, coverageArea []CoverageAreaResponse) CoverageAreaWithDistrictsResponse { + return CoverageAreaWithDistrictsResponse{ + ID: id, + Province: province, + CoverageArea: coverageArea, + } +} + + +func NewCoverageAreaDetailWithLocation(id, province, district string, locationSpecific []LocationSpecificResponse) CoverageAreaDetailWithLocation { + return CoverageAreaDetailWithLocation{ + ID: id, + Province: province, + District: district, + LocationSpecific: locationSpecific, + } +} \ No newline at end of file diff --git a/internal/api/routes.go b/internal/api/routes.go index eb1377f..ab4a066 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -17,6 +17,11 @@ func AppRouter(app *fiber.App) { app.Put("/apirijikid/user/initial-coint/:id", controllers.UpdatePoint) app.Delete("/apirijikid/user/initial-coint/:id", controllers.DeletePoint) + //# coverage area + app.Get("/apirijikid/coverage-areas", controllers.GetCoverageAreas) + app.Get("/apirijikid/coverage-areas-district/:id", controllers.GetCoverageAreaByIDProvince) + app.Get("/apirijikid/coverage-areas-subdistrict/:id", controllers.GetCoverageAreaByIDDistrict) + // # role app.Get("/apirijikid/roles", controllers.GetAllUserRoles) app.Get("/apirijikid/role/:id", controllers.GetUserRoleByID) diff --git a/internal/controllers/coveragearea.go b/internal/controllers/coveragearea.go new file mode 100644 index 0000000..177da4a --- /dev/null +++ b/internal/controllers/coveragearea.go @@ -0,0 +1,91 @@ +package controllers + +import ( + "github.com/gofiber/fiber/v2" + "github.com/pahmiudahgede/senggoldong/dto" + "github.com/pahmiudahgede/senggoldong/internal/services" + "github.com/pahmiudahgede/senggoldong/utils" +) + +func GetCoverageAreas(c *fiber.Ctx) error { + coverageAreas, err := services.GetCoverageAreas() + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( + fiber.StatusInternalServerError, + "Failed to fetch coverage areas", + nil, + )) + } + + var coverageAreaResponses []dto.CoverageAreaResponse + for _, area := range coverageAreas { + coverageAreaResponses = append(coverageAreaResponses, dto.NewCoverageAreaResponse(area.ID, area.Province)) + } + + return c.Status(fiber.StatusOK).JSON(utils.FormatResponse( + fiber.StatusOK, + "Coverage areas has been fetched", + coverageAreaResponses, + )) +} + +func GetCoverageAreaByIDProvince(c *fiber.Ctx) error { + id := c.Params("id") + + coverageArea, err := services.GetCoverageAreaByID(id) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( + fiber.StatusInternalServerError, + "Failed to fetch coverage area details by province", + nil, + )) + } + + var coverageAreaResponse dto.CoverageAreaWithDistrictsResponse + coverageAreaResponse.ID = coverageArea.ID + coverageAreaResponse.Province = coverageArea.Province + + var coverageAreas []dto.CoverageAreaResponse + for _, detail := range coverageArea.Details { + coverageAreas = append(coverageAreas, dto.NewCoverageAreaResponse(detail.ID, detail.District)) + } + + coverageAreaResponse.CoverageArea = coverageAreas + + return c.Status(fiber.StatusOK).JSON(utils.FormatResponse( + fiber.StatusOK, + "Coverage areas detail by province has been fetched", + coverageAreaResponse, + )) +} + +func GetCoverageAreaByIDDistrict(c *fiber.Ctx) error { + id := c.Params("id") + + coverageDetail, err := services.GetCoverageAreaByDistrictID(id) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( + fiber.StatusInternalServerError, + "Failed to fetch coverage area details by district", + nil, + )) + } + + var locationSpecificResponses []dto.LocationSpecificResponse + for _, loc := range coverageDetail.LocationSpecific { + locationSpecificResponses = append(locationSpecificResponses, dto.NewLocationSpecificResponse(loc.ID, loc.Subdistrict)) + } + + coverageAreaResponse := dto.CoverageAreaDetailWithLocation{ + ID: coverageDetail.ID, + Province: coverageDetail.Province, + District: coverageDetail.District, + LocationSpecific: locationSpecificResponses, + } + + return c.Status(fiber.StatusOK).JSON(utils.FormatResponse( + fiber.StatusOK, + "Coverage areas detail by district has been fetched", + coverageAreaResponse, + )) +} diff --git a/internal/repositories/coveragearea.go b/internal/repositories/coveragearea.go new file mode 100644 index 0000000..48795f4 --- /dev/null +++ b/internal/repositories/coveragearea.go @@ -0,0 +1,30 @@ +package repositories + +import ( + "github.com/pahmiudahgede/senggoldong/config" + "github.com/pahmiudahgede/senggoldong/domain" +) + +func GetCoverageAreas() ([]domain.CoverageArea, error) { + var coverageAreas []domain.CoverageArea + if err := config.DB.Preload("Details").Find(&coverageAreas).Error; err != nil { + return nil, err + } + return coverageAreas, nil +} + +func GetCoverageAreaByID(id string) (domain.CoverageArea, error) { + var coverageArea domain.CoverageArea + if err := config.DB.Preload("Details.LocationSpecific").Where("id = ?", id).First(&coverageArea).Error; err != nil { + return coverageArea, err + } + return coverageArea, nil +} + +func GetCoverageAreaByDistrictID(id string) (domain.CoverageDetail, error) { + var coverageDetail domain.CoverageDetail + if err := config.DB.Preload("LocationSpecific").Where("id = ?", id).First(&coverageDetail).Error; err != nil { + return coverageDetail, err + } + return coverageDetail, nil +} diff --git a/internal/services/coveragearea.go b/internal/services/coveragearea.go new file mode 100644 index 0000000..882e835 --- /dev/null +++ b/internal/services/coveragearea.go @@ -0,0 +1,18 @@ +package services + +import ( + "github.com/pahmiudahgede/senggoldong/domain" + "github.com/pahmiudahgede/senggoldong/internal/repositories" +) + +func GetCoverageAreas() ([]domain.CoverageArea, error) { + return repositories.GetCoverageAreas() +} + +func GetCoverageAreaByID(id string) (domain.CoverageArea, error) { + return repositories.GetCoverageAreaByID(id) +} + +func GetCoverageAreaByDistrictID(id string) (domain.CoverageDetail, error) { + return repositories.GetCoverageAreaByDistrictID(id) +}