mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-24 07:15:43 +00:00
FIX[BE]: name duplicate flock,projectflock category change,menerapkan dto seperti warehouse di projectflock
This commit is contained in:
@@ -50,7 +50,7 @@ func Run(db *gorm.DB) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
projectFlocks, err := seedProjectFlocks(tx, adminID, flocks, areas, productCategories, fcrs, locations)
|
projectFlocks, err := seedProjectFlocks(tx, adminID, flocks, areas, fcrs, locations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -239,33 +239,33 @@ func seedFlocks(tx *gorm.DB, createdBy uint) (map[string]uint, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func seedProjectFlocks(tx *gorm.DB, createdBy uint, flocks, areas, productCategories, fcrs, locations map[string]uint) (map[string]uint, error) {
|
func seedProjectFlocks(tx *gorm.DB, createdBy uint, flocks, areas, fcrs, locations map[string]uint) (map[string]uint, error) {
|
||||||
seeds := []struct {
|
seeds := []struct {
|
||||||
Key string
|
Key string
|
||||||
Flock string
|
Flock string
|
||||||
Area string
|
Area string
|
||||||
ProductCategory string
|
Category utils.ProjectFlockCategory
|
||||||
Fcr string
|
Fcr string
|
||||||
Location string
|
Location string
|
||||||
Period int
|
Period int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Key: "Singaparna Period 1",
|
Key: "Singaparna Period 1",
|
||||||
Flock: "Flock Priangan",
|
Flock: "Flock Priangan",
|
||||||
Area: "Priangan",
|
Area: "Priangan",
|
||||||
ProductCategory: "Day Old Chick",
|
Category: utils.ProjectFlockCategoryGrowing,
|
||||||
Fcr: "FCR Layer",
|
Fcr: "FCR Layer",
|
||||||
Location: "Singaparna",
|
Location: "Singaparna",
|
||||||
Period: 1,
|
Period: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: "Cikaum Period 1",
|
Key: "Cikaum Period 1",
|
||||||
Flock: "Flock Banten",
|
Flock: "Flock Banten",
|
||||||
Area: "Banten",
|
Area: "Banten",
|
||||||
ProductCategory: "Day Old Chick",
|
Category: utils.ProjectFlockCategoryGrowing,
|
||||||
Fcr: "FCR Layer",
|
Fcr: "FCR Layer",
|
||||||
Location: "Cikaum",
|
Location: "Cikaum",
|
||||||
Period: 1,
|
Period: 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,10 +280,6 @@ func seedProjectFlocks(tx *gorm.DB, createdBy uint, flocks, areas, productCatego
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("area %s not seeded", seed.Area)
|
return nil, fmt.Errorf("area %s not seeded", seed.Area)
|
||||||
}
|
}
|
||||||
categoryID, ok := productCategories[seed.ProductCategory]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("product category %s not seeded", seed.ProductCategory)
|
|
||||||
}
|
|
||||||
fcrID, ok := fcrs[seed.Fcr]
|
fcrID, ok := fcrs[seed.Fcr]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("fcr %s not seeded", seed.Fcr)
|
return nil, fmt.Errorf("fcr %s not seeded", seed.Fcr)
|
||||||
@@ -294,17 +290,17 @@ func seedProjectFlocks(tx *gorm.DB, createdBy uint, flocks, areas, productCatego
|
|||||||
}
|
}
|
||||||
|
|
||||||
var projectFlock entity.ProjectFlock
|
var projectFlock entity.ProjectFlock
|
||||||
err := tx.Where("flock_id = ? AND area_id = ? AND product_category_id = ? AND fcr_id = ? AND location_id = ? AND period = ?",
|
err := tx.Where("flock_id = ? AND area_id = ? AND category = ? AND fcr_id = ? AND location_id = ? AND period = ?",
|
||||||
flockID, areaID, categoryID, fcrID, locationID, seed.Period).First(&projectFlock).Error
|
flockID, areaID, seed.Category, fcrID, locationID, seed.Period).First(&projectFlock).Error
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
projectFlock = entity.ProjectFlock{
|
projectFlock = entity.ProjectFlock{
|
||||||
FlockId: flockID,
|
FlockId: flockID,
|
||||||
AreaId: areaID,
|
AreaId: areaID,
|
||||||
ProductCategoryId: categoryID,
|
Category: string(seed.Category),
|
||||||
FcrId: fcrID,
|
FcrId: fcrID,
|
||||||
LocationId: locationID,
|
LocationId: locationID,
|
||||||
Period: seed.Period,
|
Period: seed.Period,
|
||||||
CreatedBy: createdBy,
|
CreatedBy: createdBy,
|
||||||
}
|
}
|
||||||
if err := tx.Create(&projectFlock).Error; err != nil {
|
if err := tx.Create(&projectFlock).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -313,12 +309,12 @@ func seedProjectFlocks(tx *gorm.DB, createdBy uint, flocks, areas, productCatego
|
|||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
if err := tx.Model(&entity.ProjectFlock{}).Where("id = ?", projectFlock.Id).Updates(map[string]any{
|
if err := tx.Model(&entity.ProjectFlock{}).Where("id = ?", projectFlock.Id).Updates(map[string]any{
|
||||||
"flock_id": flockID,
|
"flock_id": flockID,
|
||||||
"area_id": areaID,
|
"area_id": areaID,
|
||||||
"product_category_id": categoryID,
|
"category": string(seed.Category),
|
||||||
"fcr_id": fcrID,
|
"fcr_id": fcrID,
|
||||||
"location_id": locationID,
|
"location_id": locationID,
|
||||||
"period": seed.Period,
|
"period": seed.Period,
|
||||||
}).Error; err != nil {
|
}).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,23 +7,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ProjectFlock struct {
|
type ProjectFlock struct {
|
||||||
Id uint `gorm:"primaryKey"`
|
Id uint `gorm:"primaryKey"`
|
||||||
FlockId uint `gorm:"not null;uniqueIndex:idx_project_flocks_flock_period,priority:1"`
|
FlockId uint `gorm:"not null;uniqueIndex:project_flocks_flock_period_unique"`
|
||||||
AreaId uint `gorm:"not null"`
|
AreaId uint `gorm:"not null"`
|
||||||
ProductCategoryId uint `gorm:"not null"`
|
Category string `gorm:"type:varchar(20);not null"`
|
||||||
FcrId uint `gorm:"not null"`
|
FcrId uint `gorm:"not null"`
|
||||||
LocationId uint `gorm:"not null"`
|
LocationId uint `gorm:"not null"`
|
||||||
Period int `gorm:"not null;uniqueIndex:idx_project_flocks_flock_period,priority:2"`
|
Period int `gorm:"not null;uniqueIndex:project_flocks_flock_period_unique"`
|
||||||
CreatedBy uint `gorm:"not null"`
|
CreatedBy uint `gorm:"not null"`
|
||||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||||
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||||
Flock Flock `gorm:"foreignKey:FlockId;references:Id"`
|
Flock Flock `gorm:"foreignKey:FlockId;references:Id"`
|
||||||
Area Area `gorm:"foreignKey:AreaId;references:Id"`
|
Area Area `gorm:"foreignKey:AreaId;references:Id"`
|
||||||
ProductCategory ProductCategory `gorm:"foreignKey:ProductCategoryId;references:Id"`
|
Fcr Fcr `gorm:"foreignKey:FcrId;references:Id"`
|
||||||
Fcr Fcr `gorm:"foreignKey:FcrId;references:Id"`
|
Location Location `gorm:"foreignKey:LocationId;references:Id"`
|
||||||
Location Location `gorm:"foreignKey:LocationId;references:Id"`
|
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
|
||||||
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
|
Kandangs []Kandang `gorm:"foreignKey:ProjectFlockId;references:Id"`
|
||||||
Kandangs []Kandang `gorm:"foreignKey:ProjectFlockId;references:Id"`
|
KandangHistory []ProjectFlockKandang `gorm:"foreignKey:ProjectFlockId;references:Id"`
|
||||||
KandangHistory []ProjectFlockKandang `gorm:"foreignKey:ProjectFlockId;references:Id"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
"context"
|
||||||
|
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FlockRepository interface {
|
type FlockRepository interface {
|
||||||
repository.BaseRepository[entity.Flock]
|
repository.BaseRepository[entity.Flock]
|
||||||
|
NameExists(ctx context.Context, name string, excludeID *uint) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type FlockRepositoryImpl struct {
|
type FlockRepositoryImpl struct {
|
||||||
*repository.BaseRepositoryImpl[entity.Flock]
|
*repository.BaseRepositoryImpl[entity.Flock]
|
||||||
|
db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFlockRepository(db *gorm.DB) FlockRepository {
|
func NewFlockRepository(db *gorm.DB) FlockRepository {
|
||||||
return &FlockRepositoryImpl{
|
return &FlockRepositoryImpl{
|
||||||
BaseRepositoryImpl: repository.NewBaseRepository[entity.Flock](db),
|
BaseRepositoryImpl: repository.NewBaseRepository[entity.Flock](db),
|
||||||
|
db: db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *FlockRepositoryImpl) NameExists(ctx context.Context, name string, excludeID *uint) (bool, error) {
|
||||||
|
return repository.ExistsByName[entity.Flock](ctx, r.db, name, excludeID)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories"
|
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories"
|
||||||
@@ -79,8 +81,22 @@ func (s *flockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entity.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := strings.TrimSpace(req.Name)
|
||||||
|
if name == "" {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Name is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
exists, err := s.Repository.NameExists(c.Context(), name, nil)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Errorf("Failed to check flock name: %+v", err)
|
||||||
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to check flock name")
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
return nil, fiber.NewError(fiber.StatusConflict, fmt.Sprintf("Flock with name %s already exists", name))
|
||||||
|
}
|
||||||
|
|
||||||
createBody := &entity.Flock{
|
createBody := &entity.Flock{
|
||||||
Name: req.Name,
|
Name: name,
|
||||||
CreatedBy: 1,
|
CreatedBy: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +116,20 @@ func (s flockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) (
|
|||||||
updateBody := make(map[string]any)
|
updateBody := make(map[string]any)
|
||||||
|
|
||||||
if req.Name != nil {
|
if req.Name != nil {
|
||||||
updateBody["name"] = *req.Name
|
name := strings.TrimSpace(*req.Name)
|
||||||
|
if name == "" {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Name cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
exists, err := s.Repository.NameExists(c.Context(), name, &id)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Errorf("Failed to check flock name: %+v", err)
|
||||||
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to check flock name")
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
return nil, fiber.NewError(fiber.StatusConflict, fmt.Sprintf("Flock with name %s already exists", name))
|
||||||
|
}
|
||||||
|
updateBody["name"] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(updateBody) == 0 {
|
if len(updateBody) == 0 {
|
||||||
|
|||||||
@@ -4,75 +4,66 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
|
||||||
|
fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
|
||||||
|
flockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto"
|
||||||
|
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
|
||||||
|
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
|
||||||
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
|
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProjectFlockBaseDTO struct {
|
type ProjectFlockBaseDTO struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
// FlockId uint `json:"flock_id"`
|
Period int `json:"period"`
|
||||||
// AreaId uint `json:"area_id"`
|
Category string `json:"category"`
|
||||||
// ProductCategoryId uint `json:"product_category_id"`
|
Flock *flockDTO.FlockBaseDTO `json:"flock"`
|
||||||
// FcrId uint `json:"fcr_id"`
|
Area *areaDTO.AreaBaseDTO `json:"area"`
|
||||||
// LocationId uint `json:"location_id"`
|
Fcr *fcrDTO.FcrBaseDTO `json:"fcr"`
|
||||||
Period int `json:"period"`
|
Location *locationDTO.LocationBaseDTO `json:"location"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToProjectFlockBaseDTO(e entity.ProjectFlock) ProjectFlockBaseDTO {
|
func ToProjectFlockBaseDTO(e entity.ProjectFlock) ProjectFlockBaseDTO {
|
||||||
return ProjectFlockBaseDTO{
|
var flock *flockDTO.FlockBaseDTO
|
||||||
Id: e.Id,
|
if e.Flock.Id != 0 {
|
||||||
// FlockId: e.FlockId,
|
mapped := flockDTO.ToFlockBaseDTO(e.Flock)
|
||||||
// AreaId: e.AreaId,
|
flock = &mapped
|
||||||
// ProductCategoryId: e.ProductCategoryId,
|
|
||||||
// FcrId: e.FcrId,
|
|
||||||
// LocationId: e.LocationId,
|
|
||||||
Period: e.Period,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
type FlockSummaryDTO struct {
|
var area *areaDTO.AreaBaseDTO
|
||||||
Id uint `json:"id"`
|
if e.Area.Id != 0 {
|
||||||
Name string `json:"name"`
|
mapped := areaDTO.ToAreaBaseDTO(e.Area)
|
||||||
}
|
area = &mapped
|
||||||
|
}
|
||||||
|
|
||||||
type AreaSummaryDTO struct {
|
var fcr *fcrDTO.FcrBaseDTO
|
||||||
Id uint `json:"id"`
|
if e.Fcr.Id != 0 {
|
||||||
Name string `json:"name"`
|
mapped := fcrDTO.ToFcrBaseDTO(e.Fcr)
|
||||||
}
|
fcr = &mapped
|
||||||
|
}
|
||||||
|
|
||||||
type ProductCategorySummaryDTO struct {
|
var location *locationDTO.LocationBaseDTO
|
||||||
Id uint `json:"id"`
|
if e.Location.Id != 0 {
|
||||||
Name string `json:"name"`
|
mapped := locationDTO.ToLocationBaseDTO(e.Location)
|
||||||
Code string `json:"code"`
|
location = &mapped
|
||||||
}
|
}
|
||||||
|
|
||||||
type FcrSummaryDTO struct {
|
return ProjectFlockBaseDTO{
|
||||||
Id uint `json:"id"`
|
Id: e.Id,
|
||||||
Name string `json:"name"`
|
Period: e.Period,
|
||||||
}
|
Category: e.Category,
|
||||||
|
Flock: flock,
|
||||||
type LocationSummaryDTO struct {
|
Area: area,
|
||||||
Id uint `json:"id"`
|
Fcr: fcr,
|
||||||
Name string `json:"name"`
|
Location: location,
|
||||||
Address string `json:"address"`
|
}
|
||||||
}
|
|
||||||
|
|
||||||
type KandangSummaryDTO struct {
|
|
||||||
Id uint `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectFlockListDTO struct {
|
type ProjectFlockListDTO struct {
|
||||||
ProjectFlockBaseDTO
|
ProjectFlockBaseDTO
|
||||||
Flock *FlockSummaryDTO `json:"flock,omitempty"`
|
Kandangs []kandangDTO.KandangBaseDTO `json:"kandangs,omitempty"`
|
||||||
Area *AreaSummaryDTO `json:"area,omitempty"`
|
CreatedUser *userDTO.UserBaseDTO `json:"created_user"`
|
||||||
ProductCategory *ProductCategorySummaryDTO `json:"product_category,omitempty"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
Fcr *FcrSummaryDTO `json:"fcr,omitempty"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
Location *LocationSummaryDTO `json:"location,omitempty"`
|
|
||||||
Kandangs []KandangSummaryDTO `json:"kandangs,omitempty"`
|
|
||||||
CreatedUser *userDTO.UserBaseDTO `json:"created_user"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectFlockDetailDTO struct {
|
type ProjectFlockDetailDTO struct {
|
||||||
@@ -80,8 +71,8 @@ type ProjectFlockDetailDTO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FlockPeriodSummaryDTO struct {
|
type FlockPeriodSummaryDTO struct {
|
||||||
Flock FlockSummaryDTO `json:"flock"`
|
Flock flockDTO.FlockBaseDTO `json:"flock"`
|
||||||
NextPeriod int `json:"next_period"`
|
NextPeriod int `json:"next_period"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToProjectFlockListDTO(e entity.ProjectFlock) ProjectFlockListDTO {
|
func ToProjectFlockListDTO(e entity.ProjectFlock) ProjectFlockListDTO {
|
||||||
@@ -91,62 +82,16 @@ func ToProjectFlockListDTO(e entity.ProjectFlock) ProjectFlockListDTO {
|
|||||||
createdUser = &mapped
|
createdUser = &mapped
|
||||||
}
|
}
|
||||||
|
|
||||||
var flockSummary *FlockSummaryDTO
|
var kandangSummaries []kandangDTO.KandangBaseDTO
|
||||||
if e.Flock.Id != 0 {
|
if len(e.Kandangs) > 0 {
|
||||||
summary := ToFlockSummaryDTO(e.Flock)
|
kandangSummaries = make([]kandangDTO.KandangBaseDTO, len(e.Kandangs))
|
||||||
flockSummary = &summary
|
for i, kandang := range e.Kandangs {
|
||||||
}
|
kandangSummaries[i] = kandangDTO.ToKandangBaseDTO(kandang)
|
||||||
|
|
||||||
var areaSummary *AreaSummaryDTO
|
|
||||||
if e.Area.Id != 0 {
|
|
||||||
areaSummary = &AreaSummaryDTO{
|
|
||||||
Id: e.Area.Id,
|
|
||||||
Name: e.Area.Name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var categorySummary *ProductCategorySummaryDTO
|
|
||||||
if e.ProductCategory.Id != 0 {
|
|
||||||
categorySummary = &ProductCategorySummaryDTO{
|
|
||||||
Id: e.ProductCategory.Id,
|
|
||||||
Name: e.ProductCategory.Name,
|
|
||||||
Code: e.ProductCategory.Code,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fcrSummary *FcrSummaryDTO
|
|
||||||
if e.Fcr.Id != 0 {
|
|
||||||
fcrSummary = &FcrSummaryDTO{
|
|
||||||
Id: e.Fcr.Id,
|
|
||||||
Name: e.Fcr.Name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var locationSummary *LocationSummaryDTO
|
|
||||||
if e.Location.Id != 0 {
|
|
||||||
locationSummary = &LocationSummaryDTO{
|
|
||||||
Id: e.Location.Id,
|
|
||||||
Name: e.Location.Name,
|
|
||||||
Address: e.Location.Address,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kandangSummaries := make([]KandangSummaryDTO, len(e.Kandangs))
|
|
||||||
for i, kandang := range e.Kandangs {
|
|
||||||
kandangSummaries[i] = KandangSummaryDTO{
|
|
||||||
Id: kandang.Id,
|
|
||||||
Name: kandang.Name,
|
|
||||||
Status: kandang.Status,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ProjectFlockListDTO{
|
return ProjectFlockListDTO{
|
||||||
ProjectFlockBaseDTO: ToProjectFlockBaseDTO(e),
|
ProjectFlockBaseDTO: ToProjectFlockBaseDTO(e),
|
||||||
Flock: flockSummary,
|
|
||||||
Area: areaSummary,
|
|
||||||
ProductCategory: categorySummary,
|
|
||||||
Fcr: fcrSummary,
|
|
||||||
Location: locationSummary,
|
|
||||||
Kandangs: kandangSummaries,
|
Kandangs: kandangSummaries,
|
||||||
CreatedAt: e.CreatedAt,
|
CreatedAt: e.CreatedAt,
|
||||||
UpdatedAt: e.UpdatedAt,
|
UpdatedAt: e.UpdatedAt,
|
||||||
@@ -168,16 +113,9 @@ func ToProjectFlockDetailDTO(e entity.ProjectFlock) ProjectFlockDetailDTO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToFlockSummaryDTO(e entity.Flock) FlockSummaryDTO {
|
|
||||||
return FlockSummaryDTO{
|
|
||||||
Id: e.Id,
|
|
||||||
Name: e.Name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToFlockPeriodSummaryDTO(flock entity.Flock, next int) FlockPeriodSummaryDTO {
|
func ToFlockPeriodSummaryDTO(flock entity.Flock, next int) FlockPeriodSummaryDTO {
|
||||||
return FlockPeriodSummaryDTO{
|
return FlockPeriodSummaryDTO{
|
||||||
Flock: ToFlockSummaryDTO(flock),
|
Flock: flockDTO.ToFlockBaseDTO(flock),
|
||||||
NextPeriod: next,
|
NextPeriod: next,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ func (s projectflockService) withRelations(db *gorm.DB) *gorm.DB {
|
|||||||
Preload("CreatedUser").
|
Preload("CreatedUser").
|
||||||
Preload("Flock").
|
Preload("Flock").
|
||||||
Preload("Area").
|
Preload("Area").
|
||||||
Preload("ProductCategory").
|
|
||||||
Preload("Fcr").
|
Preload("Fcr").
|
||||||
Preload("Location").
|
Preload("Location").
|
||||||
Preload("Kandangs")
|
Preload("Kandangs")
|
||||||
@@ -115,15 +114,13 @@ func (s projectflockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]e
|
|||||||
db = db.
|
db = db.
|
||||||
Joins("LEFT JOIN flocks ON flocks.id = project_flocks.flock_id").
|
Joins("LEFT JOIN flocks ON flocks.id = project_flocks.flock_id").
|
||||||
Joins("LEFT JOIN areas ON areas.id = project_flocks.area_id").
|
Joins("LEFT JOIN areas ON areas.id = project_flocks.area_id").
|
||||||
Joins("LEFT JOIN product_categories ON product_categories.id = project_flocks.product_category_id").
|
|
||||||
Joins("LEFT JOIN fcrs ON fcrs.id = project_flocks.fcr_id").
|
Joins("LEFT JOIN fcrs ON fcrs.id = project_flocks.fcr_id").
|
||||||
Joins("LEFT JOIN locations ON locations.id = project_flocks.location_id").
|
Joins("LEFT JOIN locations ON locations.id = project_flocks.location_id").
|
||||||
Joins("LEFT JOIN users AS created_users ON created_users.id = project_flocks.created_by").
|
Joins("LEFT JOIN users AS created_users ON created_users.id = project_flocks.created_by").
|
||||||
Where(`
|
Where(`
|
||||||
LOWER(flocks.name) LIKE ?
|
LOWER(flocks.name) LIKE ?
|
||||||
OR LOWER(areas.name) LIKE ?
|
OR LOWER(areas.name) LIKE ?
|
||||||
OR LOWER(product_categories.name) LIKE ?
|
OR LOWER(project_flocks.category) LIKE ?
|
||||||
OR LOWER(product_categories.code) LIKE ?
|
|
||||||
OR LOWER(fcrs.name) LIKE ?
|
OR LOWER(fcrs.name) LIKE ?
|
||||||
OR LOWER(locations.name) LIKE ?
|
OR LOWER(locations.name) LIKE ?
|
||||||
OR LOWER(locations.address) LIKE ?
|
OR LOWER(locations.address) LIKE ?
|
||||||
@@ -146,7 +143,6 @@ func (s projectflockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]e
|
|||||||
likeQuery,
|
likeQuery,
|
||||||
likeQuery,
|
likeQuery,
|
||||||
likeQuery,
|
likeQuery,
|
||||||
likeQuery,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
for _, expr := range s.buildOrderExpressions(params.SortBy, params.SortOrder) {
|
for _, expr := range s.buildOrderExpressions(params.SortBy, params.SortOrder) {
|
||||||
@@ -179,6 +175,11 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
category, ok := utils.NormalizeProjectFlockCategory(req.Category)
|
||||||
|
if !ok {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid category")
|
||||||
|
}
|
||||||
|
|
||||||
if len(req.KandangIds) == 0 {
|
if len(req.KandangIds) == 0 {
|
||||||
return nil, fiber.NewError(fiber.StatusBadRequest, "kandang_ids is required")
|
return nil, fiber.NewError(fiber.StatusBadRequest, "kandang_ids is required")
|
||||||
}
|
}
|
||||||
@@ -186,7 +187,6 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
|
|||||||
if err := common.EnsureRelations(c.Context(),
|
if err := common.EnsureRelations(c.Context(),
|
||||||
common.RelationCheck{Name: "Flock", ID: &req.FlockId, Exists: relationExistsChecker[entity.Flock](s.Repository.DB())},
|
common.RelationCheck{Name: "Flock", ID: &req.FlockId, Exists: relationExistsChecker[entity.Flock](s.Repository.DB())},
|
||||||
common.RelationCheck{Name: "Area", ID: &req.AreaId, Exists: relationExistsChecker[entity.Area](s.Repository.DB())},
|
common.RelationCheck{Name: "Area", ID: &req.AreaId, Exists: relationExistsChecker[entity.Area](s.Repository.DB())},
|
||||||
common.RelationCheck{Name: "Product category", ID: &req.ProductCategoryId, Exists: relationExistsChecker[entity.ProductCategory](s.Repository.DB())},
|
|
||||||
common.RelationCheck{Name: "FCR", ID: &req.FcrId, Exists: relationExistsChecker[entity.Fcr](s.Repository.DB())},
|
common.RelationCheck{Name: "FCR", ID: &req.FcrId, Exists: relationExistsChecker[entity.Fcr](s.Repository.DB())},
|
||||||
common.RelationCheck{Name: "Location", ID: &req.LocationId, Exists: relationExistsChecker[entity.Location](s.Repository.DB())},
|
common.RelationCheck{Name: "Location", ID: &req.LocationId, Exists: relationExistsChecker[entity.Location](s.Repository.DB())},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
@@ -224,13 +224,13 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
createBody := &entity.ProjectFlock{
|
createBody := &entity.ProjectFlock{
|
||||||
FlockId: req.FlockId,
|
FlockId: req.FlockId,
|
||||||
AreaId: req.AreaId,
|
AreaId: req.AreaId,
|
||||||
ProductCategoryId: req.ProductCategoryId,
|
Category: string(category),
|
||||||
FcrId: req.FcrId,
|
FcrId: req.FcrId,
|
||||||
LocationId: req.LocationId,
|
LocationId: req.LocationId,
|
||||||
Period: nextPeriod,
|
Period: nextPeriod,
|
||||||
CreatedBy: 1,
|
CreatedBy: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := projectRepo.CreateOne(c.Context(), createBody, nil); err != nil {
|
if err := projectRepo.CreateOne(c.Context(), createBody, nil); err != nil {
|
||||||
@@ -289,13 +289,12 @@ func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id
|
|||||||
Exists: relationExistsChecker[entity.Area](s.Repository.DB()),
|
Exists: relationExistsChecker[entity.Area](s.Repository.DB()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if req.ProductCategoryId != nil {
|
if req.Category != nil {
|
||||||
updateBody["product_category_id"] = *req.ProductCategoryId
|
if normalized, ok := utils.NormalizeProjectFlockCategory(*req.Category); ok {
|
||||||
relationChecks = append(relationChecks, common.RelationCheck{
|
updateBody["category"] = string(normalized)
|
||||||
Name: "Product category",
|
} else {
|
||||||
ID: req.ProductCategoryId,
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid category")
|
||||||
Exists: relationExistsChecker[entity.ProductCategory](s.Repository.DB()),
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if req.FcrId != nil {
|
if req.FcrId != nil {
|
||||||
updateBody["fcr_id"] = *req.FcrId
|
updateBody["fcr_id"] = *req.FcrId
|
||||||
@@ -541,7 +540,10 @@ func (s projectflockService) attachKandangs(ctx context.Context, tx *gorm.DB, pr
|
|||||||
|
|
||||||
if err := tx.Model(&entity.Kandang{}).
|
if err := tx.Model(&entity.Kandang{}).
|
||||||
Where("id IN ?", kandangIDs).
|
Where("id IN ?", kandangIDs).
|
||||||
Updates(map[string]any{"project_flock_id": projectFlockID}).Error; err != nil {
|
Updates(map[string]any{
|
||||||
|
"project_flock_id": projectFlockID,
|
||||||
|
"status": string(utils.KandangStatusPengajuan),
|
||||||
|
}).Error; err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
type Create struct {
|
type Create struct {
|
||||||
FlockId uint `json:"flock_id" validate:"required_strict,number,gt=0"`
|
FlockId uint `json:"flock_id" validate:"required_strict,number,gt=0"`
|
||||||
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
|
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
|
||||||
ProductCategoryId uint `json:"product_category_id" validate:"required_strict,number,gt=0"`
|
Category string `json:"category" validate:"required_strict,oneof=growing laying GROWING LAYING"`
|
||||||
FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"`
|
FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"`
|
||||||
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
|
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
|
||||||
KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"`
|
KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Update struct {
|
type Update struct {
|
||||||
FlockId *uint `json:"flock_id,omitempty" validate:"omitempty,number,gt=0"`
|
FlockId *uint `json:"flock_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||||
AreaId *uint `json:"area_id,omitempty" validate:"omitempty,number,gt=0"`
|
AreaId *uint `json:"area_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||||
ProductCategoryId *uint `json:"product_category_id,omitempty" validate:"omitempty,number,gt=0"`
|
Category *string `json:"category,omitempty" validate:"omitempty,oneof=growing laying GROWING LAYING"`
|
||||||
FcrId *uint `json:"fcr_id,omitempty" validate:"omitempty,number,gt=0"`
|
FcrId *uint `json:"fcr_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||||
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
|
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
|
||||||
Period *int `json:"period,omitempty" validate:"omitempty,number,gt=0"`
|
Period *int `json:"period,omitempty" validate:"omitempty,number,gt=0"`
|
||||||
KandangIds []uint `json:"kandang_ids,omitempty" validate:"omitempty,min=1,dive,gt=0"`
|
KandangIds []uint `json:"kandang_ids,omitempty" validate:"omitempty,min=1,dive,gt=0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query struct {
|
type Query struct {
|
||||||
Page int `query:"page" validate:"omitempty,number,min=1"`
|
Page int `query:"page" validate:"omitempty,number,min=1"`
|
||||||
Limit int `query:"limit" validate:"omitempty,number,min=1,max=100"`
|
Limit int `query:"limit" validate:"omitempty,number,min=1,max=100"`
|
||||||
Search string `query:"search" validate:"omitempty,max=50"`
|
Search string `query:"search" validate:"omitempty,max=50"`
|
||||||
SortBy string `query:"sort_by" validate:"omitempty,oneof=area location kandangs period"`
|
SortBy string `query:"sort_by" validate:"omitempty,oneof=area location kandangs period"`
|
||||||
SortOrder string `query:"sort_order" validate:"omitempty,oneof=asc desc"`
|
SortOrder string `query:"sort_order" validate:"omitempty,oneof=asc desc"`
|
||||||
AreaId uint `query:"area_id" validate:"omitempty,number,gt=0"`
|
AreaId uint `query:"area_id" validate:"omitempty,number,gt=0"`
|
||||||
LocationId uint `query:"location_id" validate:"omitempty,number,gt=0"`
|
LocationId uint `query:"location_id" validate:"omitempty,number,gt=0"`
|
||||||
Period int `query:"period" validate:"omitempty,number,gt=0"`
|
Period int `query:"period" validate:"omitempty,number,gt=0"`
|
||||||
KandangIds []uint `query:"kandang_id" validate:"omitempty,dive,gt=0"`
|
KandangIds []uint `query:"kandang_id" validate:"omitempty,dive,gt=0"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ var allFlagTypes = func() map[FlagType]struct{} {
|
|||||||
return m
|
return m
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
||||||
func AllFlagTypes() map[FlagType]struct{} {
|
func AllFlagTypes() map[FlagType]struct{} {
|
||||||
return allFlagTypes
|
return allFlagTypes
|
||||||
}
|
}
|
||||||
@@ -76,8 +75,6 @@ const (
|
|||||||
WarehouseTypeKandang WarehouseType = "KANDANG"
|
WarehouseTypeKandang WarehouseType = "KANDANG"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// WarehouseType
|
// WarehouseType
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@@ -100,19 +97,29 @@ const (
|
|||||||
SupplierCategorySapronak SupplierCategory = "SAPRONAK"
|
SupplierCategorySapronak SupplierCategory = "SAPRONAK"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Kandang Status
|
// Kandang Status
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
type KandangStatus string
|
type KandangStatus string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KandangStatusNonActive KandangStatus = "NON_ACTIVE"
|
KandangStatusNonActive KandangStatus = "NON_ACTIVE"
|
||||||
KandangStatusPengajuan KandangStatus = "PENGAJUAN"
|
KandangStatusPengajuan KandangStatus = "PENGAJUAN"
|
||||||
KandangStatusActive KandangStatus = "ACTIVE"
|
KandangStatusActive KandangStatus = "ACTIVE"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// ProjectFlockCategory
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
type ProjectFlockCategory string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProjectFlockCategoryGrowing ProjectFlockCategory = "GROWING"
|
||||||
|
ProjectFlockCategoryLaying ProjectFlockCategory = "LAYING"
|
||||||
|
)
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Validators
|
// Validators
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@@ -223,6 +230,21 @@ func IsValidCustomerSupplierType(v string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NormalizeProjectFlockCategory(v string) (ProjectFlockCategory, bool) {
|
||||||
|
normalized := ProjectFlockCategory(strings.ToUpper(strings.TrimSpace(v)))
|
||||||
|
switch normalized {
|
||||||
|
case ProjectFlockCategoryGrowing, ProjectFlockCategoryLaying:
|
||||||
|
return normalized, true
|
||||||
|
default:
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsValidProjectFlockCategory(v string) bool {
|
||||||
|
_, ok := NormalizeProjectFlockCategory(v)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
func IsValidSupplierCategory(v string) bool {
|
func IsValidSupplierCategory(v string) bool {
|
||||||
switch SupplierCategory(v) {
|
switch SupplierCategory(v) {
|
||||||
case SupplierCategoryBOP, SupplierCategorySapronak:
|
case SupplierCategoryBOP, SupplierCategorySapronak:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/entities"
|
"gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestKandangIntegration(t *testing.T) {
|
func TestKandangIntegration(t *testing.T) {
|
||||||
@@ -51,20 +52,19 @@ func TestKandangIntegration(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("cannot assign project floc with existing active kandang", func(t *testing.T) {
|
t.Run("cannot assign project floc with existing active kandang", func(t *testing.T) {
|
||||||
categoryID := createProductCategory(t, app, "DOC Category", "DOC1")
|
|
||||||
fcrID := createFcr(t, app, "FCR For Floc", []map[string]any{
|
fcrID := createFcr(t, app, "FCR For Floc", []map[string]any{
|
||||||
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
||||||
})
|
})
|
||||||
flocID := createFlock(t, app, "Floc Test")
|
flocID := createFlock(t, app, "Floc Test")
|
||||||
|
|
||||||
projectFloc := entities.ProjectFlock{
|
projectFloc := entities.ProjectFlock{
|
||||||
FlockId: flocID,
|
FlockId: flocID,
|
||||||
AreaId: areaID,
|
AreaId: areaID,
|
||||||
ProductCategoryId: categoryID,
|
Category: string(utils.ProjectFlockCategoryGrowing),
|
||||||
FcrId: fcrID,
|
FcrId: fcrID,
|
||||||
LocationId: locationID,
|
LocationId: locationID,
|
||||||
Period: 1,
|
Period: 1,
|
||||||
CreatedBy: 1,
|
CreatedBy: 1,
|
||||||
}
|
}
|
||||||
if err := db.Create(&projectFloc).Error; err != nil {
|
if err := db.Create(&projectFloc).Error; err != nil {
|
||||||
t.Fatalf("failed to seed project floc: %v", err)
|
t.Fatalf("failed to seed project floc: %v", err)
|
||||||
|
|||||||
@@ -19,19 +19,18 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
areaID := createArea(t, app, "Area Project")
|
areaID := createArea(t, app, "Area Project")
|
||||||
locationID := createLocation(t, app, "Location Project", "Address", areaID)
|
locationID := createLocation(t, app, "Location Project", "Address", areaID)
|
||||||
flockID := createFlock(t, app, "Flock Summary")
|
flockID := createFlock(t, app, "Flock Summary")
|
||||||
categoryID := createProductCategory(t, app, "DOC Summary", "DOCS")
|
|
||||||
fcrID := createFcr(t, app, "FCR Summary", []map[string]any{
|
fcrID := createFcr(t, app, "FCR Summary", []map[string]any{
|
||||||
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
||||||
})
|
})
|
||||||
kandangID := createKandang(t, app, "Kandang Summary", locationID, 1)
|
kandangID := createKandang(t, app, "Kandang Summary", locationID, 1)
|
||||||
|
|
||||||
createPayload := map[string]any{
|
createPayload := map[string]any{
|
||||||
"flock_id": flockID,
|
"flock_id": flockID,
|
||||||
"area_id": areaID,
|
"area_id": areaID,
|
||||||
"product_category_id": categoryID,
|
"category": "growing",
|
||||||
"fcr_id": fcrID,
|
"fcr_id": fcrID,
|
||||||
"location_id": locationID,
|
"location_id": locationID,
|
||||||
"kandang_ids": []uint{kandangID},
|
"kandang_ids": []uint{kandangID},
|
||||||
}
|
}
|
||||||
resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", createPayload)
|
resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", createPayload)
|
||||||
if resp.StatusCode != fiber.StatusCreated {
|
if resp.StatusCode != fiber.StatusCreated {
|
||||||
@@ -40,9 +39,10 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
|
|
||||||
var createResp struct {
|
var createResp struct {
|
||||||
Data struct {
|
Data struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Period int `json:"period"`
|
Period int `json:"period"`
|
||||||
Flock struct {
|
Category string `json:"category"`
|
||||||
|
Flock struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
} `json:"flock"`
|
} `json:"flock"`
|
||||||
@@ -50,11 +50,6 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
} `json:"area"`
|
} `json:"area"`
|
||||||
ProductCategory struct {
|
|
||||||
Id uint `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Code string `json:"code"`
|
|
||||||
} `json:"product_category"`
|
|
||||||
Fcr struct {
|
Fcr struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -86,19 +81,27 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
if createResp.Data.Area.Id != areaID || createResp.Data.Area.Name == "" {
|
if createResp.Data.Area.Id != areaID || createResp.Data.Area.Name == "" {
|
||||||
t.Fatalf("expected area detail to be present, got %+v", createResp.Data.Area)
|
t.Fatalf("expected area detail to be present, got %+v", createResp.Data.Area)
|
||||||
}
|
}
|
||||||
|
if createResp.Data.Category != string(utils.ProjectFlockCategoryGrowing) {
|
||||||
|
t.Fatalf("expected category to be %s, got %s", utils.ProjectFlockCategoryGrowing, createResp.Data.Category)
|
||||||
|
}
|
||||||
if createResp.Data.Location.Id != locationID || createResp.Data.Location.Name == "" {
|
if createResp.Data.Location.Id != locationID || createResp.Data.Location.Name == "" {
|
||||||
t.Fatalf("expected location detail to be present, got %+v", createResp.Data.Location)
|
t.Fatalf("expected location detail to be present, got %+v", createResp.Data.Location)
|
||||||
}
|
}
|
||||||
if len(createResp.Data.Kandangs) != 1 || createResp.Data.Kandangs[0].Id != kandangID {
|
if len(createResp.Data.Kandangs) != 1 || createResp.Data.Kandangs[0].Id != kandangID {
|
||||||
t.Fatalf("expected kandang detail to be present, got %+v", createResp.Data.Kandangs)
|
t.Fatalf("expected kandang detail to be present, got %+v", createResp.Data.Kandangs)
|
||||||
}
|
}
|
||||||
if createResp.Data.Kandangs[0].Status == "" {
|
if createResp.Data.Kandangs[0].Status != string(utils.KandangStatusPengajuan) {
|
||||||
t.Fatalf("expected kandang status to be present, got %+v", createResp.Data.Kandangs[0])
|
t.Fatalf("expected kandang status to be PENGAJUAN, got %s", createResp.Data.Kandangs[0].Status)
|
||||||
}
|
}
|
||||||
if createResp.Data.Period != 1 {
|
if createResp.Data.Period != 1 {
|
||||||
t.Fatalf("expected period 1 to be assigned automatically, got %d", createResp.Data.Period)
|
t.Fatalf("expected period 1 to be assigned automatically, got %d", createResp.Data.Period)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createdKandang := fetchKandang(t, db, kandangID)
|
||||||
|
if createdKandang.Status != string(utils.KandangStatusPengajuan) {
|
||||||
|
t.Fatalf("expected kandang status in DB to be PENGAJUAN, got %s", createdKandang.Status)
|
||||||
|
}
|
||||||
|
|
||||||
var pivotRecords []entities.ProjectFlockKandang
|
var pivotRecords []entities.ProjectFlockKandang
|
||||||
if err := db.Where("project_flock_id = ?", createResp.Data.Id).Find(&pivotRecords).Error; err != nil {
|
if err := db.Where("project_flock_id = ?", createResp.Data.Id).Find(&pivotRecords).Error; err != nil {
|
||||||
t.Fatalf("failed to fetch pivot records: %v", err)
|
t.Fatalf("failed to fetch pivot records: %v", err)
|
||||||
@@ -116,12 +119,12 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
|
|
||||||
secondKandangID := createKandang(t, app, "Kandang Summary 2", locationID, 1)
|
secondKandangID := createKandang(t, app, "Kandang Summary 2", locationID, 1)
|
||||||
secondPayload := map[string]any{
|
secondPayload := map[string]any{
|
||||||
"flock_id": flockID,
|
"flock_id": flockID,
|
||||||
"area_id": areaID,
|
"area_id": areaID,
|
||||||
"product_category_id": categoryID,
|
"category": "laying",
|
||||||
"fcr_id": fcrID,
|
"fcr_id": fcrID,
|
||||||
"location_id": locationID,
|
"location_id": locationID,
|
||||||
"kandang_ids": []uint{secondKandangID},
|
"kandang_ids": []uint{secondKandangID},
|
||||||
}
|
}
|
||||||
resp, body = doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", secondPayload)
|
resp, body = doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", secondPayload)
|
||||||
if resp.StatusCode != fiber.StatusCreated {
|
if resp.StatusCode != fiber.StatusCreated {
|
||||||
@@ -129,8 +132,9 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
}
|
}
|
||||||
var createRespSecond struct {
|
var createRespSecond struct {
|
||||||
Data struct {
|
Data struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Period int `json:"period"`
|
Period int `json:"period"`
|
||||||
|
Category string `json:"category"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(body, &createRespSecond); err != nil {
|
if err := json.Unmarshal(body, &createRespSecond); err != nil {
|
||||||
@@ -139,6 +143,9 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
if createRespSecond.Data.Period != 2 {
|
if createRespSecond.Data.Period != 2 {
|
||||||
t.Fatalf("expected second period to be 2, got %d", createRespSecond.Data.Period)
|
t.Fatalf("expected second period to be 2, got %d", createRespSecond.Data.Period)
|
||||||
}
|
}
|
||||||
|
if createRespSecond.Data.Category != string(utils.ProjectFlockCategoryLaying) {
|
||||||
|
t.Fatalf("expected category to be %s, got %s", utils.ProjectFlockCategoryLaying, createRespSecond.Data.Category)
|
||||||
|
}
|
||||||
|
|
||||||
pivotRecords = nil
|
pivotRecords = nil
|
||||||
if err := db.Where("project_flock_id = ?", createRespSecond.Data.Id).Find(&pivotRecords).Error; err != nil {
|
if err := db.Where("project_flock_id = ?", createRespSecond.Data.Id).Find(&pivotRecords).Error; err != nil {
|
||||||
@@ -155,6 +162,11 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
t.Fatalf("expected second pivot DetachedAt to be nil, got %v", secondPivotRecord.DetachedAt)
|
t.Fatalf("expected second pivot DetachedAt to be nil, got %v", secondPivotRecord.DetachedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secondKandang := fetchKandang(t, db, secondKandangID)
|
||||||
|
if secondKandang.Status != string(utils.KandangStatusPengajuan) {
|
||||||
|
t.Fatalf("expected second kandang status in DB to be PENGAJUAN, got %s", secondKandang.Status)
|
||||||
|
}
|
||||||
|
|
||||||
resp, body = doJSONRequest(t, app, http.MethodGet, "/api/production/project_flocks/flocks/"+uintToString(flockID)+"/periods", nil)
|
resp, body = doJSONRequest(t, app, http.MethodGet, "/api/production/project_flocks/flocks/"+uintToString(flockID)+"/periods", nil)
|
||||||
if resp.StatusCode != fiber.StatusOK {
|
if resp.StatusCode != fiber.StatusOK {
|
||||||
t.Fatalf("expected 200 when fetching summary, got %d: %s", resp.StatusCode, string(body))
|
t.Fatalf("expected 200 when fetching summary, got %d: %s", resp.StatusCode, string(body))
|
||||||
@@ -202,7 +214,7 @@ func TestProjectFlockSummary(t *testing.T) {
|
|||||||
t.Fatalf("expected 200 when deleting second project flock, got %d: %s", resp.StatusCode, string(body))
|
t.Fatalf("expected 200 when deleting second project flock, got %d: %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
secondKandang := fetchKandang(t, db, secondKandangID)
|
secondKandang = fetchKandang(t, db, secondKandangID)
|
||||||
if secondKandang.ProjectFlockId != nil {
|
if secondKandang.ProjectFlockId != nil {
|
||||||
t.Fatalf("expected second project_flock_id to be nil after delete, got %v", *secondKandang.ProjectFlockId)
|
t.Fatalf("expected second project_flock_id to be nil after delete, got %v", *secondKandang.ProjectFlockId)
|
||||||
}
|
}
|
||||||
@@ -245,19 +257,18 @@ func TestProjectFlockSearchByRelatedFields(t *testing.T) {
|
|||||||
areaID := createArea(t, app, "Area Search Target")
|
areaID := createArea(t, app, "Area Search Target")
|
||||||
locationID := createLocation(t, app, "Location Search Target", "Location Address Target", areaID)
|
locationID := createLocation(t, app, "Location Search Target", "Location Address Target", areaID)
|
||||||
flockID := createFlock(t, app, "Flock Search Target")
|
flockID := createFlock(t, app, "Flock Search Target")
|
||||||
categoryID := createProductCategory(t, app, "Category Search Target", "CATGT")
|
|
||||||
fcrID := createFcr(t, app, "FCR Search Target", []map[string]any{
|
fcrID := createFcr(t, app, "FCR Search Target", []map[string]any{
|
||||||
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
||||||
})
|
})
|
||||||
kandangID := createKandang(t, app, "Kandang Search Target", locationID, 1)
|
kandangID := createKandang(t, app, "Kandang Search Target", locationID, 1)
|
||||||
|
|
||||||
createPayload := map[string]any{
|
createPayload := map[string]any{
|
||||||
"flock_id": flockID,
|
"flock_id": flockID,
|
||||||
"area_id": areaID,
|
"area_id": areaID,
|
||||||
"product_category_id": categoryID,
|
"category": "growing",
|
||||||
"fcr_id": fcrID,
|
"fcr_id": fcrID,
|
||||||
"location_id": locationID,
|
"location_id": locationID,
|
||||||
"kandang_ids": []uint{kandangID},
|
"kandang_ids": []uint{kandangID},
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", createPayload)
|
resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", createPayload)
|
||||||
@@ -277,8 +288,8 @@ func TestProjectFlockSearchByRelatedFields(t *testing.T) {
|
|||||||
searchTerms := []string{
|
searchTerms := []string{
|
||||||
"Flock Search Target",
|
"Flock Search Target",
|
||||||
"Area Search Target",
|
"Area Search Target",
|
||||||
"Category Search Target",
|
string(utils.ProjectFlockCategoryGrowing),
|
||||||
"CATGT",
|
"growing",
|
||||||
"FCR Search Target",
|
"FCR Search Target",
|
||||||
"Kandang Search Target",
|
"Kandang Search Target",
|
||||||
"Location Search Target",
|
"Location Search Target",
|
||||||
@@ -329,7 +340,6 @@ func TestProjectFlockSorting(t *testing.T) {
|
|||||||
flockOne := createFlock(t, app, "Flock Sort One")
|
flockOne := createFlock(t, app, "Flock Sort One")
|
||||||
flockTwo := createFlock(t, app, "Flock Sort Two")
|
flockTwo := createFlock(t, app, "Flock Sort Two")
|
||||||
|
|
||||||
categoryID := createProductCategory(t, app, "Category Sort", "CSORT")
|
|
||||||
fcrID := createFcr(t, app, "FCR Sort", []map[string]any{
|
fcrID := createFcr(t, app, "FCR Sort", []map[string]any{
|
||||||
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
{"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0},
|
||||||
})
|
})
|
||||||
@@ -339,12 +349,12 @@ func TestProjectFlockSorting(t *testing.T) {
|
|||||||
kandangThree := createKandang(t, app, "Kandang Sort Three", locationB, 1)
|
kandangThree := createKandang(t, app, "Kandang Sort Three", locationB, 1)
|
||||||
|
|
||||||
projectOnePayload := map[string]any{
|
projectOnePayload := map[string]any{
|
||||||
"flock_id": flockOne,
|
"flock_id": flockOne,
|
||||||
"area_id": areaA,
|
"area_id": areaA,
|
||||||
"product_category_id": categoryID,
|
"category": "growing",
|
||||||
"fcr_id": fcrID,
|
"fcr_id": fcrID,
|
||||||
"location_id": locationA,
|
"location_id": locationA,
|
||||||
"kandang_ids": []uint{kandangOne},
|
"kandang_ids": []uint{kandangOne},
|
||||||
}
|
}
|
||||||
resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", projectOnePayload)
|
resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", projectOnePayload)
|
||||||
if resp.StatusCode != fiber.StatusCreated {
|
if resp.StatusCode != fiber.StatusCreated {
|
||||||
@@ -353,12 +363,12 @@ func TestProjectFlockSorting(t *testing.T) {
|
|||||||
projectOneID := parseProjectFlockID(t, body)
|
projectOneID := parseProjectFlockID(t, body)
|
||||||
|
|
||||||
projectTwoPayload := map[string]any{
|
projectTwoPayload := map[string]any{
|
||||||
"flock_id": flockTwo,
|
"flock_id": flockTwo,
|
||||||
"area_id": areaB,
|
"area_id": areaB,
|
||||||
"product_category_id": categoryID,
|
"category": "laying",
|
||||||
"fcr_id": fcrID,
|
"fcr_id": fcrID,
|
||||||
"location_id": locationB,
|
"location_id": locationB,
|
||||||
"kandang_ids": []uint{kandangTwo, kandangThree},
|
"kandang_ids": []uint{kandangTwo, kandangThree},
|
||||||
}
|
}
|
||||||
resp, body = doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", projectTwoPayload)
|
resp, body = doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", projectTwoPayload)
|
||||||
if resp.StatusCode != fiber.StatusCreated {
|
if resp.StatusCode != fiber.StatusCreated {
|
||||||
|
|||||||
Reference in New Issue
Block a user