package controller import ( "encoding/json" "fmt" "math" "strconv" "strings" "time" warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto" "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/dto" service "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/services" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/validations" "gitlab.com/mbugroup/lti-api.git/internal/response" "gitlab.com/mbugroup/lti-api.git/internal/utils" "github.com/gofiber/fiber/v2" ) type ProjectflockController struct { ProjectflockService service.ProjectflockService } func NewProjectflockController(projectflockService service.ProjectflockService) *ProjectflockController { return &ProjectflockController{ ProjectflockService: projectflockService, } } func (u *ProjectflockController) GetAll(c *fiber.Ctx) error { parseUintList := func(raw string) ([]uint, error) { raw = strings.TrimSpace(raw) if raw == "" { return nil, nil } var ids []uint if strings.HasPrefix(raw, "[") { if err := json.Unmarshal([]byte(raw), &ids); err == nil { return ids, nil } } parts := strings.Split(raw, ",") for _, part := range parts { part = strings.Trim(part, " \"[]") if part == "" { continue } v, err := strconv.Atoi(part) if err != nil || v <= 0 { return nil, fmt.Errorf("invalid kandang id: %s", part) } ids = append(ids, uint(v)) } return ids, nil } query := &validation.Query{ Page: c.QueryInt("page", 1), Limit: c.QueryInt("limit", 10), Search: c.Query("search", ""), SortBy: c.Query("sort_by", ""), SortOrder: c.Query("sort_order", ""), } if area := c.QueryInt("area_id", 0); area > 0 { query.AreaId = uint(area) } if location := c.QueryInt("location_id", 0); location > 0 { query.LocationId = uint(location) } if period := c.QueryInt("period", 0); period > 0 { query.Period = period } if category := c.Query("category", ""); category != "" { query.Category = category } query.TransferContext = c.Query(utils.TransferContextKey, "") if kandangRaw := c.Query("kandang_id", c.Query("kandang_ids", "")); kandangRaw != "" { ids, err := parseUintList(kandangRaw) if err != nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } query.KandangIds = ids } result, totalResults, _, err := u.ProjectflockService.GetAll(c, query) if err != nil { return err } var periodMap map[uint]int if len(result) > 0 { ids := make([]uint, len(result)) for i, item := range result { ids[i] = item.Id } if periods, err := u.ProjectflockService.GetProjectPeriods(c, ids); err == nil { periodMap = periods } } return c.Status(fiber.StatusOK). JSON(response.SuccessWithPaginate[dto.ProjectFlockListDTO]{ Code: fiber.StatusOK, Status: "success", Message: "Get all projectflocks successfully", Meta: response.Meta{ Page: query.Page, Limit: query.Limit, TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))), TotalResults: totalResults, }, Data: dto.ToProjectFlockListDTOsWithPeriods(result, periodMap), }) } func (u *ProjectflockController) GetOne(c *fiber.Ctx) error { param := c.Params("id") id, err := strconv.Atoi(param) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid Id") } result, _, err := u.ProjectflockService.GetOne(c, uint(id)) if err != nil { return err } var period int if periods, err := u.ProjectflockService.GetProjectPeriods(c, []uint{uint(id)}); err == nil { if p, ok := periods[uint(id)]; ok { period = p } } return c.Status(fiber.StatusOK). JSON(response.Success{ Code: fiber.StatusOK, Status: "success", Message: "Get projectflock successfully", Data: dto.ToProjectFlockListDTOWithPeriod(*result, period), }) } func (u *ProjectflockController) CreateOne(c *fiber.Ctx) error { req := new(validation.Create) if err := c.BodyParser(req); err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") } result, err := u.ProjectflockService.CreateOne(c, req) if err != nil { return err } return c.Status(fiber.StatusCreated). JSON(response.Success{ Code: fiber.StatusCreated, Status: "success", Message: "Create projectflock successfully", Data: dto.ToProjectFlockListDTO(*result), }) } func (u *ProjectflockController) DeleteOne(c *fiber.Ctx) error { param := c.Params("id") id, err := strconv.Atoi(param) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid Id") } if err := u.ProjectflockService.DeleteOne(c, uint(id)); err != nil { return err } return c.Status(fiber.StatusOK). JSON(response.Common{ Code: fiber.StatusOK, Status: "success", Message: "Delete projectflock successfully", }) } func (u *ProjectflockController) Approval(c *fiber.Ctx) error { req := new(validation.Approve) if err := c.BodyParser(req); err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") } results, err := u.ProjectflockService.Approval(c, req) if err != nil { return err } var ( data interface{} message = "Submit projectflock approval successfully" ) var periodMap map[uint]int if len(results) > 0 { ids := make([]uint, len(results)) for i, item := range results { ids[i] = item.Id } if periods, err := u.ProjectflockService.GetProjectPeriods(c, ids); err == nil { periodMap = periods } } if len(results) == 1 { period := 0 if periodMap != nil { if p, ok := periodMap[results[0].Id]; ok { period = p } } data = dto.ToProjectFlockListDTOWithPeriod(results[0], period) } else { message = "Submit projectflock approvals successfully" data = dto.ToProjectFlockListDTOsWithPeriods(results, periodMap) } return c.Status(fiber.StatusOK). JSON(response.Success{ Code: fiber.StatusOK, Status: "success", Message: message, Data: data, }) } func (u *ProjectflockController) GetPeriodSummary(c *fiber.Ctx) error { param := c.Params("location_id") id, err := strconv.Atoi(param) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid location_id") } summaries, err := u.ProjectflockService.GetPeriodSummary(c, uint(id)) if err != nil { return err } responseBody := make([]dto.KandangPeriodSummaryDTO, 0, len(summaries)) for _, item := range summaries { responseBody = append(responseBody, dto.KandangPeriodSummaryDTO{ Id: item.Id, Name: item.Name, Period: item.Period, }) } return c.Status(fiber.StatusOK). JSON(response.Success{ Code: fiber.StatusOK, Status: "success", Message: "Get kandang period summary successfully", Data: responseBody, }) } func (u *ProjectflockController) LookupProjectFlockKandang(c *fiber.Ctx) error { projectFlockId := c.QueryInt("project_flock_id", 0) kandangId := c.QueryInt("kandang_id", 0) withPopulation := c.QueryBool("withpopulation", false) recordDateRaw := strings.TrimSpace(c.Query("record_date", "")) var recordDate *time.Time if projectFlockId == 0 || kandangId == 0 { return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id or kandang_id") } if recordDateRaw != "" { parsed, err := time.Parse("2006-01-02", recordDateRaw) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "record_date must be in YYYY-MM-DD format") } utc := parsed.UTC() recordDate = &utc } result, availableStock, err := u.ProjectflockService.GetProjectFlockKandangByProjectAndKandang(c, uint(projectFlockId), uint(kandangId)) if err != nil { return err } _ = availableStock dtoResult := dto.ToProjectFlockKandangDTO(*result) if population, err := u.ProjectflockService.GetProjectFlockKandangPopulation(c, result.Id); err != nil { return err } else { dtoResult.AvailableQuantity = population } if chickinDate, err := u.ProjectflockService.GetProjectFlockKandangChickinDate(c, result.Id); err != nil { return err } else if chickinDate != nil { dtoResult.ChickInDate = chickinDate } if warehouse, werr := u.ProjectflockService.GetWarehouseByKandangID(c, result.KandangId); werr != nil { return werr } else if warehouse != nil { mapped := warehouseDTO.ToWarehouseRelationDTO(*warehouse) dtoResult.Warehouse = &mapped } if isTransition, isLaying, serr := u.ProjectflockService.GetProjectFlockKandangTransferStateAtDate(c, result.Id, recordDate); serr != nil { return serr } else { dtoResult.IsTransition = isTransition dtoResult.IsLaying = isLaying } if withPopulation { population := dtoResult.AvailableQuantity dtoResult.Population = &population } if dtoResult.ProjectFlock != nil { for i := range dtoResult.ProjectFlock.Kandangs { kand := &dtoResult.ProjectFlock.Kandangs[i] if kand.Id == 0 { continue } if q, qerr := u.ProjectflockService.GetAvailableDocQuantity(c, kand.Id); qerr == nil { kand.AvailableQuantity = q } } dtoResult.ProjectFlock.Kandangs = nil } return c.Status(fiber.StatusOK). JSON(response.Success{Code: fiber.StatusOK, Status: "success", Message: "Get projectflock kandang successfully", Data: dtoResult}) } func (u *ProjectflockController) Resubmit(c *fiber.Ctx) error { param := c.Params("id") req := new(validation.Resubmit) id, err := strconv.Atoi(param) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid Id") } if err := c.BodyParser(req); err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") } result, err := u.ProjectflockService.Resubmit(c, req, uint(id)) if err != nil { return err } return c.Status(fiber.StatusOK). JSON(response.Success{ Code: fiber.StatusOK, Status: "success", Message: "Resubmit projectflock successfully", Data: dto.ToProjectFlockListDTO(*result), }) }