Feat[BE] : add avaibility DOC on lookup porject flock API, add note request json on chickin

This commit is contained in:
aguhh18
2025-10-24 09:51:50 +07:00
parent 79b3dd47b8
commit aeeb5a38c1
8 changed files with 137 additions and 96 deletions
@@ -246,17 +246,39 @@ func (u *ProjectflockController) GetFlockPeriodSummary(c *fiber.Ctx) error {
}
func (u *ProjectflockController) LookupProjectFlockKandang(c *fiber.Ctx) error {
projectFlockIdStr := c.Query("project_flock_id", "")
kandangIdStr := c.Query("kandang_id", "")
projectFlockId := c.QueryInt("project_flock_id", 0)
kandangId := c.QueryInt("kandang_id", 0)
result, err := u.ProjectflockService.GetProjectFlockKandangByParams(c, "", projectFlockIdStr, kandangIdStr)
if projectFlockId == 0 || kandangId == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id or kandang_id")
}
result, availableStock, err := u.ProjectflockService.GetProjectFlockKandangByProjectAndKandang(c, uint(projectFlockId), uint(kandangId))
if err != nil {
return err
}
dtoResult := dto.ToProjectFlockKandangDTO(*result)
dtoResult.AvailableQuantity = float64(availableStock)
// populate available quantity for each kandang inside project_flock
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
}
}
// remove inner kandangs from project_flock to avoid duplication
dtoResult.ProjectFlock.Kandangs = nil
}
return c.Status(fiber.StatusOK).
JSON(response.Success{Code: fiber.StatusOK,
Status: "success",
Message: "Get projectflock kandang successfully",
Data: dto.ToProjectFlockKandangDTO(*result)})
Data: dtoResult})
}
@@ -10,10 +10,9 @@ import (
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
)
// internal DTO used only for lookup response: project flock with kandangs carrying pivot ids
type KandangWithPivotDTO struct {
kandangDTO.KandangBaseDTO
ProjectFlockKandangId *uint `json:"project_flock_kandang_id,omitempty"`
AvailableQuantity float64 `json:"available_quantity"`
}
type ProjectFlockWithPivotDTO struct {
@@ -28,11 +27,13 @@ type ProjectFlockWithPivotDTO struct {
}
type ProjectFlockKandangDTO struct {
Id uint `json:"id"`
ProjectFlockId uint `json:"project_flock_id"`
KandangId uint `json:"kandang_id"`
Kandang *kandangDTO.KandangBaseDTO `json:"kandang,omitempty"`
ProjectFlock *ProjectFlockWithPivotDTO `json:"project_flock,omitempty"`
Id uint `json:"id"`
ProjectFlockKandangId uint `json:"project_flock_kandang_id"`
ProjectFlockId uint `json:"project_flock_id"`
KandangId uint `json:"kandang_id"`
Kandang *kandangDTO.KandangBaseDTO `json:"kandang,omitempty"`
ProjectFlock *ProjectFlockWithPivotDTO `json:"project_flock,omitempty"`
AvailableQuantity float64 `json:"available_quantity"`
}
func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangDTO {
@@ -44,7 +45,7 @@ func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangD
var pf *ProjectFlockWithPivotDTO
if e.ProjectFlock.Id != 0 {
// build project flock with kandangs that include pivot ids
pfLocal := ProjectFlockWithPivotDTO{
ProjectFlockBaseDTO: ProjectFlockBaseDTO{
Id: e.ProjectFlock.Id,
@@ -53,7 +54,6 @@ func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangD
Category: e.ProjectFlock.Category,
}
// fill related small summaries
if e.ProjectFlock.Flock.Id != 0 {
mapped := ToFlockSummaryDTO(e.ProjectFlock.Flock)
pfLocal.Flock = &mapped
@@ -75,23 +75,16 @@ func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangD
pfLocal.CreatedUser = &mapped
}
// build pivot map
pivotMap := make(map[uint]uint)
for _, ph := range e.ProjectFlock.KandangHistory {
pivotMap[ph.KandangId] = ph.Id
}
// populate kandangs with pivot ids
for _, k := range e.ProjectFlock.Kandangs {
kb := kandangDTO.ToKandangBaseDTO(k)
var pid *uint
if v, ok := pivotMap[k.Id]; ok {
vv := v
pid = &vv
}
pfLocal.Kandangs = append(pfLocal.Kandangs, KandangWithPivotDTO{
KandangBaseDTO: kb,
ProjectFlockKandangId: pid,
KandangBaseDTO: kb,
AvailableQuantity: 0,
})
}
@@ -99,10 +92,12 @@ func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangD
}
return ProjectFlockKandangDTO{
Id: e.Id,
ProjectFlockId: e.ProjectFlockId,
KandangId: e.KandangId,
Kandang: kandang,
ProjectFlock: pf,
Id: e.Id,
ProjectFlockKandangId: e.Id,
ProjectFlockId: e.ProjectFlockId,
KandangId: e.KandangId,
Kandang: kandang,
ProjectFlock: pf,
AvailableQuantity: 0,
}
}
@@ -9,8 +9,10 @@ import (
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
"gorm.io/gorm"
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
rFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories"
rKandang "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories"
rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
rProjectflock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
sProjectflock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/services"
@@ -27,6 +29,8 @@ func (ProjectflockModule) RegisterRoutes(router fiber.Router, db *gorm.DB, valid
kandangRepo := rKandang.NewKandangRepository(db)
projectflockRepo := rProjectflock.NewProjectflockRepository(db)
projectflockKandangRepo := rProjectflock.NewProjectFlockKandangRepository(db)
warehouseRepo := rWarehouse.NewWarehouseRepository(db)
productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
userRepo := rUser.NewUserRepository(db)
approvalRepo := commonRepo.NewApprovalRepository(db)
@@ -35,7 +39,7 @@ func (ProjectflockModule) RegisterRoutes(router fiber.Router, db *gorm.DB, valid
panic(fmt.Sprintf("failed to register project flock approval workflow: %v", err))
}
projectflockService := sProjectflock.NewProjectflockService(projectflockRepo, flockRepo, kandangRepo, projectflockKandangRepo, approvalService, validate)
projectflockService := sProjectflock.NewProjectflockService(projectflockRepo, flockRepo, kandangRepo, projectflockKandangRepo, warehouseRepo, productWarehouseRepo, approvalService, validate)
userService := sUser.NewUserService(userRepo, validate)
ProjectflockRoutes(router, userService, projectflockService)
@@ -4,14 +4,15 @@ import (
"context"
"errors"
"fmt"
"strconv"
"strings"
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"
productWarehouseRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
flockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories"
kandangRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories"
warehouseRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/validations"
utils "gitlab.com/mbugroup/lti-api.git/internal/utils"
@@ -29,20 +30,23 @@ type ProjectflockService interface {
CreateOne(ctx *fiber.Ctx, req *validation.Create) (*entity.ProjectFlock, error)
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*entity.ProjectFlock, error)
DeleteOne(ctx *fiber.Ctx, id uint) error
GetProjectFlockKandangByParams(ctx *fiber.Ctx, idStr string, projectFlockIdStr string, kandangIdStr string) (*entity.ProjectFlockKandang, error)
GetProjectFlockKandangByProjectAndKandang(ctx *fiber.Ctx, projectFlockID uint, kandangID uint) (*entity.ProjectFlockKandang, int, error)
GetAvailableDocQuantity(ctx *fiber.Ctx, kandangID uint) (float64, error)
GetFlockPeriodSummary(ctx *fiber.Ctx, flockID uint) (*FlockPeriodSummary, error)
Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlock, error)
}
type projectflockService struct {
Log *logrus.Logger
Validate *validator.Validate
Repository repository.ProjectflockRepository
FlockRepo flockRepository.FlockRepository
KandangRepo kandangRepository.KandangRepository
PivotRepo repository.ProjectFlockKandangRepository
ApprovalSvc commonSvc.ApprovalService
approvalWorkflow approvalutils.ApprovalWorkflowKey
Log *logrus.Logger
Validate *validator.Validate
Repository repository.ProjectflockRepository
FlockRepo flockRepository.FlockRepository
KandangRepo kandangRepository.KandangRepository
WarehouseRepo warehouseRepository.WarehouseRepository
ProductWarehouseRepo productWarehouseRepository.ProductWarehouseRepository
ProjectFlockKandangRepo repository.ProjectFlockKandangRepository
ApprovalSvc commonSvc.ApprovalService
approvalWorkflow approvalutils.ApprovalWorkflowKey
}
type FlockPeriodSummary struct {
@@ -54,19 +58,23 @@ func NewProjectflockService(
repo repository.ProjectflockRepository,
flockRepo flockRepository.FlockRepository,
kandangRepo kandangRepository.KandangRepository,
pivotRepo repository.ProjectFlockKandangRepository,
ProjectFlockKandangRepo repository.ProjectFlockKandangRepository,
warehouseRepo warehouseRepository.WarehouseRepository,
productWarehouseRepo productWarehouseRepository.ProductWarehouseRepository,
approvalSvc commonSvc.ApprovalService,
validate *validator.Validate,
) ProjectflockService {
return &projectflockService{
Log: utils.Log,
Validate: validate,
Repository: repo,
FlockRepo: flockRepo,
KandangRepo: kandangRepo,
PivotRepo: pivotRepo,
ApprovalSvc: approvalSvc,
approvalWorkflow: utils.ApprovalWorkflowProjectFlock,
Log: utils.Log,
Validate: validate,
Repository: repo,
FlockRepo: flockRepo,
KandangRepo: kandangRepo,
WarehouseRepo: warehouseRepo,
ProductWarehouseRepo: productWarehouseRepo,
ProjectFlockKandangRepo: ProjectFlockKandangRepo,
ApprovalSvc: approvalSvc,
approvalWorkflow: utils.ApprovalWorkflowProjectFlock,
}
}
@@ -641,55 +649,48 @@ func (s projectflockService) DeleteOne(c *fiber.Ctx, id uint) error {
return nil
}
func (s projectflockService) GetProjectFlockKandang(ctx *fiber.Ctx, id uint) (*entity.ProjectFlockKandang, error) {
// keep for backward compatibility; delegate to new consolidated method
return s.GetProjectFlockKandangByParams(ctx, fmt.Sprintf("%d", id), "", "")
}
func (s projectflockService) GetProjectFlockKandangByProjectAndKandang(ctx *fiber.Ctx, projectFlockID uint, kandangID uint) (*entity.ProjectFlockKandang, int, error) {
func (s projectflockService) GetProjectFlockKandangByProjectAndKandang(ctx *fiber.Ctx, projectFlockID uint, kandangID uint) (*entity.ProjectFlockKandang, error) {
availableStock, err := s.GetAvailableDocQuantity(ctx, kandangID)
if err != nil {
return nil, 0, err
}
pfk, err := s.PivotRepo.GetByProjectFlockAndKandang(ctx.Context(), projectFlockID, kandangID)
projectFlockKandang, err := s.ProjectFlockKandangRepo.GetByProjectFlockAndKandang(ctx.Context(), projectFlockID, kandangID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "ProjectFlockKandang not found")
return nil, 0, fiber.NewError(fiber.StatusNotFound, "ProjectFlockKandang not found")
}
return nil, err
return nil, 0, err
}
return pfk, nil
return projectFlockKandang, int(availableStock), nil
}
func (s projectflockService) GetProjectFlockKandangByParams(ctx *fiber.Ctx, idStr string, projectFlockIdStr string, kandangIdStr string) (*entity.ProjectFlockKandang, error) {
idStr = strings.TrimSpace(idStr)
projectFlockIdStr = strings.TrimSpace(projectFlockIdStr)
kandangIdStr = strings.TrimSpace(kandangIdStr)
func (s projectflockService) GetAvailableDocQuantity(ctx *fiber.Ctx, kandangID uint) (float64, error) {
if idStr != "" {
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
}
pfk, err := s.PivotRepo.GetByID(ctx.Context(), uint(id))
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "ProjectFlockKandang not found")
}
return nil, err
}
return pfk, nil
wh, err := s.WarehouseRepo.GetByKandangID(ctx.Context(), kandangID)
if err != nil {
return 0, err
}
if projectFlockIdStr == "" || kandangIdStr == "" {
return nil, fiber.NewError(fiber.StatusBadRequest, "Missing lookup parameters")
var productWarehouses []entity.ProductWarehouse
err = s.ProductWarehouseRepo.DB().
WithContext(ctx.Context()).
Joins("JOIN products ON products.id = product_warehouses.product_id").
Joins("JOIN product_categories ON product_categories.id = products.product_category_id").
Where("product_categories.code = ? AND product_warehouses.warehouse_id = ?", "DOC", wh.Id).
Order("created_at DESC").
Find(&productWarehouses).Error
if err != nil {
return 0, err
}
pfid, err := strconv.Atoi(projectFlockIdStr)
if err != nil || pfid <= 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id")
total := 0.0
for _, pw := range productWarehouses {
total += pw.Quantity
}
kid, err := strconv.Atoi(kandangIdStr)
if err != nil || kid <= 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid kandang_id")
}
return s.GetProjectFlockKandangByProjectAndKandang(ctx, uint(pfid), uint(kid))
return total, nil
}
func (s projectflockService) GetFlockPeriodSummary(c *fiber.Ctx, flockID uint) (*FlockPeriodSummary, error) {
@@ -784,7 +785,7 @@ func (s projectflockService) attachKandangs(ctx context.Context, dbTransaction *
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs")
}
pivotRepo := s.pivotRepoWithTx(dbTransaction)
ProjectFlockKandangRepo := s.ProjectFlockKandangRepoWithTx(dbTransaction)
records := make([]*entity.ProjectFlockKandang, len(kandangIDs))
for i, id := range kandangIDs {
records[i] = &entity.ProjectFlockKandang{
@@ -792,7 +793,7 @@ func (s projectflockService) attachKandangs(ctx context.Context, dbTransaction *
KandangId: id,
}
}
if err := pivotRepo.CreateMany(ctx, records); err != nil {
if err := ProjectFlockKandangRepo.CreateMany(ctx, records); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to persist project flock history")
}
return nil
@@ -814,15 +815,15 @@ func (s projectflockService) detachKandangs(ctx context.Context, dbTransaction *
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs")
}
if err := s.pivotRepoWithTx(dbTransaction).DeleteMany(ctx, projectFlockID, kandangIDs); err != nil {
if err := s.ProjectFlockKandangRepoWithTx(dbTransaction).DeleteMany(ctx, projectFlockID, kandangIDs); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to persist project flock history")
}
return nil
}
func (s projectflockService) pivotRepoWithTx(dbTransaction *gorm.DB) repository.ProjectFlockKandangRepository {
if s.PivotRepo == nil {
func (s projectflockService) ProjectFlockKandangRepoWithTx(dbTransaction *gorm.DB) repository.ProjectFlockKandangRepository {
if s.ProjectFlockKandangRepo == nil {
return repository.NewProjectFlockKandangRepository(dbTransaction)
}
return s.PivotRepo.WithTx(dbTransaction)
return s.ProjectFlockKandangRepo.WithTx(dbTransaction)
}