mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Merge branch 'dev/teguh' into 'development'
fix(BE): fix error get location id when only attach to location in expense See merge request mbugroup/lti-api!119
This commit is contained in:
+20
@@ -0,0 +1,20 @@
|
||||
-- Drop CASCADE constraint
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'fk_project_chickins_kandang'
|
||||
AND conrelid = 'project_chickins'::regclass
|
||||
) THEN
|
||||
ALTER TABLE project_chickins
|
||||
DROP CONSTRAINT fk_project_chickins_kandang;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Recreate foreign key constraint with RESTRICT (original behavior)
|
||||
ALTER TABLE project_chickins
|
||||
ADD CONSTRAINT fk_project_chickins_kandang
|
||||
FOREIGN KEY (project_flock_kandang_id)
|
||||
REFERENCES project_flock_kandangs(id)
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,20 @@
|
||||
-- Drop existing foreign key constraint with RESTRICT
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'fk_project_chickins_kandang'
|
||||
AND conrelid = 'project_chickins'::regclass
|
||||
) THEN
|
||||
ALTER TABLE project_chickins
|
||||
DROP CONSTRAINT fk_project_chickins_kandang;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Add new foreign key constraint with CASCADE delete
|
||||
ALTER TABLE project_chickins
|
||||
ADD CONSTRAINT fk_project_chickins_kandang
|
||||
FOREIGN KEY (project_flock_kandang_id)
|
||||
REFERENCES project_flock_kandangs(id)
|
||||
ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -203,12 +203,12 @@ func (u *ExpenseController) UpdateOne(c *fiber.Ctx) error {
|
||||
func (u *ExpenseController) DeleteOne(c *fiber.Ctx) error {
|
||||
param := c.Params("id")
|
||||
|
||||
id, err := strconv.Atoi(param)
|
||||
id64, err := strconv.ParseUint(param, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
|
||||
}
|
||||
|
||||
if err := u.ExpenseService.DeleteOne(c, uint(id)); err != nil {
|
||||
if err := u.ExpenseService.DeleteOne(c, id64); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -105,12 +105,10 @@ func ToExpenseBaseDTO(e *entity.Expense) ExpenseBaseDTO {
|
||||
realizationDate = &e.RealizationDate
|
||||
}
|
||||
|
||||
if len(e.Nonstocks) > 0 && e.Nonstocks[0].Kandang != nil {
|
||||
if e.Nonstocks[0].Kandang.Location.Id != 0 {
|
||||
mapped := locationDTO.ToLocationRelationDTO(e.Nonstocks[0].Kandang.Location)
|
||||
if e.Location != nil && e.Location.Id != 0 {
|
||||
mapped := locationDTO.ToLocationRelationDTO(*e.Location)
|
||||
location = &mapped
|
||||
}
|
||||
}
|
||||
|
||||
if e.Supplier != nil && e.Supplier.Id != 0 {
|
||||
mapped := supplierDTO.ToSupplierRelationDTO(*e.Supplier)
|
||||
|
||||
@@ -3,6 +3,8 @@ package repository
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
@@ -17,6 +19,7 @@ type ExpenseRepository interface {
|
||||
GetWithSupplier(ctx context.Context, id uint64) (*entity.Expense, error)
|
||||
WithProjectFlockKandangFilter(pfkID, kandangID uint) func(*gorm.DB) *gorm.DB
|
||||
CountUnfinishedByProjectFlockKandang(ctx context.Context, pfkID, kandangID uint, isFinished func(*entity.Approval) bool) (int64, error)
|
||||
DeleteOne(ctx context.Context, id uint) error
|
||||
}
|
||||
|
||||
type ExpenseRepositoryImpl struct {
|
||||
@@ -107,3 +110,23 @@ func (r *ExpenseRepositoryImpl) CountUnfinishedByProjectFlockKandang(ctx context
|
||||
}
|
||||
return unfinished, nil
|
||||
}
|
||||
|
||||
func (r *ExpenseRepositoryImpl) DeleteOne(ctx context.Context, id uint) error {
|
||||
// Cast to uint64 to match entity.Id type
|
||||
id64 := uint64(id)
|
||||
deletedAt := time.Now()
|
||||
|
||||
// Use raw SQL with interpolated integer to avoid type issues
|
||||
// Interpolate id directly as integer literal (safe because it's uint64)
|
||||
result := r.DB().WithContext(ctx).
|
||||
Exec(`UPDATE "expenses" SET "deleted_at" = $1 WHERE "id" = `+fmt.Sprintf("%d", id64)+` AND "deleted_at" IS NULL`,
|
||||
deletedAt)
|
||||
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -22,16 +22,16 @@ func ExpenseRoutes(v1 fiber.Router, u user.UserService, s expense.ExpenseService
|
||||
// route.Patch("/:id", m.Auth(u), ctrl.UpdateOne)
|
||||
// route.Delete("/:id", m.Auth(u), ctrl.DeleteOne)
|
||||
|
||||
route.Get("/",m.RequirePermissions(m.P_ExpenseGetAll), ctrl.GetAll)
|
||||
route.Post("/",m.RequirePermissions(m.P_ExpenseCreateOne), ctrl.CreateOne)
|
||||
route.Get("/:id",m.RequirePermissions(m.P_ExpenseGetOne), ctrl.GetOne)
|
||||
route.Patch("/:id",m.RequirePermissions(m.P_ExpenseUpdateOne), ctrl.UpdateOne)
|
||||
route.Delete("/:id",m.RequirePermissions(m.P_ExpenseDeleteOne), ctrl.DeleteOne)
|
||||
route.Post("/approvals/manager",m.RequirePermissions(m.P_ExpenseApprovalManager), ctrl.Approval)
|
||||
route.Post("/approvals/finance",m.RequirePermissions(m.P_ExpenseApprovalFinance), ctrl.Approval)
|
||||
route.Post("/:id/realizations",m.RequirePermissions(m.P_ExpenseCreateRealizations), ctrl.CreateRealization)
|
||||
route.Patch("/:id/realizations",m.RequirePermissions(m.P_ExpenseUpdateRealizations), ctrl.UpdateRealization)
|
||||
route.Post("/:id/complete",m.RequirePermissions(m.P_ExpenseCompleteExpense), ctrl.CompleteExpense)
|
||||
route.Delete("/:id/documents/:documentId",m.RequirePermissions(m.P_ExpenseDocument), ctrl.DeleteDocument)
|
||||
route.Delete("/:id/realization-documents/:documentId",m.RequirePermissions(m.P_ExpenseDocumentRealizations), ctrl.DeleteRealizationDocument)
|
||||
route.Get("/", m.RequirePermissions(m.P_ExpenseGetAll), ctrl.GetAll)
|
||||
route.Post("/", m.RequirePermissions(m.P_ExpenseCreateOne), ctrl.CreateOne)
|
||||
route.Get("/:id", m.RequirePermissions(m.P_ExpenseGetOne), ctrl.GetOne)
|
||||
route.Patch("/:id", m.RequirePermissions(m.P_ExpenseUpdateOne), ctrl.UpdateOne)
|
||||
route.Delete("/:id", m.RequirePermissions(m.P_ExpenseDeleteOne), ctrl.DeleteOne)
|
||||
route.Post("/approvals/manager", m.RequirePermissions(m.P_ExpenseApprovalManager), ctrl.Approval)
|
||||
route.Post("/approvals/finance", m.RequirePermissions(m.P_ExpenseApprovalFinance), ctrl.Approval)
|
||||
route.Post("/:id/realizations", m.RequirePermissions(m.P_ExpenseCreateRealizations), ctrl.CreateRealization)
|
||||
route.Patch("/:id/realizations", m.RequirePermissions(m.P_ExpenseUpdateRealizations), ctrl.UpdateRealization)
|
||||
route.Post("/:id/complete", m.RequirePermissions(m.P_ExpenseCompleteExpense), ctrl.CompleteExpense)
|
||||
route.Delete("/:id/documents/:documentId", m.RequirePermissions(m.P_ExpenseDocument), ctrl.DeleteDocument)
|
||||
route.Delete("/:id/realization-documents/:documentId", m.RequirePermissions(m.P_ExpenseDocumentRealizations), ctrl.DeleteRealizationDocument)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ type ExpenseService interface {
|
||||
GetOne(ctx *fiber.Ctx, id uint) (*expenseDto.ExpenseDetailDTO, error)
|
||||
CreateOne(ctx *fiber.Ctx, req *validation.Create) (*expenseDto.ExpenseDetailDTO, error)
|
||||
UpdateOne(ctx *fiber.Ctx, req *validation.Update, id uint) (*expenseDto.ExpenseDetailDTO, error)
|
||||
DeleteOne(ctx *fiber.Ctx, id uint) error
|
||||
DeleteOne(ctx *fiber.Ctx, id uint64) error
|
||||
CreateRealization(ctx *fiber.Ctx, expenseID uint, req *validation.CreateRealization) (*expenseDto.ExpenseDetailDTO, error)
|
||||
CompleteExpense(ctx *fiber.Ctx, id uint, notes *string) (*expenseDto.ExpenseDetailDTO, error)
|
||||
UpdateRealization(ctx *fiber.Ctx, expenseID uint, req *validation.UpdateRealization) (*expenseDto.ExpenseDetailDTO, error)
|
||||
@@ -68,6 +68,7 @@ func (s expenseService) withRelations(db *gorm.DB) *gorm.DB {
|
||||
return db.
|
||||
Preload("CreatedUser").
|
||||
Preload("Supplier").
|
||||
Preload("Location").
|
||||
Preload("Nonstocks.Nonstock").
|
||||
Preload("Nonstocks.Realization").
|
||||
Preload("Nonstocks.ProjectFlockKandang.Kandang.Location").
|
||||
@@ -621,14 +622,15 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
||||
return responseDTO, nil
|
||||
}
|
||||
|
||||
func (s expenseService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
func (s expenseService) DeleteOne(c *fiber.Ctx, id uint64) error {
|
||||
idUint := uint(id)
|
||||
|
||||
if err := commonSvc.EnsureRelations(c.Context(),
|
||||
commonSvc.RelationCheck{Name: "Expense", ID: &id, Exists: s.Repository.IdExists},
|
||||
commonSvc.RelationCheck{Name: "Expense", ID: &idUint, Exists: s.Repository.IdExists},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
expense, err := s.Repository.GetByID(c.Context(), id, func(db *gorm.DB) *gorm.DB {
|
||||
expense, err := s.Repository.GetByID(c.Context(), idUint, func(db *gorm.DB) *gorm.DB {
|
||||
return db.Preload("Nonstocks")
|
||||
})
|
||||
if err != nil {
|
||||
@@ -643,7 +645,7 @@ func (s expenseService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
if err := s.ensureProjectFlockNotClosedForExpense(c.Context(), expense); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Repository.DeleteOne(c.Context(), id); err != nil {
|
||||
if err := s.Repository.DeleteOne(c.Context(), idUint); err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
s.Log.Errorf("Expense not found for ID %d: %+v", id, err)
|
||||
return fiber.NewError(fiber.StatusNotFound, "Expense not found")
|
||||
|
||||
@@ -118,10 +118,9 @@ func (s *adjustmentService) Adjustment(c *fiber.Ctx, req *validation.Create) (*e
|
||||
var createdLogId uint
|
||||
|
||||
var projectFlockKandangID *uint
|
||||
pfk, err := s.ProjectFlockKandangRepo.GetActiveByKandangID(ctx, uint(req.WarehouseID))
|
||||
if err == nil && pfk != nil {
|
||||
idCopy := uint(pfk.Id)
|
||||
projectFlockKandangID = &idCopy
|
||||
pfkID, err := s.getActiveProjectFlockKandangID(ctx, uint(req.WarehouseID))
|
||||
if err == nil && pfkID > 0 {
|
||||
projectFlockKandangID = &pfkID
|
||||
}
|
||||
|
||||
pw, err := s.ProductWarehouseRepo.FindByProductWarehouseAndPfk(
|
||||
|
||||
@@ -59,6 +59,14 @@ func (s nonstockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entit
|
||||
|
||||
nonstocks, total, err := s.Repository.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
|
||||
db = s.withRelations(db)
|
||||
|
||||
if params.SupplierID != nil {
|
||||
supplierID := *params.SupplierID
|
||||
db = db.Joins("JOIN nonstock_suppliers ON nonstock_suppliers.nonstock_id = nonstocks.id").
|
||||
Where("nonstock_suppliers.supplier_id = ?", supplierID).
|
||||
Group("nonstocks.id") // Prevent duplicates from join
|
||||
}
|
||||
|
||||
if params.Search != "" {
|
||||
return db.Where("name LIKE ?", "%"+params.Search+"%")
|
||||
}
|
||||
|
||||
@@ -18,4 +18,5 @@ type Query struct {
|
||||
Page int `query:"page" validate:"omitempty,number,min=1"`
|
||||
Limit int `query:"limit" validate:"omitempty,number,min=1,max=100"`
|
||||
Search string `query:"search" validate:"omitempty,max=50"`
|
||||
SupplierID *uint `query:"supplier_id" validate:"omitempty,gt=0"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user