fix(BE): merge conflict

This commit is contained in:
Hafizh A. Y
2025-10-21 15:11:04 +07:00
parent 55b14f5fc7
commit e4799fa2dd
8 changed files with 216 additions and 117 deletions
+2 -2
View File
@@ -394,9 +394,9 @@ func seedKandangs(tx *gorm.DB, createdBy uint, locations map[string]uint, users
ProjectFlockKey *string ProjectFlockKey *string
}{ }{
{Name: "Singaparna 1", Status: utils.KandangStatusActive, Location: "Singaparna", PicKey: "admin", ProjectFlockKey: strPtr("Singaparna Period 1")}, {Name: "Singaparna 1", Status: utils.KandangStatusActive, Location: "Singaparna", PicKey: "admin", ProjectFlockKey: strPtr("Singaparna Period 1")},
{Name: "Singaparna 2", Status: utils.KandangStatusNonActive, Location: "Singaparna", PicKey: "admin", ProjectFlockKey: strPtr("Singaparna Period 1")}, {Name: "Singaparna 2", Status: utils.KandangStatusNonActive, Location: "Singaparna", PicKey: "admin"},
{Name: "Cikaum 1", Status: utils.KandangStatusActive, Location: "Cikaum", PicKey: "admin", ProjectFlockKey: strPtr("Cikaum Period 1")}, {Name: "Cikaum 1", Status: utils.KandangStatusActive, Location: "Cikaum", PicKey: "admin", ProjectFlockKey: strPtr("Cikaum Period 1")},
{Name: "Cikaum 2", Status: utils.KandangStatusPengajuan, Location: "Cikaum", PicKey: "admin"}, {Name: "Cikaum 2", Status: utils.KandangStatusNonActive, Location: "Cikaum", PicKey: "admin"},
} }
result := make(map[string]uint, len(seeds)) result := make(map[string]uint, len(seeds))
+1
View File
@@ -26,4 +26,5 @@ type ProjectFlock struct {
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"` CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
Kandangs []Kandang `gorm:"foreignKey:ProjectFlockId;references:Id"` Kandangs []Kandang `gorm:"foreignKey:ProjectFlockId;references:Id"`
KandangHistory []ProjectFlockKandang `gorm:"foreignKey:ProjectFlockId;references:Id"` KandangHistory []ProjectFlockKandang `gorm:"foreignKey:ProjectFlockId;references:Id"`
LatestApproval *Approval `gorm:"-" json:"-"`
} }
@@ -17,6 +17,7 @@ type KandangRepository interface {
ProjectFlockExists(ctx context.Context, projectFlockID uint) (bool, error) ProjectFlockExists(ctx context.Context, projectFlockID uint) (bool, error)
GetFirstByProjectFlockID(ctx context.Context, projectFlockID uint) (*entity.Kandang, error) GetFirstByProjectFlockID(ctx context.Context, projectFlockID uint) (*entity.Kandang, error)
HasActiveKandangForProjectFlock(ctx context.Context, projectFlockID uint, excludeID *uint) (bool, error) HasActiveKandangForProjectFlock(ctx context.Context, projectFlockID uint, excludeID *uint) (bool, error)
UpdateStatusByProjectFlockID(ctx context.Context, projectFlockID uint, status utils.KandangStatus) error
} }
type KandangRepositoryImpl struct { type KandangRepositoryImpl struct {
@@ -81,3 +82,10 @@ func (r *KandangRepositoryImpl) GetFirstByProjectFlockID(ctx context.Context, pr
} }
return kandang, nil return kandang, nil
} }
func (r *KandangRepositoryImpl) UpdateStatusByProjectFlockID(ctx context.Context, projectFlockID uint, status utils.KandangStatus) error {
return r.db.WithContext(ctx).
Model(&entity.Kandang{}).
Where("project_flock_id = ?", projectFlockID).
Update("status", string(status)).Error
}
@@ -9,7 +9,6 @@ import (
flockBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto" flockBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto"
kandangBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
productCategoryBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/product-categories/dto"
userBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" userBaseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
) )
@@ -24,13 +23,13 @@ type ChickinBaseDTO struct {
} }
type ProjectFlockDTO struct { type ProjectFlockDTO struct {
Id uint `json:"id"` Id uint `json:"id"`
Period int `json:"period"` Period int `json:"period"`
Flock *flockBaseDTO.FlockBaseDTO `json:"flock"` Category string `json:"category"`
ProductCategory *productCategoryBaseDTO.ProductCategoryBaseDTO `json:"product_category"` Flock *flockBaseDTO.FlockBaseDTO `json:"flock"`
Area *areaBaseDTO.AreaBaseDTO `json:"area"` Area *areaBaseDTO.AreaBaseDTO `json:"area"`
Fcr *fcrBaseDTO.FcrBaseDTO `json:"fcr"` Fcr *fcrBaseDTO.FcrBaseDTO `json:"fcr"`
Location *locationBaseDTO.LocationBaseDTO `json:"location"` Location *locationBaseDTO.LocationBaseDTO `json:"location"`
} }
type ProjectFlockKandangDTO struct { type ProjectFlockKandangDTO struct {
@@ -71,11 +70,6 @@ func ToFlockDTO(e entity.Flock) flockBaseDTO.FlockBaseDTO {
func ToKandangDTO(e entity.Kandang) kandangBaseDTO.KandangBaseDTO { func ToKandangDTO(e entity.Kandang) kandangBaseDTO.KandangBaseDTO {
return kandangBaseDTO.ToKandangBaseDTO(e) return kandangBaseDTO.ToKandangBaseDTO(e)
} }
func ToProductCategoryDTO(e entity.ProductCategory) productCategoryBaseDTO.ProductCategoryBaseDTO {
return productCategoryBaseDTO.ToProductCategoryBaseDTO(e)
}
func ToAreaDTO(e entity.Area) areaBaseDTO.AreaBaseDTO { func ToAreaDTO(e entity.Area) areaBaseDTO.AreaBaseDTO {
return areaBaseDTO.ToAreaBaseDTO(e) return areaBaseDTO.ToAreaBaseDTO(e)
} }
@@ -98,11 +92,6 @@ func ToProjectFlockDTO(e entity.ProjectFlock) ProjectFlockDTO {
mapped := flockBaseDTO.ToFlockBaseDTO(e.Flock) mapped := flockBaseDTO.ToFlockBaseDTO(e.Flock)
flock = &mapped flock = &mapped
} }
var productCategory *productCategoryBaseDTO.ProductCategoryBaseDTO
if e.ProductCategory.Id != 0 {
mapped := productCategoryBaseDTO.ToProductCategoryBaseDTO(e.ProductCategory)
productCategory = &mapped
}
var area *areaBaseDTO.AreaBaseDTO var area *areaBaseDTO.AreaBaseDTO
if e.Area.Id != 0 { if e.Area.Id != 0 {
mapped := areaBaseDTO.ToAreaBaseDTO(e.Area) mapped := areaBaseDTO.ToAreaBaseDTO(e.Area)
@@ -119,13 +108,13 @@ func ToProjectFlockDTO(e entity.ProjectFlock) ProjectFlockDTO {
location = &mapped location = &mapped
} }
return ProjectFlockDTO{ return ProjectFlockDTO{
Id: e.Id, Id: e.Id,
Period: e.Period, Period: e.Period,
Flock: flock, Category: e.Category,
ProductCategory: productCategory, Flock: flock,
Area: area, Area: area,
Fcr: fcr, Fcr: fcr,
Location: location, Location: location,
} }
} }
@@ -67,7 +67,6 @@ func (s chickinService) withRelations(db *gorm.DB) *gorm.DB {
Preload("ProjectFlockKandang.Kandang.Pic"). Preload("ProjectFlockKandang.Kandang.Pic").
Preload("ProjectFlockKandang.ProjectFlock"). Preload("ProjectFlockKandang.ProjectFlock").
Preload("ProjectFlockKandang.ProjectFlock.Flock"). Preload("ProjectFlockKandang.ProjectFlock.Flock").
Preload("ProjectFlockKandang.ProjectFlock.ProductCategory").
Preload("ProjectFlockKandang.ProjectFlock.Area"). Preload("ProjectFlockKandang.ProjectFlock.Area").
Preload("ProjectFlockKandang.ProjectFlock.Fcr"). Preload("ProjectFlockKandang.ProjectFlock.Fcr").
Preload("ProjectFlockKandang.ProjectFlock.Location"). Preload("ProjectFlockKandang.ProjectFlock.Location").
@@ -129,7 +128,7 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
c.Context(), c.Context(),
projectflockkandang.ProjectFlockId, projectflockkandang.ProjectFlockId,
func(db *gorm.DB) *gorm.DB { func(db *gorm.DB) *gorm.DB {
return db.Preload("ProductCategory") return db
}, },
) )
if err != nil { if err != nil {
@@ -141,7 +140,7 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
WithContext(c.Context()). WithContext(c.Context()).
Joins("JOIN products ON products.id = product_warehouses.product_id"). Joins("JOIN products ON products.id = product_warehouses.product_id").
Joins("JOIN product_categories ON product_categories.id = products.product_category_id"). Joins("JOIN product_categories ON product_categories.id = products.product_category_id").
Where("product_categories.code = ? AND product_warehouses.warehouse_id = ?", projectFlock.ProductCategory.Code, warehouse.Id). Where("product_categories.code = ? AND product_warehouses.warehouse_id = ?", projectFlock.Category, warehouse.Id).
Order("created_at DESC"). Order("created_at DESC").
Find(&productWarehouses).Error Find(&productWarehouses).Error
if err != nil { if err != nil {
@@ -298,7 +297,7 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
c.Context(), c.Context(),
projectflockkandang.ProjectFlockId, projectflockkandang.ProjectFlockId,
func(db *gorm.DB) *gorm.DB { func(db *gorm.DB) *gorm.DB {
return db.Preload("ProductCategory") return db
}, },
) )
@@ -310,7 +309,7 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
err = s.ProductWarehouseRepo.DB().WithContext(c.Context()). err = s.ProductWarehouseRepo.DB().WithContext(c.Context()).
Joins("JOIN products ON products.id = product_warehouses.product_id"). Joins("JOIN products ON products.id = product_warehouses.product_id").
Joins("JOIN product_categories ON product_categories.id = products.product_category_id"). Joins("JOIN product_categories ON product_categories.id = products.product_category_id").
Where("product_categories.code = ? AND product_warehouses.warehouse_id = ?", projectFlock.ProductCategory.Code, warehouse.Id). Where("product_categories.code = ? AND product_warehouses.warehouse_id = ?", projectFlock.Category, warehouse.Id).
Order("created_at DESC"). Order("created_at DESC").
First(&productWarehouse).Error First(&productWarehouse).Error
@@ -70,7 +70,7 @@ func ToProjectFlockListDTO(e entity.ProjectFlock) ProjectFlockListDTO {
} }
return ProjectFlockListDTO{ return ProjectFlockListDTO{
ProjectFlockBaseDTO: ToProjectFlockBaseDTO(e), ProjectFlockBaseDTO: createProjectFlockBaseDTO(e),
Kandangs: kandangSummaries, Kandangs: kandangSummaries,
CreatedAt: e.CreatedAt, CreatedAt: e.CreatedAt,
UpdatedAt: e.UpdatedAt, UpdatedAt: e.UpdatedAt,
@@ -125,6 +125,42 @@ func defaultProjectFlockLatestApproval(e entity.ProjectFlock) approvalDTO.Approv
return result return result
} }
func createProjectFlockBaseDTO(e entity.ProjectFlock) ProjectFlockBaseDTO {
var flock *flockDTO.FlockBaseDTO
if e.Flock.Id != 0 {
mapped := flockDTO.ToFlockBaseDTO(e.Flock)
flock = &mapped
}
var area *areaDTO.AreaBaseDTO
if e.Area.Id != 0 {
mapped := areaDTO.ToAreaBaseDTO(e.Area)
area = &mapped
}
var fcr *fcrDTO.FcrBaseDTO
if e.Fcr.Id != 0 {
mapped := fcrDTO.ToFcrBaseDTO(e.Fcr)
fcr = &mapped
}
var location *locationDTO.LocationBaseDTO
if e.Location.Id != 0 {
mapped := locationDTO.ToLocationBaseDTO(e.Location)
location = &mapped
}
return ProjectFlockBaseDTO{
Id: e.Id,
Period: e.Period,
Category: e.Category,
Flock: flock,
Area: area,
Fcr: fcr,
Location: location,
}
}
func ToFlockSummaryDTO(e entity.Flock) flockDTO.FlockBaseDTO { func ToFlockSummaryDTO(e entity.Flock) flockDTO.FlockBaseDTO {
return flockDTO.FlockBaseDTO{ return flockDTO.FlockBaseDTO{
Id: e.Id, Id: e.Id,
@@ -38,7 +38,7 @@ type projectflockService struct {
Repository repository.ProjectflockRepository Repository repository.ProjectflockRepository
FlockRepo flockRepository.FlockRepository FlockRepo flockRepository.FlockRepository
KandangRepo kandangRepository.KandangRepository KandangRepo kandangRepository.KandangRepository
PivotRepo repository.ProjectFlockKandangRepository PivotRepo repository.ProjectFlockKandangRepository
ApprovalSvc commonSvc.ApprovalService ApprovalSvc commonSvc.ApprovalService
approvalWorkflow approvalutils.ApprovalWorkflowKey approvalWorkflow approvalutils.ApprovalWorkflowKey
} }
@@ -62,7 +62,7 @@ func NewProjectflockService(
Repository: repo, Repository: repo,
FlockRepo: flockRepo, FlockRepo: flockRepo,
KandangRepo: kandangRepo, KandangRepo: kandangRepo,
PivotRepo: pivotRepo, PivotRepo: pivotRepo,
ApprovalSvc: approvalSvc, ApprovalSvc: approvalSvc,
approvalWorkflow: utils.ApprovalWorkflowProjectFlock, approvalWorkflow: utils.ApprovalWorkflowProjectFlock,
} }
@@ -260,13 +260,11 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
Category: string(category), Category: string(category),
FcrId: req.FcrId, FcrId: req.FcrId,
LocationId: req.LocationId, LocationId: req.LocationId,
Period: nextPeriod,
CreatedBy: 1, CreatedBy: 1,
} }
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error { err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
projectRepo := repository.NewProjectflockRepository(tx) projectRepo := repository.NewProjectflockRepository(dbTransaction)
// kandangRepo := kandangRepository.NewKandangRepository(tx)
period, err := projectRepo.GetNextPeriodForFlock(c.Context(), req.FlockId) period, err := projectRepo.GetNextPeriodForFlock(c.Context(), req.FlockId)
if err != nil { if err != nil {
@@ -278,33 +276,13 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
return err return err
} }
// kandangUpdates := make([]*entity.Kandang, len(kandangs)) if err := s.attachKandangs(c.Context(), dbTransaction, createBody.Id, kandangIDs); err != nil {
// for i := range kandangs {
// kandangs[i].ProjectFlockId = &createBody.Id
// kandangUpdates[i] = &kandangs[i]
// }
// if err := kandangRepo.UpdateMany(
// c.Context(),
// kandangUpdates,
// func(db *gorm.DB) *gorm.DB {
// return db.Select("project_flock_id")
// },
// ); err != nil {
// return err
// }
if err := tx.Model(&entity.Kandang{}).
Where("id IN ?", kandangIDs).
Updates(map[string]any{
"project_flock_id": createBody.Id,
"status": string(utils.KandangStatusPengajuan),
}).Error; err != nil {
return err return err
} }
actorID := uint(1) //TODO: Change From Auth actorID := uint(1) //TODO: Change From Auth
action := entity.ApprovalActionCreated action := entity.ApprovalActionCreated
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(tx)) approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
_, err = approvalSvcTx.CreateApproval( _, err = approvalSvcTx.CreateApproval(
c.Context(), c.Context(),
utils.ApprovalWorkflowProjectFlock, utils.ApprovalWorkflowProjectFlock,
@@ -325,17 +303,6 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
return nil, err return nil, err
} }
if err := s.attachKandangs(c.Context(), tx, createBody.Id, kandangIDs); err != nil {
tx.Rollback()
s.Log.Errorf("Failed to attach kandangs to projectflock %d: %+v", createBody.Id, err)
return nil, err
}
if err := tx.Commit().Error; err != nil {
tx.Rollback()
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to commit transaction")
}
return s.GetOne(c, createBody.Id) return s.GetOne(c, createBody.Id)
} }
@@ -399,10 +366,6 @@ func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id
Exists: relationExistsChecker[entity.Location](s.Repository.DB()), Exists: relationExistsChecker[entity.Location](s.Repository.DB()),
}) })
} }
if req.Period != nil {
updateBody["period"] = *req.Period
hasBodyChanges = true
}
if len(relationChecks) > 0 { if len(relationChecks) > 0 {
if err := commonSvc.EnsureRelations(c.Context(), relationChecks...); err != nil { if err := commonSvc.EnsureRelations(c.Context(), relationChecks...); err != nil {
@@ -440,8 +403,8 @@ func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id
return s.GetOne(c, id) return s.GetOne(c, id)
} }
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error { err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
projectRepo := repository.NewProjectflockRepository(tx) projectRepo := repository.NewProjectflockRepository(dbTransaction)
if len(updateBody) > 0 { if len(updateBody) > 0 {
if err := projectRepo.PatchOne(c.Context(), id, updateBody, nil); err != nil { if err := projectRepo.PatchOne(c.Context(), id, updateBody, nil); err != nil {
@@ -477,26 +440,136 @@ func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id
} }
} }
if len(toDetach) > 0 { if len(toDetach) > 0 {
if err := s.detachKandangs(c.Context(), tx, id, toDetach, false); err != nil { if err := s.detachKandangs(c.Context(), dbTransaction, id, toDetach, true); err != nil {
tx.Rollback() return err
s.Log.Errorf("Failed to detach kandangs from projectflock %d: %+v", id, err) }
return nil, err }
if len(toAttach) > 0 {
if err := s.attachKandangs(c.Context(), dbTransaction, id, toAttach); err != nil {
return err
}
} }
} }
if len(toAttach) > 0 { if hasChanges {
if err := s.attachKandangs(c.Context(), tx, id, toAttach); err != nil { actorID := uint(1) //TODO: Change From Auth
tx.Rollback() approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
s.Log.Errorf("Failed to attach kandangs to projectflock %d: %+v", id, err) if approvalSvc != nil {
return nil, err latestBeforeReset, err := approvalSvc.LatestByTarget(c.Context(), s.approvalWorkflow, id, nil)
if err != nil {
return err
}
shouldRecordUpdate := latestBeforeReset == nil ||
latestBeforeReset.StepNumber != uint16(utils.ProjectFlockStepPengajuan) ||
latestBeforeReset.Action == nil ||
(latestBeforeReset.Action != nil && *latestBeforeReset.Action != entity.ApprovalActionUpdated)
if shouldRecordUpdate {
action := entity.ApprovalActionUpdated
if _, err := approvalSvc.CreateApproval(
c.Context(),
utils.ApprovalWorkflowProjectFlock,
id,
utils.ProjectFlockStepPengajuan,
&action,
actorID,
nil,
); err != nil {
return err
}
}
} }
} }
return nil
})
if err != nil {
if fiberErr, ok := err.(*fiber.Error); ok {
return nil, fiberErr
}
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Projectflock not found")
}
s.Log.Errorf("Failed to update projectflock %d: %+v", id, err)
return nil, err
} }
if err := tx.Commit().Error; err != nil { return s.GetOne(c, id)
tx.Rollback() }
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to commit transaction")
func (s projectflockService) Approval(c *fiber.Ctx, id uint, req *validation.Approve) (*entity.ProjectFlock, error) {
if err := s.Validate.Struct(req); err != nil {
return nil, err
}
project, err := s.GetOne(c, id)
if err != nil {
s.Log.Errorf("Failed to fetch projectflock %d before approval: %+v", id, err)
return nil, err
}
actorID := uint(1) // TODO: change from auth context
var action entity.ApprovalAction
switch strings.ToUpper(strings.TrimSpace(req.Action)) {
case string(entity.ApprovalActionRejected):
action = entity.ApprovalActionRejected
case string(entity.ApprovalActionApproved):
action = entity.ApprovalActionApproved
default:
return nil, fiber.NewError(fiber.StatusBadRequest, "action must be APPROVED or REJECTED")
}
step := utils.ProjectFlockStepPengajuan
if action == entity.ApprovalActionApproved {
step = utils.ProjectFlockStepAktif
}
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
if _, err := approvalSvc.CreateApproval(
c.Context(),
utils.ApprovalWorkflowProjectFlock,
project.Id,
step,
&action,
actorID,
req.Notes,
); err != nil {
return err
}
kandangRepoTx := kandangRepository.NewKandangRepository(dbTransaction)
switch action {
case entity.ApprovalActionApproved:
if err := kandangRepoTx.UpdateStatusByProjectFlockID(
c.Context(),
project.Id,
utils.KandangStatusActive,
); err != nil {
return err
}
case entity.ApprovalActionRejected:
if err := kandangRepoTx.UpdateStatusByProjectFlockID(
c.Context(),
project.Id,
utils.KandangStatusNonActive,
); err != nil {
return err
}
}
return nil
})
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Projectflock not found")
}
s.Log.Errorf("Failed to record approval for projectflock %d: %+v", id, err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to record approval")
} }
return s.GetOne(c, id) return s.GetOne(c, id)
@@ -512,24 +585,18 @@ func (s projectflockService) DeleteOne(c *fiber.Ctx, id uint) error {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch project flock") return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch project flock")
} }
tx := s.Repository.DB().Begin() err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
if tx.Error != nil { if len(existing.Kandangs) > 0 {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to start transaction") ids := make([]uint, len(existing.Kandangs))
} for i, k := range existing.Kandangs {
ids[i] = k.Id
if len(existing.Kandangs) > 0 { }
ids := make([]uint, len(existing.Kandangs)) if err := s.detachKandangs(c.Context(), dbTransaction, id, ids, true); err != nil {
for i, k := range existing.Kandangs { return err
ids[i] = k.Id }
} }
if err := s.detachKandangs(c.Context(), tx, id, ids, true); err != nil {
tx.Rollback()
s.Log.Errorf("Failed to detach kandangs before deleting projectflock %d: %+v", id, err)
return err
}
}
if err := repository.NewProjectflockRepository(tx).DeleteOne(c.Context(), id); err != nil { if err := repository.NewProjectflockRepository(dbTransaction).DeleteOne(c.Context(), id); err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, "Projectflock not found") return fiber.NewError(fiber.StatusNotFound, "Projectflock not found")
} }
@@ -627,12 +694,12 @@ func (s projectflockService) buildOrderExpressions(sortBy, sortOrder string) []s
} }
} }
func (s projectflockService) attachKandangs(ctx context.Context, tx *gorm.DB, projectFlockID uint, kandangIDs []uint) error { func (s projectflockService) attachKandangs(ctx context.Context, dbTransaction *gorm.DB, projectFlockID uint, kandangIDs []uint) error {
if len(kandangIDs) == 0 { if len(kandangIDs) == 0 {
return nil return nil
} }
if err := tx.Model(&entity.Kandang{}). if err := dbTransaction.Model(&entity.Kandang{}).
Where("id IN ?", kandangIDs). Where("id IN ?", kandangIDs).
Updates(map[string]any{ Updates(map[string]any{
"project_flock_id": projectFlockID, "project_flock_id": projectFlockID,
@@ -641,7 +708,7 @@ func (s projectflockService) attachKandangs(ctx context.Context, tx *gorm.DB, pr
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs") return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs")
} }
pivotRepo := s.pivotRepoWithTx(tx) pivotRepo := s.pivotRepoWithTx(dbTransaction)
records := make([]*entity.ProjectFlockKandang, len(kandangIDs)) records := make([]*entity.ProjectFlockKandang, len(kandangIDs))
for i, id := range kandangIDs { for i, id := range kandangIDs {
records[i] = &entity.ProjectFlockKandang{ records[i] = &entity.ProjectFlockKandang{
@@ -655,7 +722,7 @@ func (s projectflockService) attachKandangs(ctx context.Context, tx *gorm.DB, pr
return nil return nil
} }
func (s projectflockService) detachKandangs(ctx context.Context, tx *gorm.DB, projectFlockID uint, kandangIDs []uint, resetStatus bool) error { func (s projectflockService) detachKandangs(ctx context.Context, dbTransaction *gorm.DB, projectFlockID uint, kandangIDs []uint, resetStatus bool) error {
if len(kandangIDs) == 0 { if len(kandangIDs) == 0 {
return nil return nil
} }
@@ -665,21 +732,21 @@ func (s projectflockService) detachKandangs(ctx context.Context, tx *gorm.DB, pr
updates["status"] = string(utils.KandangStatusNonActive) updates["status"] = string(utils.KandangStatusNonActive)
} }
if err := tx.Model(&entity.Kandang{}). if err := dbTransaction.Model(&entity.Kandang{}).
Where("id IN ?", kandangIDs). Where("id IN ?", kandangIDs).
Updates(updates).Error; err != nil { Updates(updates).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs") return fiber.NewError(fiber.StatusInternalServerError, "Failed to update kandangs")
} }
if err := s.pivotRepoWithTx(tx).DeleteMany(ctx, projectFlockID, kandangIDs); err != nil { if err := s.pivotRepoWithTx(dbTransaction).DeleteMany(ctx, projectFlockID, kandangIDs); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to persist project flock history") return fiber.NewError(fiber.StatusInternalServerError, "Failed to persist project flock history")
} }
return nil return nil
} }
func (s projectflockService) pivotRepoWithTx(tx *gorm.DB) repository.ProjectFlockKandangRepository { func (s projectflockService) pivotRepoWithTx(dbTransaction *gorm.DB) repository.ProjectFlockKandangRepository {
if s.PivotRepo == nil { if s.PivotRepo == nil {
return repository.NewProjectFlockKandangRepository(tx) return repository.NewProjectFlockKandangRepository(dbTransaction)
} }
return s.PivotRepo.WithTx(tx) return s.PivotRepo.WithTx(dbTransaction)
} }
@@ -15,7 +15,6 @@ type Update struct {
Category *string `json:"category,omitempty" validate:"omitempty,oneof=growing laying GROWING LAYING"` Category *string `json:"category,omitempty" validate:"omitempty,oneof=growing laying GROWING LAYING"`
FcrId *uint `json:"fcr_id,omitempty" validate:"omitempty,number,gt=0"` FcrId *uint `json:"fcr_id,omitempty" validate:"omitempty,number,gt=0"`
LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"` LocationId *uint `json:"location_id,omitempty" validate:"omitempty,number,gt=0"`
Period *int `json:"period,omitempty" validate:"omitempty,number,gt=0"`
KandangIds []uint `json:"kandang_ids,omitempty" validate:"omitempty,min=1,dive,gt=0"` KandangIds []uint `json:"kandang_ids,omitempty" validate:"omitempty,min=1,dive,gt=0"`
} }