]> localhost Git - tq-wave11-pf.git/commitdiff
feat: create ingredient requirements done + fixed error handling
authorJansen <[email protected]>
Thu, 7 Aug 2025 19:04:51 +0000 (15:04 -0400)
committerJansen <[email protected]>
Thu, 7 Aug 2025 19:04:51 +0000 (15:04 -0400)
persistence/ingredient.go
persistence/inmemory/ingredients.go
pkg/http/errors.go
pkg/http/ingredient.go
pkg/services/errors.go
pkg/services/ingredient.go

index 8aeca27abfecb1b930579c832fb527c1fe4473d0..795944e1a116fdb02fa011765227d065c3daf35f 100644 (file)
@@ -9,6 +9,7 @@ type IngredientRepository interface {
        IngredientUpdate(core.Ingredient) error
        IngredientDeactivate(int) error
        IngredientGet(int) (*core.Ingredient, error)
+       IngredientGetByName(name string) (*core.Ingredient, error)
        // TODO: add search params
        IngredientList() ([]core.Ingredient, error)
 }
index 4a30c4825a0c602934b3c93e2a4303ce07ebd898..a37622a898fc0fab7487e8be08c2d315134775cb 100644 (file)
@@ -8,6 +8,16 @@ import (
 )
 
 func (p *InmemoryPersistence) IngredientCreate(in core.Ingredient) (core.Ingredient, error) {
+       // IRW this would be an index, so np leaving it here
+       found, err := p.IngredientGetByName(in.Name)
+       if err != nil {
+               return core.Ingredient{}, err
+       }
+       if found != nil {
+               return core.Ingredient{}, errors.New("name_in_use")
+       }
+
+
        id := len(p.ingredients) + 1
 
        createdAt := time.Now()
@@ -29,11 +39,20 @@ func (p *InmemoryPersistence) IngredientDeactivate(id int) error {
 
 func (p *InmemoryPersistence) IngredientGet(id int) (*core.Ingredient, error) {
        if id < 0 || id > len(p.ingredients) {
-               return nil, errors.New("not_found")
+               return nil, nil
        }
        return &p.ingredients[id-1], nil
 }
 
+func (p *InmemoryPersistence) IngredientGetByName(name string) (*core.Ingredient, error) {
+       for _, in := range p.ingredients {
+               if in.Name == name {
+                       return &in, nil
+               }
+       }
+       return nil, nil
+}
+
 func (p *InmemoryPersistence) IngredientList() ([]core.Ingredient, error) {
        return p.ingredients, nil
 }
index 8806ad26a3ca5b6407741d4ac9fec855e4d6b532..6cb51ebfc50d3f09af9fd8d7465cc3be1fd209a3 100644 (file)
@@ -2,6 +2,7 @@ package http
 
 import (
        "encoding/json"
+       "log"
        shttp "net/http"
 
        "jsdaj.tq/pf/pkg/services"
@@ -36,7 +37,14 @@ func handleErrorByCode(w shttp.ResponseWriter, status int) {
        }
 }
 
-func handleServiceError(w shttp.ResponseWriter, err services.Error) {
-       status := err.Code.MapToHTTP()
-       handleError(w, status, err.Message)
+func handleServiceError(w shttp.ResponseWriter, err error) {
+       switch err.(type) {
+       case services.Error:
+               e := err.(services.Error)
+               status := e.Code.MapToHTTP()
+               handleError(w, status, e.Message)
+       default:
+               log.Printf("error: Expecting 'services.Error', received: %s\n", err)
+               handleErrorByCode(w, shttp.StatusInternalServerError)
+       }
 }
index e02cd8fc17d8d7981ca27c88be4a9e93e8b5a6cf..c35ef8d223b61da618126a280578d695e06c2b4e 100644 (file)
@@ -20,7 +20,7 @@ func (s *Server) ingredientHandleCreate(w shttp.ResponseWriter, r *shttp.Request
 
        ingredient, err := s.ingredients.Create(input)
        if err != nil {
-               handleError(w, shttp.StatusInternalServerError, err.Error())
+               handleServiceError(w, err)
                return
        }
 
@@ -30,6 +30,7 @@ func (s *Server) ingredientHandleCreate(w shttp.ResponseWriter, r *shttp.Request
                return
        }
        
+       w.WriteHeader(shttp.StatusCreated)
        w.Write(response)
 }
 
index 11f3cb746d92abc5eabe2ae9708d14daf1732446..0f842bc13e484163e87f92f48194f697c740a5c5 100644 (file)
@@ -7,12 +7,15 @@ type ErrorCode int
 const (
        DefaultError   ErrorCode = iota
        BadInputError 
+       ConflictError
 )
 
 func (c ErrorCode) MapToHTTP() int {
        switch c {
        case BadInputError:
                return 400
+       case ConflictError:
+               return 409
        default:
                return 500
        }
@@ -24,5 +27,5 @@ type Error struct {
 }
 
 func (e Error) Error() string {
-       return fmt.Sprintf("%d :: %s", e.Code, e.Message)
+       return fmt.Sprintf("(%d)%s", e.Code, e.Message)
 }
index b3a1bb026625b7995ed0179069099632549c4737..2b0faac06fc24768e56b19989a19f33799b677bd 100644 (file)
@@ -10,8 +10,25 @@ type Ingredient struct {
 }
 
 func (s *Ingredient) Create(ingredient core.Ingredient) (*core.Ingredient, error) {
+       isMissingRequiredFields := ingredient.Name == "" || ingredient.Quantity == 0 
+       isBadName := len(ingredient.Name) < 3
+       isBadQuantity := ingredient.Quantity < 0
+
+       if isMissingRequiredFields {
+               return nil, Error{Code: BadInputError, Message: "fields required: name, quantity"}
+       }
+       if isBadName {
+               return nil, Error{Code: BadInputError, Message: "name should be have more than 2 chars"}
+       }
+       if isBadQuantity {
+               return nil, Error{Code: BadInputError, Message: "quantity should be positive"}
+       }
+
        ingredient, err := s.repository.IngredientCreate(ingredient)
        if err != nil {
+               if err.Error() == "name_in_use" {
+                       return nil, Error{Code: ConflictError, Message: err.Error()}
+               }
                return nil, err
        }
        return &ingredient, nil