mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 05:21:57 +00:00
fix(BE): kandang capacity and fix err response
This commit is contained in:
@@ -3,6 +3,8 @@ package validation
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
@@ -21,34 +23,41 @@ var customMessages = map[string]string{
|
||||
"alphanum": "Field %s must contain only alphanumeric characters",
|
||||
"oneof": "Invalid value for field %s",
|
||||
"password": "Field %s must be at least 8 characters, contain uppercase, lowercase, number, and special character",
|
||||
"gt": "Invalid %s, must be greater than %s",
|
||||
}
|
||||
|
||||
func CustomErrorMessages(err error) map[string]string {
|
||||
func CustomErrorMessages(err error) (string, map[string]string) {
|
||||
var validationErrors validator.ValidationErrors
|
||||
if errors.As(err, &validationErrors) {
|
||||
return generateErrorMessages(validationErrors)
|
||||
}
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func generateErrorMessages(validationErrors validator.ValidationErrors) map[string]string {
|
||||
func generateErrorMessages(validationErrors validator.ValidationErrors) (string, map[string]string) {
|
||||
errorsMap := make(map[string]string)
|
||||
for _, err := range validationErrors {
|
||||
var firstMessage string
|
||||
for i, err := range validationErrors {
|
||||
fieldName := err.StructNamespace()
|
||||
tag := err.Tag()
|
||||
|
||||
customMessage := customMessages[tag]
|
||||
var msg string
|
||||
if customMessage != "" {
|
||||
errorsMap[fieldName] = formatErrorMessage(customMessage, err, tag)
|
||||
msg = formatErrorMessage(customMessage, err, tag)
|
||||
} else {
|
||||
errorsMap[fieldName] = defaultErrorMessage(err)
|
||||
msg = defaultErrorMessage(err)
|
||||
}
|
||||
errorsMap[fieldName] = msg
|
||||
if i == 0 {
|
||||
firstMessage = msg
|
||||
}
|
||||
}
|
||||
return errorsMap
|
||||
return firstMessage, errorsMap
|
||||
}
|
||||
|
||||
func formatErrorMessage(customMessage string, err validator.FieldError, tag string) string {
|
||||
if tag == "min" || tag == "max" || tag == "len" {
|
||||
if tag == "min" || tag == "max" || tag == "len" || tag == "gt" {
|
||||
return fmt.Sprintf(customMessage, err.Field(), err.Param())
|
||||
}
|
||||
return fmt.Sprintf(customMessage, err.Field())
|
||||
@@ -61,6 +70,16 @@ func defaultErrorMessage(err validator.FieldError) string {
|
||||
func Validator() *validator.Validate {
|
||||
validate := validator.New()
|
||||
|
||||
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
|
||||
if jsonTag := getTagName(fld, "json"); jsonTag != "" {
|
||||
return jsonTag
|
||||
}
|
||||
if queryTag := getTagName(fld, "query"); queryTag != "" {
|
||||
return queryTag
|
||||
}
|
||||
return fld.Name
|
||||
})
|
||||
|
||||
if err := validate.RegisterValidation("password", Password); err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -72,3 +91,16 @@ func Validator() *validator.Validate {
|
||||
}
|
||||
return validate
|
||||
}
|
||||
|
||||
func getTagName(fld reflect.StructField, tag string) string {
|
||||
value, ok := fld.Tag.Lookup(tag)
|
||||
if !ok || value == "-" {
|
||||
return ""
|
||||
}
|
||||
|
||||
name := strings.Split(value, ",")[0]
|
||||
if name == "" || name == "-" {
|
||||
return ""
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE kandangs
|
||||
DROP COLUMN IF EXISTS capacity;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE kandangs
|
||||
ADD COLUMN capacity NUMERIC(15,3) NOT NULL;
|
||||
@@ -235,13 +235,14 @@ func seedKandangs(tx *gorm.DB, createdBy uint, locations map[string]uint, users
|
||||
seeds := []struct {
|
||||
Name string
|
||||
Status utils.KandangStatus
|
||||
Capacity float64
|
||||
Location string
|
||||
PicKey string
|
||||
}{
|
||||
{Name: "Singaparna 1", Status: utils.KandangStatusNonActive, Location: "Singaparna", PicKey: "admin"},
|
||||
{Name: "Singaparna 2", Status: utils.KandangStatusNonActive, Location: "Singaparna", PicKey: "admin"},
|
||||
{Name: "Cikaum 1", Status: utils.KandangStatusNonActive, Location: "Cikaum", PicKey: "admin"},
|
||||
{Name: "Cikaum 2", Status: utils.KandangStatusNonActive, Location: "Cikaum", PicKey: "admin"},
|
||||
{Name: "Singaparna 1", Status: utils.KandangStatusNonActive, Capacity: 50000, Location: "Singaparna", PicKey: "admin"},
|
||||
{Name: "Singaparna 2", Status: utils.KandangStatusNonActive, Capacity: 50000, Location: "Singaparna", PicKey: "admin"},
|
||||
{Name: "Cikaum 1", Status: utils.KandangStatusNonActive, Capacity: 50000, Location: "Cikaum", PicKey: "admin"},
|
||||
{Name: "Cikaum 2", Status: utils.KandangStatusNonActive, Capacity: 50000, Location: "Cikaum", PicKey: "admin"},
|
||||
}
|
||||
|
||||
result := make(map[string]uint, len(seeds))
|
||||
@@ -571,52 +572,44 @@ func seedProducts(tx *gorm.DB, createdBy uint, uoms map[string]uint, categories
|
||||
Flags: []utils.FlagType{utils.FlagDOC},
|
||||
},
|
||||
{
|
||||
Name: "Ayam Afkir",
|
||||
Brand: "-",
|
||||
Sku: "1",
|
||||
Uom: "Ekor",
|
||||
Category: "Day Old Chick",
|
||||
Price: 1,
|
||||
|
||||
|
||||
Name: "Ayam Afkir",
|
||||
Brand: "-",
|
||||
Sku: "1",
|
||||
Uom: "Ekor",
|
||||
Category: "Day Old Chick",
|
||||
Price: 1,
|
||||
},
|
||||
{
|
||||
Name: "Ayam Mati",
|
||||
Brand: "-",
|
||||
Sku: "2",
|
||||
Uom: "Ekor",
|
||||
Category: "Day Old Chick",
|
||||
Price: 1,
|
||||
|
||||
|
||||
Name: "Ayam Mati",
|
||||
Brand: "-",
|
||||
Sku: "2",
|
||||
Uom: "Ekor",
|
||||
Category: "Day Old Chick",
|
||||
Price: 1,
|
||||
},
|
||||
{
|
||||
Name: "Ayam Culling",
|
||||
Brand: "-",
|
||||
Sku: "3",
|
||||
Uom: "Ekor",
|
||||
Category: "Day Old Chick",
|
||||
Price: 1,
|
||||
|
||||
|
||||
Name: "Ayam Culling",
|
||||
Brand: "-",
|
||||
Sku: "3",
|
||||
Uom: "Ekor",
|
||||
Category: "Day Old Chick",
|
||||
Price: 1,
|
||||
},
|
||||
{
|
||||
Name: "Telur Konsumsi Baik",
|
||||
Brand: "-",
|
||||
Sku: "4",
|
||||
Uom: "Unit",
|
||||
Category: "Telur",
|
||||
Price: 1,
|
||||
|
||||
Name: "Telur Konsumsi Baik",
|
||||
Brand: "-",
|
||||
Sku: "4",
|
||||
Uom: "Unit",
|
||||
Category: "Telur",
|
||||
Price: 1,
|
||||
},
|
||||
{
|
||||
Name: "Telur Pecah",
|
||||
Brand: "-",
|
||||
Sku: "5",
|
||||
Uom: "Unit",
|
||||
Category: "Telur",
|
||||
Price: 1,
|
||||
|
||||
Name: "Telur Pecah",
|
||||
Brand: "-",
|
||||
Sku: "5",
|
||||
Uom: "Unit",
|
||||
Category: "Telur",
|
||||
Price: 1,
|
||||
},
|
||||
{
|
||||
Name: "281 SPECIAL STARTER",
|
||||
|
||||
@@ -7,17 +7,18 @@ import (
|
||||
)
|
||||
|
||||
type Kandang struct {
|
||||
Id uint `gorm:"primaryKey"`
|
||||
Name string `gorm:"not null;uniqueIndex:kandangs_name_unique,where:deleted_at IS NULL"`
|
||||
Status string `gorm:"type:varchar(50);not null"`
|
||||
LocationId uint `gorm:"not null"`
|
||||
PicId uint `gorm:"not null"`
|
||||
CreatedBy uint `gorm:"not null"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
|
||||
Location Location `gorm:"foreignKey:LocationId;references:Id"`
|
||||
Pic User `gorm:"foreignKey:PicId;references:Id"`
|
||||
Id uint `gorm:"primaryKey"`
|
||||
Name string `gorm:"not null;uniqueIndex:kandangs_name_unique,where:deleted_at IS NULL"`
|
||||
Status string `gorm:"type:varchar(50);not null"`
|
||||
LocationId uint `gorm:"not null"`
|
||||
Capacity float64 `gorm:"not null"`
|
||||
PicId uint `gorm:"not null"`
|
||||
CreatedBy uint `gorm:"not null"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
|
||||
Location Location `gorm:"foreignKey:LocationId;references:Id"`
|
||||
Pic User `gorm:"foreignKey:PicId;references:Id"`
|
||||
ProjectFlockKandangs []ProjectFlockKandang `gorm:"foreignKey:KandangId;references:Id" json:"-"`
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ type KandangBaseDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Capacity float64 `json:"capacity"`
|
||||
Location *locationDTO.LocationBaseDTO `json:"location"`
|
||||
Pic *userDTO.UserBaseDTO `json:"pic"`
|
||||
}
|
||||
@@ -48,6 +49,7 @@ func ToKandangBaseDTO(e entity.Kandang) KandangBaseDTO {
|
||||
Id: e.Id,
|
||||
Name: e.Name,
|
||||
Status: e.Status,
|
||||
Capacity: e.Capacity,
|
||||
Location: location,
|
||||
Pic: pic,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package kandangs
|
||||
|
||||
import (
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/controllers"
|
||||
kandang "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/services"
|
||||
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||
@@ -13,7 +13,7 @@ func KandangRoutes(v1 fiber.Router, u user.UserService, s kandang.KandangService
|
||||
ctrl := controller.NewKandangController(s)
|
||||
|
||||
route := v1.Group("/kandangs")
|
||||
route.Use(m.Auth(u))
|
||||
// route.Use(m.Auth(u))
|
||||
|
||||
route.Get("/", ctrl.GetAll)
|
||||
route.Post("/", ctrl.CreateOne)
|
||||
|
||||
@@ -134,6 +134,7 @@ func (s *kandangService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
|
||||
createBody := &entity.Kandang{
|
||||
Name: req.Name,
|
||||
LocationId: req.LocationId,
|
||||
Capacity: req.Capacity,
|
||||
Status: status,
|
||||
PicId: req.PicId,
|
||||
CreatedBy: 1,
|
||||
@@ -194,6 +195,10 @@ func (s kandangService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
updateBody["pic_id"] = *req.PicId
|
||||
}
|
||||
|
||||
if req.Capacity != nil {
|
||||
updateBody["capacity"] = *req.Capacity
|
||||
}
|
||||
|
||||
finalStatus := strings.ToUpper(existing.Status)
|
||||
if req.Status != nil {
|
||||
status := strings.ToUpper(*req.Status)
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package validation
|
||||
|
||||
type Create struct {
|
||||
Name string `json:"name" validate:"required_strict,min=3"`
|
||||
Status string `json:"status,omitempty" validate:"omitempty,min=3"`
|
||||
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
|
||||
PicId uint `json:"pic_id" validate:"required_strict,number,gt=0"`
|
||||
ProjectFlockId *uint `json:"project_flock_id" validate:"omitempty,number,gt=0"`
|
||||
Name string `json:"name" validate:"required_strict,min=3"`
|
||||
Status string `json:"status,omitempty" validate:"omitempty,min=3"`
|
||||
Capacity float64 `json:"capacity" validate:"required_strict,gt=0"`
|
||||
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
|
||||
PicId uint `json:"pic_id" validate:"required_strict,number,gt=0"`
|
||||
ProjectFlockId *uint `json:"project_flock_id" validate:"omitempty,number,gt=0"`
|
||||
}
|
||||
|
||||
type Update struct {
|
||||
Name *string `json:"name,omitempty" validate:"omitempty"`
|
||||
Status *string `json:"status,omitempty" validate:"omitempty,min=3"`
|
||||
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||
PicId *uint `json:"pic_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||
ProjectFlockId *uint `json:"project_flock_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||
Name *string `json:"name,omitempty" validate:"omitempty"`
|
||||
Status *string `json:"status,omitempty" validate:"omitempty,min=3"`
|
||||
Capacity *float64 `json:"capacity" validate:"omitempty,gt=0"`
|
||||
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||
PicId *uint `json:"pic_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||
ProjectFlockId *uint `json:"project_flock_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
|
||||
@@ -15,7 +15,8 @@ type UomBaseDTO struct {
|
||||
}
|
||||
|
||||
type UomListDTO struct {
|
||||
UomBaseDTO
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CreatedUser *userDTO.UserBaseDTO `json:"created_user"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
@@ -42,7 +43,8 @@ func ToUomListDTO(e entity.Uom) UomListDTO {
|
||||
}
|
||||
|
||||
return UomListDTO{
|
||||
UomBaseDTO: ToUomBaseDTO(e),
|
||||
Id: e.Id,
|
||||
Name: e.Name,
|
||||
CreatedAt: e.CreatedAt,
|
||||
UpdatedAt: e.UpdatedAt,
|
||||
CreatedUser: createdUser,
|
||||
|
||||
@@ -67,6 +67,7 @@ type RecordingStockDTO struct {
|
||||
}
|
||||
|
||||
type RecordingEggDTO struct {
|
||||
Id uint `json:"id"`
|
||||
ProductWarehouseId uint `json:"product_warehouse_id"`
|
||||
Qty int `json:"qty"`
|
||||
ProductWarehouse *RecordingProductWarehouseDTO `json:"product_warehouse,omitempty"`
|
||||
@@ -199,6 +200,7 @@ func ToRecordingEggDTOs(eggs []entity.RecordingEgg) []RecordingEggDTO {
|
||||
result := make([]RecordingEggDTO, len(eggs))
|
||||
for i, egg := range eggs {
|
||||
result[i] = RecordingEggDTO{
|
||||
Id: egg.Id,
|
||||
ProductWarehouseId: egg.ProductWarehouseId,
|
||||
Qty: egg.Qty,
|
||||
ProductWarehouse: toRecordingProductWarehouseDTO(&egg.ProductWarehouse),
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
func ErrorHandler(c *fiber.Ctx, err error) error {
|
||||
if errorsMap := validation.CustomErrorMessages(err); len(errorsMap) > 0 {
|
||||
return response.Error(c, fiber.StatusBadRequest, "Bad Request", errorsMap)
|
||||
if message, errorsMap := validation.CustomErrorMessages(err); len(errorsMap) > 0 {
|
||||
return response.Error(c, fiber.StatusBadRequest, message, nil)
|
||||
}
|
||||
|
||||
var fiberErr *fiber.Error
|
||||
|
||||
@@ -10,15 +10,16 @@ import (
|
||||
// === DTO Structs ===
|
||||
|
||||
type {{Pascal .Entity}}BaseDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type {{Pascal .Entity}}ListDTO struct {
|
||||
{{Pascal .Entity}}BaseDTO
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CreatedUser *userDTO.UserBaseDTO `json:"created_user"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type {{Pascal .Entity}}DetailDTO struct {
|
||||
@@ -42,7 +43,8 @@ func To{{Pascal .Entity}}ListDTO(e entity.{{Pascal .Entity}}) {{Pascal .Entity}}
|
||||
}
|
||||
|
||||
return {{Pascal .Entity}}ListDTO{
|
||||
{{Pascal .Entity}}BaseDTO: To{{Pascal .Entity}}BaseDTO(e),
|
||||
Id: e.Id,
|
||||
Name: e.Name,
|
||||
CreatedAt: e.CreatedAt,
|
||||
UpdatedAt: e.UpdatedAt,
|
||||
CreatedUser: createdUser,
|
||||
|
||||
Reference in New Issue
Block a user