feat(BE): enhance ProjectFlockKandang structure and approval fetching methods

This commit is contained in:
aguhh18
2026-01-07 13:39:54 +07:00
parent 0a84e427c1
commit 76d5b6b69a
3 changed files with 94 additions and 57 deletions
+5 -4
View File
@@ -10,8 +10,9 @@ type ProjectFlockKandang struct {
ClosedAt *time.Time `gorm:"index"`
CreatedAt time.Time `gorm:"autoCreateTime"`
ProjectFlock ProjectFlock `gorm:"foreignKey:ProjectFlockId;references:Id"`
Kandang Kandang `gorm:"foreignKey:KandangId;references:Id"`
Chickins []ProjectChickin `gorm:"foreignKey:ProjectFlockKandangId;references:Id"`
LatestApproval *Approval `gorm:"-" json:"-"`
ProjectFlock ProjectFlock `gorm:"foreignKey:ProjectFlockId;references:Id"`
Kandang Kandang `gorm:"foreignKey:KandangId;references:Id"`
Chickins []ProjectChickin `gorm:"foreignKey:ProjectFlockKandangId;references:Id"`
LatestProjectFlockApproval *Approval `gorm:"-" json:"-"`
LatestChickinApproval *Approval `gorm:"-" json:"-"`
}
@@ -28,14 +28,14 @@ type ProjectFlockKandangRelationDTO struct {
type ProjectFlockDTO struct {
projectFlockDTO.ProjectFlockRelationDTO
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"`
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"`
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ProductWarehouseDTO struct {
@@ -51,11 +51,12 @@ type AvailableQtyDTO struct {
type ProjectFlockKandangListDTO struct {
ProjectFlockKandangRelationDTO
ProjectFlock *ProjectFlockDTO `json:"project_flock,omitempty"`
Kandang *kandangDTO.KandangRelationDTO `json:"kandang,omitempty"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
CreatedAt time.Time `json:"created_at"`
Approval *approvalDTO.ApprovalRelationDTO `json:"approval,omitempty"`
ProjectFlock *ProjectFlockDTO `json:"project_flock,omitempty"`
Kandang *kandangDTO.KandangRelationDTO `json:"kandang,omitempty"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
CreatedAt time.Time `json:"created_at"`
Approval *approvalDTO.ApprovalRelationDTO `json:"approval,omitempty"`
ChickinApproval *approvalDTO.ApprovalRelationDTO `json:"chickin_approval,omitempty"`
}
type ProjectFlockKandangDetailDTO struct {
@@ -105,7 +106,8 @@ func ToProjectFlockKandangDetailDTOWithAvailableQty(e entity.ProjectFlockKandang
Kandang: toKandangRelation(e.Kandang),
CreatedAt: e.CreatedAt,
CreatedUser: toCreatedUserDTO(e.ProjectFlock),
Approval: toApprovalDTO(e),
Approval: toApprovalDTOSelector(e, func(x entity.ProjectFlockKandang) *entity.Approval { return x.LatestProjectFlockApproval }),
ChickinApproval: toApprovalDTOSelector(e, func(x entity.ProjectFlockKandang) *entity.Approval { return x.LatestChickinApproval }),
}
return ProjectFlockKandangDetailDTO{
@@ -124,9 +126,11 @@ func toKandangRelation(kandang entity.Kandang) *kandangDTO.KandangRelationDTO {
return &mapped
}
func toApprovalDTO(e entity.ProjectFlockKandang) *approvalDTO.ApprovalRelationDTO {
if e.LatestApproval != nil {
mapped := approvalDTO.ToApprovalDTO(*e.LatestApproval)
func toApprovalDTOSelector(
e entity.ProjectFlockKandang, selector func(entity.ProjectFlockKandang) *entity.Approval) *approvalDTO.ApprovalRelationDTO {
approval := selector(e)
if approval != nil {
mapped := approvalDTO.ToApprovalDTO(*approval)
return &mapped
}
return nil
@@ -145,18 +149,11 @@ func ToProjectFlockKandangListDTO(e entity.ProjectFlockKandang) ProjectFlockKand
Kandang: toKandangRelation(e.Kandang),
CreatedAt: e.CreatedAt,
CreatedUser: toCreatedUserDTO(e.ProjectFlock),
Approval: toApprovalDTO(e),
Approval: toApprovalDTOSelector(e, func(x entity.ProjectFlockKandang) *entity.Approval { return x.LatestProjectFlockApproval }),
ChickinApproval: toApprovalDTOSelector(e, func(x entity.ProjectFlockKandang) *entity.Approval { return x.LatestChickinApproval }),
}
}
func ToProjectFlockKandangListDTOs(e []entity.ProjectFlockKandang) []ProjectFlockKandangListDTO {
result := make([]ProjectFlockKandangListDTO, len(e))
for i, r := range e {
result[i] = ToProjectFlockKandangListDTO(r)
}
return result
}
func toCreatedUserDTO(pf entity.ProjectFlock) *userDTO.UserRelationDTO {
if pf.CreatedUser.Id != 0 {
mapped := userDTO.ToUserRelationDTO(pf.CreatedUser)
@@ -187,7 +184,6 @@ func toAvailableQtyDTOsFromMap(chickins []entity.ProjectChickin, availableQtyMap
return nil
}
// First, build map from chickins
pwMap := make(map[uint]*entity.ProductWarehouse)
for _, chickin := range chickins {
if chickin.ProductWarehouse != nil && chickin.ProductWarehouse.Id != 0 {
@@ -195,7 +191,6 @@ func toAvailableQtyDTOsFromMap(chickins []entity.ProjectChickin, availableQtyMap
}
}
// Then, add productWarehouses that are not in chickins yet
for i := range productWarehouses {
if _, exists := pwMap[productWarehouses[i].Id]; !exists {
pwMap[productWarehouses[i].Id] = &productWarehouses[i]
@@ -204,7 +199,7 @@ func toAvailableQtyDTOsFromMap(chickins []entity.ProjectChickin, availableQtyMap
result := make([]AvailableQtyDTO, 0, len(availableQtyMap))
for pwId, availableQty := range availableQtyMap {
// Skip jika available qty = 0
if availableQty <= 0 {
continue
}
@@ -98,23 +98,8 @@ func (s projectFlockKandangService) GetAll(c *fiber.Ctx, params *validation.Quer
}
if s.ApprovalSvc != nil {
projectFlockKandangIDs := make([]uint, len(projectFlockKandangs))
for i, pfk := range projectFlockKandangs {
projectFlockKandangIDs[i] = pfk.Id
}
approvalMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandangIDs, func(db *gorm.DB) *gorm.DB {
return db.Preload("ActionUser")
})
if err != nil {
s.Log.Warnf("Failed to fetch approvals for projectFlockKandangs: %+v", err)
} else {
for i := range projectFlockKandangs {
if approval, ok := approvalMap[projectFlockKandangs[i].Id]; ok {
projectFlockKandangs[i].LatestApproval = approval
}
}
}
s.fetchProjectFlockApprovals(c, projectFlockKandangs)
s.fetchChickinApprovals(c, projectFlockKandangs)
}
return projectFlockKandangs, total, nil
@@ -130,14 +115,8 @@ func (s projectFlockKandangService) GetOne(c *fiber.Ctx, id uint) (*entity.Proje
}
if len(projectFlockKandang.Chickins) > 0 && s.ApprovalSvc != nil {
latest, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandang.Id, nil)
if err != nil {
s.Log.Errorf("Failed to fetch latest kandang approval for projectFlockKandang %d: %+v", projectFlockKandang.Id, err)
}
if latest != nil {
projectFlockKandang.LatestApproval = latest
}
s.fetchProjectFlockApproval(c, projectFlockKandang)
s.fetchChickinApproval(c, projectFlockKandang)
}
availableQtyMap, err := s.getAvailableQuantities(c, projectFlockKandang)
@@ -164,6 +143,68 @@ func (s projectFlockKandangService) GetOne(c *fiber.Ctx, id uint) (*entity.Proje
return projectFlockKandang, availableQtyMap, productWarehouses, nil
}
func (s projectFlockKandangService) fetchProjectFlockApprovals(c *fiber.Ctx, projectFlockKandangs []entity.ProjectFlockKandang) {
projectFlockKandangIDs := make([]uint, len(projectFlockKandangs))
for i, pfk := range projectFlockKandangs {
projectFlockKandangIDs[i] = pfk.Id
}
approvalMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandangIDs, func(db *gorm.DB) *gorm.DB {
return db.Preload("ActionUser")
})
if err != nil {
s.Log.Warnf("Failed to fetch approvals for projectFlockKandangs: %+v", err)
} else {
for i := range projectFlockKandangs {
if approval, ok := approvalMap[projectFlockKandangs[i].Id]; ok {
projectFlockKandangs[i].LatestProjectFlockApproval = approval
}
}
}
}
func (s projectFlockKandangService) fetchChickinApprovals(c *fiber.Ctx, projectFlockKandangs []entity.ProjectFlockKandang) {
projectFlockKandangIDs := make([]uint, len(projectFlockKandangs))
for i, pfk := range projectFlockKandangs {
projectFlockKandangIDs[i] = pfk.Id
}
chickinApprovalMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), utils.ApprovalWorkflowChickin, projectFlockKandangIDs, func(db *gorm.DB) *gorm.DB {
return db.Preload("ActionUser")
})
if err != nil {
s.Log.Warnf("Failed to fetch chickin approvals for projectFlockKandangs: %+v", err)
} else {
for i := range projectFlockKandangs {
if approval, ok := chickinApprovalMap[projectFlockKandangs[i].Id]; ok {
projectFlockKandangs[i].LatestChickinApproval = approval
}
}
}
}
func (s projectFlockKandangService) fetchProjectFlockApproval(c *fiber.Ctx, projectFlockKandang *entity.ProjectFlockKandang) {
latest, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandang.Id, nil)
if err != nil {
s.Log.Errorf("Failed to fetch latest kandang approval for projectFlockKandang %d: %+v", projectFlockKandang.Id, err)
}
if latest != nil {
projectFlockKandang.LatestProjectFlockApproval = latest
}
}
func (s projectFlockKandangService) fetchChickinApproval(c *fiber.Ctx, projectFlockKandang *entity.ProjectFlockKandang) {
latestChickin, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowChickin, projectFlockKandang.Id, nil)
if err != nil {
s.Log.Errorf("Failed to fetch latest chickin approval for projectFlockKandang %d: %+v", projectFlockKandang.Id, err)
}
if latestChickin != nil {
projectFlockKandang.LatestChickinApproval = latestChickin
}
}
func (s projectFlockKandangService) getAvailableQuantities(c *fiber.Ctx, projectFlockKandang *entity.ProjectFlockKandang) (map[uint]float64, error) {
if projectFlockKandang.Kandang.Id == 0 || s.WarehouseRepo == nil || s.ProductWarehouseRepo == nil {
return nil, nil