diff --git a/domain/coveragearea.go b/domain/coveragearea.go index ba2e0b6..0a3192b 100644 --- a/domain/coveragearea.go +++ b/domain/coveragearea.go @@ -7,22 +7,21 @@ type CoverageArea struct { 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"` + Details []CoverageDetail `gorm:"foreignKey:CoverageAreaID;constraint:OnDelete:CASCADE;OnUpdate:CASCADE;" 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"` + CoverageAreaID string `gorm:"not null;constraint:OnDelete:CASCADE;OnUpdate:CASCADE;" json:"coverage_area_id"` District string `gorm:"not null" json:"district"` + LocationSpecific []LocationSpecific `gorm:"foreignKey:CoverageDetailID;constraint:OnDelete:CASCADE;OnUpdate:CASCADE;" json:"location_specific"` 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"` + CoverageDetailID string `gorm:"not null;constraint:OnDelete:CASCADE;OnUpdate:CASCADE;" 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 index 0083a3e..c0ffcd3 100644 --- a/dto/coveragearea.go +++ b/dto/coveragearea.go @@ -1,24 +1,17 @@ package dto type CoverageAreaResponse struct { - ID string `json:"id"` - Province string `json:"province"` + ID string `json:"id"` + Province string `json:"province"` } type CoverageAreaWithDistrictsResponse struct { - ID string `json:"id"` - Province string `json:"province"` + 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"` @@ -30,6 +23,24 @@ type LocationSpecificResponse struct { Subdistrict string `json:"subdistrict"` } +type CoverageDetailResponse struct { + ID string `json:"id"` + Province string `json:"province"` + District string `json:"district"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +func NewCoverageDetailResponse(id, province, district, createdAt, updatedAt string) CoverageDetailResponse { + return CoverageDetailResponse{ + ID: id, + Province: province, + District: district, + CreatedAt: createdAt, + UpdatedAt: updatedAt, + } +} + func NewCoverageAreaResponse(id, province string) CoverageAreaResponse { return CoverageAreaResponse{ ID: id, @@ -37,15 +48,6 @@ func NewCoverageAreaResponse(id, province string) CoverageAreaResponse { } } -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, @@ -61,7 +63,6 @@ func NewCoverageAreaWithDistrictsResponse(id, province string, coverageArea []Co } } - func NewCoverageAreaDetailWithLocation(id, province, district string, locationSpecific []LocationSpecificResponse) CoverageAreaDetailWithLocation { return CoverageAreaDetailWithLocation{ ID: id, @@ -69,4 +70,19 @@ func NewCoverageAreaDetailWithLocation(id, province, district string, locationSp District: district, LocationSpecific: locationSpecific, } +} + +type CoverageAreaRequest struct { + Province string `json:"province" validate:"required"` +} + +type CoverageDetailRequest struct { + CoverageAreaID string `json:"coverage_area_id" validate:"required"` + Province string `json:"province" validate:"required"` + District string `json:"district" validate:"required"` +} + +type LocationSpecificRequest struct { + CoverageDetailID string `json:"coverage_detail_id" validate:"required"` + Subdistrict string `json:"subdistrict" validate:"required"` } \ No newline at end of file diff --git a/internal/api/routes.go b/internal/api/routes.go index ab4a066..063e6de 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -21,6 +21,9 @@ func AppRouter(app *fiber.App) { 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) + app.Post("/apirijikid/coverage-areas", controllers.CreateCoverageArea) + app.Post("/apirijikid/coverage-areas-district", controllers.CreateCoverageDetail) + app.Post("/apirijikid/coverage-areas-subdistrict", controllers.CreateLocationSpecific) // # role app.Get("/apirijikid/roles", controllers.GetAllUserRoles) diff --git a/internal/controllers/coveragearea.go b/internal/controllers/coveragearea.go index 177da4a..c231f32 100644 --- a/internal/controllers/coveragearea.go +++ b/internal/controllers/coveragearea.go @@ -78,7 +78,6 @@ func GetCoverageAreaByIDDistrict(c *fiber.Ctx) error { coverageAreaResponse := dto.CoverageAreaDetailWithLocation{ ID: coverageDetail.ID, - Province: coverageDetail.Province, District: coverageDetail.District, LocationSpecific: locationSpecificResponses, } @@ -89,3 +88,81 @@ func GetCoverageAreaByIDDistrict(c *fiber.Ctx) error { coverageAreaResponse, )) } + +func CreateCoverageArea(c *fiber.Ctx) error { + var request dto.CoverageAreaRequest + if err := c.BodyParser(&request); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse( + fiber.StatusBadRequest, + "Invalid input data", + nil, + )) + } + + coverageArea, err := services.CreateCoverageArea(request.Province) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( + fiber.StatusInternalServerError, + "Failed to create coverage area", + nil, + )) + } + + return c.Status(fiber.StatusOK).JSON(utils.FormatResponse( + fiber.StatusOK, + "Coverage area has been created successfully", + coverageArea, + )) +} + +func CreateCoverageDetail(c *fiber.Ctx) error { + var request dto.CoverageDetailRequest + if err := c.BodyParser(&request); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse( + fiber.StatusBadRequest, + "Invalid input data", + nil, + )) + } + + coverageDetail, err := services.CreateCoverageDetail(request.CoverageAreaID, request.Province, request.District) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( + fiber.StatusInternalServerError, + "Failed to create coverage detail", + nil, + )) + } + + return c.Status(fiber.StatusOK).JSON(utils.FormatResponse( + fiber.StatusOK, + "Coverage detail has been created successfully", + coverageDetail, + )) +} + +func CreateLocationSpecific(c *fiber.Ctx) error { + var request dto.LocationSpecificRequest + if err := c.BodyParser(&request); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse( + fiber.StatusBadRequest, + "Invalid input data", + nil, + )) + } + + locationSpecific, err := services.CreateLocationSpecific(request.CoverageDetailID, request.Subdistrict) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( + fiber.StatusInternalServerError, + "Failed to create location specific", + nil, + )) + } + + return c.Status(fiber.StatusOK).JSON(utils.FormatResponse( + fiber.StatusOK, + "Location specific has been created successfully", + locationSpecific, + )) +} diff --git a/internal/repositories/coveragearea.go b/internal/repositories/coveragearea.go index 48795f4..84477c7 100644 --- a/internal/repositories/coveragearea.go +++ b/internal/repositories/coveragearea.go @@ -1,6 +1,8 @@ package repositories import ( + "errors" + "github.com/pahmiudahgede/senggoldong/config" "github.com/pahmiudahgede/senggoldong/domain" ) @@ -15,8 +17,8 @@ func GetCoverageAreas() ([]domain.CoverageArea, error) { 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 + if err := config.DB.Preload("Details").Where("id = ?", id).First(&coverageArea).Error; err != nil { + return coverageArea, errors.New("coverage area not found") } return coverageArea, nil } @@ -28,3 +30,41 @@ func GetCoverageAreaByDistrictID(id string) (domain.CoverageDetail, error) { } return coverageDetail, nil } + +func CreateCoverageArea(province string) (domain.CoverageArea, error) { + coverageArea := domain.CoverageArea{ + Province: province, + } + + if err := config.DB.Create(&coverageArea).Error; err != nil { + return domain.CoverageArea{}, err + } + + return coverageArea, nil +} + +func CreateCoverageDetail(coverageAreaID, province, district string) (domain.CoverageDetail, error) { + coverageDetail := domain.CoverageDetail{ + CoverageAreaID: coverageAreaID, + District: district, + } + + if err := config.DB.Create(&coverageDetail).Error; err != nil { + return domain.CoverageDetail{}, err + } + + return coverageDetail, nil +} + +func CreateLocationSpecific(coverageDetailID, subdistrict string) (domain.LocationSpecific, error) { + locationSpecific := domain.LocationSpecific{ + CoverageDetailID: coverageDetailID, + Subdistrict: subdistrict, + } + + if err := config.DB.Create(&locationSpecific).Error; err != nil { + return domain.LocationSpecific{}, err + } + + return locationSpecific, nil +} diff --git a/internal/services/coveragearea.go b/internal/services/coveragearea.go index 882e835..0acc675 100644 --- a/internal/services/coveragearea.go +++ b/internal/services/coveragearea.go @@ -16,3 +16,15 @@ func GetCoverageAreaByID(id string) (domain.CoverageArea, error) { func GetCoverageAreaByDistrictID(id string) (domain.CoverageDetail, error) { return repositories.GetCoverageAreaByDistrictID(id) } + +func CreateCoverageArea(province string) (domain.CoverageArea, error) { + return repositories.CreateCoverageArea(province) +} + +func CreateCoverageDetail(coverageAreaID, province, district string) (domain.CoverageDetail, error) { + return repositories.CreateCoverageDetail(coverageAreaID, province, district) +} + +func CreateLocationSpecific(coverageDetailID, subdistrict string) (domain.LocationSpecific, error) { + return repositories.CreateLocationSpecific(coverageDetailID, subdistrict) +} \ No newline at end of file