mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-23 14:55:42 +00:00
Merge branch 'dev/ragil-before-sso' of https://gitlab.com/mbugroup/lti-api into dev/teguh
This commit is contained in:
@@ -12,7 +12,7 @@ import (
|
||||
func ProjectflockRoutes(v1 fiber.Router, u user.UserService, s projectflock.ProjectflockService) {
|
||||
ctrl := controller.NewProjectflockController(s)
|
||||
|
||||
route := v1.Group("/project_flocks")
|
||||
route := v1.Group("/project-flocks")
|
||||
|
||||
// route.Get("/", m.Auth(u), ctrl.GetAll)
|
||||
// route.Post("/", m.Auth(u), ctrl.CreateOne)
|
||||
@@ -27,6 +27,6 @@ func ProjectflockRoutes(v1 fiber.Router, u user.UserService, s projectflock.Proj
|
||||
route.Delete("/:id", ctrl.DeleteOne)
|
||||
route.Get("/kandangs/lookup", ctrl.LookupProjectFlockKandang)
|
||||
route.Post("/approvals", ctrl.Approval)
|
||||
route.Get("/kandangs/:project_flock_kandang_id/periods", ctrl.GetFlockPeriodSummary)
|
||||
route.Get("/kandangs/:project-flock_kandang-id/periods", ctrl.GetFlockPeriodSummary)
|
||||
|
||||
}
|
||||
|
||||
@@ -254,18 +254,22 @@ func (r *RecordingRepositoryImpl) FindPreviousRecording(tx *gorm.DB, projectFloc
|
||||
}
|
||||
|
||||
func (r *RecordingRepositoryImpl) GetTotalChick(tx *gorm.DB, projectFlockKandangId uint) (int64, error) {
|
||||
var population entity.ProjectFlockPopulation
|
||||
var total float64
|
||||
err := tx.
|
||||
Where("project_flock_kandang_id = ?", projectFlockKandangId).
|
||||
Order("created_at DESC").
|
||||
First(&population).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return 0, nil
|
||||
}
|
||||
Table("project_flock_populations").
|
||||
Select("COALESCE(SUM(project_flock_populations.total_qty - project_flock_populations.total_used_qty), 0) AS total_qty").
|
||||
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
||||
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangId).
|
||||
Scan(&total).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(math.Round(population.TotalQty)), nil
|
||||
|
||||
if total < 0 {
|
||||
total = 0
|
||||
}
|
||||
|
||||
return int64(math.Round(total)), nil
|
||||
}
|
||||
|
||||
func (r *RecordingRepositoryImpl) GetAverageBodyWeight(tx *gorm.DB, recordingID uint) (float64, error) {
|
||||
|
||||
@@ -261,6 +261,10 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.BodyWeights == nil && req.Stocks == nil && req.Depletions == nil && req.Eggs == nil {
|
||||
return s.GetOne(c, id)
|
||||
}
|
||||
|
||||
ctx := c.Context()
|
||||
|
||||
var recordingEntity *entity.Recording
|
||||
@@ -277,12 +281,21 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
||||
}
|
||||
recordingEntity = recording
|
||||
|
||||
hasBodyChanges := req.BodyWeights != nil
|
||||
hasStockChanges := req.Stocks != nil
|
||||
hasDepletionChanges := req.Depletions != nil
|
||||
hasEggChanges := req.Eggs != nil
|
||||
|
||||
if !hasBodyChanges && !hasStockChanges && !hasDepletionChanges && !hasEggChanges {
|
||||
return nil
|
||||
}
|
||||
|
||||
var category string
|
||||
if recordingEntity.ProjectFlockKandang != nil && recordingEntity.ProjectFlockKandang.ProjectFlock.Id != 0 {
|
||||
category = strings.ToUpper(recordingEntity.ProjectFlockKandang.ProjectFlock.Category)
|
||||
}
|
||||
isLaying := category == strings.ToUpper(string(utils.ProjectFlockCategoryLaying))
|
||||
if req.Eggs != nil {
|
||||
if hasEggChanges {
|
||||
if !isLaying && len(req.Eggs) > 0 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Egg details permitted only for laying project flocks")
|
||||
}
|
||||
@@ -291,7 +304,29 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
||||
}
|
||||
}
|
||||
|
||||
if req.BodyWeights != nil {
|
||||
if hasStockChanges {
|
||||
if err := s.ensureProductWarehousesExist(c, req.Stocks, nil, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if hasDepletionChanges || hasEggChanges {
|
||||
if err := s.ensureProductWarehousesExist(c, nil, req.Depletions, req.Eggs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
hasExistingGradings := false
|
||||
for _, egg := range recordingEntity.Eggs {
|
||||
if len(egg.GradingEggs) > 0 {
|
||||
hasExistingGradings = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
hasEggsAfterUpdate := len(recordingEntity.Eggs) > 0
|
||||
|
||||
if hasBodyChanges {
|
||||
if err := s.Repository.DeleteBodyWeights(tx, recordingEntity.Id); err != nil {
|
||||
s.Log.Errorf("Failed to clear body weights: %+v", err)
|
||||
return err
|
||||
@@ -302,11 +337,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
||||
}
|
||||
}
|
||||
|
||||
if req.Stocks != nil {
|
||||
if err := s.ensureProductWarehousesExist(c, req.Stocks, nil, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hasStockChanges {
|
||||
existingStocks, err := s.Repository.ListStocks(tx, recordingEntity.Id)
|
||||
if err != nil {
|
||||
s.Log.Errorf("Failed to list existing stocks: %+v", err)
|
||||
@@ -330,17 +361,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
||||
}
|
||||
}
|
||||
|
||||
if req.Eggs != nil && req.Depletions == nil {
|
||||
if err := s.ensureProductWarehousesExist(c, nil, nil, req.Eggs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if req.Depletions != nil {
|
||||
if err := s.ensureProductWarehousesExist(c, nil, req.Depletions, req.Eggs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hasDepletionChanges {
|
||||
existingDepletions, err := s.Repository.ListDepletions(tx, recordingEntity.Id)
|
||||
if err != nil {
|
||||
s.Log.Errorf("Failed to list existing depletions: %+v", err)
|
||||
@@ -364,7 +385,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
||||
}
|
||||
}
|
||||
|
||||
if req.Eggs != nil {
|
||||
if hasEggChanges {
|
||||
existingEggs, err := s.Repository.ListEggs(tx, recordingEntity.Id)
|
||||
if err != nil {
|
||||
s.Log.Errorf("Failed to list existing eggs: %+v", err)
|
||||
@@ -386,17 +407,71 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
||||
s.Log.Errorf("Failed to adjust product warehouses for eggs: %+v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
hasExistingGradings = false
|
||||
hasEggsAfterUpdate = len(req.Eggs) > 0
|
||||
}
|
||||
|
||||
if err := s.computeAndUpdateMetrics(ctx, tx, recordingEntity); err != nil {
|
||||
s.Log.Errorf("Failed to recompute recording metrics: %+v", err)
|
||||
return err
|
||||
if hasBodyChanges || hasStockChanges || hasDepletionChanges {
|
||||
if err := s.computeAndUpdateMetrics(ctx, tx, recordingEntity); err != nil {
|
||||
s.Log.Errorf("Failed to recompute recording metrics: %+v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
action := entity.ApprovalActionUpdated
|
||||
if err := s.createRecordingApproval(ctx, tx, recordingEntity.Id, utils.RecordingStepPengajuan, action, recordingEntity.CreatedBy, nil); err != nil {
|
||||
s.Log.Errorf("Failed to create approval after recording update %d: %+v", recordingEntity.Id, err)
|
||||
return err
|
||||
actorID := recordingEntity.CreatedBy
|
||||
if actorID == 0 {
|
||||
actorID = 1
|
||||
}
|
||||
|
||||
var step approvalutils.ApprovalStep
|
||||
if isLaying {
|
||||
if !hasEggsAfterUpdate {
|
||||
step = utils.RecordingStepGradingTelur
|
||||
} else if hasEggChanges {
|
||||
step = utils.RecordingStepGradingTelur
|
||||
} else if hasExistingGradings {
|
||||
step = utils.RecordingStepPengajuan
|
||||
} else {
|
||||
step = utils.RecordingStepGradingTelur
|
||||
}
|
||||
} else {
|
||||
step = utils.RecordingStepPengajuan
|
||||
}
|
||||
|
||||
latestApproval := recordingEntity.LatestApproval
|
||||
if latestApproval == nil {
|
||||
if s.ApprovalSvc != nil {
|
||||
if fetched, fetchErr := s.ApprovalSvc.LatestByTarget(ctx, utils.ApprovalWorkflowRecording, recordingEntity.Id, nil); fetchErr != nil {
|
||||
s.Log.Errorf("Failed to load latest approval for recording %d: %+v", recordingEntity.Id, fetchErr)
|
||||
return fetchErr
|
||||
} else {
|
||||
latestApproval = fetched
|
||||
}
|
||||
} else if s.ApprovalRepo != nil {
|
||||
if fetched, fetchErr := s.ApprovalRepo.LatestByTarget(ctx, utils.ApprovalWorkflowRecording.String(), recordingEntity.Id, nil); fetchErr != nil {
|
||||
s.Log.Errorf("Failed to load latest approval for recording %d: %+v", recordingEntity.Id, fetchErr)
|
||||
return fetchErr
|
||||
} else {
|
||||
latestApproval = fetched
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shouldCreateApproval := true
|
||||
if latestApproval != nil &&
|
||||
latestApproval.StepNumber == uint16(step) &&
|
||||
latestApproval.Action != nil &&
|
||||
*latestApproval.Action == action {
|
||||
shouldCreateApproval = false
|
||||
}
|
||||
|
||||
if shouldCreateApproval {
|
||||
if err := s.createRecordingApproval(ctx, tx, recordingEntity.Id, step, action, actorID, nil); err != nil {
|
||||
s.Log.Errorf("Failed to create approval after recording update %d: %+v", recordingEntity.Id, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1015,13 +1090,21 @@ func (s *recordingService) ensureChickInExists(ctx context.Context, projectFlock
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Project flock kandang tidak valid")
|
||||
}
|
||||
|
||||
_, err := s.ProjectFlockPopulationRepo.GetByProjectFlockKandangID(ctx, projectFlockKandangID)
|
||||
if err == nil {
|
||||
return nil
|
||||
populations, err := s.ProjectFlockPopulationRepo.GetByProjectFlockKandangID(ctx, projectFlockKandangID)
|
||||
if err != nil {
|
||||
s.Log.Errorf("Failed to check project flock population for project_flock_kandang_id=%d: %+v", projectFlockKandangID, err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memeriksa data chick in")
|
||||
}
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Project flock belum melakukan chick in sehingga belum dapat membuat recording")
|
||||
|
||||
if len(populations) == 0 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Project flock belum memiliki chick in yang disetujui sehingga belum dapat membuat recording")
|
||||
}
|
||||
s.Log.Errorf("Failed to check project flock population for project_flock_kandang_id=%d: %+v", projectFlockKandangID, err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memeriksa data chick in")
|
||||
|
||||
for _, population := range populations {
|
||||
if population.TotalQty > 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Chick in project flock belum disetujui sehingga belum dapat membuat recording")
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package validation
|
||||
|
||||
type (
|
||||
BodyWeight struct {
|
||||
AvgWeight float64 `json:"avg_weight" validate:"required"`
|
||||
Qty float64 `json:"qty" validate:"required,gt=0"`
|
||||
TotalWeight float64 `json:"total_weight" validate:"required,gte=0"`
|
||||
AvgWeight float64 `json:"avg_weight" validate:"required"`
|
||||
Qty float64 `json:"qty" validate:"required,gt=0"`
|
||||
TotalWeight *float64 `json:"total_weight,omitempty" validate:"omitempty,gte=0"`
|
||||
}
|
||||
|
||||
Stock struct {
|
||||
|
||||
Reference in New Issue
Block a user