From 644896edfa8bab01eef86ab81f3ed9183c622ec0 Mon Sep 17 00:00:00 2001 From: ragilap Date: Mon, 29 Dec 2025 00:21:26 +0700 Subject: [PATCH 01/12] feat(BE-281): unfinished uniformity and create project flock triger productwarehouse and add new filtering lookup --- .DS_Store | Bin 6148 -> 6148 bytes go.mod | 7 + go.sum | 22 +- ..._project_flock_kandang_uniformity.down.sql | 6 + ...te_project_flock_kandang_uniformity.up.sql | 58 ++ .../project_flock_kandang_uniformity.go | 33 + internal/entities/uniformity.go | 18 + .../product_warehouse.repository.go | 26 + .../controllers/projectflock.controller.go | 8 + .../dto/projectflock_kandang.dto.go | 1 + .../production/project_flocks/module.go | 5 +- .../project_flock_population_repository.go | 18 + .../projectflock_kandang.repository.go | 15 + .../services/projectflock.service.go | 129 +++ .../repositories/recording.repository.go | 22 + internal/modules/production/route.go | 6 +- .../controllers/uniformity.controller.go | 246 ++++++ .../uniformities/dto/uniformity.dto.go | 208 +++++ .../modules/production/uniformities/module.go | 43 + .../repositories/uniformity.repository.go | 21 + .../modules/production/uniformities/route.go | 30 + .../services/uniformity.body_weight_excel.go | 195 +++++ .../services/uniformity.service.go | 738 ++++++++++++++++++ .../validations/uniformity.validation.go | 173 ++++ internal/utils/constant.go | 23 +- 25 files changed, 2043 insertions(+), 8 deletions(-) create mode 100644 internal/database/migrations/20251227234328_create_project_flock_kandang_uniformity.down.sql create mode 100644 internal/database/migrations/20251227234328_create_project_flock_kandang_uniformity.up.sql create mode 100644 internal/entities/project_flock_kandang_uniformity.go create mode 100644 internal/entities/uniformity.go create mode 100644 internal/modules/production/uniformities/controllers/uniformity.controller.go create mode 100644 internal/modules/production/uniformities/dto/uniformity.dto.go create mode 100644 internal/modules/production/uniformities/module.go create mode 100644 internal/modules/production/uniformities/repositories/uniformity.repository.go create mode 100644 internal/modules/production/uniformities/route.go create mode 100644 internal/modules/production/uniformities/services/uniformity.body_weight_excel.go create mode 100644 internal/modules/production/uniformities/services/uniformity.service.go create mode 100644 internal/modules/production/uniformities/validations/uniformity.validation.go diff --git a/.DS_Store b/.DS_Store index 4c14efd89e4d913a63e6242a245ab626c5fffe6d..e39247fdff6549a6304ce8065c332c38da11c1a4 100644 GIT binary patch delta 31 ncmZoMXfc@J&nU4mU^g?P#AF_p{LPzLLYOBuSZrqJ_{$Ffpo$73 delta 70 zcmZoMXfc@J&nUSuU^g?P 0 { + return *latest.TotalChickQty, nil + } + } + + total, err := s.PopulationRepo.GetAvailableQtyByProjectFlockKandangID(ctx.Context(), projectFlockKandangID) + if err != nil { + s.Log.Errorf("Failed to fetch project flock kandang population %d: %+v", projectFlockKandangID, err) + return 0, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch project flock kandang population") + } + + return total, nil +} + func (s projectflockService) GetProjectFlockKandangByParams(ctx *fiber.Ctx, idStr string, projectFlockIdStr string, kandangIdStr string) (*entity.ProjectFlockKandang, float64, error) { idStr = strings.TrimSpace(idStr) projectFlockIdStr = strings.TrimSpace(projectFlockIdStr) @@ -793,6 +830,9 @@ func (s projectflockService) attachKandangs(ctx context.Context, dbTransaction * } return fiber.NewError(fiber.StatusInternalServerError, "Failed to persist project flock history") } + if err := s.ensureProjectFlockKandangProductWarehouses(ctx, dbTransaction, records); err != nil { + return err + } return nil } @@ -818,6 +858,23 @@ func (s projectflockService) detachKandangs(ctx context.Context, dbTransaction * return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Tidak dapat melepas kandang karena sudah memiliki recording: %s", strings.Join(names, ", "))) } + pfkIDs, err := s.pivotRepoWithTx(dbTransaction).ListIDsByProjectAndKandang(ctx, projectFlockID, kandangIDs) + if err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Failed to load project flock kandang ids") + } + + if len(pfkIDs) > 0 { + pwRepo := s.ProductWarehouseRepo + if dbTransaction != nil { + pwRepo = productWarehouseRepository.NewProductWarehouseRepository(dbTransaction) + } else if pwRepo == nil { + pwRepo = productWarehouseRepository.NewProductWarehouseRepository(s.Repository.DB()) + } + if err := pwRepo.DeleteByProjectFlockKandangIDs(ctx, pfkIDs); err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Failed to remove product warehouses for project flock kandang") + } + } + if resetStatus { if err := s.kandangRepoWithTx(dbTransaction).UpdateStatusByIDs(ctx, kandangIDs, utils.KandangStatusNonActive); err != nil { return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs status") @@ -854,6 +911,78 @@ func (s projectflockService) kandangRepoWithTx(tx *gorm.DB) kandangRepository.Ka return kandangRepository.NewKandangRepository(s.Repository.DB()) } +func (s projectflockService) ensureProjectFlockKandangProductWarehouses(ctx context.Context, dbTransaction *gorm.DB, records []*entity.ProjectFlockKandang) error { + if len(records) == 0 { + return nil + } + + pwRepo := s.ProductWarehouseRepo + if dbTransaction != nil { + pwRepo = productWarehouseRepository.NewProductWarehouseRepository(dbTransaction) + } else if pwRepo == nil { + pwRepo = productWarehouseRepository.NewProductWarehouseRepository(s.Repository.DB()) + } + + warehouseRepo := s.WarehouseRepo + if dbTransaction != nil { + warehouseRepo = warehouseRepository.NewWarehouseRepository(dbTransaction) + } else if warehouseRepo == nil { + warehouseRepo = warehouseRepository.NewWarehouseRepository(s.Repository.DB()) + } + + flags := []utils.FlagType{ + utils.FlagAyamAfkir, + utils.FlagAyamCulling, + utils.FlagAyamMati, + utils.FlagTelurPecah, + utils.FlagTelurUtuh, + } + + productIDs := make(map[utils.FlagType]uint, len(flags)) + for _, flag := range flags { + product, err := pwRepo.GetFirstProductByFlag(ctx, string(flag)) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Product untuk flag %s tidak ditemukan", flag)) + } + return err + } + productIDs[flag] = product.Id + } + + for _, record := range records { + if record == nil || record.Id == 0 { + continue + } + + warehouse, err := warehouseRepo.GetByKandangID(ctx, record.KandangId) + if err != nil { + return err + } + + for _, flag := range flags { + productID := productIDs[flag] + if _, err := pwRepo.GetByProductWarehouseAndProjectFlockKandang(ctx, productID, warehouse.Id, record.Id); err == nil { + continue + } else if !errors.Is(err, gorm.ErrRecordNotFound) { + return err + } + + newPW := entity.ProductWarehouse{ + ProductId: productID, + WarehouseId: warehouse.Id, + ProjectFlockKandangId: &record.Id, + Quantity: 0, + } + if err := pwRepo.CreateOne(ctx, &newPW, nil); err != nil { + return err + } + } + } + + return nil +} + func (s projectflockService) Resubmit(c *fiber.Ctx, req *validation.Resubmit, id uint) (*entity.ProjectFlock, error) { if err := s.Validate.Struct(req); err != nil { return nil, err diff --git a/internal/modules/production/recordings/repositories/recording.repository.go b/internal/modules/production/recordings/repositories/recording.repository.go index 6e362ba7..a615692f 100644 --- a/internal/modules/production/recordings/repositories/recording.repository.go +++ b/internal/modules/production/recordings/repositories/recording.repository.go @@ -17,6 +17,7 @@ type RecordingRepository interface { repository.BaseRepository[entity.Recording] WithRelations(db *gorm.DB) *gorm.DB + GetLatestByProjectFlockKandangID(ctx context.Context, projectFlockKandangId uint) (*entity.Recording, error) GenerateNextDay(tx *gorm.DB, projectFlockKandangId uint) (int, error) CreateBodyWeights(tx *gorm.DB, bodyWeights []entity.RecordingBW) error @@ -81,6 +82,27 @@ func (r *RecordingRepositoryImpl) WithRelations(db *gorm.DB) *gorm.DB { Preload("Eggs.ProductWarehouse.Warehouse") } +func (r *RecordingRepositoryImpl) GetLatestByProjectFlockKandangID(ctx context.Context, projectFlockKandangId uint) (*entity.Recording, error) { + if projectFlockKandangId == 0 { + return nil, errors.New("project_flock_kandang_id is required") + } + + var record entity.Recording + err := r.DB().WithContext(ctx). + Where("project_flock_kandangs_id = ?", projectFlockKandangId). + Order("record_datetime DESC"). + Order("created_at DESC"). + Limit(1). + Find(&record).Error + if errors.Is(err, gorm.ErrRecordNotFound) || record.Id == 0 { + return nil, nil + } + if err != nil { + return nil, err + } + return &record, nil +} + func (r *RecordingRepositoryImpl) GenerateNextDay(tx *gorm.DB, projectFlockKandangId uint) (int, error) { var days []int if err := tx.Model(&entity.Recording{}). diff --git a/internal/modules/production/route.go b/internal/modules/production/route.go index d1425b7c..4066121a 100644 --- a/internal/modules/production/route.go +++ b/internal/modules/production/route.go @@ -8,10 +8,11 @@ import ( "gorm.io/gorm" chickins "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins" + projectFlockKandangs "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs" projectflocks "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks" recordings "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings" transferLayings "gitlab.com/mbugroup/lti-api.git/internal/modules/production/transfer_layings" - projectFlockKandangs "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs" + uniformitys "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities" // MODULE IMPORTS ) @@ -24,8 +25,9 @@ func RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Valida chickins.ChickinModule{}, transferLayings.TransferLayingModule{}, projectFlockKandangs.ProjectFlockKandangModule{}, + uniformitys.UniformityModule{}, // MODULE REGISTRY -} + } for _, m := range allModules { m.RegisterRoutes(group, db, validate) diff --git a/internal/modules/production/uniformities/controllers/uniformity.controller.go b/internal/modules/production/uniformities/controllers/uniformity.controller.go new file mode 100644 index 00000000..b6874ba4 --- /dev/null +++ b/internal/modules/production/uniformities/controllers/uniformity.controller.go @@ -0,0 +1,246 @@ +package controller + +import ( + "math" + + "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/dto" + service "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/services" + validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/validations" + "gitlab.com/mbugroup/lti-api.git/internal/response" + + "github.com/gofiber/fiber/v2" + entity "gitlab.com/mbugroup/lti-api.git/internal/entities" +) + +type UniformityController struct { + UniformityService service.UniformityService +} + +func NewUniformityController(uniformityService service.UniformityService) *UniformityController { + return &UniformityController{ + UniformityService: uniformityService, + } +} + +func (u *UniformityController) GetAll(c *fiber.Ctx) error { + query, err := validation.ParseQuery(c) + if err != nil { + return err + } + + result, totalResults, err := u.UniformityService.GetAll(c, query) + if err != nil { + return err + } + + return c.Status(fiber.StatusOK). + JSON(response.SuccessWithPaginate[dto.UniformityListDTO]{ + Code: fiber.StatusOK, + Status: "success", + Message: "Get all production uniformities successfully", + Meta: response.Meta{ + Page: query.Page, + Limit: query.Limit, + TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))), + TotalResults: totalResults, + Filters: fiber.Map{ + "location_id": "", + "project_flock_id": "", + "status": "Pengajuan", + }, + }, + Data: dto.ToUniformityListDTOs(result), + }) +} + +func (u *UniformityController) GetOne(c *fiber.Ctx) error { + id, err := validation.ParseIDParam(c, "id") + if err != nil { + return err + } + + result, err := u.UniformityService.GetOne(c, id) + if err != nil { + return err + } + + withDetails := c.QueryBool("with_details", false) + calculation := service.UniformityCalculation{} + var document *entity.Document + var meanWeight float64 + if result.MeanUp > 0 { + meanWeight = math.Round(result.MeanUp / 1.10) + } + if withDetails { + var err error + calculation, document, err = u.UniformityService.CalculateUniformityFromDocument(c, id) + if err != nil { + return err + } + } else { + calculation = service.UniformityCalculation{ + ChickQtyOfWeight: result.ChickQtyOfWeight, + MeanWeight: meanWeight, + MeanDown: result.MeanDown, + MeanUp: result.MeanUp, + UniformQty: result.UniformQty, + OutsideQty: result.NotUniformQty, + Uniformity: result.Uniformity, + Cv: result.Cv, + } + } + + return c.Status(fiber.StatusOK). + JSON(response.Success{ + Code: fiber.StatusOK, + Status: "success", + Message: "Get production uniformity successfully", + Data: dto.ToUniformityDetailDTO(*result, calculation, document), + }) +} + +func (u *UniformityController) CreateOne(c *fiber.Ctx) error { + req, file, err := validation.ParseCreate(c) + if err != nil { + return err + } + + rows, err := u.UniformityService.ParseBodyWeightExcel(c, file) + if err != nil { + return err + } + + calculation, err := u.UniformityService.ComputeUniformity(rows) + if err != nil { + return err + } + + result, err := u.UniformityService.CreateOne(c, req, file, rows) + if err != nil { + return err + } + + document := dto.NewDocumentForResponse(file.Filename) + + return c.Status(fiber.StatusCreated). + JSON(response.Success{ + Code: fiber.StatusCreated, + Status: "success", + Message: "Create uniformity successfully", + Data: dto.ToUniformityDetailDTO(*result, calculation, document), + }) +} + +func (u *UniformityController) UploadBodyWeightExcel(c *fiber.Ctx) error { + files, err := validation.ParseUploadFiles(c) + if err != nil { + return err + } + + rows, err := u.UniformityService.ParseBodyWeightExcel(c, files[0]) + if err != nil { + return err + } + + calculation, err := u.UniformityService.ComputeUniformity(rows) + if err != nil { + return err + } + + return c.Status(fiber.StatusOK). + JSON(response.Success{ + Code: fiber.StatusOK, + Status: "success", + Message: "Uniformity verified successfully", + Data: dto.ToUniformityVerificationDTO(calculation), + }) +} + +func (u *UniformityController) UpdateOne(c *fiber.Ctx) error { + id, err := validation.ParseIDParam(c, "id") + if err != nil { + return err + } + + req, file, err := validation.ParseUpdate(c) + if err != nil { + return err + } + + var rows []service.BodyWeightExcelRow + if file != nil { + parsed, err := u.UniformityService.ParseBodyWeightExcel(c, file) + if err != nil { + return err + } + rows = parsed + } + + result, err := u.UniformityService.UpdateOne(c, req, id, file, rows) + if err != nil { + return err + } + + calculation, document, err := u.UniformityService.CalculateUniformityFromDocument(c, id) + if err != nil { + return err + } + + return c.Status(fiber.StatusOK). + JSON(response.Success{ + Code: fiber.StatusOK, + Status: "success", + Message: "Update uniformity successfully", + Data: dto.ToUniformityDetailDTO(*result, calculation, document), + }) +} + +func (u *UniformityController) DeleteOne(c *fiber.Ctx) error { + id, err := validation.ParseIDParam(c, "id") + if err != nil { + return err + } + + if err := u.UniformityService.DeleteOne(c, id); err != nil { + return err + } + + return c.Status(fiber.StatusOK). + JSON(response.Common{ + Code: fiber.StatusOK, + Status: "success", + Message: "Delete uniformity successfully", + }) +} + +func (u *UniformityController) Approve(c *fiber.Ctx) error { + req, err := validation.ParseApprove(c) + if err != nil { + return err + } + + results, err := u.UniformityService.Approval(c, req) + if err != nil { + return err + } + + var ( + data interface{} + message = "Submit uniformity approvals successfully" + ) + + if len(results) == 1 { + message = "Submit uniformity approval successfully" + data = dto.ToUniformityListDTOs(results)[0] + } else { + data = dto.ToUniformityListDTOs(results) + } + + return c.Status(fiber.StatusOK). + JSON(response.Success{ + Code: fiber.StatusOK, + Status: "success", + Message: message, + Data: data, + }) +} diff --git a/internal/modules/production/uniformities/dto/uniformity.dto.go b/internal/modules/production/uniformities/dto/uniformity.dto.go new file mode 100644 index 00000000..1c9f4c4d --- /dev/null +++ b/internal/modules/production/uniformities/dto/uniformity.dto.go @@ -0,0 +1,208 @@ +package dto + +import ( + "time" + + entity "gitlab.com/mbugroup/lti-api.git/internal/entities" + approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto" + service "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/services" +) + +type UniformitySamplingDTO struct { + ChickQtyOfWeight float64 `json:"chick_qty_of_weight"` + MeanWeight float64 `json:"mean_weight"` + MeanDown float64 `json:"mean_down"` + MeanUp float64 `json:"mean_up"` +} + +type UniformityResultDTO struct { + UniformQty float64 `json:"uniform_qty"` + OutsideQty float64 `json:"outside_qty"` + Uniformity float64 `json:"uniformity"` + Cv float64 `json:"cv"` +} + +type UniformityDetailItemDTO struct { + Id int `json:"id"` + Weight float64 `json:"weight"` + Range string `json:"range"` +} + +type UniformityVerificationDTO struct { + Sampling UniformitySamplingDTO `json:"sampling"` + Result UniformityResultDTO `json:"result"` + UniformityDetails []UniformityDetailItemDTO `json:"uniformity_details"` +} + +type UniformityInfoDTO struct { + Tanggal string `json:"tanggal"` + LokasiFarm string `json:"lokasi_farm"` + ProjectFlock string `json:"project_flock"` + Kandang string `json:"kandang"` + FileName string `json:"file_name"` +} + +type UniformityDetailDTO struct { + Id uint `json:"id"` + InfoUmum UniformityInfoDTO `json:"info_umum"` + Sampling UniformitySamplingDTO `json:"sampling"` + Result UniformityResultDTO `json:"result"` + UniformityDetails []UniformityDetailItemDTO `json:"uniformity_details"` +} + +type UniformityListDTO struct { + Id uint `json:"id"` + ProjectFlockKandangId uint `json:"project_flock_kandang_id"` + LocationName string `json:"location_name"` + FlockName string `json:"flock_name"` + KandangName string `json:"kandang_name"` + AppliedAt *time.Time `json:"applied_at"` + Week int `json:"week"` + Status string `json:"status"` + Uniformity float64 `json:"uniformity"` + Cv float64 `json:"cv"` + ChickQtyOfWeight float64 `json:"chick_qty_of_weight"` + UniformQty float64 `json:"uniform_qty"` + MeanUp float64 `json:"mean_up"` + MeanDown float64 `json:"mean_down"` + CreatedAt time.Time `json:"created_at"` + CreatedBy uint `json:"created_by"` + LatestApproval *approvalDTO.ApprovalRelationDTO `json:"latest_approval"` +} + +func NewDocumentForResponse(name string) *entity.Document { + if name == "" { + return nil + } + return &entity.Document{Name: name} +} + +func ToUniformityVerificationDTO(calc service.UniformityCalculation) UniformityVerificationDTO { + return UniformityVerificationDTO{ + Sampling: toUniformitySamplingDTO(calc), + Result: toUniformityResultDTO(calc), + UniformityDetails: toUniformityDetailItemsDTO(calc), + } +} + +func ToUniformityDetailDTO( + entityData entity.ProjectFlockKandangUniformity, + calc service.UniformityCalculation, + document *entity.Document, +) UniformityDetailDTO { + info := UniformityInfoDTO{ + Tanggal: formatUniformityDate(entityData.UniformDate), + LokasiFarm: resolveLocationName(entityData.ProjectFlockKandang), + ProjectFlock: resolveProjectFlockName(entityData.ProjectFlockKandang), + Kandang: resolveKandangName(entityData.ProjectFlockKandang), + FileName: "", + } + if document != nil { + info.FileName = document.Name + } + + return UniformityDetailDTO{ + Id: entityData.Id, + InfoUmum: info, + Sampling: toUniformitySamplingDTO(calc), + Result: toUniformityResultDTO(calc), + UniformityDetails: toUniformityDetailItemsDTO(calc), + } +} + +func ToUniformityListDTOs(items []entity.ProjectFlockKandangUniformity) []UniformityListDTO { + result := make([]UniformityListDTO, len(items)) + for i, item := range items { + var latestApproval *approvalDTO.ApprovalRelationDTO + status := "Pengajuan" + if item.LatestApproval != nil { + mapped := approvalDTO.ToApprovalDTO(*item.LatestApproval) + latestApproval = &mapped + if mapped.StepName != "" { + status = mapped.StepName + } + } + + result[i] = UniformityListDTO{ + Id: item.Id, + ProjectFlockKandangId: item.ProjectFlockKandangId, + LocationName: resolveLocationName(item.ProjectFlockKandang), + FlockName: resolveProjectFlockName(item.ProjectFlockKandang), + KandangName: resolveKandangName(item.ProjectFlockKandang), + AppliedAt: item.UniformDate, + Week: item.Week, + Status: status, + Uniformity: item.Uniformity, + Cv: item.Cv, + ChickQtyOfWeight: item.ChickQtyOfWeight, + UniformQty: item.UniformQty, + MeanUp: item.MeanUp, + MeanDown: item.MeanDown, + CreatedAt: item.CreatedAt, + CreatedBy: item.CreatedBy, + LatestApproval: latestApproval, + } + } + return result +} + +func toUniformitySamplingDTO(calc service.UniformityCalculation) UniformitySamplingDTO { + return UniformitySamplingDTO{ + ChickQtyOfWeight: calc.ChickQtyOfWeight, + MeanWeight: calc.MeanWeight, + MeanDown: calc.MeanDown, + MeanUp: calc.MeanUp, + } +} + +func toUniformityResultDTO(calc service.UniformityCalculation) UniformityResultDTO { + return UniformityResultDTO{ + UniformQty: calc.UniformQty, + OutsideQty: calc.OutsideQty, + Uniformity: calc.Uniformity, + Cv: calc.Cv, + } +} + +func toUniformityDetailItemsDTO(calc service.UniformityCalculation) []UniformityDetailItemDTO { + result := make([]UniformityDetailItemDTO, len(calc.Details)) + for i, item := range calc.Details { + result[i] = UniformityDetailItemDTO{ + Id: item.Id, + Weight: item.Weight, + Range: item.Range, + } + } + return result +} + +func resolveLocationName(pfk entity.ProjectFlockKandang) string { + if pfk.Kandang.Id != 0 && pfk.Kandang.Location.Id != 0 { + return pfk.Kandang.Location.Name + } + if pfk.ProjectFlock.Id != 0 && pfk.ProjectFlock.Location.Id != 0 { + return pfk.ProjectFlock.Location.Name + } + return "" +} + +func resolveProjectFlockName(pfk entity.ProjectFlockKandang) string { + if pfk.ProjectFlock.Id != 0 { + return pfk.ProjectFlock.FlockName + } + return "" +} + +func resolveKandangName(pfk entity.ProjectFlockKandang) string { + if pfk.Kandang.Id != 0 { + return pfk.Kandang.Name + } + return "" +} + +func formatUniformityDate(date *time.Time) string { + if date == nil || date.IsZero() { + return "" + } + return date.Format("2006-01-02") +} diff --git a/internal/modules/production/uniformities/module.go b/internal/modules/production/uniformities/module.go new file mode 100644 index 00000000..1032cdcf --- /dev/null +++ b/internal/modules/production/uniformities/module.go @@ -0,0 +1,43 @@ +package uniformitys + +import ( + "context" + "fmt" + + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" + "gorm.io/gorm" + + commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" + commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" + rUniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/repositories" + sUniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/services" + + rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories" + sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" + "gitlab.com/mbugroup/lti-api.git/internal/utils" +) + +type UniformityModule struct{} + +func (UniformityModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) { + uniformityRepo := rUniformity.NewUniformityRepository(db) + documentRepo := commonRepo.NewDocumentRepository(db) + approvalRepo := commonRepo.NewApprovalRepository(db) + userRepo := rUser.NewUserRepository(db) + + documentSvc, err := commonSvc.NewDocumentServiceFromConfig(context.Background(), documentRepo) + if err != nil { + panic(fmt.Sprintf("failed to create document service: %v", err)) + } + + approvalSvc := commonSvc.NewApprovalService(approvalRepo) + if err := approvalSvc.RegisterWorkflowSteps(utils.ApprovalWorkflowUniformity, utils.UniformityApprovalSteps); err != nil { + panic(fmt.Sprintf("failed to register uniformity approval workflow: %v", err)) + } + + uniformityService := sUniformity.NewUniformityService(uniformityRepo, documentSvc, approvalRepo, approvalSvc, validate) + userService := sUser.NewUserService(userRepo, validate) + + UniformityRoutes(router, userService, uniformityService) +} diff --git a/internal/modules/production/uniformities/repositories/uniformity.repository.go b/internal/modules/production/uniformities/repositories/uniformity.repository.go new file mode 100644 index 00000000..3bc66f4f --- /dev/null +++ b/internal/modules/production/uniformities/repositories/uniformity.repository.go @@ -0,0 +1,21 @@ +package repository + +import ( + "gitlab.com/mbugroup/lti-api.git/internal/common/repository" + entity "gitlab.com/mbugroup/lti-api.git/internal/entities" + "gorm.io/gorm" +) + +type UniformityRepository interface { + repository.BaseRepository[entity.ProjectFlockKandangUniformity] +} + +type UniformityRepositoryImpl struct { + *repository.BaseRepositoryImpl[entity.ProjectFlockKandangUniformity] +} + +func NewUniformityRepository(db *gorm.DB) UniformityRepository { + return &UniformityRepositoryImpl{ + BaseRepositoryImpl: repository.NewBaseRepository[entity.ProjectFlockKandangUniformity](db), + } +} diff --git a/internal/modules/production/uniformities/route.go b/internal/modules/production/uniformities/route.go new file mode 100644 index 00000000..d22e8761 --- /dev/null +++ b/internal/modules/production/uniformities/route.go @@ -0,0 +1,30 @@ +package uniformitys + +import ( + // m "gitlab.com/mbugroup/lti-api.git/internal/middleware" + controller "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/controllers" + uniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/services" + user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" + + "github.com/gofiber/fiber/v2" +) + +func UniformityRoutes(v1 fiber.Router, u user.UserService, s uniformity.UniformityService) { + ctrl := controller.NewUniformityController(s) + + route := v1.Group("/uniformities") + + // route.Get("/", m.Auth(u), ctrl.GetAll) + // route.Post("/", m.Auth(u), ctrl.CreateOne) + // route.Get("/:id", m.Auth(u), ctrl.GetOne) + // route.Patch("/:id", m.Auth(u), ctrl.UpdateOne) + // route.Delete("/:id", m.Auth(u), ctrl.DeleteOne) + + route.Get("/", ctrl.GetAll) + route.Post("/", ctrl.CreateOne) + route.Post("/verify", ctrl.UploadBodyWeightExcel) + route.Post("/approvals", ctrl.Approve) + route.Get("/:id", ctrl.GetOne) + route.Patch("/:id", ctrl.UpdateOne) + route.Delete("/:id", ctrl.DeleteOne) +} diff --git a/internal/modules/production/uniformities/services/uniformity.body_weight_excel.go b/internal/modules/production/uniformities/services/uniformity.body_weight_excel.go new file mode 100644 index 00000000..97155a3b --- /dev/null +++ b/internal/modules/production/uniformities/services/uniformity.body_weight_excel.go @@ -0,0 +1,195 @@ +package service + +import ( + "io" + "mime/multipart" + "strconv" + "strings" + + "github.com/gofiber/fiber/v2" + "github.com/xuri/excelize/v2" +) + +type BodyWeightExcelRow struct { + No int `json:"no"` + Weight float64 `json:"weight"` + Range string `json:"range,omitempty"` +} + +func (s uniformityService) ParseBodyWeightExcel(_ *fiber.Ctx, file *multipart.FileHeader) ([]BodyWeightExcelRow, error) { + if file == nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "file is required") + } + + reader, err := file.Open() + if err != nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "failed to open file") + } + defer reader.Close() + + rows, err := parseBodyWeightExcelReader(reader) + if err != nil { + return nil, err + } + + return rows, nil +} + +func parseBodyWeightExcelReader(reader io.Reader) ([]BodyWeightExcelRow, error) { + xlsx, err := excelize.OpenReader(reader) + if err != nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "failed to read excel file") + } + defer func() { + _ = xlsx.Close() + }() + + sheets := xlsx.GetSheetList() + if len(sheets) == 0 { + return nil, fiber.NewError(fiber.StatusBadRequest, "no sheets found in file") + } + + rows, err := xlsx.GetRows(sheets[0], excelize.Options{RawCellValue: true}) + if err != nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "failed to read sheet rows") + } + + return parseBodyWeightRows(rows) +} + +func parseBodyWeightRows(rows [][]string) ([]BodyWeightExcelRow, error) { + headerRowIdx, noCol, bwCol, rangeCol := findBodyWeightHeader(rows) + if headerRowIdx < 0 || bwCol < 0 { + return nil, fiber.NewError(fiber.StatusBadRequest, "header BW not found") + } + + result := make([]BodyWeightExcelRow, 0) + lastNo := 0 + + for i := headerRowIdx + 1; i < len(rows); i++ { + row := rows[i] + weightStr := cellAt(row, bwCol) + weightVal, ok := parseNumber(weightStr) + if !ok { + continue + } + + noVal := 0 + if noCol >= 0 { + if parsed, ok := parseNumber(cellAt(row, noCol)); ok { + noVal = int(parsed) + } + } + if noVal <= 0 { + noVal = lastNo + 1 + } + if noVal > lastNo { + lastNo = noVal + } + + rangeVal := "" + if rangeCol >= 0 { + rangeVal = strings.TrimSpace(cellAt(row, rangeCol)) + } + + rowPayload := BodyWeightExcelRow{ + No: noVal, + Weight: weightVal, + Range: rangeVal, + } + if rowPayload.No <= 0 || rowPayload.Weight <= 0 { + return nil, fiber.NewError(fiber.StatusBadRequest, "invalid body weight row data") + } + + result = append(result, rowPayload) + } + + if len(result) == 0 { + return nil, fiber.NewError(fiber.StatusBadRequest, "no body weight data found") + } + + return result, nil +} + +func findBodyWeightHeader(rows [][]string) (rowIdx int, noCol int, bwCol int, rangeCol int) { + rowIdx = -1 + noCol = -1 + bwCol = -1 + rangeCol = -1 + + for i, row := range rows { + tempNo := -1 + tempBW := -1 + tempRange := -1 + for j, cell := range row { + label := normalizeHeader(cell) + switch label { + case "no": + tempNo = j + case "bw": + tempBW = j + case "outsiderange": + tempRange = j + default: + if strings.HasPrefix(label, "bw") { + tempBW = j + } else if strings.HasPrefix(label, "no") { + tempNo = j + } else if strings.Contains(label, "range") { + tempRange = j + } + } + } + if tempBW >= 0 { + rowIdx = i + bwCol = tempBW + noCol = tempNo + rangeCol = tempRange + break + } + } + + return rowIdx, noCol, bwCol, rangeCol +} + +func cellAt(row []string, idx int) string { + if idx < 0 || idx >= len(row) { + return "" + } + return strings.TrimSpace(row[idx]) +} + +func normalizeHeader(value string) string { + trimmed := strings.ToLower(strings.TrimSpace(value)) + if trimmed == "" { + return "" + } + var b strings.Builder + for _, r := range trimmed { + if r >= 'a' && r <= 'z' { + b.WriteRune(r) + } + } + return b.String() +} + +func parseNumber(value string) (float64, bool) { + trimmed := strings.TrimSpace(value) + if trimmed == "" { + return 0, false + } + + if strings.Contains(trimmed, ",") { + if strings.Contains(trimmed, ".") { + trimmed = strings.ReplaceAll(trimmed, ",", "") + } else { + trimmed = strings.ReplaceAll(trimmed, ",", ".") + } + } + + parsed, err := strconv.ParseFloat(trimmed, 64) + if err != nil { + return 0, false + } + return parsed, true +} diff --git a/internal/modules/production/uniformities/services/uniformity.service.go b/internal/modules/production/uniformities/services/uniformity.service.go new file mode 100644 index 00000000..786d3662 --- /dev/null +++ b/internal/modules/production/uniformities/services/uniformity.service.go @@ -0,0 +1,738 @@ +package service + +import ( + "context" + "errors" + "fmt" + "math" + "mime/multipart" + "net/http" + "strings" + "time" + + commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" + commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" + entity "gitlab.com/mbugroup/lti-api.git/internal/entities" + m "gitlab.com/mbugroup/lti-api.git/internal/middleware" + repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/repositories" + validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/validations" + "gitlab.com/mbugroup/lti-api.git/internal/utils" + approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals" + + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +type UniformityService interface { + GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlockKandangUniformity, int64, error) + GetOne(ctx *fiber.Ctx, id uint) (*entity.ProjectFlockKandangUniformity, error) + GetSummary(ctx *fiber.Ctx, id uint) (*entity.ProjectFlockKandangUniformity, error) + CreateOne(ctx *fiber.Ctx, req *validation.Create, file *multipart.FileHeader, rows []BodyWeightExcelRow) (*entity.ProjectFlockKandangUniformity, error) + UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint, file *multipart.FileHeader, rows []BodyWeightExcelRow) (*entity.ProjectFlockKandangUniformity, error) + DeleteOne(ctx *fiber.Ctx, id uint) error + Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlockKandangUniformity, error) + ParseBodyWeightExcel(ctx *fiber.Ctx, file *multipart.FileHeader) ([]BodyWeightExcelRow, error) + ComputeUniformity(rows []BodyWeightExcelRow) (UniformityCalculation, error) + CalculateUniformityFromDocument(ctx *fiber.Ctx, uniformityID uint) (UniformityCalculation, *entity.Document, error) +} + +type uniformityService struct { + Log *logrus.Logger + Validate *validator.Validate + Repository repository.UniformityRepository + DocumentSvc commonSvc.DocumentService + ApprovalRepo commonRepo.ApprovalRepository + ApprovalSvc commonSvc.ApprovalService +} + +func NewUniformityService( + repo repository.UniformityRepository, + documentSvc commonSvc.DocumentService, + approvalRepo commonRepo.ApprovalRepository, + approvalSvc commonSvc.ApprovalService, + validate *validator.Validate, +) UniformityService { + return &uniformityService{ + Log: utils.Log, + Validate: validate, + Repository: repo, + DocumentSvc: documentSvc, + ApprovalRepo: approvalRepo, + ApprovalSvc: approvalSvc, + } +} + +func (s uniformityService) withRelations(db *gorm.DB) *gorm.DB { + return db. + Preload("ProjectFlockKandang.ProjectFlock.Location"). + Preload("ProjectFlockKandang.Kandang.Location") +} + +func (s uniformityService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlockKandangUniformity, int64, error) { + if err := s.Validate.Struct(params); err != nil { + return nil, 0, err + } + + offset := (params.Page - 1) * params.Limit + + uniformitys, total, err := s.Repository.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB { + db = s.withRelations(db) + if params.ProjectFlockKandangId != 0 { + db = db.Where("project_flock_kandang_id = ?", params.ProjectFlockKandangId) + } + if params.Week != 0 { + db = db.Where("week = ?", params.Week) + } + return db.Order("uniform_date DESC").Order("created_at DESC") + }) + + if err != nil { + s.Log.Errorf("Failed to get uniformitys: %+v", err) + return nil, 0, err + } + if err := s.attachLatestApprovals(c.Context(), uniformitys); err != nil { + return nil, 0, err + } + return uniformitys, total, nil +} + +func (s uniformityService) GetOne(c *fiber.Ctx, id uint) (*entity.ProjectFlockKandangUniformity, error) { + uniformity, err := s.Repository.GetByID(c.Context(), id, s.withRelations) + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, fiber.NewError(fiber.StatusNotFound, "Uniformity not found") + } + if err != nil { + s.Log.Errorf("Failed get uniformity by id: %+v", err) + return nil, err + } + if err := s.attachLatestApproval(c.Context(), uniformity); err != nil { + return nil, err + } + return uniformity, nil +} + +func (s uniformityService) GetSummary(c *fiber.Ctx, id uint) (*entity.ProjectFlockKandangUniformity, error) { + return s.GetOne(c, id) +} + +func (s *uniformityService) CreateOne(c *fiber.Ctx, req *validation.Create, file *multipart.FileHeader, rows []BodyWeightExcelRow) (*entity.ProjectFlockKandangUniformity, error) { + if err := s.Validate.Struct(req); err != nil { + return nil, err + } + + if file == nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "document is required") + } + + uniformDate, err := time.Parse("2006-01-02", req.Date) + if err != nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "date must be in YYYY-MM-DD format") + } + + if len(rows) == 0 { + parsedRows, err := s.ParseBodyWeightExcel(c, file) + if err != nil { + return nil, err + } + rows = parsedRows + } + + calculation, err := s.ComputeUniformity(rows) + if err != nil { + return nil, err + } + actorID, err := m.ActorIDFromContext(c) + if err != nil { + return nil, err + } + + createBody := &entity.ProjectFlockKandangUniformity{ + Uniformity: calculation.Uniformity, + Week: req.Week, + Cv: calculation.Cv, + ChickQtyOfWeight: calculation.ChickQtyOfWeight, + MeanUp: calculation.MeanUp, + MeanDown: calculation.MeanDown, + ProjectFlockKandangId: req.ProjectFlockKandangId, + UniformQty: calculation.UniformQty, + NotUniformQty: calculation.OutsideQty, + UniformDate: &uniformDate, + CreatedBy: actorID, + } + + if err := s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error { + repoTx := s.Repository.WithTx(tx) + if err := repoTx.CreateOne(c.Context(), createBody, nil); err != nil { + return err + } + if err := s.createUniformityApproval( + c.Context(), + tx, + createBody.Id, + utils.UniformityStepPengajuan, + entity.ApprovalActionCreated, + actorID, + nil, + ); err != nil { + return err + } + return nil + }); err != nil { + s.Log.Errorf("Failed to create uniformity: %+v", err) + return nil, err + } + + if s.DocumentSvc != nil { + actorIDCopy := actorID + _, err := s.DocumentSvc.UploadDocuments(c.Context(), commonSvc.DocumentUploadRequest{ + DocumentableType: "UNIFORMITY", + DocumentableID: uint64(createBody.Id), + CreatedBy: &actorIDCopy, + Files: []commonSvc.DocumentFile{ + { + File: file, + Type: "UNIFORMITY", + }, + }, + }) + if err != nil { + s.rollbackUniformityCreate(c.Context(), createBody.Id) + return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to upload uniformity document") + } + } + + return s.GetOne(c, createBody.Id) +} + +func (s uniformityService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint, file *multipart.FileHeader, rows []BodyWeightExcelRow) (*entity.ProjectFlockKandangUniformity, error) { + if err := s.Validate.Struct(req); err != nil { + return nil, err + } + + updateBody := make(map[string]any) + + if req.Date != nil { + parsed, err := time.Parse("2006-01-02", *req.Date) + if err != nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "date must be in YYYY-MM-DD format") + } + updateBody["uniform_date"] = parsed + } + if req.ProjectFlockKandangId != nil { + updateBody["project_flock_kandang_id"] = *req.ProjectFlockKandangId + } + if req.Week != nil { + updateBody["week"] = *req.Week + } + + if file != nil { + if s.DocumentSvc == nil { + return nil, fiber.NewError(fiber.StatusInternalServerError, "Document service not available") + } + + if len(rows) == 0 { + parsedRows, err := s.ParseBodyWeightExcel(c, file) + if err != nil { + return nil, err + } + rows = parsedRows + } + + calculation, err := s.ComputeUniformity(rows) + if err != nil { + return nil, err + } + + updateBody["uniformity"] = calculation.Uniformity + updateBody["cv"] = calculation.Cv + updateBody["chick_qty_of_weight"] = calculation.ChickQtyOfWeight + updateBody["mean_up"] = calculation.MeanUp + updateBody["mean_down"] = calculation.MeanDown + updateBody["uniform_qty"] = calculation.UniformQty + updateBody["not_uniform_qty"] = calculation.OutsideQty + } + + if len(updateBody) == 0 { + return s.GetOne(c, id) + } + + if file == nil { + if err := s.Repository.PatchOne(c.Context(), id, updateBody, nil); err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, fiber.NewError(fiber.StatusNotFound, "Uniformity not found") + } + s.Log.Errorf("Failed to update uniformity: %+v", err) + return nil, err + } + + return s.GetOne(c, id) + } + + existingDocs, err := s.DocumentSvc.ListByTarget(c.Context(), "UNIFORMITY", uint64(id)) + if err != nil { + return nil, err + } + + actorID, err := m.ActorIDFromContext(c) + if err != nil { + return nil, err + } + + actorIDCopy := actorID + uploadResults, err := s.DocumentSvc.UploadDocuments(c.Context(), commonSvc.DocumentUploadRequest{ + DocumentableType: "UNIFORMITY", + DocumentableID: uint64(id), + CreatedBy: &actorIDCopy, + Files: []commonSvc.DocumentFile{ + { + File: file, + Type: "UNIFORMITY", + }, + }, + }) + if err != nil { + return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to upload uniformity document") + } + + if err := s.Repository.PatchOne(c.Context(), id, updateBody, nil); err != nil { + if len(uploadResults) > 0 { + ids := make([]uint, 0, len(uploadResults)) + for _, result := range uploadResults { + if result.Document.Id != 0 { + ids = append(ids, result.Document.Id) + } + } + if len(ids) > 0 { + _ = s.DocumentSvc.DeleteDocuments(c.Context(), ids, true) + } + } + + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, fiber.NewError(fiber.StatusNotFound, "Uniformity not found") + } + s.Log.Errorf("Failed to update uniformity: %+v", err) + return nil, err + } + + if len(existingDocs) > 0 { + oldIDs := make([]uint, 0, len(existingDocs)) + for _, doc := range existingDocs { + if doc.Id != 0 { + oldIDs = append(oldIDs, doc.Id) + } + } + if len(oldIDs) > 0 { + _ = s.DocumentSvc.DeleteDocuments(c.Context(), oldIDs, true) + } + } + + return s.GetOne(c, id) +} + +func (s uniformityService) DeleteOne(c *fiber.Ctx, id uint) error { + if err := s.Repository.DeleteOne(c.Context(), id); err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return fiber.NewError(fiber.StatusNotFound, "Uniformity not found") + } + s.Log.Errorf("Failed to delete uniformity: %+v", err) + return err + } + return nil +} + +func (s uniformityService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlockKandangUniformity, error) { + if err := s.Validate.Struct(req); err != nil { + return nil, err + } + + actionValue := strings.ToUpper(strings.TrimSpace(req.Action)) + var action entity.ApprovalAction + switch actionValue { + case string(entity.ApprovalActionApproved): + action = entity.ApprovalActionApproved + case string(entity.ApprovalActionRejected): + action = entity.ApprovalActionRejected + default: + return nil, fiber.NewError(fiber.StatusBadRequest, "action must be APPROVED or REJECTED") + } + + ids := uniqueUintSlice(req.ApprovableIds) + if len(ids) == 0 { + return nil, fiber.NewError(fiber.StatusBadRequest, "approvable_ids must contain at least one id") + } + + step := utils.UniformityStepPengajuan + if action == entity.ApprovalActionApproved { + step = utils.UniformityStepDisetujui + } + + actorID, err := m.ActorIDFromContext(c) + if err != nil { + return nil, err + } + + ctx := c.Context() + transactionErr := s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { + repoTx := s.Repository.WithTx(tx) + approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(tx)) + + for _, id := range ids { + if _, err := repoTx.GetByID(ctx, id, nil); err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Uniformity %d not found", id)) + } + return err + } + + if _, err := approvalSvc.CreateApproval( + ctx, + utils.ApprovalWorkflowUniformity, + id, + step, + &action, + actorID, + req.Notes, + ); err != nil { + return err + } + } + + return nil + }) + if transactionErr != nil { + if fiberErr, ok := transactionErr.(*fiber.Error); ok { + return nil, fiberErr + } + s.Log.Errorf("Failed to record approvals for uniformities %+v: %+v", ids, transactionErr) + return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to submit uniformity approval") + } + + results := make([]entity.ProjectFlockKandangUniformity, 0, len(ids)) + for _, id := range ids { + loaded, err := s.GetOne(c, id) + if err != nil { + return nil, err + } + results = append(results, *loaded) + } + + return results, nil +} + +type UniformityDetailItem struct { + Id int + Weight float64 + Range string +} + +type UniformityCalculation struct { + ChickQtyOfWeight float64 + MeanWeight float64 + MeanDown float64 + MeanUp float64 + UniformQty float64 + OutsideQty float64 + Uniformity float64 + Cv float64 + Details []UniformityDetailItem +} + +func (s uniformityService) ComputeUniformity(rows []BodyWeightExcelRow) (UniformityCalculation, error) { + return computeUniformity(rows) +} + +func (s uniformityService) CalculateUniformityFromDocument(c *fiber.Ctx, uniformityID uint) (UniformityCalculation, *entity.Document, error) { + if s.DocumentSvc == nil { + return UniformityCalculation{}, nil, fiber.NewError(fiber.StatusInternalServerError, "Document service not available") + } + + documents, err := s.DocumentSvc.ListByTarget(c.Context(), "UNIFORMITY", uint64(uniformityID)) + if err != nil { + return UniformityCalculation{}, nil, err + } + if len(documents) == 0 { + return UniformityCalculation{}, nil, fiber.NewError(fiber.StatusNotFound, "Uniformity document not found") + } + + document := documents[0] + url := s.DocumentSvc.PublicURL(document) + if url == "" { + return UniformityCalculation{}, nil, fiber.NewError(fiber.StatusBadRequest, "Uniformity document URL not available") + } + + req, err := http.NewRequestWithContext(c.Context(), http.MethodGet, url, nil) + if err != nil { + return UniformityCalculation{}, nil, err + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return UniformityCalculation{}, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return UniformityCalculation{}, nil, fiber.NewError(fiber.StatusBadRequest, "Failed to download uniformity document") + } + + rows, err := parseBodyWeightExcelReader(resp.Body) + if err != nil { + return UniformityCalculation{}, nil, err + } + + calculation, err := computeUniformity(rows) + if err != nil { + return UniformityCalculation{}, nil, err + } + + return calculation, &document, nil +} + +func (s *uniformityService) createUniformityApproval( + ctx context.Context, + db *gorm.DB, + uniformityID uint, + step approvalutils.ApprovalStep, + action entity.ApprovalAction, + actorID uint, + notes *string, +) error { + if uniformityID == 0 { + return fiber.NewError(fiber.StatusBadRequest, "Uniformity tidak valid untuk approval") + } + if actorID == 0 { + return fiber.NewError(fiber.StatusBadRequest, "Actor Id tidak valid untuk approval") + } + + var svc commonSvc.ApprovalService + if db != nil { + svc = commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(db)) + } else if s.ApprovalSvc != nil { + svc = s.ApprovalSvc + } else { + svc = commonSvc.NewApprovalService(s.ApprovalRepo) + } + + _, err := svc.CreateApproval(ctx, utils.ApprovalWorkflowUniformity, uniformityID, step, &action, actorID, notes) + return err +} + +func (s *uniformityService) attachLatestApprovals(ctx context.Context, items []entity.ProjectFlockKandangUniformity) error { + if len(items) == 0 || s.ApprovalSvc == nil { + return nil + } + + ids := make([]uint, 0, len(items)) + visited := make(map[uint]struct{}, len(items)) + for _, item := range items { + if item.Id == 0 { + continue + } + if _, ok := visited[item.Id]; ok { + continue + } + visited[item.Id] = struct{}{} + ids = append(ids, item.Id) + } + + if len(ids) == 0 { + return nil + } + + latestMap, err := s.ApprovalSvc.LatestByTargets(ctx, utils.ApprovalWorkflowUniformity, ids, func(db *gorm.DB) *gorm.DB { + return db.Preload("ActionUser") + }) + if err != nil { + s.Log.Warnf("Unable to load latest approvals for uniformities: %+v", err) + return nil + } + + if len(latestMap) == 0 { + return nil + } + + for i := range items { + if items[i].Id == 0 { + continue + } + if approval, ok := latestMap[items[i].Id]; ok { + items[i].LatestApproval = approval + } + } + + return nil +} + +func (s *uniformityService) attachLatestApproval(ctx context.Context, item *entity.ProjectFlockKandangUniformity) error { + if item == nil || item.Id == 0 || s.ApprovalSvc == nil { + return nil + } + + approvals, err := s.ApprovalSvc.ListByTarget(ctx, utils.ApprovalWorkflowUniformity, item.Id, func(db *gorm.DB) *gorm.DB { + return db.Preload("ActionUser") + }) + if err != nil { + s.Log.Warnf("Unable to load approvals for uniformity %d: %+v", item.Id, err) + return nil + } + + if len(approvals) == 0 { + item.LatestApproval = nil + return nil + } + + latest := approvals[len(approvals)-1] + item.LatestApproval = &latest + return nil +} + +func (s *uniformityService) rollbackUniformityCreate(ctx context.Context, uniformityID uint) { + if uniformityID == 0 { + return + } + + if s.ApprovalRepo != nil { + if err := s.ApprovalRepo.DeleteByTarget(ctx, utils.ApprovalWorkflowUniformity.String(), uniformityID); err != nil { + s.Log.WithError(err).Warnf("Failed to rollback uniformity approvals for %d", uniformityID) + } + } + + if err := s.Repository.DeleteOne(ctx, uniformityID); err != nil { + s.Log.WithError(err).Warnf("Failed to rollback uniformity %d", uniformityID) + } +} + +func uniqueUintSlice(values []uint) []uint { + if len(values) == 0 { + return nil + } + + seen := make(map[uint]struct{}, len(values)) + result := make([]uint, 0, len(values)) + for _, v := range values { + if v == 0 { + continue + } + if _, ok := seen[v]; ok { + continue + } + seen[v] = struct{}{} + result = append(result, v) + } + return result +} + +func computeUniformity(rows []BodyWeightExcelRow) (UniformityCalculation, error) { + weights := make([]float64, 0, len(rows)) + details := make([]UniformityDetailItem, 0, len(rows)) + hasRangeLabels := false + for idx, row := range rows { + if row.Weight <= 0 { + continue + } + id := row.No + if id <= 0 { + id = idx + 1 + } + weights = append(weights, row.Weight) + rangeLabel := strings.TrimSpace(row.Range) + if rangeLabel != "" { + upper := strings.ToUpper(rangeLabel) + if upper == "HIGH" || upper == "LOW" { + hasRangeLabels = true + } + rangeLabel = upper + } + details = append(details, UniformityDetailItem{ + Id: id, + Weight: row.Weight, + Range: rangeLabel, + }) + } + + total := float64(len(weights)) + if total == 0 { + return UniformityCalculation{}, fiber.NewError(fiber.StatusBadRequest, "no body weight data found") + } + + var sum float64 + for _, w := range weights { + sum += w + } + mean := sum / total + meanUpThreshold := roundToPrecision(mean*1.10, 3) + meanDownThreshold := roundToPrecision(mean*0.90, 3) + + var uniformCount float64 + for i := range details { + if hasRangeLabels { + if details[i].Range == "HIGH" || details[i].Range == "LOW" { + details[i].Range = "Outside" + continue + } + details[i].Range = "Ideal" + uniformCount++ + continue + } + + w := details[i].Weight + if w > meanUpThreshold || w < meanDownThreshold { + details[i].Range = "Outside" + continue + } + details[i].Range = "Ideal" + uniformCount++ + } + outsideCount := total - uniformCount + + var cv float64 + if mean > 0 && total > 1 { + stddevWeights := weights + if len(stddevWeights) > 100 { + stddevWeights = stddevWeights[:100] + } + stddevCount := float64(len(stddevWeights)) + if stddevCount > 1 { + var stddevSum float64 + for _, w := range stddevWeights { + stddevSum += w + } + stddevMean := stddevSum / stddevCount + var sumSquares float64 + for _, w := range stddevWeights { + diff := w - stddevMean + sumSquares += diff * diff + } + stddev := math.Sqrt(sumSquares / (stddevCount - 1)) + cv = (stddev / mean) * 100 + } + } + + uniformity := (uniformCount / total) * 100 + + return UniformityCalculation{ + ChickQtyOfWeight: total, + MeanWeight: roundToPrecision(mean, 0), + MeanDown: roundToPrecision(mean*0.90, 0), + MeanUp: roundToPrecision(mean*1.10, 0), + UniformQty: uniformCount, + OutsideQty: outsideCount, + Uniformity: roundToPrecision(uniformity, 0), + Cv: roundToPrecision(cv, 1), + Details: details, + }, nil +} + +func roundToPrecision(value float64, precision int) float64 { + if precision < 0 { + return value + } + scale := math.Pow10(precision) + scaled := value * scale + fraction := scaled - math.Floor(scaled) + if fraction >= 0.5 { + return math.Ceil(scaled) / scale + } + return math.Floor(scaled) / scale +} diff --git a/internal/modules/production/uniformities/validations/uniformity.validation.go b/internal/modules/production/uniformities/validations/uniformity.validation.go new file mode 100644 index 00000000..d27ed287 --- /dev/null +++ b/internal/modules/production/uniformities/validations/uniformity.validation.go @@ -0,0 +1,173 @@ +package validation + +import ( + "mime/multipart" + "strconv" + "strings" + + "github.com/gofiber/fiber/v2" +) + +type Create struct { + Date string `form:"date" validate:"required"` + ProjectFlockKandangId uint `form:"project_flock_kandang_id" validate:"required,number,min=1"` + Week int `form:"week" validate:"required,min=1"` +} + +type Update struct { + Date *string `json:"date,omitempty" form:"date" validate:"omitempty"` + ProjectFlockKandangId *uint `json:"project_flock_kandang_id,omitempty" form:"project_flock_kandang_id" validate:"omitempty,number,min=1"` + Week *int `json:"week,omitempty" form:"week" validate:"omitempty,min=1"` +} + +type Query struct { + Page int `query:"page" validate:"omitempty,number,min=1,gt=0"` + Limit int `query:"limit" validate:"omitempty,number,min=1,max=100,gt=0"` + ProjectFlockKandangId uint `query:"project_flock_kandang_id" validate:"omitempty,number,min=1"` + Week int `query:"week" validate:"omitempty,min=1"` +} + +type UploadExcelRequest struct { + Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"` +} + +type Approve struct { + Action string `json:"action" validate:"required_strict"` + ApprovableIds []uint `json:"approvable_ids" validate:"required_strict,min=1,dive,gt=0"` + Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"` +} + +func ParseIDParam(c *fiber.Ctx, name string) (uint, error) { + raw := strings.TrimSpace(c.Params(name)) + if raw == "" { + return 0, fiber.NewError(fiber.StatusBadRequest, "Invalid Id") + } + id, err := strconv.Atoi(raw) + if err != nil || id <= 0 { + return 0, fiber.NewError(fiber.StatusBadRequest, "Invalid Id") + } + return uint(id), nil +} + +func ParseQuery(c *fiber.Ctx) (*Query, error) { + query := &Query{ + Page: c.QueryInt("page", 1), + Limit: c.QueryInt("limit", 10), + ProjectFlockKandangId: uint(c.QueryInt("project_flock_kandang_id", 0)), + Week: c.QueryInt("week", 0), + } + + if query.Page < 1 || query.Limit < 1 { + return nil, fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0") + } + + return query, nil +} + +func ParseCreate(c *fiber.Ctx) (*Create, *multipart.FileHeader, error) { + date := strings.TrimSpace(c.FormValue("date")) + if date == "" { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "date is required") + } + + projectFlockKandangIDStr := strings.TrimSpace(c.FormValue("project_flock_kandang_id")) + if projectFlockKandangIDStr == "" { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "project_flock_kandang_id is required") + } + + projectFlockKandangID, err := strconv.Atoi(projectFlockKandangIDStr) + if err != nil || projectFlockKandangID <= 0 { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "project_flock_kandang_id is required") + } + + weekStr := strings.TrimSpace(c.FormValue("week")) + if weekStr == "" { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "week is required") + } + + week, err := strconv.Atoi(weekStr) + if err != nil || week <= 0 { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "week is required") + } + + file, err := c.FormFile("document") + if err != nil { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "document is required") + } + + return &Create{ + Date: date, + ProjectFlockKandangId: uint(projectFlockKandangID), + Week: week, + }, file, nil +} + +func ParseUpdate(c *fiber.Ctx) (*Update, *multipart.FileHeader, error) { + contentType := strings.ToLower(c.Get("Content-Type")) + if strings.Contains(contentType, "multipart/form-data") { + req := &Update{} + + date := strings.TrimSpace(c.FormValue("date")) + if date != "" { + req.Date = &date + } + + projectFlockKandangIDStr := strings.TrimSpace(c.FormValue("project_flock_kandang_id")) + if projectFlockKandangIDStr != "" { + projectFlockKandangID, err := strconv.Atoi(projectFlockKandangIDStr) + if err != nil || projectFlockKandangID <= 0 { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "project_flock_kandang_id is invalid") + } + idCopy := uint(projectFlockKandangID) + req.ProjectFlockKandangId = &idCopy + } + + weekStr := strings.TrimSpace(c.FormValue("week")) + if weekStr != "" { + week, err := strconv.Atoi(weekStr) + if err != nil || week <= 0 { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "week is invalid") + } + req.Week = &week + } + + file, err := c.FormFile("document") + if err != nil { + file = nil + } + + return req, file, nil + } + + req := new(Update) + if err := c.BodyParser(req); err != nil { + return nil, nil, fiber.NewError(fiber.StatusBadRequest, "Invalid request body") + } + return req, nil, nil +} + +func ParseUploadFiles(c *fiber.Ctx) ([]*multipart.FileHeader, error) { + form, err := c.MultipartForm() + if err != nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid multipart form") + } + + files := form.File["documents"] + if len(files) == 0 { + if file, err := c.FormFile("document"); err == nil && file != nil { + files = []*multipart.FileHeader{file} + } else { + return nil, fiber.NewError(fiber.StatusBadRequest, "documents is required") + } + } + + return files, nil +} + +func ParseApprove(c *fiber.Ctx) (*Approve, error) { + req := new(Approve) + if err := c.BodyParser(req); err != nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid request body") + } + return req, nil +} diff --git a/internal/utils/constant.go b/internal/utils/constant.go index 354c9042..d003d996 100644 --- a/internal/utils/constant.go +++ b/internal/utils/constant.go @@ -250,6 +250,21 @@ var RecordingApprovalSteps = map[approvalutils.ApprovalStep]string{ RecordingStepDisetujui: "Disetujui", } +// ------------------------------------------------------------------- +// Uniformity Approval +// ------------------------------------------------------------------- + +const ( + ApprovalWorkflowUniformity approvalutils.ApprovalWorkflowKey = approvalutils.ApprovalWorkflowKey("UNIFORMITIES") + UniformityStepPengajuan approvalutils.ApprovalStep = 1 + UniformityStepDisetujui approvalutils.ApprovalStep = 2 +) + +var UniformityApprovalSteps = map[approvalutils.ApprovalStep]string{ + UniformityStepPengajuan: "Pengajuan", + UniformityStepDisetujui: "Disetujui", +} + // ------------------------------------------------------------------- // Purchase Approval // ------------------------------------------------------------------- @@ -324,12 +339,12 @@ type DocumentType string type DocumentableType string const ( - DocumentTypeTransfer DocumentType = "STOCK_TRANSFER_DOCUMENT" - DocumentTypeExpense DocumentType = "EXPENSE_DOCUMENT" + DocumentTypeTransfer DocumentType = "STOCK_TRANSFER_DOCUMENT" + DocumentTypeExpense DocumentType = "EXPENSE_DOCUMENT" DocumentTypeExpenseRealization DocumentType = "EXPENSE_REALIZATION_DOCUMENT" - DocumentableTypeTransfer DocumentableType = "STOCK_TRANSFER" - DocumentableTypeExpense DocumentableType = "EXPENSE" + DocumentableTypeTransfer DocumentableType = "STOCK_TRANSFER" + DocumentableTypeExpense DocumentableType = "EXPENSE" DocumentableTypeExpenseRealization DocumentableType = "EXPENSE_REALIZATION" ) From 8dfb2246142d6fa745063e179fb4b9e22f2301a0 Mon Sep 17 00:00:00 2001 From: ragilap Date: Mon, 29 Dec 2025 10:13:29 +0700 Subject: [PATCH 02/12] feat(BE-281): changes std deviasi first 100 data to all --- .../production/uniformities/services/uniformity.service.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/modules/production/uniformities/services/uniformity.service.go b/internal/modules/production/uniformities/services/uniformity.service.go index 786d3662..871f4816 100644 --- a/internal/modules/production/uniformities/services/uniformity.service.go +++ b/internal/modules/production/uniformities/services/uniformity.service.go @@ -689,9 +689,6 @@ func computeUniformity(rows []BodyWeightExcelRow) (UniformityCalculation, error) var cv float64 if mean > 0 && total > 1 { stddevWeights := weights - if len(stddevWeights) > 100 { - stddevWeights = stddevWeights[:100] - } stddevCount := float64(len(stddevWeights)) if stddevCount > 1 { var stddevSum float64 From a2066979c1af83b9ed1c244e4ab1f569c2fe24cd Mon Sep 17 00:00:00 2001 From: ragilap Date: Mon, 29 Dec 2025 19:04:10 +0700 Subject: [PATCH 03/12] feat(BE-281): adjustment uniformity for make unique for week,projectflockandang, and date --- .../modules/production/uniformities/module.go | 4 +- .../services/uniformity.service.go | 101 +++++++++++++++--- 2 files changed, 92 insertions(+), 13 deletions(-) diff --git a/internal/modules/production/uniformities/module.go b/internal/modules/production/uniformities/module.go index 1032cdcf..27a73fbc 100644 --- a/internal/modules/production/uniformities/module.go +++ b/internal/modules/production/uniformities/module.go @@ -10,6 +10,7 @@ import ( commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" + rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" rUniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/repositories" sUniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/services" @@ -24,6 +25,7 @@ func (UniformityModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validat uniformityRepo := rUniformity.NewUniformityRepository(db) documentRepo := commonRepo.NewDocumentRepository(db) approvalRepo := commonRepo.NewApprovalRepository(db) + projectFlockKandangRepo := rProjectFlock.NewProjectFlockKandangRepository(db) userRepo := rUser.NewUserRepository(db) documentSvc, err := commonSvc.NewDocumentServiceFromConfig(context.Background(), documentRepo) @@ -36,7 +38,7 @@ func (UniformityModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validat panic(fmt.Sprintf("failed to register uniformity approval workflow: %v", err)) } - uniformityService := sUniformity.NewUniformityService(uniformityRepo, documentSvc, approvalRepo, approvalSvc, validate) + uniformityService := sUniformity.NewUniformityService(uniformityRepo, documentSvc, approvalRepo, approvalSvc, projectFlockKandangRepo, validate) userService := sUser.NewUserService(userRepo, validate) UniformityRoutes(router, userService, uniformityService) diff --git a/internal/modules/production/uniformities/services/uniformity.service.go b/internal/modules/production/uniformities/services/uniformity.service.go index 871f4816..6f8ba6ac 100644 --- a/internal/modules/production/uniformities/services/uniformity.service.go +++ b/internal/modules/production/uniformities/services/uniformity.service.go @@ -14,6 +14,7 @@ import ( commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" m "gitlab.com/mbugroup/lti-api.git/internal/middleware" + rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/repositories" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/validations" "gitlab.com/mbugroup/lti-api.git/internal/utils" @@ -39,12 +40,13 @@ type UniformityService interface { } type uniformityService struct { - Log *logrus.Logger - Validate *validator.Validate - Repository repository.UniformityRepository - DocumentSvc commonSvc.DocumentService - ApprovalRepo commonRepo.ApprovalRepository - ApprovalSvc commonSvc.ApprovalService + Log *logrus.Logger + Validate *validator.Validate + Repository repository.UniformityRepository + DocumentSvc commonSvc.DocumentService + ApprovalRepo commonRepo.ApprovalRepository + ApprovalSvc commonSvc.ApprovalService + ProjectFlockKandangRepo rProjectFlock.ProjectFlockKandangRepository } func NewUniformityService( @@ -52,15 +54,17 @@ func NewUniformityService( documentSvc commonSvc.DocumentService, approvalRepo commonRepo.ApprovalRepository, approvalSvc commonSvc.ApprovalService, + projectFlockKandangRepo rProjectFlock.ProjectFlockKandangRepository, validate *validator.Validate, ) UniformityService { return &uniformityService{ - Log: utils.Log, - Validate: validate, - Repository: repo, - DocumentSvc: documentSvc, - ApprovalRepo: approvalRepo, - ApprovalSvc: approvalSvc, + Log: utils.Log, + Validate: validate, + Repository: repo, + DocumentSvc: documentSvc, + ApprovalRepo: approvalRepo, + ApprovalSvc: approvalSvc, + ProjectFlockKandangRepo: projectFlockKandangRepo, } } @@ -121,6 +125,9 @@ func (s *uniformityService) CreateOne(c *fiber.Ctx, req *validation.Create, file if err := s.Validate.Struct(req); err != nil { return nil, err } + if s.ProjectFlockKandangRepo == nil { + return nil, fiber.NewError(fiber.StatusInternalServerError, "Project flock kandang repository not available") + } if file == nil { return nil, fiber.NewError(fiber.StatusBadRequest, "document is required") @@ -131,6 +138,16 @@ func (s *uniformityService) CreateOne(c *fiber.Ctx, req *validation.Create, file return nil, fiber.NewError(fiber.StatusBadRequest, "date must be in YYYY-MM-DD format") } + if err := commonSvc.EnsureRelations( + c.Context(), + commonSvc.RelationCheck{Name: "Project Flock Kandang", ID: &req.ProjectFlockKandangId, Exists: s.ProjectFlockKandangRepo.IdExists}, + ); err != nil { + return nil, err + } + if err := s.ensureUniqueUniformity(c.Context(), 0, req.ProjectFlockKandangId, req.Week, &uniformDate); err != nil { + return nil, err + } + if len(rows) == 0 { parsedRows, err := s.ParseBodyWeightExcel(c, file) if err != nil { @@ -212,6 +229,7 @@ func (s uniformityService) UpdateOne(c *fiber.Ctx, req *validation.Update, id ui } updateBody := make(map[string]any) + var uniformDate *time.Time if req.Date != nil { parsed, err := time.Parse("2006-01-02", *req.Date) @@ -219,14 +237,51 @@ func (s uniformityService) UpdateOne(c *fiber.Ctx, req *validation.Update, id ui return nil, fiber.NewError(fiber.StatusBadRequest, "date must be in YYYY-MM-DD format") } updateBody["uniform_date"] = parsed + uniformDate = &parsed } if req.ProjectFlockKandangId != nil { + if s.ProjectFlockKandangRepo == nil { + return nil, fiber.NewError(fiber.StatusInternalServerError, "Project flock kandang repository not available") + } + if err := commonSvc.EnsureRelations( + c.Context(), + commonSvc.RelationCheck{Name: "Project Flock Kandang", ID: req.ProjectFlockKandangId, Exists: s.ProjectFlockKandangRepo.IdExists}, + ); err != nil { + return nil, err + } updateBody["project_flock_kandang_id"] = *req.ProjectFlockKandangId } if req.Week != nil { updateBody["week"] = *req.Week } + if req.Date != nil || req.ProjectFlockKandangId != nil || req.Week != nil { + current, err := s.Repository.GetByID(c.Context(), id, nil) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, fiber.NewError(fiber.StatusNotFound, "Uniformity not found") + } + return nil, err + } + targetDate := uniformDate + if targetDate == nil { + targetDate = current.UniformDate + } + targetWeek := current.Week + if req.Week != nil { + targetWeek = *req.Week + } + targetPFKID := current.ProjectFlockKandangId + if req.ProjectFlockKandangId != nil { + targetPFKID = *req.ProjectFlockKandangId + } + if targetDate != nil { + if err := s.ensureUniqueUniformity(c.Context(), id, targetPFKID, targetWeek, targetDate); err != nil { + return nil, err + } + } + } + if file != nil { if s.DocumentSvc == nil { return nil, fiber.NewError(fiber.StatusInternalServerError, "Document service not available") @@ -331,6 +386,28 @@ func (s uniformityService) UpdateOne(c *fiber.Ctx, req *validation.Update, id ui return s.GetOne(c, id) } +func (s *uniformityService) ensureUniqueUniformity(ctx context.Context, id uint, projectFlockKandangID uint, week int, uniformDate *time.Time) error { + if projectFlockKandangID == 0 || week == 0 || uniformDate == nil || uniformDate.IsZero() { + return nil + } + + query := s.Repository.DB().WithContext(ctx). + Model(&entity.ProjectFlockKandangUniformity{}). + Where("project_flock_kandang_id = ? AND week = ? AND uniform_date = ?", projectFlockKandangID, week, *uniformDate) + if id != 0 { + query = query.Where("id <> ?", id) + } + + var count int64 + if err := query.Count(&count).Error; err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Failed to validate uniformity uniqueness") + } + if count > 0 { + return fiber.NewError(fiber.StatusConflict, "Uniformity already exists for the same project flock kandang, week, and date") + } + return nil +} + func (s uniformityService) DeleteOne(c *fiber.Ctx, id uint) error { if err := s.Repository.DeleteOne(c.Context(), id); err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { From 6523290aaf44f62ed1875dbb219120e3377ce066 Mon Sep 17 00:00:00 2001 From: ragilap Date: Mon, 29 Dec 2025 19:44:10 +0700 Subject: [PATCH 04/12] feat(BE-281): change template excel --- Tamplate-Uniformity.xlsx | Bin 0 -> 123855 bytes .../services/uniformity.body_weight_excel.go | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Tamplate-Uniformity.xlsx diff --git a/Tamplate-Uniformity.xlsx b/Tamplate-Uniformity.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..bb24c303ef9e441d65d7ae1ee72a9286ecf9dbf7 GIT binary patch literal 123855 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

beG<&g&;kXK%L9Vc0Dk;fl@6ib6O3_j{FYs1F# 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 literal 0 HcmV?d00001 diff --git a/internal/modules/production/uniformities/services/uniformity.body_weight_excel.go b/internal/modules/production/uniformities/services/uniformity.body_weight_excel.go index 97155a3b..4e87f0cc 100644 --- a/internal/modules/production/uniformities/services/uniformity.body_weight_excel.go +++ b/internal/modules/production/uniformities/services/uniformity.body_weight_excel.go @@ -49,7 +49,12 @@ func parseBodyWeightExcelReader(reader io.Reader) ([]BodyWeightExcelRow, error) return nil, fiber.NewError(fiber.StatusBadRequest, "no sheets found in file") } - rows, err := xlsx.GetRows(sheets[0], excelize.Options{RawCellValue: true}) + sheetName := sheets[0] + if len(sheets) > 1 { + sheetName = sheets[1] + } + + rows, err := xlsx.GetRows(sheetName, excelize.Options{RawCellValue: true}) if err != nil { return nil, fiber.NewError(fiber.StatusBadRequest, "failed to read sheet rows") } From 9a094b8bfed3ee3a0644dcca6d3f7ccb02a04fd8 Mon Sep 17 00:00:00 2001 From: ragilap Date: Tue, 30 Dec 2025 09:56:48 +0700 Subject: [PATCH 05/12] feat(BE-281):fix document payload --- .../validations/uniformity.validation.go | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/internal/modules/production/uniformities/validations/uniformity.validation.go b/internal/modules/production/uniformities/validations/uniformity.validation.go index d27ed287..b2aeaf26 100644 --- a/internal/modules/production/uniformities/validations/uniformity.validation.go +++ b/internal/modules/production/uniformities/validations/uniformity.validation.go @@ -147,21 +147,12 @@ func ParseUpdate(c *fiber.Ctx) (*Update, *multipart.FileHeader, error) { } func ParseUploadFiles(c *fiber.Ctx) ([]*multipart.FileHeader, error) { - form, err := c.MultipartForm() - if err != nil { - return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid multipart form") + file, err := c.FormFile("document") + if err != nil || file == nil { + return nil, fiber.NewError(fiber.StatusBadRequest, "document is required") } - files := form.File["documents"] - if len(files) == 0 { - if file, err := c.FormFile("document"); err == nil && file != nil { - files = []*multipart.FileHeader{file} - } else { - return nil, fiber.NewError(fiber.StatusBadRequest, "documents is required") - } - } - - return files, nil + return []*multipart.FileHeader{file}, nil } func ParseApprove(c *fiber.Ctx) (*Approve, error) { From 90125ffe1a2717f95ea368be019b88fe2da06b89 Mon Sep 17 00:00:00 2001 From: ragilap Date: Tue, 30 Dec 2025 12:07:28 +0700 Subject: [PATCH 06/12] feat(BE-281):add dto standart mean bw and uniformity --- .../controllers/uniformity.controller.go | 56 +++++- .../uniformities/dto/uniformity.dto.go | 28 +++ .../modules/production/uniformities/module.go | 14 +- .../services/uniformity.service.go | 175 ++++++++++++++++-- 4 files changed, 253 insertions(+), 20 deletions(-) diff --git a/internal/modules/production/uniformities/controllers/uniformity.controller.go b/internal/modules/production/uniformities/controllers/uniformity.controller.go index b6874ba4..12cc3739 100644 --- a/internal/modules/production/uniformities/controllers/uniformity.controller.go +++ b/internal/modules/production/uniformities/controllers/uniformity.controller.go @@ -32,6 +32,10 @@ func (u *UniformityController) GetAll(c *fiber.Ctx) error { if err != nil { return err } + standards, err := u.UniformityService.MapStandards(c, result) + if err != nil { + return err + } return c.Status(fiber.StatusOK). JSON(response.SuccessWithPaginate[dto.UniformityListDTO]{ @@ -49,7 +53,7 @@ func (u *UniformityController) GetAll(c *fiber.Ctx) error { "status": "Pengajuan", }, }, - Data: dto.ToUniformityListDTOs(result), + Data: dto.ToUniformityListDTOsWithStandard(result, standards), }) } @@ -90,12 +94,24 @@ func (u *UniformityController) GetOne(c *fiber.Ctx) error { } } + standard, err := u.UniformityService.GetStandard(c, result) + if err != nil { + return err + } + var standardDTO *dto.UniformityStandardDTO + if standard != nil { + standardDTO = &dto.UniformityStandardDTO{ + MeanWeight: standard.MeanWeight, + Uniformity: standard.Uniformity, + } + } + return c.Status(fiber.StatusOK). JSON(response.Success{ Code: fiber.StatusOK, Status: "success", Message: "Get production uniformity successfully", - Data: dto.ToUniformityDetailDTO(*result, calculation, document), + Data: dto.ToUniformityDetailDTO(*result, calculation, document, standardDTO), }) } @@ -121,13 +137,24 @@ func (u *UniformityController) CreateOne(c *fiber.Ctx) error { } document := dto.NewDocumentForResponse(file.Filename) + standard, err := u.UniformityService.GetStandard(c, result) + if err != nil { + return err + } + var standardDTO *dto.UniformityStandardDTO + if standard != nil { + standardDTO = &dto.UniformityStandardDTO{ + MeanWeight: standard.MeanWeight, + Uniformity: standard.Uniformity, + } + } return c.Status(fiber.StatusCreated). JSON(response.Success{ Code: fiber.StatusCreated, Status: "success", Message: "Create uniformity successfully", - Data: dto.ToUniformityDetailDTO(*result, calculation, document), + Data: dto.ToUniformityDetailDTO(*result, calculation, document, standardDTO), }) } @@ -181,17 +208,36 @@ func (u *UniformityController) UpdateOne(c *fiber.Ctx) error { return err } - calculation, document, err := u.UniformityService.CalculateUniformityFromDocument(c, id) + standard, err := u.UniformityService.GetStandard(c, result) if err != nil { return err } + var standardDTO *dto.UniformityStandardDTO + if standard != nil { + standardDTO = &dto.UniformityStandardDTO{ + MeanWeight: standard.MeanWeight, + Uniformity: standard.Uniformity, + } + } + + calculation := service.UniformityCalculation{ + ChickQtyOfWeight: result.ChickQtyOfWeight, + MeanWeight: math.Round(result.MeanUp / 1.10), + MeanDown: result.MeanDown, + MeanUp: result.MeanUp, + UniformQty: result.UniformQty, + OutsideQty: result.NotUniformQty, + Uniformity: result.Uniformity, + Cv: result.Cv, + } + var document *entity.Document return c.Status(fiber.StatusOK). JSON(response.Success{ Code: fiber.StatusOK, Status: "success", Message: "Update uniformity successfully", - Data: dto.ToUniformityDetailDTO(*result, calculation, document), + Data: dto.ToUniformityDetailDTO(*result, calculation, document, standardDTO), }) } diff --git a/internal/modules/production/uniformities/dto/uniformity.dto.go b/internal/modules/production/uniformities/dto/uniformity.dto.go index 1c9f4c4d..1324d805 100644 --- a/internal/modules/production/uniformities/dto/uniformity.dto.go +++ b/internal/modules/production/uniformities/dto/uniformity.dto.go @@ -22,6 +22,11 @@ type UniformityResultDTO struct { Cv float64 `json:"cv"` } +type UniformityStandardDTO struct { + MeanWeight *float64 `json:"mean_weight"` + Uniformity *float64 `json:"uniformity"` +} + type UniformityDetailItemDTO struct { Id int `json:"id"` Weight float64 `json:"weight"` @@ -47,6 +52,7 @@ type UniformityDetailDTO struct { InfoUmum UniformityInfoDTO `json:"info_umum"` Sampling UniformitySamplingDTO `json:"sampling"` Result UniformityResultDTO `json:"result"` + Standard *UniformityStandardDTO `json:"standard"` UniformityDetails []UniformityDetailItemDTO `json:"uniformity_details"` } @@ -65,6 +71,8 @@ type UniformityListDTO struct { UniformQty float64 `json:"uniform_qty"` MeanUp float64 `json:"mean_up"` MeanDown float64 `json:"mean_down"` + StandardMeanWeight *float64 `json:"standard_mean_weight"` + StandardUniformity *float64 `json:"standard_uniformity"` CreatedAt time.Time `json:"created_at"` CreatedBy uint `json:"created_by"` LatestApproval *approvalDTO.ApprovalRelationDTO `json:"latest_approval"` @@ -89,6 +97,7 @@ func ToUniformityDetailDTO( entityData entity.ProjectFlockKandangUniformity, calc service.UniformityCalculation, document *entity.Document, + standard *UniformityStandardDTO, ) UniformityDetailDTO { info := UniformityInfoDTO{ Tanggal: formatUniformityDate(entityData.UniformDate), @@ -106,6 +115,7 @@ func ToUniformityDetailDTO( InfoUmum: info, Sampling: toUniformitySamplingDTO(calc), Result: toUniformityResultDTO(calc), + Standard: standard, UniformityDetails: toUniformityDetailItemsDTO(calc), } } @@ -146,6 +156,24 @@ func ToUniformityListDTOs(items []entity.ProjectFlockKandangUniformity) []Unifor return result } +func ToUniformityListDTOsWithStandard( + items []entity.ProjectFlockKandangUniformity, + standards map[uint]service.UniformityStandard, +) []UniformityListDTO { + result := ToUniformityListDTOs(items) + if len(result) == 0 || len(standards) == 0 { + return result + } + + for i := range result { + if std, ok := standards[result[i].Id]; ok { + result[i].StandardMeanWeight = std.MeanWeight + result[i].StandardUniformity = std.Uniformity + } + } + return result +} + func toUniformitySamplingDTO(calc service.UniformityCalculation) UniformitySamplingDTO { return UniformitySamplingDTO{ ChickQtyOfWeight: calc.ChickQtyOfWeight, diff --git a/internal/modules/production/uniformities/module.go b/internal/modules/production/uniformities/module.go index 27a73fbc..b3162940 100644 --- a/internal/modules/production/uniformities/module.go +++ b/internal/modules/production/uniformities/module.go @@ -10,6 +10,7 @@ import ( commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" + rProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/repositories" rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" rUniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/repositories" sUniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/services" @@ -26,6 +27,8 @@ func (UniformityModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validat documentRepo := commonRepo.NewDocumentRepository(db) approvalRepo := commonRepo.NewApprovalRepository(db) projectFlockKandangRepo := rProjectFlock.NewProjectFlockKandangRepository(db) + productionStandardRepo := rProductionStandard.NewProductionStandardRepository(db) + standardGrowthDetailRepo := rProductionStandard.NewStandardGrowthDetailRepository(db) userRepo := rUser.NewUserRepository(db) documentSvc, err := commonSvc.NewDocumentServiceFromConfig(context.Background(), documentRepo) @@ -38,7 +41,16 @@ func (UniformityModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validat panic(fmt.Sprintf("failed to register uniformity approval workflow: %v", err)) } - uniformityService := sUniformity.NewUniformityService(uniformityRepo, documentSvc, approvalRepo, approvalSvc, projectFlockKandangRepo, validate) + uniformityService := sUniformity.NewUniformityService( + uniformityRepo, + documentSvc, + approvalRepo, + approvalSvc, + projectFlockKandangRepo, + productionStandardRepo, + standardGrowthDetailRepo, + validate, + ) userService := sUser.NewUserService(userRepo, validate) UniformityRoutes(router, userService, uniformityService) diff --git a/internal/modules/production/uniformities/services/uniformity.service.go b/internal/modules/production/uniformities/services/uniformity.service.go index 6f8ba6ac..2e76e48f 100644 --- a/internal/modules/production/uniformities/services/uniformity.service.go +++ b/internal/modules/production/uniformities/services/uniformity.service.go @@ -14,6 +14,7 @@ import ( commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" m "gitlab.com/mbugroup/lti-api.git/internal/middleware" + rProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/repositories" rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/repositories" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/validations" @@ -30,6 +31,8 @@ type UniformityService interface { GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlockKandangUniformity, int64, error) GetOne(ctx *fiber.Ctx, id uint) (*entity.ProjectFlockKandangUniformity, error) GetSummary(ctx *fiber.Ctx, id uint) (*entity.ProjectFlockKandangUniformity, error) + GetStandard(ctx *fiber.Ctx, uniformity *entity.ProjectFlockKandangUniformity) (*UniformityStandard, error) + MapStandards(ctx *fiber.Ctx, items []entity.ProjectFlockKandangUniformity) (map[uint]UniformityStandard, error) CreateOne(ctx *fiber.Ctx, req *validation.Create, file *multipart.FileHeader, rows []BodyWeightExcelRow) (*entity.ProjectFlockKandangUniformity, error) UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint, file *multipart.FileHeader, rows []BodyWeightExcelRow) (*entity.ProjectFlockKandangUniformity, error) DeleteOne(ctx *fiber.Ctx, id uint) error @@ -40,13 +43,15 @@ type UniformityService interface { } type uniformityService struct { - Log *logrus.Logger - Validate *validator.Validate - Repository repository.UniformityRepository - DocumentSvc commonSvc.DocumentService - ApprovalRepo commonRepo.ApprovalRepository - ApprovalSvc commonSvc.ApprovalService - ProjectFlockKandangRepo rProjectFlock.ProjectFlockKandangRepository + Log *logrus.Logger + Validate *validator.Validate + Repository repository.UniformityRepository + DocumentSvc commonSvc.DocumentService + ApprovalRepo commonRepo.ApprovalRepository + ApprovalSvc commonSvc.ApprovalService + ProjectFlockKandangRepo rProjectFlock.ProjectFlockKandangRepository + ProductionStandardRepo rProductionStandard.ProductionStandardRepository + StandardGrowthDetailRepo rProductionStandard.StandardGrowthDetailRepository } func NewUniformityService( @@ -55,16 +60,20 @@ func NewUniformityService( approvalRepo commonRepo.ApprovalRepository, approvalSvc commonSvc.ApprovalService, projectFlockKandangRepo rProjectFlock.ProjectFlockKandangRepository, + productionStandardRepo rProductionStandard.ProductionStandardRepository, + standardGrowthDetailRepo rProductionStandard.StandardGrowthDetailRepository, validate *validator.Validate, ) UniformityService { return &uniformityService{ - Log: utils.Log, - Validate: validate, - Repository: repo, - DocumentSvc: documentSvc, - ApprovalRepo: approvalRepo, - ApprovalSvc: approvalSvc, - ProjectFlockKandangRepo: projectFlockKandangRepo, + Log: utils.Log, + Validate: validate, + Repository: repo, + DocumentSvc: documentSvc, + ApprovalRepo: approvalRepo, + ApprovalSvc: approvalSvc, + ProjectFlockKandangRepo: projectFlockKandangRepo, + ProductionStandardRepo: productionStandardRepo, + StandardGrowthDetailRepo: standardGrowthDetailRepo, } } @@ -121,6 +130,64 @@ func (s uniformityService) GetSummary(c *fiber.Ctx, id uint) (*entity.ProjectFlo return s.GetOne(c, id) } +func (s uniformityService) GetStandard(c *fiber.Ctx, uniformity *entity.ProjectFlockKandangUniformity) (*UniformityStandard, error) { + if uniformity == nil { + return nil, nil + } + return s.resolveUniformityStandard(c.Context(), *uniformity) +} + +func (s uniformityService) MapStandards(c *fiber.Ctx, items []entity.ProjectFlockKandangUniformity) (map[uint]UniformityStandard, error) { + if len(items) == 0 { + return nil, nil + } + if s.ProductionStandardRepo == nil || s.StandardGrowthDetailRepo == nil { + return nil, nil + } + + categoryStandard := make(map[string]*entity.ProductionStandard) + detailCache := make(map[uint]map[int]entity.StandardGrowthDetail) + result := make(map[uint]UniformityStandard, len(items)) + + for _, item := range items { + if item.Id == 0 { + continue + } + standard, err := s.resolveCategoryStandard(c.Context(), item.ProjectFlockKandang.ProjectFlock.Category, categoryStandard) + if err != nil { + return nil, err + } + if standard == nil { + continue + } + + weekMap, ok := detailCache[standard.Id] + if !ok { + details, err := s.StandardGrowthDetailRepo.GetByProductionStandardID(c.Context(), standard.Id) + if err != nil { + return nil, err + } + weekMap = make(map[int]entity.StandardGrowthDetail, len(details)) + for _, detail := range details { + weekMap[detail.Week] = detail + } + detailCache[standard.Id] = weekMap + } + + detail, ok := weekMap[item.Week] + if !ok { + continue + } + standardDTO := UniformityStandard{ + MeanWeight: cloneFloat64(detail.TargetMeanBw), + Uniformity: float64Ptr(detail.MinUniformity), + } + result[item.Id] = standardDTO + } + + return result, nil +} + func (s *uniformityService) CreateOne(c *fiber.Ctx, req *validation.Create, file *multipart.FileHeader, rows []BodyWeightExcelRow) (*entity.ProjectFlockKandangUniformity, error) { if err := s.Validate.Struct(req); err != nil { return nil, err @@ -516,6 +583,11 @@ type UniformityCalculation struct { Details []UniformityDetailItem } +type UniformityStandard struct { + MeanWeight *float64 + Uniformity *float64 +} + func (s uniformityService) ComputeUniformity(rows []BodyWeightExcelRow) (UniformityCalculation, error) { return computeUniformity(rows) } @@ -664,6 +736,81 @@ func (s *uniformityService) attachLatestApproval(ctx context.Context, item *enti return nil } +func (s *uniformityService) resolveUniformityStandard(ctx context.Context, item entity.ProjectFlockKandangUniformity) (*UniformityStandard, error) { + if s.ProductionStandardRepo == nil || s.StandardGrowthDetailRepo == nil { + return nil, nil + } + + standard, err := s.resolveCategoryStandard(ctx, item.ProjectFlockKandang.ProjectFlock.Category, nil) + if err != nil || standard == nil { + return nil, err + } + + detail, err := s.StandardGrowthDetailRepo.GetByStandardIDAndWeek(ctx, standard.Id, item.Week) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + + return &UniformityStandard{ + MeanWeight: cloneFloat64(detail.TargetMeanBw), + Uniformity: float64Ptr(detail.MinUniformity), + }, nil +} + +func (s *uniformityService) resolveCategoryStandard( + ctx context.Context, + category string, + cache map[string]*entity.ProductionStandard, +) (*entity.ProductionStandard, error) { + category = strings.TrimSpace(category) + if category == "" { + return nil, nil + } + if cache != nil { + if cached, ok := cache[category]; ok { + return cached, nil + } + } + + var standard entity.ProductionStandard + err := s.ProductionStandardRepo.DB().WithContext(ctx). + Where("project_category = ?", category). + Where("deleted_at IS NULL"). + Order("created_at DESC"). + First(&standard).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + if cache != nil { + cache[category] = nil + } + return nil, nil + } + return nil, err + } + + standardCopy := standard + if cache != nil { + cache[category] = &standardCopy + } + return &standardCopy, nil +} + +func cloneFloat64(value *float64) *float64 { + if value == nil { + return nil + } + copy := *value + return © +} + +func float64Ptr(value float64) *float64 { + copy := value + return © +} + func (s *uniformityService) rollbackUniformityCreate(ctx context.Context, uniformityID uint) { if uniformityID == 0 { return From 0c776e83328f1e7dc630282af3fd15ee7af4c71b Mon Sep 17 00:00:00 2001 From: ragilap Date: Tue, 30 Dec 2025 12:08:49 +0700 Subject: [PATCH 07/12] feat(BE-281): uncoment auth --- Tamplate-Uniformity.xlsx | Bin 123855 -> 0 bytes internal/middleware/auth.go | 11 +++++------ 2 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 Tamplate-Uniformity.xlsx diff --git a/Tamplate-Uniformity.xlsx b/Tamplate-Uniformity.xlsx deleted file mode 100644 index bb24c303ef9e441d65d7ae1ee72a9286ecf9dbf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123855 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

beG<&g&;kXK%L9Vc0Dk;fl@6ib6O3_j{FYs1F# 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 diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index a08d431b..a831c25b 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -104,12 +104,11 @@ func AuthenticatedUser(c *fiber.Ctx) (*entity.User, bool) { } func ActorIDFromContext(c *fiber.Ctx) (uint, error) { - // user, ok := AuthenticatedUser(c) - // if !ok || user == nil || user.Id == 0 { - // return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") - // } - // return user.Id, nil - return 1, nil + user, ok := AuthenticatedUser(c) + if !ok || user == nil || user.Id == 0 { + return 0, fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") + } + return user.Id, nil } // AuthDetails returns the full authentication context (token, claims, user). From 4e5caa8cbafa5bc32c48b0bd17a3e3061008f526 Mon Sep 17 00:00:00 2001 From: ragilap Date: Tue, 30 Dec 2025 15:23:34 +0700 Subject: [PATCH 08/12] feat(BE-281): add rbac for uniformity --- internal/middleware/permissions.go | 10 ++++++++ .../modules/production/uniformities/route.go | 23 ++++++++----------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/internal/middleware/permissions.go b/internal/middleware/permissions.go index d384fee7..32ee5ecb 100644 --- a/internal/middleware/permissions.go +++ b/internal/middleware/permissions.go @@ -193,6 +193,16 @@ const ( P_PurchaseApprovalManager = "lti.Purchase.approve.manager" ) +const ( + P_Uniformities_GetAll = "lti.production.uniformity.list" + P_Uniformities_GetOne = "lti.production.uniformity.detail" + P_Uniformities_Verify = "lti.production.uniformity.verify" + P_Uniformities_CreateOne = "lti.production.uniformity.create" + P_Uniformities_UpdateOne = "lti.production.uniformity.update" + P_Uniformities_DeleteOne = "lti.production.uniformity.delete" + P_Uniformities_Approval = "lti.production.uniformity.approve" +) + const ( P_UserGetAll = "lti.users.list" P_UserGetOne = "lti.users.detail" diff --git a/internal/modules/production/uniformities/route.go b/internal/modules/production/uniformities/route.go index d22e8761..ff2b1805 100644 --- a/internal/modules/production/uniformities/route.go +++ b/internal/modules/production/uniformities/route.go @@ -1,7 +1,7 @@ package uniformitys 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/production/uniformities/controllers" uniformity "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" @@ -13,18 +13,13 @@ func UniformityRoutes(v1 fiber.Router, u user.UserService, s uniformity.Uniformi ctrl := controller.NewUniformityController(s) route := v1.Group("/uniformities") + route.Use(m.Auth(u)) - // route.Get("/", m.Auth(u), ctrl.GetAll) - // route.Post("/", m.Auth(u), ctrl.CreateOne) - // route.Get("/:id", m.Auth(u), ctrl.GetOne) - // route.Patch("/:id", m.Auth(u), ctrl.UpdateOne) - // route.Delete("/:id", m.Auth(u), ctrl.DeleteOne) - - route.Get("/", ctrl.GetAll) - route.Post("/", ctrl.CreateOne) - route.Post("/verify", ctrl.UploadBodyWeightExcel) - route.Post("/approvals", ctrl.Approve) - route.Get("/:id", ctrl.GetOne) - route.Patch("/:id", ctrl.UpdateOne) - route.Delete("/:id", ctrl.DeleteOne) + route.Get("/", m.RequirePermissions(m.P_Uniformities_GetAll), ctrl.GetAll) + route.Post("/", m.RequirePermissions(m.P_Uniformities_CreateOne), ctrl.CreateOne) + route.Post("/verify", m.RequirePermissions(m.P_Uniformities_Verify), ctrl.UploadBodyWeightExcel) + route.Post("/approvals", m.RequirePermissions(m.P_Uniformities_Approval), ctrl.Approve) + route.Get("/:id", m.RequirePermissions(m.P_Uniformities_GetOne), ctrl.GetOne) + route.Patch("/:id", m.RequirePermissions(m.P_Uniformities_UpdateOne), ctrl.UpdateOne) + route.Delete("/:id", m.RequirePermissions(m.P_Uniformities_DeleteOne), ctrl.DeleteOne) } From 78359db88052fed61c658dedf290143a196923ce Mon Sep 17 00:00:00 2001 From: "Hafizh A. Y" Date: Tue, 30 Dec 2025 23:52:37 +0700 Subject: [PATCH 09/12] fix: setup seeder for development --- internal/database/seed/seeder.backup | 1047 ++++++++++++++++++++++++++ internal/database/seed/seeder.go | 873 ++++----------------- 2 files changed, 1186 insertions(+), 734 deletions(-) create mode 100644 internal/database/seed/seeder.backup diff --git a/internal/database/seed/seeder.backup b/internal/database/seed/seeder.backup new file mode 100644 index 00000000..c0e3628c --- /dev/null +++ b/internal/database/seed/seeder.backup @@ -0,0 +1,1047 @@ +// package seed + +// import ( +// "errors" +// "fmt" +// "strings" +// "time" + +// entity "gitlab.com/mbugroup/lti-api.git/internal/entities" +// "gitlab.com/mbugroup/lti-api.git/internal/utils" + +// "gorm.io/gorm" +// ) + +// func Run(db *gorm.DB) error { +// return db.Transaction(func(tx *gorm.DB) error { +// users, err := seedUsers(tx) +// if err != nil { +// return err +// } +// adminID := users["admin"] + +// uoms, err := seedUoms(tx, adminID) +// if err != nil { +// return err +// } + +// areas, err := seedAreas(tx, adminID) +// if err != nil { +// return err +// } + +// locations, err := seedLocations(tx, adminID, areas) +// if err != nil { +// return err +// } + +// productCategories, err := seedProductCategories(tx, adminID) +// if err != nil { +// return err +// } + +// if _, err := seedFlocks(tx, adminID); err != nil { +// return err +// } + +// if _, err := seedFcr(tx, adminID); err != nil { +// return err +// } + +// kandangs, err := seedKandangs(tx, adminID, locations, users) +// if err != nil { +// return err +// } + +// if err := seedWarehouses(tx, adminID, areas, locations, kandangs); err != nil { +// return err +// } + +// suppliers, err := seedSuppliers(tx, adminID) +// if err != nil { +// return err +// } + +// if err := seedCustomers(tx, adminID, users); err != nil { +// return err +// } + +// if err := seedProducts(tx, adminID, uoms, productCategories, suppliers); err != nil { +// return err +// } + +// if err := seedNonstocks(tx, adminID, uoms, suppliers); err != nil { +// return err +// } + +// if err := seedBanks(tx, adminID); err != nil { +// return err +// } + +// if err := seedProductWarehouse(tx, adminID); err != nil { +// return err +// } + +// if err := seedTransferStock(tx); err != nil { +// return err +// } +// fmt.Println("✅ Master data seeding completed") +// return nil +// }) +// } + +// func seedUsers(tx *gorm.DB) (map[string]uint, error) { +// seeds := []struct { +// Key string +// Data entity.User +// }{ +// { +// Key: "admin", +// Data: entity.User{Email: "admin@mbugroup.id", IdUser: 1, Name: "Super Admin"}, +// }, +// } + +// result := make(map[string]uint, len(seeds)) + +// for _, seed := range seeds { +// var user entity.User +// err := tx.Where("email = ?", seed.Data.Email).First(&user).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// user = seed.Data +// if err := tx.Create(&user).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } +// result[seed.Key] = user.Id +// } + +// return result, nil +// } + +// func seedUoms(tx *gorm.DB, createdBy uint) (map[string]uint, error) { +// names := []string{"Kilogram", "Gram", "Liter", "Unit", "Ekor"} +// result := make(map[string]uint, len(names)) + +// for _, name := range names { +// var uom entity.Uom +// err := tx.Where("name = ?", name).First(&uom).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// uom = entity.Uom{Name: name, CreatedBy: createdBy} +// if err := tx.Create(&uom).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } +// result[name] = uom.Id +// } + +// return result, nil +// } + +// func seedAreas(tx *gorm.DB, createdBy uint) (map[string]uint, error) { +// names := []string{"Priangan", "Banten"} +// result := make(map[string]uint, len(names)) + +// for _, name := range names { +// var area entity.Area +// err := tx.Where("name = ?", name).First(&area).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// area = entity.Area{Name: name, CreatedBy: createdBy} +// if err := tx.Create(&area).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } +// result[name] = area.Id +// } + +// return result, nil +// } + +// func seedLocations(tx *gorm.DB, createdBy uint, areas map[string]uint) (map[string]uint, error) { +// seeds := []struct { +// Name string +// Address string +// Area string +// }{ +// {"Singaparna", "Tasik", "Priangan"}, +// {"Cikaum", "Cikaum", "Banten"}, +// } + +// result := make(map[string]uint, len(seeds)) + +// for _, seed := range seeds { +// areaID, ok := areas[seed.Area] +// if !ok { +// return nil, fmt.Errorf("area %s not seeded", seed.Area) +// } + +// var loc entity.Location +// err := tx.Where("name = ?", seed.Name).First(&loc).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// loc = entity.Location{ +// Name: seed.Name, +// Address: seed.Address, +// AreaId: areaID, +// CreatedBy: createdBy, +// } +// if err := tx.Create(&loc).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } +// result[seed.Name] = loc.Id +// } + +// return result, nil +// } + +// func seedFlocks(tx *gorm.DB, createdBy uint) (map[string]uint, error) { +// names := []string{"Flock Priangan", "Flock Banten"} +// result := make(map[string]uint, len(names)) + +// for _, name := range names { +// var flock entity.Flock +// err := tx.Where("name = ?", name).First(&flock).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// flock = entity.Flock{ +// Name: name, +// CreatedBy: createdBy, +// } +// if err := tx.Create(&flock).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } else { +// if err := tx.Model(&entity.Flock{}).Where("id = ?", flock.Id).Updates(map[string]any{ +// "created_by": createdBy, +// }).Error; err != nil { +// return nil, err +// } +// } +// result[name] = flock.Id +// } + +// return result, nil +// } + +// func seedKandangs(tx *gorm.DB, createdBy uint, locations map[string]uint, users map[string]uint) (map[string]uint, error) { +// seeds := []struct { +// Name string +// Status utils.KandangStatus +// Capacity float64 +// Location string +// PicKey string +// }{ +// {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)) + +// for _, seed := range seeds { +// locID, ok := locations[seed.Location] +// if !ok { +// return nil, fmt.Errorf("location %s not seeded", seed.Location) +// } +// picID, ok := users[seed.PicKey] +// if !ok { +// return nil, fmt.Errorf("user %s not seeded", seed.PicKey) +// } + +// var kandang entity.Kandang +// err := tx.Where("name = ?", seed.Name).First(&kandang).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// kandang = entity.Kandang{ +// Name: seed.Name, +// Status: string(seed.Status), +// LocationId: locID, +// PicId: picID, +// CreatedBy: createdBy, +// } +// if err := tx.Create(&kandang).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } else { +// updates := map[string]any{ +// "location_id": locID, +// "pic_id": picID, +// "status": string(seed.Status), +// } +// if err := tx.Model(&entity.Kandang{}).Where("id = ?", kandang.Id).Updates(updates).Error; err != nil { +// return nil, err +// } +// } +// result[seed.Name] = kandang.Id +// } + +// return result, nil +// } + +// func seedWarehouses(tx *gorm.DB, createdBy uint, areas map[string]uint, locations map[string]uint, kandangs map[string]uint) error { +// seeds := []struct { +// Name string +// Type string +// Area string +// Location *string +// Kandang *string +// }{ +// {Name: "Gudang Priangan", Type: string(utils.WarehouseTypeArea), Area: "Priangan"}, +// {Name: "Gudang Singaparna", Type: string(utils.WarehouseTypeLokasi), Area: "Priangan", Location: strPtr("Singaparna")}, +// {Name: "Gudang Singaparna 1", Type: string(utils.WarehouseTypeKandang), Area: "Priangan", Location: strPtr("Singaparna"), Kandang: strPtr("Singaparna 1")}, +// {Name: "Gudang Singaparna 2", Type: string(utils.WarehouseTypeKandang), Area: "Priangan", Location: strPtr("Singaparna"), Kandang: strPtr("Singaparna 2")}, +// {Name: "Gudang Banten", Type: string(utils.WarehouseTypeArea), Area: "Banten"}, +// {Name: "Gudang Cikaum", Type: string(utils.WarehouseTypeLokasi), Area: "Banten", Location: strPtr("Cikaum")}, +// {Name: "Gudang Cikaum 1", Type: string(utils.WarehouseTypeKandang), Area: "Banten", Location: strPtr("Cikaum"), Kandang: strPtr("Cikaum 1")}, +// {Name: "Gudang Cikaum 2", Type: string(utils.WarehouseTypeKandang), Area: "Banten", Location: strPtr("Cikaum"), Kandang: strPtr("Cikaum 2")}, +// } + +// for _, seed := range seeds { +// areaID, ok := areas[seed.Area] +// if !ok { +// return fmt.Errorf("area %s not seeded", seed.Area) +// } + +// var warehouse entity.Warehouse +// err := tx.Where("name = ?", seed.Name).First(&warehouse).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// warehouse = entity.Warehouse{ +// Name: seed.Name, +// Type: seed.Type, +// AreaId: areaID, +// CreatedBy: createdBy, +// } +// } else if err != nil { +// return err +// } + +// if seed.Location != nil { +// locID, ok := locations[*seed.Location] +// if !ok { +// return fmt.Errorf("location %s not seeded", *seed.Location) +// } +// warehouse.LocationId = uintPtr(locID) +// } +// if seed.Kandang != nil { +// kandangID, ok := kandangs[*seed.Kandang] +// if !ok { +// return fmt.Errorf("kandang %s not seeded", *seed.Kandang) +// } +// warehouse.KandangId = uintPtr(kandangID) +// } + +// if warehouse.Id == 0 { +// if err := tx.Create(&warehouse).Error; err != nil { +// return err +// } +// } else { +// if err := tx.Model(&entity.Warehouse{}).Where("id = ?", warehouse.Id).Updates(map[string]any{ +// "type": warehouse.Type, +// "area_id": warehouse.AreaId, +// "location_id": warehouse.LocationId, +// "kandang_id": warehouse.KandangId, +// }).Error; err != nil { +// return err +// } +// } +// } + +// return nil +// } + +// func seedProductCategories(tx *gorm.DB, createdBy uint) (map[string]uint, error) { +// seeds := []struct { +// Name string +// Code string +// }{ +// {"Pullet", "PLT"}, +// {"Bahan Baku", "RAW"}, +// {"Day Old Chick", "DOC"}, +// {"Telur", "EGG"}, +// } + +// result := make(map[string]uint, len(seeds)) + +// for _, seed := range seeds { +// var category entity.ProductCategory +// err := tx.Where("name = ?", seed.Name).First(&category).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// category = entity.ProductCategory{Name: seed.Name, Code: seed.Code, CreatedBy: createdBy} +// if err := tx.Create(&category).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } else { +// if err := tx.Model(&entity.ProductCategory{}).Where("id = ?", category.Id).Updates(map[string]any{ +// "code": seed.Code, +// }).Error; err != nil { +// return nil, err +// } +// } +// result[seed.Name] = category.Id +// } + +// return result, nil +// } + +// func seedSuppliers(tx *gorm.DB, createdBy uint) (map[string]uint, error) { +// seeds := []struct { +// Name string +// Alias string +// Category string +// Email string +// Phone string +// Address string +// }{ +// {"PT CHAROEN POKPHAND INDONESIA Tbk", "CPI", string(utils.SupplierCategorySapronak), "cpi@gmail.com", "081200000001", "Jl. Pakan 1, Bekasi"}, +// {"BOP Vendor", "BOP", string(utils.SupplierCategoryBOP), "bop@gmail.com", "081200000002", "Jl. Veteriner 3, Bogor"}, +// {"Ekspedisi", "EKS", string(utils.SupplierCategoryBOP), "bop@gmail.com", "081200000002", "Jl. Veteriner 3, Bogor"}, +// } + +// result := make(map[string]uint, len(seeds)) + +// for idx, seed := range seeds { +// var supplier entity.Supplier +// err := tx.Where("name = ?", seed.Name).First(&supplier).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// supplier = entity.Supplier{ +// Name: seed.Name, +// Alias: seed.Alias, +// Pic: "John Doe", +// Type: string(utils.CustomerSupplierTypeBisnis), +// Category: seed.Category, +// Phone: seed.Phone, +// Email: seed.Email, +// Address: seed.Address, +// DueDate: 30, +// CreatedBy: createdBy, +// AccountNumber: strPtr(fmt.Sprintf("%03d", idx+1)), +// } +// if err := tx.Create(&supplier).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } +// result[seed.Name] = supplier.Id +// } + +// return result, nil +// } + +// func seedCustomers(tx *gorm.DB, createdBy uint, users map[string]uint) error { +// seeds := []struct { +// Name string +// PicKey string +// Address string +// Phone string +// Email string +// }{ +// {"Abdul Azis", "admin", "Jl. Raya Utama 1, Bekasi", "082100000001", "abdul.azis@gmail.com"}, +// } + +// for idx, seed := range seeds { +// picID, ok := users[seed.PicKey] +// if !ok { +// return fmt.Errorf("user %s not seeded", seed.PicKey) +// } + +// var customer entity.Customer +// err := tx.Where("name = ?", seed.Name).First(&customer).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// customer = entity.Customer{ +// Name: seed.Name, +// PicId: picID, +// Type: string(utils.CustomerSupplierTypeBisnis), +// Address: seed.Address, +// Phone: seed.Phone, +// Email: seed.Email, +// AccountNumber: *strPtr(fmt.Sprintf("%03d", idx+1)), +// CreatedBy: createdBy, +// } +// if err := tx.Create(&customer).Error; err != nil { +// return err +// } +// } else if err != nil { +// return err +// } +// } + +// return nil +// } + +// func seedFcr(tx *gorm.DB, createdBy uint) (map[string]uint, error) { +// seeds := []struct { +// Name string +// Standards []struct { +// Weight float64 +// FcrNumber float64 +// Mortality float64 +// } +// }{ +// { +// Name: "FCR Layer", +// Standards: []struct { +// Weight float64 +// FcrNumber float64 +// Mortality float64 +// }{ +// {Weight: 0.8, FcrNumber: 1.60, Mortality: 2.0}, +// {Weight: 1.5, FcrNumber: 1.75, Mortality: 3.5}, +// }, +// }, +// } + +// result := make(map[string]uint, len(seeds)) + +// for _, seed := range seeds { +// var fcr entity.Fcr +// err := tx.Where("name = ?", seed.Name).First(&fcr).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// fcr = entity.Fcr{Name: seed.Name, CreatedBy: createdBy} +// if err := tx.Create(&fcr).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } +// result[seed.Name] = fcr.Id + +// for _, std := range seed.Standards { +// var standard entity.FcrStandard +// err := tx.Where("fcr_id = ? AND weight = ?", fcr.Id, std.Weight).First(&standard).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// standard = entity.FcrStandard{ +// FcrID: fcr.Id, +// Weight: std.Weight, +// FcrNumber: std.FcrNumber, +// Mortality: std.Mortality, +// } +// if err := tx.Create(&standard).Error; err != nil { +// return nil, err +// } +// } else if err != nil { +// return nil, err +// } else { +// if err := tx.Model(&entity.FcrStandard{}).Where("id = ?", standard.Id).Updates(map[string]any{ +// "fcr_number": std.FcrNumber, +// "mortality": std.Mortality, +// }).Error; err != nil { +// return nil, err +// } +// } +// } +// } + +// return result, nil +// } + +// func seedProducts(tx *gorm.DB, createdBy uint, uoms map[string]uint, categories map[string]uint, suppliers map[string]uint) error { +// seeds := []struct { +// Name string +// Brand string +// Sku string +// Uom string +// Category string +// Price float64 +// Selling *float64 +// Tax *float64 +// Expiry *int +// Suppliers []string +// Flags []utils.FlagType +// }{ +// { +// Name: "DOC Broiler", +// Brand: "MBU Broiler", +// Sku: "BRO0001", +// Uom: "Ekor", +// Category: "Day Old Chick", +// Price: 7500, +// Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, +// Flags: []utils.FlagType{utils.FlagDOC}, +// }, +// { +// Name: "Ayam Pullet", +// Brand: "MBU Pullet", +// Sku: "PLT0001", +// Uom: "Ekor", +// Category: "Pullet", +// Price: 15000, +// Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, +// Flags: []utils.FlagType{utils.FlagPullet}, +// }, +// { +// Name: "Ayam Afkir", +// Brand: "-", +// Sku: "1", +// Uom: "Ekor", +// Category: "Day Old Chick", +// Price: 1, +// Flags: []utils.FlagType{utils.FlagAyamAfkir}, +// }, +// { +// Name: "Ayam Mati", +// Brand: "-", +// Sku: "2", +// Uom: "Ekor", +// Category: "Day Old Chick", +// Price: 1, +// Flags: []utils.FlagType{utils.FlagAyamMati}, +// }, +// { +// Name: "Ayam Culling", +// Brand: "-", +// Sku: "3", +// Uom: "Ekor", +// Category: "Day Old Chick", +// Price: 1, +// Flags: []utils.FlagType{utils.FlagAyamCulling}, +// }, +// { +// Name: "Telur Konsumsi Baik", +// Brand: "-", +// Sku: "4", +// Uom: "Unit", +// Category: "Telur", +// Price: 1, +// Flags: []utils.FlagType{utils.FlagTelurUtuh}, +// }, +// { +// Name: "Telur Pecah", +// Brand: "-", +// Sku: "5", +// Uom: "Unit", +// Category: "Telur", +// Price: 1, +// Flags: []utils.FlagType{utils.FlagTelurPecah}, +// }, +// { +// Name: "281 SPECIAL STARTER", +// Brand: "281 STARTER", +// Sku: "281", +// Uom: "Kilogram", +// Category: "Bahan Baku", +// Price: 7850, +// Expiry: intPtr(60), +// Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, +// Flags: []utils.FlagType{utils.FlagPakan, utils.FlagStarter}, +// }, +// { +// Name: "Ayam Layer", +// Brand: "-", +// Sku: "LYR0001", +// Uom: "Ekor", +// Category: "Pullet", +// Price: 20000, +// Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, +// Flags: []utils.FlagType{utils.FlagLayer}, +// }, +// } + +// for _, seed := range seeds { +// uomID, ok := uoms[seed.Uom] +// if !ok { +// return fmt.Errorf("uom %s not seeded", seed.Uom) +// } +// categoryID, ok := categories[seed.Category] +// if !ok { +// return fmt.Errorf("product category %s not seeded", seed.Category) +// } + +// var product entity.Product +// err := tx.Where("name = ?", seed.Name).First(&product).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// selling := seed.Selling +// tax := seed.Tax +// product = entity.Product{ +// Name: seed.Name, +// Brand: seed.Brand, +// Sku: &seed.Sku, +// UomId: uomID, +// ProductCategoryId: categoryID, +// ProductPrice: seed.Price, +// SellingPrice: selling, +// Tax: tax, +// ExpiryPeriod: seed.Expiry, +// CreatedBy: createdBy, +// } +// if err := tx.Create(&product).Error; err != nil { +// return err +// } +// } else if err != nil { +// return err +// } else { +// updates := map[string]any{ +// "brand": seed.Brand, +// "uom_id": uomID, +// "product_category_id": categoryID, +// "product_price": seed.Price, +// "selling_price": seed.Selling, +// "tax": seed.Tax, +// "expiry_period": seed.Expiry, +// } +// if seed.Sku != "" { +// updates["sku"] = seed.Sku +// } +// if err := tx.Model(&entity.Product{}).Where("id = ?", product.Id).Updates(updates).Error; err != nil { +// return err +// } +// } + +// for _, supplierName := range seed.Suppliers { +// supplierID, ok := suppliers[supplierName] +// if !ok { +// return fmt.Errorf("supplier %s not seeded", supplierName) +// } +// var existing entity.ProductSupplier +// err := tx.Where("product_id = ? AND supplier_id = ?", product.Id, supplierID).First(&existing).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// link := entity.ProductSupplier{ProductId: product.Id, SupplierId: supplierID} +// if err := tx.Create(&link).Error; err != nil { +// return err +// } +// } else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { +// return err +// } +// } + +// if err := seedFlags(tx, product.Id, entity.FlagableTypeProduct, seed.Flags); err != nil { +// return err +// } +// } + +// return nil +// } + +// func seedNonstocks(tx *gorm.DB, createdBy uint, uoms map[string]uint, suppliers map[string]uint) error { +// seeds := []struct { +// Name string +// Uom string +// Suppliers []string +// Flags []utils.FlagType +// }{ +// { +// Name: "Expedisi DOC", +// Uom: "Ekor", +// Suppliers: []string{"Ekspedisi"}, +// Flags: []utils.FlagType{utils.FlagEkspedisi}, +// }, +// { +// Name: "Solar", +// Uom: "Liter", +// Suppliers: []string{"BOP Vendor"}, +// Flags: []utils.FlagType{}, +// }, +// } + +// for _, seed := range seeds { +// uomID, ok := uoms[seed.Uom] +// if !ok { +// return fmt.Errorf("uom %s not seeded", seed.Uom) +// } + +// var nonstock entity.Nonstock +// err := tx.Where("name = ?", seed.Name).First(&nonstock).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// nonstock = entity.Nonstock{ +// Name: seed.Name, +// UomId: uomID, +// CreatedBy: createdBy, +// } +// if err := tx.Create(&nonstock).Error; err != nil { +// return err +// } +// } else if err != nil { +// return err +// } else { +// if err := tx.Model(&entity.Nonstock{}).Where("id = ?", nonstock.Id).Updates(map[string]any{ +// "uom_id": uomID, +// }).Error; err != nil { +// return err +// } +// } + +// for _, supplierName := range seed.Suppliers { +// supplierID, ok := suppliers[supplierName] +// if !ok { +// return fmt.Errorf("supplier %s not seeded", supplierName) +// } +// var existing entity.NonstockSupplier +// err := tx.Where("nonstock_id = ? AND supplier_id = ?", nonstock.Id, supplierID).First(&existing).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// link := entity.NonstockSupplier{NonstockId: nonstock.Id, SupplierId: supplierID} +// if err := tx.Create(&link).Error; err != nil { +// return err +// } +// } else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { +// return err +// } +// } + +// if err := seedFlags(tx, nonstock.Id, entity.FlagableTypeNonstock, seed.Flags); err != nil { +// return err +// } +// } + +// return nil +// } + +// // nanti saya isi + +// func seedFlags(tx *gorm.DB, flagableID uint, flagableType string, flags []utils.FlagType) error { +// if len(flags) == 0 { +// return nil +// } +// for _, flag := range flags { +// name := strings.ToUpper(string(flag)) +// var existing entity.Flag +// err := tx.Where("name = ? AND flagable_id = ? AND flagable_type = ?", name, flagableID, flagableType).First(&existing).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// record := entity.Flag{ +// Name: name, +// FlagableID: flagableID, +// FlagableType: flagableType, +// } +// if err := tx.Create(&record).Error; err != nil { +// return err +// } +// } else if err != nil { +// return err +// } +// } +// return nil +// } + +// func seedBanks(tx *gorm.DB, createdBy uint) error { +// seeds := []struct { +// Name string +// Alias string +// Owner *string +// AccountNumber string +// }{ +// { +// Name: "Bank Central Asia", +// Alias: "BCA", +// AccountNumber: "1234567890", +// Owner: ptr("PT MBU Group"), +// }, +// { +// Name: "Bank Rakyat Indonesia", +// Alias: "BRI", +// AccountNumber: "9876543210", +// Owner: ptr("PT MBU Group"), +// }, +// { +// Name: "Bank Mandiri", +// Alias: "MAND", +// AccountNumber: "1122334455", +// Owner: ptr("PT MBU Group"), +// }, +// } + +// for _, seed := range seeds { +// var bank entity.Bank +// err := tx.Where("name = ?", seed.Name).First(&bank).Error + +// if errors.Is(err, gorm.ErrRecordNotFound) { +// bank = entity.Bank{ +// Name: seed.Name, +// Alias: seed.Alias, +// Owner: seed.Owner, +// AccountNumber: seed.AccountNumber, +// CreatedBy: createdBy, +// CreatedAt: time.Now(), +// UpdatedAt: time.Now(), +// } +// if err := tx.Create(&bank).Error; err != nil { +// return err +// } +// } else if err != nil { +// return err +// } else { +// // update data jika sudah ada +// if err := tx.Model(&entity.Bank{}).Where("id = ?", bank.Id).Updates(map[string]any{ +// "alias": seed.Alias, +// "owner": seed.Owner, +// "account_number": seed.AccountNumber, +// "updated_at": time.Now(), +// }).Error; err != nil { +// return err +// } +// } +// } + +// return nil +// } + +// func seedProductWarehouse(tx *gorm.DB, createdBy uint) error { +// seeds := []struct { +// ProductName string +// WarehouseName string +// Quantity float64 +// }{ +// {ProductName: "DOC Broiler", WarehouseName: "Gudang Priangan", Quantity: 0}, +// {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Singaparna", Quantity: 0}, +// {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Banten", Quantity: 0}, +// {ProductName: "DOC Broiler", WarehouseName: "Gudang Singaparna 1", Quantity: 0}, +// {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Singaparna 1", Quantity: 0}, +// {ProductName: "Telur Pecah", WarehouseName: "Gudang Singaparna 1", Quantity: 0}, +// {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Cikaum 1", Quantity: 0}, +// {ProductName: "Telur Pecah", WarehouseName: "Gudang Cikaum 1", Quantity: 0}, +// } + +// for _, seed := range seeds { +// var product entity.Product +// if err := tx.Where("name = ?", seed.ProductName).First(&product).Error; err != nil { +// if errors.Is(err, gorm.ErrRecordNotFound) { +// return fmt.Errorf("product %q not found for product warehouse seeding", seed.ProductName) +// } +// return err +// } + +// var warehouse entity.Warehouse +// if err := tx.Where("name = ?", seed.WarehouseName).First(&warehouse).Error; err != nil { +// if errors.Is(err, gorm.ErrRecordNotFound) { +// return fmt.Errorf("warehouse %q not found for product warehouse seeding", seed.WarehouseName) +// } +// return err +// } + +// var productWarehouse entity.ProductWarehouse +// err := tx.Where("product_id = ? AND warehouse_id = ?", product.Id, warehouse.Id).First(&productWarehouse).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// productWarehouse = entity.ProductWarehouse{ +// ProductId: product.Id, +// WarehouseId: warehouse.Id, +// Quantity: seed.Quantity, +// // CreatedBy: createdBy, +// } +// if err := tx.Create(&productWarehouse).Error; err != nil { +// return err +// } +// } else if err != nil { +// return err +// } else { +// if err := tx.Model(&productWarehouse).Updates(map[string]any{ +// "quantity": seed.Quantity, +// }).Error; err != nil { +// return err +// } +// } +// } + +// return nil +// } + +// func seedTransferStock(tx *gorm.DB) error { + +// transfer := entity.StockTransfer{ +// FromWarehouseId: 1, +// ToWarehouseId: 2, +// Reason: "Seed transfer stock", +// TransferDate: time.Now(), +// MovementNumber: "SEED-TRF-00001", +// CreatedBy: 1, +// } +// if err := tx.Create(&transfer).Error; err != nil { +// return err +// } + +// details := []entity.StockTransferDetail{ +// { +// StockTransferId: transfer.Id, +// ProductId: 1, + +// 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, +// ProductId: 2, + +// 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 { +// if err := tx.Create(&details[i]).Error; err != nil { +// return err +// } +// } + +// deliveries := []entity.StockTransferDelivery{ +// { +// StockTransferId: transfer.Id, +// SupplierId: 1, +// VehiclePlate: "B 1234 XYZ", +// DriverName: "Driver Seed", +// DocumentPath: "seed.pdf", +// ShippingCostItem: 1000, +// ShippingCostTotal: 2000, +// }, +// } +// for i := range deliveries { +// if err := tx.Create(&deliveries[i]).Error; err != nil { +// return err +// } +// } + +// detailMap := make(map[uint64]uint64) +// for _, d := range details { +// detailMap[d.ProductId] = d.Id +// } + +// deliveryItems := []entity.StockTransferDeliveryItem{ +// { +// StockTransferDeliveryId: deliveries[0].Id, +// StockTransferDetailId: detailMap[1], +// Quantity: 50, +// }, +// { +// StockTransferDeliveryId: deliveries[0].Id, +// StockTransferDetailId: detailMap[2], +// Quantity: 30, +// }, +// } +// for i := range deliveryItems { +// if err := tx.Create(&deliveryItems[i]).Error; err != nil { +// return err +// } +// } + +// return nil +// } +// func ptr[T any](v T) *T { +// return &v +// } + +// func strPtr(s string) *string { +// return &s +// } + +// func intPtr(v int) *int { +// return &v +// } + +// func uintPtr(v uint) *uint { +// return &v +// } diff --git a/internal/database/seed/seeder.go b/internal/database/seed/seeder.go index 26c3f6e8..b4f6886e 100644 --- a/internal/database/seed/seeder.go +++ b/internal/database/seed/seeder.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "strings" - "time" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/utils" @@ -25,66 +24,20 @@ func Run(db *gorm.DB) error { return err } - areas, err := seedAreas(tx, adminID) - if err != nil { - return err - } - - locations, err := seedLocations(tx, adminID, areas) - if err != nil { - return err - } - productCategories, err := seedProductCategories(tx, adminID) if err != nil { return err } - if _, err := seedFlocks(tx, adminID); err != nil { - return err - } - - if _, err := seedFcr(tx, adminID); err != nil { - return err - } - - kandangs, err := seedKandangs(tx, adminID, locations, users) - if err != nil { - return err - } - - if err := seedWarehouses(tx, adminID, areas, locations, kandangs); err != nil { - return err - } - suppliers, err := seedSuppliers(tx, adminID) if err != nil { return err } - if err := seedCustomers(tx, adminID, users); err != nil { - return err - } - if err := seedProducts(tx, adminID, uoms, productCategories, suppliers); err != nil { return err } - if err := seedNonstocks(tx, adminID, uoms, suppliers); err != nil { - return err - } - - if err := seedBanks(tx, adminID); err != nil { - return err - } - - if err := seedProductWarehouse(tx, adminID); err != nil { - return err - } - - if err := seedTransferStock(tx); err != nil { - return err - } fmt.Println("✅ Master data seeding completed") return nil }) @@ -141,224 +94,6 @@ func seedUoms(tx *gorm.DB, createdBy uint) (map[string]uint, error) { return result, nil } -func seedAreas(tx *gorm.DB, createdBy uint) (map[string]uint, error) { - names := []string{"Priangan", "Banten"} - result := make(map[string]uint, len(names)) - - for _, name := range names { - var area entity.Area - err := tx.Where("name = ?", name).First(&area).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - area = entity.Area{Name: name, CreatedBy: createdBy} - if err := tx.Create(&area).Error; err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } - result[name] = area.Id - } - - return result, nil -} - -func seedLocations(tx *gorm.DB, createdBy uint, areas map[string]uint) (map[string]uint, error) { - seeds := []struct { - Name string - Address string - Area string - }{ - {"Singaparna", "Tasik", "Priangan"}, - {"Cikaum", "Cikaum", "Banten"}, - } - - result := make(map[string]uint, len(seeds)) - - for _, seed := range seeds { - areaID, ok := areas[seed.Area] - if !ok { - return nil, fmt.Errorf("area %s not seeded", seed.Area) - } - - var loc entity.Location - err := tx.Where("name = ?", seed.Name).First(&loc).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - loc = entity.Location{ - Name: seed.Name, - Address: seed.Address, - AreaId: areaID, - CreatedBy: createdBy, - } - if err := tx.Create(&loc).Error; err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } - result[seed.Name] = loc.Id - } - - return result, nil -} - -func seedFlocks(tx *gorm.DB, createdBy uint) (map[string]uint, error) { - names := []string{"Flock Priangan", "Flock Banten"} - result := make(map[string]uint, len(names)) - - for _, name := range names { - var flock entity.Flock - err := tx.Where("name = ?", name).First(&flock).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - flock = entity.Flock{ - Name: name, - CreatedBy: createdBy, - } - if err := tx.Create(&flock).Error; err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } else { - if err := tx.Model(&entity.Flock{}).Where("id = ?", flock.Id).Updates(map[string]any{ - "created_by": createdBy, - }).Error; err != nil { - return nil, err - } - } - result[name] = flock.Id - } - - return result, nil -} - -func seedKandangs(tx *gorm.DB, createdBy uint, locations map[string]uint, users map[string]uint) (map[string]uint, error) { - seeds := []struct { - Name string - Status utils.KandangStatus - Capacity float64 - Location string - PicKey string - }{ - {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)) - - for _, seed := range seeds { - locID, ok := locations[seed.Location] - if !ok { - return nil, fmt.Errorf("location %s not seeded", seed.Location) - } - picID, ok := users[seed.PicKey] - if !ok { - return nil, fmt.Errorf("user %s not seeded", seed.PicKey) - } - - var kandang entity.Kandang - err := tx.Where("name = ?", seed.Name).First(&kandang).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - kandang = entity.Kandang{ - Name: seed.Name, - Status: string(seed.Status), - LocationId: locID, - PicId: picID, - CreatedBy: createdBy, - } - if err := tx.Create(&kandang).Error; err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } else { - updates := map[string]any{ - "location_id": locID, - "pic_id": picID, - "status": string(seed.Status), - } - if err := tx.Model(&entity.Kandang{}).Where("id = ?", kandang.Id).Updates(updates).Error; err != nil { - return nil, err - } - } - result[seed.Name] = kandang.Id - } - - return result, nil -} - -func seedWarehouses(tx *gorm.DB, createdBy uint, areas map[string]uint, locations map[string]uint, kandangs map[string]uint) error { - seeds := []struct { - Name string - Type string - Area string - Location *string - Kandang *string - }{ - {Name: "Gudang Priangan", Type: string(utils.WarehouseTypeArea), Area: "Priangan"}, - {Name: "Gudang Singaparna", Type: string(utils.WarehouseTypeLokasi), Area: "Priangan", Location: strPtr("Singaparna")}, - {Name: "Gudang Singaparna 1", Type: string(utils.WarehouseTypeKandang), Area: "Priangan", Location: strPtr("Singaparna"), Kandang: strPtr("Singaparna 1")}, - {Name: "Gudang Singaparna 2", Type: string(utils.WarehouseTypeKandang), Area: "Priangan", Location: strPtr("Singaparna"), Kandang: strPtr("Singaparna 2")}, - {Name: "Gudang Banten", Type: string(utils.WarehouseTypeArea), Area: "Banten"}, - {Name: "Gudang Cikaum", Type: string(utils.WarehouseTypeLokasi), Area: "Banten", Location: strPtr("Cikaum")}, - {Name: "Gudang Cikaum 1", Type: string(utils.WarehouseTypeKandang), Area: "Banten", Location: strPtr("Cikaum"), Kandang: strPtr("Cikaum 1")}, - {Name: "Gudang Cikaum 2", Type: string(utils.WarehouseTypeKandang), Area: "Banten", Location: strPtr("Cikaum"), Kandang: strPtr("Cikaum 2")}, - } - - for _, seed := range seeds { - areaID, ok := areas[seed.Area] - if !ok { - return fmt.Errorf("area %s not seeded", seed.Area) - } - - var warehouse entity.Warehouse - err := tx.Where("name = ?", seed.Name).First(&warehouse).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - warehouse = entity.Warehouse{ - Name: seed.Name, - Type: seed.Type, - AreaId: areaID, - CreatedBy: createdBy, - } - } else if err != nil { - return err - } - - if seed.Location != nil { - locID, ok := locations[*seed.Location] - if !ok { - return fmt.Errorf("location %s not seeded", *seed.Location) - } - warehouse.LocationId = uintPtr(locID) - } - if seed.Kandang != nil { - kandangID, ok := kandangs[*seed.Kandang] - if !ok { - return fmt.Errorf("kandang %s not seeded", *seed.Kandang) - } - warehouse.KandangId = uintPtr(kandangID) - } - - if warehouse.Id == 0 { - if err := tx.Create(&warehouse).Error; err != nil { - return err - } - } else { - if err := tx.Model(&entity.Warehouse{}).Where("id = ?", warehouse.Id).Updates(map[string]any{ - "type": warehouse.Type, - "area_id": warehouse.AreaId, - "location_id": warehouse.LocationId, - "kandang_id": warehouse.KandangId, - }).Error; err != nil { - return err - } - } - } - - return nil -} - func seedProductCategories(tx *gorm.DB, createdBy uint) (map[string]uint, error) { seeds := []struct { Name string @@ -440,113 +175,6 @@ func seedSuppliers(tx *gorm.DB, createdBy uint) (map[string]uint, error) { return result, nil } -func seedCustomers(tx *gorm.DB, createdBy uint, users map[string]uint) error { - seeds := []struct { - Name string - PicKey string - Address string - Phone string - Email string - }{ - {"Abdul Azis", "admin", "Jl. Raya Utama 1, Bekasi", "082100000001", "abdul.azis@gmail.com"}, - } - - for idx, seed := range seeds { - picID, ok := users[seed.PicKey] - if !ok { - return fmt.Errorf("user %s not seeded", seed.PicKey) - } - - var customer entity.Customer - err := tx.Where("name = ?", seed.Name).First(&customer).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - customer = entity.Customer{ - Name: seed.Name, - PicId: picID, - Type: string(utils.CustomerSupplierTypeBisnis), - Address: seed.Address, - Phone: seed.Phone, - Email: seed.Email, - AccountNumber: *strPtr(fmt.Sprintf("%03d", idx+1)), - CreatedBy: createdBy, - } - if err := tx.Create(&customer).Error; err != nil { - return err - } - } else if err != nil { - return err - } - } - - return nil -} - -func seedFcr(tx *gorm.DB, createdBy uint) (map[string]uint, error) { - seeds := []struct { - Name string - Standards []struct { - Weight float64 - FcrNumber float64 - Mortality float64 - } - }{ - { - Name: "FCR Layer", - Standards: []struct { - Weight float64 - FcrNumber float64 - Mortality float64 - }{ - {Weight: 0.8, FcrNumber: 1.60, Mortality: 2.0}, - {Weight: 1.5, FcrNumber: 1.75, Mortality: 3.5}, - }, - }, - } - - result := make(map[string]uint, len(seeds)) - - for _, seed := range seeds { - var fcr entity.Fcr - err := tx.Where("name = ?", seed.Name).First(&fcr).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - fcr = entity.Fcr{Name: seed.Name, CreatedBy: createdBy} - if err := tx.Create(&fcr).Error; err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } - result[seed.Name] = fcr.Id - - for _, std := range seed.Standards { - var standard entity.FcrStandard - err := tx.Where("fcr_id = ? AND weight = ?", fcr.Id, std.Weight).First(&standard).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - standard = entity.FcrStandard{ - FcrID: fcr.Id, - Weight: std.Weight, - FcrNumber: std.FcrNumber, - Mortality: std.Mortality, - } - if err := tx.Create(&standard).Error; err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } else { - if err := tx.Model(&entity.FcrStandard{}).Where("id = ?", standard.Id).Updates(map[string]any{ - "fcr_number": std.FcrNumber, - "mortality": std.Mortality, - }).Error; err != nil { - return nil, err - } - } - } - } - - return result, nil -} - func seedProducts(tx *gorm.DB, createdBy uint, uoms map[string]uint, categories map[string]uint, suppliers map[string]uint) error { seeds := []struct { Name string @@ -560,92 +188,88 @@ func seedProducts(tx *gorm.DB, createdBy uint, uoms map[string]uint, categories Expiry *int Suppliers []string Flags []utils.FlagType + IsVisible bool }{ { - Name: "DOC Broiler", - Brand: "MBU Broiler", - Sku: "BRO0001", + Name: "ISA Brown", + Brand: "ISA Brown", + Sku: "ISA0001", Uom: "Ekor", Category: "Day Old Chick", Price: 7500, Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, - Flags: []utils.FlagType{utils.FlagDOC}, + Flags: []utils.FlagType{utils.FlagDOC, utils.FlagPullet, utils.FlagLayer}, + IsVisible: true, }, { - Name: "Ayam Pullet", - Brand: "MBU Pullet", - Sku: "PLT0001", - Uom: "Ekor", - Category: "Pullet", - Price: 15000, - Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, - Flags: []utils.FlagType{utils.FlagPullet}, - }, - { - Name: "Ayam Afkir", - Brand: "-", - Sku: "1", - Uom: "Ekor", - Category: "Day Old Chick", - Price: 1, - Flags: []utils.FlagType{utils.FlagAyamAfkir}, - }, - { - Name: "Ayam Mati", - Brand: "-", - Sku: "2", - Uom: "Ekor", - Category: "Day Old Chick", - Price: 1, - Flags: []utils.FlagType{utils.FlagAyamMati}, - }, - { - Name: "Ayam Culling", - Brand: "-", - Sku: "3", - Uom: "Ekor", - Category: "Day Old Chick", - Price: 1, - Flags: []utils.FlagType{utils.FlagAyamCulling}, - }, - { - Name: "Telur Konsumsi Baik", - Brand: "-", - Sku: "4", - Uom: "Unit", - Category: "Telur", - Price: 1, - Flags: []utils.FlagType{utils.FlagTelurUtuh}, - }, - { - Name: "Telur Pecah", - Brand: "-", - Sku: "5", - Uom: "Unit", - Category: "Telur", - Price: 1, - Flags: []utils.FlagType{utils.FlagTelurPecah}, - }, - { - Name: "281 SPECIAL STARTER", - Brand: "281 STARTER", - Sku: "281", - Uom: "Kilogram", - Category: "Bahan Baku", - Price: 7850, - Expiry: intPtr(60), - Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, - Flags: []utils.FlagType{utils.FlagPakan, utils.FlagStarter}, - }, - { - Name: "Ayam Layer", + Name: "Ayam Afkir", Brand: "-", - Sku: "LYR0001", + Sku: "1", Uom: "Ekor", - Category: "Pullet", - Price: 20000, - Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, - Flags: []utils.FlagType{utils.FlagLayer}, + Category: "Day Old Chick", + Price: 1, + Flags: []utils.FlagType{utils.FlagAyamAfkir}, + IsVisible: false, + }, + { + Name: "Ayam Mati", + Brand: "-", + Sku: "2", + Uom: "Ekor", + Category: "Day Old Chick", + Price: 1, + Flags: []utils.FlagType{utils.FlagAyamMati}, + IsVisible: false, + }, + { + Name: "Ayam Culling", + Brand: "-", + Sku: "3", + Uom: "Ekor", + Category: "Day Old Chick", + Price: 1, + Flags: []utils.FlagType{utils.FlagAyamCulling}, + IsVisible: false, + }, + { + Name: "Telur Utuh", + Brand: "-", + Sku: "4", + Uom: "Gram", + Category: "Telur", + Price: 1, + Flags: []utils.FlagType{utils.FlagTelurUtuh}, + IsVisible: false, + }, + { + Name: "Telur Pecah", + Brand: "-", + Sku: "5", + Uom: "Gram", + Category: "Telur", + Price: 1, + Flags: []utils.FlagType{utils.FlagTelurPecah}, + IsVisible: false, + }, + { + Name: "Telur Putih", + Brand: "-", + Sku: "6", + Uom: "Gram", + Category: "Telur", + Price: 1, + Flags: []utils.FlagType{utils.FlagTelurPutih}, + IsVisible: false, + }, + { + Name: "Telur Retak", + Brand: "-", + Sku: "7", + Uom: "Gram", + Category: "Telur", + Price: 1, + Flags: []utils.FlagType{utils.FlagTelurRetak}, + IsVisible: false, }, } @@ -724,78 +348,78 @@ func seedProducts(tx *gorm.DB, createdBy uint, uoms map[string]uint, categories return nil } -func seedNonstocks(tx *gorm.DB, createdBy uint, uoms map[string]uint, suppliers map[string]uint) error { - seeds := []struct { - Name string - Uom string - Suppliers []string - Flags []utils.FlagType - }{ - { - Name: "Expedisi DOC", - Uom: "Ekor", - Suppliers: []string{"Ekspedisi"}, - Flags: []utils.FlagType{utils.FlagEkspedisi}, - }, - { - Name: "Solar", - Uom: "Liter", - Suppliers: []string{"BOP Vendor"}, - Flags: []utils.FlagType{}, - }, - } +// func seedNonstocks(tx *gorm.DB, createdBy uint, uoms map[string]uint, suppliers map[string]uint) error { +// seeds := []struct { +// Name string +// Uom string +// Suppliers []string +// Flags []utils.FlagType +// }{ +// { +// Name: "LAJ", +// Uom: "Unit", +// Suppliers: []string{"Ekspedisi"}, +// Flags: []utils.FlagType{utils.FlagEkspedisi}, +// }, +// { +// Name: "Solar", +// Uom: "Liter", +// Suppliers: []string{"BOP Vendor"}, +// Flags: []utils.FlagType{}, +// }, +// } - for _, seed := range seeds { - uomID, ok := uoms[seed.Uom] - if !ok { - return fmt.Errorf("uom %s not seeded", seed.Uom) - } +// for _, seed := range seeds { +// uomID, ok := uoms[seed.Uom] +// if !ok { +// return fmt.Errorf("uom %s not seeded", seed.Uom) +// } - var nonstock entity.Nonstock - err := tx.Where("name = ?", seed.Name).First(&nonstock).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - nonstock = entity.Nonstock{ - Name: seed.Name, - UomId: uomID, - CreatedBy: createdBy, - } - if err := tx.Create(&nonstock).Error; err != nil { - return err - } - } else if err != nil { - return err - } else { - if err := tx.Model(&entity.Nonstock{}).Where("id = ?", nonstock.Id).Updates(map[string]any{ - "uom_id": uomID, - }).Error; err != nil { - return err - } - } +// var nonstock entity.Nonstock +// err := tx.Where("name = ?", seed.Name).First(&nonstock).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// nonstock = entity.Nonstock{ +// Name: seed.Name, +// UomId: uomID, +// CreatedBy: createdBy, +// } +// if err := tx.Create(&nonstock).Error; err != nil { +// return err +// } +// } else if err != nil { +// return err +// } else { +// if err := tx.Model(&entity.Nonstock{}).Where("id = ?", nonstock.Id).Updates(map[string]any{ +// "uom_id": uomID, +// }).Error; err != nil { +// return err +// } +// } - for _, supplierName := range seed.Suppliers { - supplierID, ok := suppliers[supplierName] - if !ok { - return fmt.Errorf("supplier %s not seeded", supplierName) - } - var existing entity.NonstockSupplier - err := tx.Where("nonstock_id = ? AND supplier_id = ?", nonstock.Id, supplierID).First(&existing).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - link := entity.NonstockSupplier{NonstockId: nonstock.Id, SupplierId: supplierID} - if err := tx.Create(&link).Error; err != nil { - return err - } - } else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - return err - } - } +// for _, supplierName := range seed.Suppliers { +// supplierID, ok := suppliers[supplierName] +// if !ok { +// return fmt.Errorf("supplier %s not seeded", supplierName) +// } +// var existing entity.NonstockSupplier +// err := tx.Where("nonstock_id = ? AND supplier_id = ?", nonstock.Id, supplierID).First(&existing).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// link := entity.NonstockSupplier{NonstockId: nonstock.Id, SupplierId: supplierID} +// if err := tx.Create(&link).Error; err != nil { +// return err +// } +// } else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { +// return err +// } +// } - if err := seedFlags(tx, nonstock.Id, entity.FlagableTypeNonstock, seed.Flags); err != nil { - return err - } - } +// if err := seedFlags(tx, nonstock.Id, entity.FlagableTypeNonstock, seed.Flags); err != nil { +// return err +// } +// } - return nil -} +// return nil +// } // nanti saya isi @@ -823,225 +447,6 @@ func seedFlags(tx *gorm.DB, flagableID uint, flagableType string, flags []utils. return nil } -func seedBanks(tx *gorm.DB, createdBy uint) error { - seeds := []struct { - Name string - Alias string - Owner *string - AccountNumber string - }{ - { - Name: "Bank Central Asia", - Alias: "BCA", - AccountNumber: "1234567890", - Owner: ptr("PT MBU Group"), - }, - { - Name: "Bank Rakyat Indonesia", - Alias: "BRI", - AccountNumber: "9876543210", - Owner: ptr("PT MBU Group"), - }, - { - Name: "Bank Mandiri", - Alias: "MAND", - AccountNumber: "1122334455", - Owner: ptr("PT MBU Group"), - }, - } - - for _, seed := range seeds { - var bank entity.Bank - err := tx.Where("name = ?", seed.Name).First(&bank).Error - - if errors.Is(err, gorm.ErrRecordNotFound) { - bank = entity.Bank{ - Name: seed.Name, - Alias: seed.Alias, - Owner: seed.Owner, - AccountNumber: seed.AccountNumber, - CreatedBy: createdBy, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - } - if err := tx.Create(&bank).Error; err != nil { - return err - } - } else if err != nil { - return err - } else { - // update data jika sudah ada - if err := tx.Model(&entity.Bank{}).Where("id = ?", bank.Id).Updates(map[string]any{ - "alias": seed.Alias, - "owner": seed.Owner, - "account_number": seed.AccountNumber, - "updated_at": time.Now(), - }).Error; err != nil { - return err - } - } - } - - return nil -} - -func seedProductWarehouse(tx *gorm.DB, createdBy uint) error { - seeds := []struct { - ProductName string - WarehouseName string - Quantity float64 - }{ - {ProductName: "DOC Broiler", WarehouseName: "Gudang Priangan", Quantity: 0}, - {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Singaparna", Quantity: 0}, - {ProductName: "281 SPECIAL STARTER", WarehouseName: "Gudang Banten", Quantity: 0}, - {ProductName: "DOC Broiler", WarehouseName: "Gudang Singaparna 1", Quantity: 0}, - {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Singaparna 1", Quantity: 0}, - {ProductName: "Telur Pecah", WarehouseName: "Gudang Singaparna 1", Quantity: 0}, - {ProductName: "Telur Konsumsi Baik", WarehouseName: "Gudang Cikaum 1", Quantity: 0}, - {ProductName: "Telur Pecah", WarehouseName: "Gudang Cikaum 1", Quantity: 0}, - } - - for _, seed := range seeds { - var product entity.Product - if err := tx.Where("name = ?", seed.ProductName).First(&product).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return fmt.Errorf("product %q not found for product warehouse seeding", seed.ProductName) - } - return err - } - - var warehouse entity.Warehouse - if err := tx.Where("name = ?", seed.WarehouseName).First(&warehouse).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return fmt.Errorf("warehouse %q not found for product warehouse seeding", seed.WarehouseName) - } - return err - } - - var productWarehouse entity.ProductWarehouse - err := tx.Where("product_id = ? AND warehouse_id = ?", product.Id, warehouse.Id).First(&productWarehouse).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - productWarehouse = entity.ProductWarehouse{ - ProductId: product.Id, - WarehouseId: warehouse.Id, - Quantity: seed.Quantity, - // CreatedBy: createdBy, - } - if err := tx.Create(&productWarehouse).Error; err != nil { - return err - } - } else if err != nil { - return err - } else { - if err := tx.Model(&productWarehouse).Updates(map[string]any{ - "quantity": seed.Quantity, - }).Error; err != nil { - return err - } - } - } - - return nil -} - -func seedTransferStock(tx *gorm.DB) error { - - transfer := entity.StockTransfer{ - FromWarehouseId: 1, - ToWarehouseId: 2, - Reason: "Seed transfer stock", - TransferDate: time.Now(), - MovementNumber: "SEED-TRF-00001", - CreatedBy: 1, - } - if err := tx.Create(&transfer).Error; err != nil { - return err - } - - details := []entity.StockTransferDetail{ - { - StockTransferId: transfer.Id, - ProductId: 1, - - 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, - ProductId: 2, - - 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 { - if err := tx.Create(&details[i]).Error; err != nil { - return err - } - } - - deliveries := []entity.StockTransferDelivery{ - { - StockTransferId: transfer.Id, - SupplierId: 1, - VehiclePlate: "B 1234 XYZ", - DriverName: "Driver Seed", - DocumentPath: "seed.pdf", - ShippingCostItem: 1000, - ShippingCostTotal: 2000, - }, - } - for i := range deliveries { - if err := tx.Create(&deliveries[i]).Error; err != nil { - return err - } - } - - detailMap := make(map[uint64]uint64) - for _, d := range details { - detailMap[d.ProductId] = d.Id - } - - deliveryItems := []entity.StockTransferDeliveryItem{ - { - StockTransferDeliveryId: deliveries[0].Id, - StockTransferDetailId: detailMap[1], - Quantity: 50, - }, - { - StockTransferDeliveryId: deliveries[0].Id, - StockTransferDetailId: detailMap[2], - Quantity: 30, - }, - } - for i := range deliveryItems { - if err := tx.Create(&deliveryItems[i]).Error; err != nil { - return err - } - } - - return nil -} -func ptr[T any](v T) *T { - return &v -} - func strPtr(s string) *string { return &s } - -func intPtr(v int) *int { - return &v -} - -func uintPtr(v uint) *uint { - return &v -} From 6c42119f4dda73b1bfacbc625a3f53876ffcd28d Mon Sep 17 00:00:00 2001 From: "Hafizh A. Y" Date: Wed, 31 Dec 2025 06:43:34 +0700 Subject: [PATCH 10/12] fix(be): remove omitempty in dto and validation nonstock --- internal/modules/master/nonstocks/dto/nonstock.dto.go | 5 +++-- .../master/nonstocks/validations/nonstock.validation.go | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/modules/master/nonstocks/dto/nonstock.dto.go b/internal/modules/master/nonstocks/dto/nonstock.dto.go index b2af526c..71e1bb20 100644 --- a/internal/modules/master/nonstocks/dto/nonstock.dto.go +++ b/internal/modules/master/nonstocks/dto/nonstock.dto.go @@ -1,11 +1,12 @@ package dto import ( + "time" + entity "gitlab.com/mbugroup/lti-api.git/internal/entities" supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto" uomDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/dto" userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" - "time" ) // === DTO Structs === @@ -22,7 +23,7 @@ type NonstockListDTO struct { Name string `json:"name"` Flags []string `json:"flags"` Uom *uomDTO.UomRelationDTO `json:"uom"` - Suppliers []supplierDTO.SupplierRelationDTO `json:"suppliers,omitempty"` + Suppliers []supplierDTO.SupplierRelationDTO `json:"suppliers"` CreatedUser *userDTO.UserRelationDTO `json:"created_user"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` diff --git a/internal/modules/master/nonstocks/validations/nonstock.validation.go b/internal/modules/master/nonstocks/validations/nonstock.validation.go index c421b7ec..f3a298ef 100644 --- a/internal/modules/master/nonstocks/validations/nonstock.validation.go +++ b/internal/modules/master/nonstocks/validations/nonstock.validation.go @@ -3,8 +3,8 @@ package validation type Create struct { Name string `json:"name" validate:"required_strict,min=3,max=50"` UomID uint `json:"uom_id" validate:"required,gt=0"` - SupplierIDs []uint `json:"supplier_ids,omitempty" validate:"omitempty,dive,gt=0"` - Flags []string `json:"flags,omitempty" validate:"omitempty,dive,max=50"` + SupplierIDs []uint `json:"supplier_ids" validate:"dive,gt=0"` + Flags []string `json:"flags" validate:"dive,max=50"` } type Update struct { From 5302713811af99a07327838994749575182cf7a5 Mon Sep 17 00:00:00 2001 From: "Hafizh A. Y" Date: Wed, 31 Dec 2025 06:52:38 +0700 Subject: [PATCH 11/12] fix(be): nonstock response supplier null to empty array --- internal/modules/master/nonstocks/dto/nonstock.dto.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/modules/master/nonstocks/dto/nonstock.dto.go b/internal/modules/master/nonstocks/dto/nonstock.dto.go index 71e1bb20..9954ee76 100644 --- a/internal/modules/master/nonstocks/dto/nonstock.dto.go +++ b/internal/modules/master/nonstocks/dto/nonstock.dto.go @@ -101,7 +101,7 @@ func ToNonstockDetailDTO(e entity.Nonstock) NonstockDetailDTO { func toNonstockSupplierDTOs(relations []entity.NonstockSupplier) []supplierDTO.SupplierRelationDTO { if len(relations) == 0 { - return nil + return make([]supplierDTO.SupplierRelationDTO, 0) } result := make([]supplierDTO.SupplierRelationDTO, 0, len(relations)) @@ -113,7 +113,7 @@ func toNonstockSupplierDTOs(relations []entity.NonstockSupplier) []supplierDTO.S } if len(result) == 0 { - return nil + return make([]supplierDTO.SupplierRelationDTO, 0) } return result From 709e304f7ff47d0b6f264e62a4a309cedd934891 Mon Sep 17 00:00:00 2001 From: ragilap Date: Wed, 31 Dec 2025 07:39:20 +0700 Subject: [PATCH 12/12] feat(BE-281): adjustment bug erorr 500 if 404 record projectflock --- .../production/project_flocks/services/projectflock.service.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/modules/production/project_flocks/services/projectflock.service.go b/internal/modules/production/project_flocks/services/projectflock.service.go index 75c89c8e..1e859e47 100644 --- a/internal/modules/production/project_flocks/services/projectflock.service.go +++ b/internal/modules/production/project_flocks/services/projectflock.service.go @@ -959,6 +959,9 @@ func (s projectflockService) ensureProjectFlockKandangProductWarehouses(ctx cont warehouse, err := warehouseRepo.GetByKandangID(ctx, record.KandangId) if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Warehouse untuk kandang %d belum tersedia", record.KandangId)) + } return err }