Merge branch 'dev/teguh' into 'feat/BE/Sprint-8'

feat(BE US#386): add standard_fcr column to production_standard_details and update existing API

See merge request mbugroup/lti-api!114
This commit is contained in:
Hafizh A. Y.
2025-12-30 09:36:00 +00:00
15 changed files with 115 additions and 74 deletions
@@ -0,0 +1,3 @@
-- Remove standard_fcr column from production_standard_details table
ALTER TABLE production_standard_details
DROP COLUMN IF EXISTS standard_fcr;
@@ -0,0 +1,3 @@
-- Add standard_fcr column to production_standard_details table
ALTER TABLE production_standard_details
ADD COLUMN standard_fcr NUMERIC(15, 3);
+22 -10
View File
@@ -891,14 +891,14 @@ func seedProductWarehouse(tx *gorm.DB, createdBy uint) error {
WarehouseName string WarehouseName string
Quantity float64 Quantity float64
}{ }{
{ProductName: "DOC Broiler", WarehouseName: "Gudang Priangan", Quantity: 100}, {ProductName: "DOC Broiler", WarehouseName: "Gudang Priangan", Quantity: 0},
{ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Singaparna", Quantity: 200}, {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Singaparna", Quantity: 0},
{ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Banten", Quantity: 300}, {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Banten", Quantity: 0},
{ProductName: "DOC Broiler", WarehouseName: "Gudang Singaparna 1", Quantity: 5000}, {ProductName: "DOC Broiler", WarehouseName: "Gudang Singaparna 1", Quantity: 0},
{ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Singaparna 1", Quantity: 600}, {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Singaparna 1", Quantity: 0},
{ProductName: "Telur Pecah", WarehouseName: "Gudang Singaparna 1", Quantity: 80}, {ProductName: "Telur Pecah", WarehouseName: "Gudang Singaparna 1", Quantity: 0},
{ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Cikaum 1", Quantity: 450}, {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Cikaum 1", Quantity: 0},
{ProductName: "Telur Pecah", WarehouseName: "Gudang Cikaum 1", Quantity: 60}, {ProductName: "Telur Pecah", WarehouseName: "Gudang Cikaum 1", Quantity: 0},
} }
for _, seed := range seeds { for _, seed := range seeds {
@@ -962,12 +962,24 @@ func seedTransferStock(tx *gorm.DB) error {
{ {
StockTransferId: transfer.Id, StockTransferId: transfer.Id,
ProductId: 1, ProductId: 1,
// Quantity: 10,
SourceProductWarehouseID: func() *uint64 { id := uint64(1); return &id }(),
DestProductWarehouseID: func() *uint64 { id := uint64(2); return &id }(),
UsageQty: 10,
PendingQty: 0,
TotalQty: 10,
TotalUsed: 0,
}, },
{ {
StockTransferId: transfer.Id, StockTransferId: transfer.Id,
ProductId: 2, ProductId: 2,
// Quantity: 5,
SourceProductWarehouseID: func() *uint64 { id := uint64(1); return &id }(),
DestProductWarehouseID: func() *uint64 { id := uint64(2); return &id }(),
UsageQty: 5,
PendingQty: 0,
TotalQty: 5,
TotalUsed: 0,
}, },
} }
for i := range details { for i := range details {
@@ -12,6 +12,7 @@ type ProductionStandardDetail struct {
TargetHenHouseProduction *float64 `gorm:"type:numeric(15,3)"` TargetHenHouseProduction *float64 `gorm:"type:numeric(15,3)"`
TargetEggWeight *float64 `gorm:"type:numeric(15,3)"` TargetEggWeight *float64 `gorm:"type:numeric(15,3)"`
TargetEggMass *float64 `gorm:"type:numeric(15,3)"` TargetEggMass *float64 `gorm:"type:numeric(15,3)"`
StandardFCR *float64 `gorm:"type:numeric(15,3)"`
CreatedAt time.Time `gorm:"type:timestamptz;not null"` CreatedAt time.Time `gorm:"type:timestamptz;not null"`
UpdatedAt time.Time `gorm:"type:timestamptz;not null"` UpdatedAt time.Time `gorm:"type:timestamptz;not null"`
@@ -117,39 +117,37 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
var createdLogId uint var createdLogId uint
isProductWarehouseExist, err := s.ProductWarehouseRepo.ProductWarehouseExistByProductAndWarehouseID(ctx, uint(req.ProductID), uint(req.WarehouseID)) var projectFlockKandangID *uint
if err != nil { pfk, err := s.ProjectFlockKandangRepo.GetActiveByKandangID(ctx, uint(req.WarehouseID))
s.Log.Errorf("Failed to check product warehouse existence: %+v", err) if err == nil && pfk != nil {
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate product warehouse") idCopy := uint(pfk.Id)
projectFlockKandangID = &idCopy
} }
if !isProductWarehouseExist {
projectFlockKandangID, err := s.getActiveProjectFlockKandangID(ctx, uint(req.WarehouseID)) pw, err := s.ProductWarehouseRepo.FindByProductWarehouseAndPfk(
if err != nil { ctx,
return nil, err uint(req.ProductID),
uint(req.WarehouseID),
projectFlockKandangID,
)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
s.Log.Errorf("Failed to find product warehouse: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to get product warehouse")
} }
newPW := &entity.ProductWarehouse{ newPW := &entity.ProductWarehouse{
ProductId: uint(req.ProductID), ProductId: uint(req.ProductID),
WarehouseId: uint(req.WarehouseID), WarehouseId: uint(req.WarehouseID),
Quantity: 0, Quantity: 0,
ProjectFlockKandangId: &projectFlockKandangID, ProjectFlockKandangId: projectFlockKandangID,
// CreatedBy: 1, // TODO: should Get from auth middleware
} }
if err := s.ProductWarehouseRepo.CreateOne(ctx, newPW, nil); err != nil { if err := s.ProductWarehouseRepo.CreateOne(ctx, newPW, nil); err != nil {
s.Log.Errorf("Failed to create product warehouse: %+v", err) s.Log.Errorf("Failed to create product warehouse: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to create product warehouse") return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to create product warehouse")
} }
s.Log.Infof("Product warehouse created: %+v", newPW.Id) pw = newPW
}
pw, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(
ctx,
uint(req.ProductID),
uint(req.WarehouseID),
)
if err != nil {
s.Log.Errorf("Failed to get product warehouse for project flock check: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate product warehouse")
} }
if err := common.EnsureProjectFlockNotClosedForProductWarehouses( if err := common.EnsureProjectFlockNotClosedForProductWarehouses(
@@ -18,6 +18,7 @@ type ProductWarehouseRepository interface {
ProductWarehouseExistByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (bool, error) ProductWarehouseExistByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (bool, error)
ExistsByID(ctx context.Context, id uint) (bool, error) ExistsByID(ctx context.Context, id uint) (bool, error)
GetProductWarehouseByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (*entity.ProductWarehouse, error) GetProductWarehouseByProductAndWarehouseID(ctx context.Context, productId, warehouseId uint) (*entity.ProductWarehouse, error)
FindByProductWarehouseAndPfk(ctx context.Context, productID uint, warehouseID uint, projectFlockKandangID *uint) (*entity.ProductWarehouse, error)
GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error) GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error)
GetLatestByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint, db *gorm.DB) (*entity.ProductWarehouse, error) GetLatestByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint, db *gorm.DB) (*entity.ProductWarehouse, error)
GetByFlagAndWarehouseID(ctx context.Context, flagName string, warehouseId uint) ([]entity.ProductWarehouse, error) GetByFlagAndWarehouseID(ctx context.Context, flagName string, warehouseId uint) ([]entity.ProductWarehouse, error)
@@ -107,6 +108,20 @@ func (r *ProductWarehouseRepositoryImpl) GetProductWarehouseByProductAndWarehous
return &productWarehouse, nil return &productWarehouse, nil
} }
func (r *ProductWarehouseRepositoryImpl) FindByProductWarehouseAndPfk(ctx context.Context, productID uint, warehouseID uint, projectFlockKandangID *uint) (*entity.ProductWarehouse, error) {
var productWarehouse entity.ProductWarehouse
err := r.DB().WithContext(ctx).
Where("product_id = ? AND warehouse_id = ? AND project_flock_kandang_id IS NOT DISTINCT FROM ?", productID, warehouseID, projectFlockKandangID).
First(&productWarehouse).Error
if err != nil {
return nil, err
}
return &productWarehouse, nil
}
func (r *ProductWarehouseRepositoryImpl) GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error) { func (r *ProductWarehouseRepositoryImpl) GetByCategoryCodeAndWarehouseID(ctx context.Context, categoryCode string, warehouseId uint) ([]entity.ProductWarehouse, error) {
var productWarehouses []entity.ProductWarehouse var productWarehouses []entity.ProductWarehouse
q := r.DB().WithContext(ctx).Model(&entity.ProductWarehouse{}). q := r.DB().WithContext(ctx).Model(&entity.ProductWarehouse{}).
@@ -106,23 +106,17 @@ func (s transferService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entit
} }
func (s transferService) GetOne(c *fiber.Ctx, id uint) (*entity.StockTransfer, error) { func (s transferService) GetOne(c *fiber.Ctx, id uint) (*entity.StockTransfer, error) {
s.Log.Infof("Attempting to get StockTransfer with ID: %d", id)
transferPtr, err := s.StockTransferRepo.GetByID(c.Context(), id, func(db *gorm.DB) *gorm.DB { transferPtr, err := s.StockTransferRepo.GetByID(c.Context(), id, func(db *gorm.DB) *gorm.DB {
return s.withRelations(db) return s.withRelations(db)
}) })
if err != nil { if err != nil {
s.Log.Errorf("Error getting StockTransfer ID %d: %+v", id, err)
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Transfer not found") return nil, fiber.NewError(fiber.StatusNotFound, "Transfer not found")
} }
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to get transfer") return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to get transfer")
} }
if transferPtr != nil {
s.Log.Infof("StockTransfer %d has %d documents", transferPtr.Id, len(transferPtr.Documents))
}
return transferPtr, nil return transferPtr, nil
} }
@@ -336,7 +330,9 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
Files: documentFiles, Files: documentFiles,
}) })
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to upload document for delivery %d", idx+1)) s.Log.WithError(err).Errorf("Failed to upload document for delivery %d (delivery_id: %d, filename: %s)",
idx+1, deliveries[idx].Id, file.Filename)
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to upload document for delivery %d: %v", idx+1, err))
} }
} }
} }
@@ -396,7 +392,6 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
}) })
if err != nil { if err != nil {
s.Log.Errorf("Transaction failed in CreateOne: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to process transfer transaction: %v", err)) return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to process transfer transaction: %v", err))
} }
@@ -247,11 +247,15 @@ func (s *deliveryOrdersService) CreateOne(c *fiber.Ctx, req *validation.Delivery
itemDeliveryDate = &parsedDate itemDeliveryDate = &parsedDate
} }
// Hitung total_weight dan total_price otomatis
totalWeight := requestedProduct.Qty * requestedProduct.AvgWeight
totalPrice := requestedProduct.UnitPrice * requestedProduct.Qty
deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId
deliveryProduct.UnitPrice = requestedProduct.UnitPrice deliveryProduct.UnitPrice = requestedProduct.UnitPrice
deliveryProduct.AvgWeight = requestedProduct.AvgWeight deliveryProduct.AvgWeight = requestedProduct.AvgWeight
deliveryProduct.TotalWeight = requestedProduct.TotalWeight deliveryProduct.TotalWeight = totalWeight
deliveryProduct.TotalPrice = requestedProduct.TotalPrice deliveryProduct.TotalPrice = totalPrice
deliveryProduct.DeliveryDate = itemDeliveryDate deliveryProduct.DeliveryDate = itemDeliveryDate
deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber
@@ -357,11 +361,15 @@ func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.DeliveryO
oldRequestedQty := deliveryProduct.UsageQty + deliveryProduct.PendingQty oldRequestedQty := deliveryProduct.UsageQty + deliveryProduct.PendingQty
// Hitung total_weight dan total_price otomatis
totalWeight := requestedProduct.Qty * requestedProduct.AvgWeight
totalPrice := requestedProduct.UnitPrice * requestedProduct.Qty
deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId
deliveryProduct.UnitPrice = requestedProduct.UnitPrice deliveryProduct.UnitPrice = requestedProduct.UnitPrice
deliveryProduct.AvgWeight = requestedProduct.AvgWeight deliveryProduct.AvgWeight = requestedProduct.AvgWeight
deliveryProduct.TotalWeight = requestedProduct.TotalWeight deliveryProduct.TotalWeight = totalWeight
deliveryProduct.TotalPrice = requestedProduct.TotalPrice deliveryProduct.TotalPrice = totalPrice
deliveryProduct.DeliveryDate = itemDeliveryDate deliveryProduct.DeliveryDate = itemDeliveryDate
deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber
@@ -75,7 +75,6 @@ func (s salesOrdersService) getOne(c *fiber.Ctx, id uint) (*entity.Marketing, er
return nil, fiber.NewError(fiber.StatusNotFound, "SalesOrders not found") return nil, fiber.NewError(fiber.StatusNotFound, "SalesOrders not found")
} }
if err != nil { if err != nil {
s.Log.Errorf("Failed get marketing by id: %+v", err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch sales order") return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch sales order")
} }
@@ -293,13 +292,17 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
for _, rp := range req.MarketingProducts { for _, rp := range req.MarketingProducts {
if old, ok := oldByPW[rp.ProductWarehouseId]; ok { if old, ok := oldByPW[rp.ProductWarehouseId]; ok {
// Hitung total_weight dan total_price otomatis
totalWeight := rp.Qty * rp.AvgWeight
totalPrice := rp.UnitPrice * rp.Qty
updateBody := map[string]any{ updateBody := map[string]any{
"product_warehouse_id": rp.ProductWarehouseId, "product_warehouse_id": rp.ProductWarehouseId,
"qty": rp.Qty, "qty": rp.Qty,
"unit_price": rp.UnitPrice, "unit_price": rp.UnitPrice,
"avg_weight": rp.AvgWeight, "avg_weight": rp.AvgWeight,
"total_weight": rp.TotalWeight, "total_weight": totalWeight,
"total_price": rp.TotalPrice, "total_price": totalPrice,
} }
if err := marketingProductRepoTx.PatchOne(c.Context(), old.Id, updateBody, nil); err != nil { if err := marketingProductRepoTx.PatchOne(c.Context(), old.Id, updateBody, nil); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update marketing product") return fiber.NewError(fiber.StatusInternalServerError, "Failed to update marketing product")
@@ -589,30 +592,34 @@ func (s salesOrdersService) Approval(c *fiber.Ctx, req *validation.Approve) ([]e
func (s *salesOrdersService) createMarketingProductWithDelivery(ctx context.Context, marketingId uint, rp validation.CreateMarketingProduct, marketingProductRepo repository.MarketingProductRepository, invDeliveryRepo repository.MarketingDeliveryProductRepository) error { func (s *salesOrdersService) createMarketingProductWithDelivery(ctx context.Context, marketingId uint, rp validation.CreateMarketingProduct, marketingProductRepo repository.MarketingProductRepository, invDeliveryRepo repository.MarketingDeliveryProductRepository) error {
// Hitung total_weight dan total_price otomatis
totalWeight := rp.Qty * rp.AvgWeight
totalPrice := rp.UnitPrice * rp.Qty
marketingProduct := &entity.MarketingProduct{ marketingProduct := &entity.MarketingProduct{
MarketingId: marketingId, MarketingId: marketingId,
ProductWarehouseId: rp.ProductWarehouseId, ProductWarehouseId: rp.ProductWarehouseId,
Qty: rp.Qty, Qty: rp.Qty,
UnitPrice: rp.UnitPrice, UnitPrice: rp.UnitPrice,
AvgWeight: rp.AvgWeight, AvgWeight: rp.AvgWeight,
TotalWeight: rp.TotalWeight, TotalWeight: totalWeight,
TotalPrice: rp.TotalPrice, TotalPrice: totalPrice,
} }
if err := marketingProductRepo.CreateOne(ctx, marketingProduct, nil); err != nil { if err := marketingProductRepo.CreateOne(ctx, marketingProduct, nil); err != nil {
return err return err
} }
marketingDeliveryProduct := &entity.MarketingDeliveryProduct{ marketingDeliveryProduct := &entity.MarketingDeliveryProduct{
MarketingProductId: marketingProduct.Id, MarketingProductId: marketingProduct.Id,
ProductWarehouseId: marketingProduct.ProductWarehouseId, ProductWarehouseId: marketingProduct.ProductWarehouseId,
UnitPrice: 0, UnitPrice: 0,
TotalWeight: 0, TotalWeight: 0,
AvgWeight: 0, AvgWeight: 0,
TotalPrice: 0, TotalPrice: 0,
DeliveryDate: nil, DeliveryDate: nil,
VehicleNumber: rp.VehicleNumber, VehicleNumber: rp.VehicleNumber,
UsageQty: 0, UsageQty: 0,
PendingQty: 0, PendingQty: 0,
} }
if err := invDeliveryRepo.CreateOne(ctx, marketingDeliveryProduct, nil); err != nil { if err := invDeliveryRepo.CreateOne(ctx, marketingDeliveryProduct, nil); err != nil {
return err return err
@@ -5,8 +5,6 @@ type DeliveryProduct struct {
Qty float64 `json:"qty" validate:"omitempty,gte=0"` Qty float64 `json:"qty" validate:"omitempty,gte=0"`
UnitPrice float64 `json:"unit_price" validate:"omitempty,gte=0"` UnitPrice float64 `json:"unit_price" validate:"omitempty,gte=0"`
AvgWeight float64 `json:"avg_weight" validate:"omitempty,gte=0"` AvgWeight float64 `json:"avg_weight" validate:"omitempty,gte=0"`
TotalWeight float64 `json:"total_weight" validate:"omitempty,gte=0"`
TotalPrice float64 `json:"total_price" validate:"omitempty,gte=0"`
DeliveryDate string `json:"delivery_date" validate:"omitempty,datetime=2006-01-02"` DeliveryDate string `json:"delivery_date" validate:"omitempty,datetime=2006-01-02"`
VehicleNumber string `json:"vehicle_number" validate:"omitempty,max=50"` VehicleNumber string `json:"vehicle_number" validate:"omitempty,max=50"`
} }
@@ -12,10 +12,8 @@ type CreateMarketingProduct struct {
VehicleNumber string `json:"vehicle_number" validate:"required,min=1,max=50"` VehicleNumber string `json:"vehicle_number" validate:"required,min=1,max=50"`
ProductWarehouseId uint `json:"product_warehouse_id" validate:"required,gt=0"` ProductWarehouseId uint `json:"product_warehouse_id" validate:"required,gt=0"`
UnitPrice float64 `json:"unit_price" validate:"required,gt=0"` UnitPrice float64 `json:"unit_price" validate:"required,gt=0"`
TotalWeight float64 `json:"total_weight" validate:"required,gt=0"`
Qty float64 `json:"qty" validate:"required,gt=0"` Qty float64 `json:"qty" validate:"required,gt=0"`
AvgWeight float64 `json:"avg_weight" validate:"required,gt=0"` AvgWeight float64 `json:"avg_weight" validate:"required,gt=0"`
TotalPrice float64 `json:"total_price" validate:"required,gt=0"`
} }
type Update struct { type Update struct {
@@ -33,6 +33,7 @@ type EggProductionStandardDetailDTO struct {
TargetHenHouseProduction *float64 `json:"target_hen_house_production"` TargetHenHouseProduction *float64 `json:"target_hen_house_production"`
TargetEggWeight *float64 `json:"target_egg_weight"` TargetEggWeight *float64 `json:"target_egg_weight"`
TargetEggMass *float64 `json:"target_egg_mass"` TargetEggMass *float64 `json:"target_egg_mass"`
StandardFCR *float64 `json:"standard_fcr"`
} }
type WeeklyProductionStandardDTO struct { type WeeklyProductionStandardDTO struct {
@@ -95,6 +96,7 @@ func ToWeeklyProductionStandardDTOWithDetails(growth entity.StandardGrowthDetail
TargetHenHouseProduction: detail.TargetHenHouseProduction, TargetHenHouseProduction: detail.TargetHenHouseProduction,
TargetEggWeight: detail.TargetEggWeight, TargetEggWeight: detail.TargetEggWeight,
TargetEggMass: detail.TargetEggMass, TargetEggMass: detail.TargetEggMass,
StandardFCR: detail.StandardFCR,
} }
return WeeklyProductionStandardDTO{ return WeeklyProductionStandardDTO{
@@ -148,6 +150,7 @@ func ToEggProductionStandardDetailDTO(e entity.ProductionStandardDetail) EggProd
TargetHenHouseProduction: e.TargetHenHouseProduction, TargetHenHouseProduction: e.TargetHenHouseProduction,
TargetEggWeight: e.TargetEggWeight, TargetEggWeight: e.TargetEggWeight,
TargetEggMass: e.TargetEggMass, TargetEggMass: e.TargetEggMass,
StandardFCR: e.StandardFCR,
} }
} }
@@ -84,7 +84,6 @@ func (s productionStandardService) GetOne(c *fiber.Ctx, id uint) (*entity.Produc
return nil, fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found") return nil, fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found")
} }
if err != nil { if err != nil {
s.Log.Errorf("Failed get productionStandard by id: %+v", err)
return nil, err return nil, err
} }
return productionStandard, nil return productionStandard, nil
@@ -111,6 +110,7 @@ func (s *productionStandardService) CreateOne(c *fiber.Ctx, req *validation.Crea
var createdStandard *entity.ProductionStandard var createdStandard *entity.ProductionStandard
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error { err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
standardRepoTx := repository.NewProductionStandardRepository(tx) standardRepoTx := repository.NewProductionStandardRepository(tx)
productionStandardDetailRepoTx := repository.NewProductionStandardDetailRepository(tx) productionStandardDetailRepoTx := repository.NewProductionStandardDetailRepository(tx)
standardGrowthDetailRepoTx := repository.NewStandardGrowthDetailRepository(tx) standardGrowthDetailRepoTx := repository.NewStandardGrowthDetailRepository(tx)
@@ -142,6 +142,7 @@ func (s *productionStandardService) CreateOne(c *fiber.Ctx, req *validation.Crea
TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction, TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction,
TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight, TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight,
TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass, TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass,
StandardFCR: detailReq.ProductionStandardDetails.StandardFCR,
} }
if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil { if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil {
@@ -206,7 +207,6 @@ func (s productionStandardService) UpdateOne(c *fiber.Ctx, req *validation.Updat
nameExists, err := s.Repository.NameExists(c.Context(), *req.Name, &id) nameExists, err := s.Repository.NameExists(c.Context(), *req.Name, &id)
if err != nil { if err != nil {
s.Log.Errorf("Failed to check existing production standard: %+v", err)
return err return err
} }
if nameExists { if nameExists {
@@ -255,6 +255,7 @@ func (s productionStandardService) UpdateOne(c *fiber.Ctx, req *validation.Updat
TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction, TargetHenHouseProduction: detailReq.ProductionStandardDetails.TargetHenHouseProduction,
TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight, TargetEggWeight: detailReq.ProductionStandardDetails.TargetEggWeight,
TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass, TargetEggMass: detailReq.ProductionStandardDetails.TargetEggMass,
StandardFCR: detailReq.ProductionStandardDetails.StandardFCR,
} }
if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil { if err := productionStandardDetailRepoTx.CreateOne(c.Context(), productionStandardDetail, nil); err != nil {
@@ -283,7 +284,6 @@ func (s productionStandardService) UpdateOne(c *fiber.Ctx, req *validation.Updat
}) })
if err != nil { if err != nil {
s.Log.Errorf("Failed to update production standard: %+v", err)
return nil, err return nil, err
} }
@@ -295,7 +295,6 @@ func (s productionStandardService) DeleteOne(c *fiber.Ctx, id uint) error {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found") return fiber.NewError(fiber.StatusNotFound, "ProductionStandard not found")
} }
s.Log.Errorf("Failed to delete productionStandard: %+v", err)
return err return err
} }
return nil return nil
@@ -5,6 +5,7 @@ type ProductionStandardDetailItem struct {
TargetHenHouseProduction *float64 `json:"target_hen_house_production" validate:"omitempty,gte=0"` TargetHenHouseProduction *float64 `json:"target_hen_house_production" validate:"omitempty,gte=0"`
TargetEggWeight *float64 `json:"target_egg_weight" validate:"omitempty,gte=0"` TargetEggWeight *float64 `json:"target_egg_weight" validate:"omitempty,gte=0"`
TargetEggMass *float64 `json:"target_egg_mass" validate:"omitempty,gte=0"` TargetEggMass *float64 `json:"target_egg_mass" validate:"omitempty,gte=0"`
StandardFCR *float64 `json:"standard_fcr" validate:"omitempty,gte=0"`
} }
type StandardGrowthDetailItem struct { type StandardGrowthDetailItem struct {
@@ -1,14 +1,14 @@
package validation package validation
type Create struct { type Create struct {
FlockName string `json:"flock_name" validate:"required_strict"` FlockName string `json:"flock_name" validate:"required_strict"`
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"` AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
Category string `json:"category" validate:"required_strict"` Category string `json:"category" validate:"required_strict"`
FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"` FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"`
ProductionStandardId uint `json:"production_standard_id" validate:"required_strict,number,gt=0"` ProductionStandardId uint `json:"production_standard_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"`
ProjectBudgets []ProjectBudget `json:"project_budgets" validate:"required,min=1,dive"` ProjectBudgets []ProjectBudget `json:"project_budgets" validate:"required,min=1,dive"`
} }
type Query struct { type Query struct {