Update
This commit is contained in:
@@ -2,6 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"eslogad-be/internal/appcontext"
|
||||
|
||||
"eslogad-be/internal/contract"
|
||||
|
||||
@@ -71,12 +72,9 @@ func (h *DispositionRouteHandler) Get(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *DispositionRouteHandler) ListByFromDept(c *gin.Context) {
|
||||
fromID, err := uuid.Parse(c.Param("from_department_id"))
|
||||
if err != nil {
|
||||
c.JSON(400, &contract.ErrorResponse{Error: "invalid from_department_id", Code: 400})
|
||||
return
|
||||
}
|
||||
resp, err := h.svc.ListByFromDept(c.Request.Context(), fromID)
|
||||
appCtx := appcontext.FromGinContext(c.Request.Context())
|
||||
|
||||
resp, err := h.svc.ListByFromDept(c.Request.Context(), appCtx.DepartmentID)
|
||||
if err != nil {
|
||||
c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
|
||||
@@ -2,6 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"eslogad-be/internal/appcontext"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
@@ -19,7 +20,7 @@ type LetterService interface {
|
||||
SoftDeleteIncomingLetter(ctx context.Context, id uuid.UUID) error
|
||||
|
||||
CreateDispositions(ctx context.Context, req *contract.CreateLetterDispositionRequest) (*contract.ListDispositionsResponse, error)
|
||||
ListDispositionsByLetter(ctx context.Context, letterID uuid.UUID) (*contract.ListDispositionsResponse, error)
|
||||
GetEnhancedDispositionsByLetter(ctx context.Context, letterID uuid.UUID) (*contract.ListEnhancedDispositionsResponse, error)
|
||||
|
||||
CreateDiscussion(ctx context.Context, letterID uuid.UUID, req *contract.CreateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, error)
|
||||
UpdateDiscussion(ctx context.Context, letterID uuid.UUID, discussionID uuid.UUID, req *contract.UpdateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, error)
|
||||
@@ -112,11 +113,13 @@ func (h *LetterHandler) DeleteIncomingLetter(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *LetterHandler) CreateDispositions(c *gin.Context) {
|
||||
appCtx := appcontext.FromGinContext(c.Request.Context())
|
||||
var req contract.CreateLetterDispositionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
|
||||
return
|
||||
}
|
||||
req.FromDepartment = appCtx.DepartmentID
|
||||
resp, err := h.svc.CreateDispositions(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
@@ -125,13 +128,13 @@ func (h *LetterHandler) CreateDispositions(c *gin.Context) {
|
||||
c.JSON(201, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *LetterHandler) ListDispositionsByLetter(c *gin.Context) {
|
||||
func (h *LetterHandler) GetEnhancedDispositionsByLetter(c *gin.Context) {
|
||||
letterID, err := uuid.Parse(c.Param("letter_id"))
|
||||
if err != nil {
|
||||
c.JSON(400, &contract.ErrorResponse{Error: "invalid letter_id", Code: 400})
|
||||
return
|
||||
}
|
||||
resp, err := h.svc.ListDispositionsByLetter(c.Request.Context(), letterID)
|
||||
resp, err := h.svc.GetEnhancedDispositionsByLetter(c.Request.Context(), letterID)
|
||||
if err != nil {
|
||||
c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
|
||||
@@ -24,7 +24,7 @@ type MasterService interface {
|
||||
CreateInstitution(ctx context.Context, req *contract.CreateInstitutionRequest) (*contract.InstitutionResponse, error)
|
||||
UpdateInstitution(ctx context.Context, id uuid.UUID, req *contract.UpdateInstitutionRequest) (*contract.InstitutionResponse, error)
|
||||
DeleteInstitution(ctx context.Context, id uuid.UUID) error
|
||||
ListInstitutions(ctx context.Context) (*contract.ListInstitutionsResponse, error)
|
||||
ListInstitutions(ctx context.Context, req *contract.ListInstitutionsRequest) (*contract.ListInstitutionsResponse, error)
|
||||
|
||||
CreateDispositionAction(ctx context.Context, req *contract.CreateDispositionActionRequest) (*contract.DispositionActionResponse, error)
|
||||
UpdateDispositionAction(ctx context.Context, id uuid.UUID, req *contract.UpdateDispositionActionRequest) (*contract.DispositionActionResponse, error)
|
||||
@@ -190,7 +190,13 @@ func (h *MasterHandler) DeleteInstitution(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *MasterHandler) ListInstitutions(c *gin.Context) {
|
||||
resp, err := h.svc.ListInstitutions(c.Request.Context())
|
||||
var req contract.ListInstitutionsRequest
|
||||
|
||||
if search := c.Query("search"); search != "" {
|
||||
req.Search = &search
|
||||
}
|
||||
|
||||
resp, err := h.svc.ListInstitutions(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
|
||||
return
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"eslogad-be/internal/contract"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// MockMasterService is a mock implementation of MasterService
|
||||
type MockMasterService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *MockMasterService) CreateLabel(ctx context.Context, req *contract.CreateLabelRequest) (*contract.LabelResponse, error) {
|
||||
args := m.Called(ctx, req)
|
||||
return args.Get(0).(*contract.LabelResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) UpdateLabel(ctx context.Context, id uuid.UUID, req *contract.UpdateLabelRequest) (*contract.LabelResponse, error) {
|
||||
args := m.Called(ctx, id, req)
|
||||
return args.Get(0).(*contract.LabelResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) DeleteLabel(ctx context.Context, id uuid.UUID) error {
|
||||
args := m.Called(ctx, id)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) ListLabels(ctx context.Context) (*contract.ListLabelsResponse, error) {
|
||||
args := m.Called(ctx)
|
||||
return args.Get(0).(*contract.ListLabelsResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) CreatePriority(ctx context.Context, req *contract.CreatePriorityRequest) (*contract.PriorityResponse, error) {
|
||||
args := m.Called(ctx, req)
|
||||
return args.Get(0).(*contract.PriorityResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) UpdatePriority(ctx context.Context, id uuid.UUID, req *contract.UpdatePriorityRequest) (*contract.PriorityResponse, error) {
|
||||
args := m.Called(ctx, id, req)
|
||||
return args.Get(0).(*contract.PriorityResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) DeletePriority(ctx context.Context, id uuid.UUID) error {
|
||||
args := m.Called(ctx, id)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) ListPriorities(ctx context.Context) (*contract.ListPrioritiesResponse, error) {
|
||||
args := m.Called(ctx)
|
||||
return args.Get(0).(*contract.ListPrioritiesResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) CreateInstitution(ctx context.Context, req *contract.CreateInstitutionRequest) (*contract.InstitutionResponse, error) {
|
||||
args := m.Called(ctx, req)
|
||||
return args.Get(0).(*contract.InstitutionResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) UpdateInstitution(ctx context.Context, id uuid.UUID, req *contract.UpdateInstitutionRequest) (*contract.InstitutionResponse, error) {
|
||||
args := m.Called(ctx, id, req)
|
||||
return args.Get(0).(*contract.InstitutionResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) DeleteInstitution(ctx context.Context, id uuid.UUID) error {
|
||||
args := m.Called(ctx, id)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) ListInstitutions(ctx context.Context, req *contract.ListInstitutionsRequest) (*contract.ListInstitutionsResponse, error) {
|
||||
args := m.Called(ctx, req)
|
||||
return args.Get(0).(*contract.ListInstitutionsResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) CreateDispositionAction(ctx context.Context, req *contract.CreateDispositionActionRequest) (*contract.DispositionActionResponse, error) {
|
||||
args := m.Called(ctx, req)
|
||||
return args.Get(0).(*contract.DispositionActionResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) UpdateDispositionAction(ctx context.Context, id uuid.UUID, req *contract.UpdateDispositionActionRequest) (*contract.DispositionActionResponse, error) {
|
||||
args := m.Called(ctx, id, req)
|
||||
return args.Get(0).(*contract.DispositionActionResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) DeleteDispositionAction(ctx context.Context, id uuid.UUID) error {
|
||||
args := m.Called(ctx, id)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *MockMasterService) ListDispositionActions(ctx context.Context) (*contract.ListDispositionActionsResponse, error) {
|
||||
args := m.Called(ctx)
|
||||
return args.Get(0).(*contract.ListDispositionActionsResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func TestMasterHandler_ListInstitutions_WithSearch(t *testing.T) {
|
||||
// Setup
|
||||
gin.SetMode(gin.TestMode)
|
||||
mockService := new(MockMasterService)
|
||||
handler := NewMasterHandler(mockService)
|
||||
|
||||
// Test data
|
||||
searchTerm := "university"
|
||||
expectedResponse := &contract.ListInstitutionsResponse{
|
||||
Institutions: []contract.InstitutionResponse{
|
||||
{
|
||||
ID: "123",
|
||||
Name: "Test University",
|
||||
Type: "university",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Setup mock expectations
|
||||
mockService.On("ListInstitutions", mock.Anything, &contract.ListInstitutionsRequest{
|
||||
Search: &searchTerm,
|
||||
}).Return(expectedResponse, nil)
|
||||
|
||||
// Create request
|
||||
req, _ := http.NewRequest("GET", "/institutions?search="+searchTerm, nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Create gin context
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = req
|
||||
|
||||
// Execute
|
||||
handler.ListInstitutions(c)
|
||||
|
||||
// Assertions
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var response map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Verify mock was called correctly
|
||||
mockService.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestMasterHandler_ListInstitutions_WithoutSearch(t *testing.T) {
|
||||
// Setup
|
||||
gin.SetMode(gin.TestMode)
|
||||
mockService := new(MockMasterService)
|
||||
handler := NewMasterHandler(mockService)
|
||||
|
||||
// Test data
|
||||
expectedResponse := &contract.ListInstitutionsResponse{
|
||||
Institutions: []contract.InstitutionResponse{
|
||||
{
|
||||
ID: "123",
|
||||
Name: "Test Institution",
|
||||
Type: "company",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Setup mock expectations
|
||||
mockService.On("ListInstitutions", mock.Anything, &contract.ListInstitutionsRequest{
|
||||
Search: nil,
|
||||
}).Return(expectedResponse, nil)
|
||||
|
||||
// Create request
|
||||
req, _ := http.NewRequest("GET", "/institutions", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// Create gin context
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = req
|
||||
|
||||
// Execute
|
||||
handler.ListInstitutions(c)
|
||||
|
||||
// Assertions
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var response map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Verify mock was called correctly
|
||||
mockService.AssertExpectations(t)
|
||||
}
|
||||
@@ -285,12 +285,48 @@ func (h *UserHandler) UpdateProfile(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *UserHandler) ListTitles(c *gin.Context) {
|
||||
resp, err := h.userService.ListTitles(c.Request.Context())
|
||||
titles, err := h.userService.ListTitles(c.Request.Context())
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::ListTitles -> Failed to get titles from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
|
||||
logger.FromContext(c).Infof("UserHandler::ListTitles -> Successfully retrieved titles = %+v", titles)
|
||||
c.JSON(http.StatusOK, titles)
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetActiveUsersForMention(c *gin.Context) {
|
||||
search := c.Query("search")
|
||||
limitStr := c.DefaultQuery("limit", "50")
|
||||
|
||||
limit, err := strconv.Atoi(limitStr)
|
||||
if err != nil || limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
if limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
|
||||
var searchPtr *string
|
||||
if search != "" {
|
||||
searchPtr = &search
|
||||
}
|
||||
|
||||
users, err := h.userService.GetActiveUsersForMention(c.Request.Context(), searchPtr, limit)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::GetActiveUsersForMention -> Failed to get active users from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
response := contract.MentionUsersResponse{
|
||||
Users: users,
|
||||
Count: len(users),
|
||||
}
|
||||
|
||||
logger.FromContext(c).Infof("UserHandler::GetActiveUsersForMention -> Successfully retrieved %d active users", len(users))
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
func (h *UserHandler) sendErrorResponse(c *gin.Context, message string, statusCode int) {
|
||||
|
||||
@@ -20,4 +20,7 @@ type UserService interface {
|
||||
UpdateProfile(ctx context.Context, userID uuid.UUID, req *contract.UpdateUserProfileRequest) (*contract.UserProfileResponse, error)
|
||||
|
||||
ListTitles(ctx context.Context) (*contract.ListTitlesResponse, error)
|
||||
|
||||
// Get active users for mention purposes
|
||||
GetActiveUsersForMention(ctx context.Context, search *string, limit int) ([]contract.UserResponse, error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user