add pagination approval flows
This commit is contained in:
parent
239f052a9a
commit
3717b0b53c
@ -245,7 +245,8 @@ type ApprovalFlowStepResponse struct {
|
|||||||
|
|
||||||
type ListApprovalFlowsRequest struct {
|
type ListApprovalFlowsRequest struct {
|
||||||
Limit int `json:"limit"`
|
Limit int `json:"limit"`
|
||||||
Offset int `json:"offset"`
|
Page int `json:"page"`
|
||||||
|
Search *string `json:"search"`
|
||||||
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
|
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
|
||||||
IsActive *bool `json:"is_active,omitempty"`
|
IsActive *bool `json:"is_active,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -159,42 +159,47 @@ func (h *AdminApprovalFlowHandler) DeleteApprovalFlow(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *AdminApprovalFlowHandler) ListApprovalFlows(c *gin.Context) {
|
func (h *AdminApprovalFlowHandler) ListApprovalFlows(c *gin.Context) {
|
||||||
|
// Parse query params
|
||||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||||
offset := (page - 1) * limit
|
|
||||||
|
// Parse department_id
|
||||||
departmentIDStr := c.Query("department_id")
|
|
||||||
isActiveStr := c.Query("is_active")
|
|
||||||
|
|
||||||
var departmentID *uuid.UUID
|
var departmentID *uuid.UUID
|
||||||
var isActive *bool
|
if departmentIDStr := c.Query("department_id"); departmentIDStr != "" {
|
||||||
|
|
||||||
if departmentIDStr != "" {
|
|
||||||
if id, err := uuid.Parse(departmentIDStr); err == nil {
|
if id, err := uuid.Parse(departmentIDStr); err == nil {
|
||||||
departmentID = &id
|
departmentID = &id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isActiveStr != "" {
|
// Parse is_active
|
||||||
if isActiveStr == "true" {
|
var isActive *bool
|
||||||
active := true
|
if isActiveStr := c.Query("is_active"); isActiveStr != "" {
|
||||||
isActive = &active
|
if active, err := strconv.ParseBool(isActiveStr); err == nil {
|
||||||
} else if isActiveStr == "false" {
|
|
||||||
active := false
|
|
||||||
isActive = &active
|
isActive = &active
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse search
|
||||||
|
var search *string
|
||||||
|
if searchStr := c.Query("search"); searchStr != "" {
|
||||||
|
search = &searchStr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build request - pass PAGE, bukan OFFSET
|
||||||
req := &contract.ListApprovalFlowsRequest{
|
req := &contract.ListApprovalFlowsRequest{
|
||||||
|
Page: page, // ✅ Pass page number
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
|
||||||
DepartmentID: departmentID,
|
DepartmentID: departmentID,
|
||||||
IsActive: isActive,
|
IsActive: isActive,
|
||||||
|
Search: search, // tambahkan ini juga
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := h.svc.ListApprovalFlows(c.Request.Context(), req)
|
resp, err := h.svc.ListApprovalFlows(c.Request.Context(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{
|
||||||
|
Error: err.Error(),
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +215,7 @@ func (h *AdminApprovalFlowHandler) ListApprovalFlowsByDepartment(c *gin.Context)
|
|||||||
|
|
||||||
req := &contract.ListApprovalFlowsRequest{
|
req := &contract.ListApprovalFlowsRequest{
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
Page: offset,
|
||||||
DepartmentID: &appCtx.DepartmentID,
|
DepartmentID: &appCtx.DepartmentID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -368,7 +368,7 @@ func (p *NotificationProcessorImpl) SendOutgoingLetterNotification(ctx context.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build notification URL for outgoing letters
|
// Build notification URL for outgoing letters
|
||||||
url := fmt.Sprintf("/en/apps/surat-menyurat/keluar-detail/%s", letterID.String())
|
url := fmt.Sprintf("/en/apps/surat-keluar-detail/%s", letterID.String())
|
||||||
|
|
||||||
// Use workflow ID from config (defaults to "notification-dashbpard")
|
// Use workflow ID from config (defaults to "notification-dashbpard")
|
||||||
workflowID := p.workflowID
|
workflowID := p.workflowID
|
||||||
|
|||||||
@ -66,37 +66,64 @@ func (r *ApprovalFlowRepository) Delete(ctx context.Context, id uuid.UUID) error
|
|||||||
|
|
||||||
type ListApprovalFlowsFilter struct {
|
type ListApprovalFlowsFilter struct {
|
||||||
DepartmentID *uuid.UUID
|
DepartmentID *uuid.UUID
|
||||||
|
Search *string
|
||||||
IsActive *bool
|
IsActive *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ApprovalFlowRepository) List(ctx context.Context, filter ListApprovalFlowsFilter, limit, offset int) ([]entities.ApprovalFlow, int64, error) {
|
func (r *ApprovalFlowRepository) List(ctx context.Context, filter ListApprovalFlowsFilter, limit, offset int) ([]entities.ApprovalFlow, int64, error) {
|
||||||
db := DBFromContext(ctx, r.db)
|
var list []entities.ApprovalFlow
|
||||||
query := db.WithContext(ctx).Model(&entities.ApprovalFlow{})
|
var total int64
|
||||||
|
|
||||||
|
// Build base query for counting
|
||||||
|
countQuery := r.db.WithContext(ctx).Model(&entities.ApprovalFlow{})
|
||||||
|
|
||||||
if filter.DepartmentID != nil {
|
if filter.DepartmentID != nil {
|
||||||
query = query.Where("department_id = ?", *filter.DepartmentID)
|
countQuery = countQuery.Where("department_id = ?", *filter.DepartmentID)
|
||||||
}
|
|
||||||
if filter.IsActive != nil {
|
|
||||||
query = query.Where("is_active = ?", *filter.IsActive)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var total int64
|
if filter.IsActive != nil {
|
||||||
if err := query.Count(&total).Error; err != nil {
|
countQuery = countQuery.Where("is_active = ?", *filter.IsActive)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Search != nil && *filter.Search != "" {
|
||||||
|
like := "%" + *filter.Search + "%"
|
||||||
|
countQuery = countQuery.Where("name ILIKE ? OR description ILIKE ?", like, like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get total count
|
||||||
|
if err := countQuery.Count(&total).Error; err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build query for fetching data - BUAT QUERY BARU DARI AWAL
|
||||||
|
dataQuery := r.db.WithContext(ctx).Model(&entities.ApprovalFlow{})
|
||||||
|
|
||||||
var list []entities.ApprovalFlow
|
if filter.DepartmentID != nil {
|
||||||
if err := query.
|
dataQuery = dataQuery.Where("department_id = ?", *filter.DepartmentID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.IsActive != nil {
|
||||||
|
dataQuery = dataQuery.Where("is_active = ?", *filter.IsActive)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Search != nil && *filter.Search != "" {
|
||||||
|
like := "%" + *filter.Search + "%"
|
||||||
|
dataQuery = dataQuery.Where("name ILIKE ? OR description ILIKE ?", like, like)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch data with pagination and preloads
|
||||||
|
if err := dataQuery.
|
||||||
|
Order("created_at DESC").
|
||||||
|
Limit(limit).
|
||||||
|
Offset(offset).
|
||||||
Preload("Department").
|
Preload("Department").
|
||||||
Preload("Steps", func(db *gorm.DB) *gorm.DB {
|
Preload("Steps", func(db *gorm.DB) *gorm.DB {
|
||||||
return db.Order("step_order ASC, parallel_group ASC")
|
return db.Order("step_order ASC, parallel_group ASC")
|
||||||
}).
|
}).
|
||||||
Order("created_at DESC").
|
|
||||||
Limit(limit).
|
|
||||||
Offset(offset).
|
|
||||||
Find(&list).Error; err != nil {
|
Find(&list).Error; err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return list, total, nil
|
return list, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -173,10 +173,26 @@ func (s *ApprovalFlowServiceImpl) DeleteApprovalFlow(ctx context.Context, id uui
|
|||||||
func (s *ApprovalFlowServiceImpl) ListApprovalFlows(ctx context.Context, req *contract.ListApprovalFlowsRequest) (*contract.ListApprovalFlowsResponse, error) {
|
func (s *ApprovalFlowServiceImpl) ListApprovalFlows(ctx context.Context, req *contract.ListApprovalFlowsRequest) (*contract.ListApprovalFlowsResponse, error) {
|
||||||
filter := repository.ListApprovalFlowsFilter{
|
filter := repository.ListApprovalFlowsFilter{
|
||||||
DepartmentID: req.DepartmentID,
|
DepartmentID: req.DepartmentID,
|
||||||
|
Search: req.Search,
|
||||||
IsActive: req.IsActive,
|
IsActive: req.IsActive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
page := req.Page
|
||||||
|
if page <= 0 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
|
||||||
flows, total, err := s.flowRepo.List(ctx, filter, req.Limit, req.Offset)
|
limit := req.Limit
|
||||||
|
if limit <= 0 {
|
||||||
|
limit = 10
|
||||||
|
}
|
||||||
|
if limit > 100 {
|
||||||
|
limit = 100 // Max limit to prevent performance issues
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := (page - 1) * limit
|
||||||
|
|
||||||
|
flows, total, err := s.flowRepo.List(ctx, filter, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user