Add letter and user id
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"eslogad-be/internal/contract"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ApprovalFlowService interface {
|
||||
CreateApprovalFlow(ctx context.Context, req *contract.ApprovalFlowRequest) (*contract.ApprovalFlowResponse, error)
|
||||
GetApprovalFlow(ctx context.Context, id uuid.UUID) (*contract.ApprovalFlowResponse, error)
|
||||
GetApprovalFlowByDepartment(ctx context.Context, departmentID uuid.UUID) (*contract.ApprovalFlowResponse, error)
|
||||
UpdateApprovalFlow(ctx context.Context, id uuid.UUID, req *contract.ApprovalFlowRequest) (*contract.ApprovalFlowResponse, error)
|
||||
DeleteApprovalFlow(ctx context.Context, id uuid.UUID) error
|
||||
ListApprovalFlows(ctx context.Context, req *contract.ListApprovalFlowsRequest) (*contract.ListApprovalFlowsResponse, error)
|
||||
}
|
||||
|
||||
type AdminApprovalFlowHandler struct {
|
||||
svc ApprovalFlowService
|
||||
}
|
||||
|
||||
func NewAdminApprovalFlowHandler(svc ApprovalFlowService) *AdminApprovalFlowHandler {
|
||||
return &AdminApprovalFlowHandler{svc: svc}
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) CreateApprovalFlow(c *gin.Context) {
|
||||
var req contract.ApprovalFlowRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate that at least one step is provided
|
||||
if len(req.Steps) == 0 {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "at least one approval step is required", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate each step has either a role or user as approver
|
||||
for i, step := range req.Steps {
|
||||
if step.ApproverRoleID == nil && step.ApproverUserID == nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "step " + strconv.Itoa(i+1) + " must have either approver_role_id or approver_user_id",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
if step.ApproverRoleID != nil && step.ApproverUserID != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "step " + strconv.Itoa(i+1) + " cannot have both approver_role_id and approver_user_id",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.svc.CreateApprovalFlow(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) GetApprovalFlow(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.svc.GetApprovalFlow(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) GetApprovalFlowByDepartment(c *gin.Context) {
|
||||
departmentID, err := uuid.Parse(c.Param("department_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid department_id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.svc.GetApprovalFlowByDepartment(c.Request.Context(), departmentID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) UpdateApprovalFlow(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.ApprovalFlowRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate that at least one step is provided
|
||||
if len(req.Steps) == 0 {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "at least one approval step is required", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate each step has either a role or user as approver
|
||||
for i, step := range req.Steps {
|
||||
if step.ApproverRoleID == nil && step.ApproverUserID == nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "step " + strconv.Itoa(i+1) + " must have either approver_role_id or approver_user_id",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
if step.ApproverRoleID != nil && step.ApproverUserID != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "step " + strconv.Itoa(i+1) + " cannot have both approver_role_id and approver_user_id",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.svc.UpdateApprovalFlow(c.Request.Context(), id, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) DeleteApprovalFlow(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteApprovalFlow(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "approval flow deleted"})
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) ListApprovalFlows(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
offset := (page - 1) * limit
|
||||
|
||||
departmentIDStr := c.Query("department_id")
|
||||
isActiveStr := c.Query("is_active")
|
||||
|
||||
var departmentID *uuid.UUID
|
||||
var isActive *bool
|
||||
|
||||
if departmentIDStr != "" {
|
||||
if id, err := uuid.Parse(departmentIDStr); err == nil {
|
||||
departmentID = &id
|
||||
}
|
||||
}
|
||||
|
||||
if isActiveStr != "" {
|
||||
if isActiveStr == "true" {
|
||||
active := true
|
||||
isActive = &active
|
||||
} else if isActiveStr == "false" {
|
||||
active := false
|
||||
isActive = &active
|
||||
}
|
||||
}
|
||||
|
||||
req := &contract.ListApprovalFlowsRequest{
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
DepartmentID: departmentID,
|
||||
IsActive: isActive,
|
||||
}
|
||||
|
||||
resp, err := h.svc.ListApprovalFlows(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) ActivateApprovalFlow(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
// Get the current flow
|
||||
flow, err := h.svc.GetApprovalFlow(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
// Update only the IsActive field
|
||||
req := &contract.ApprovalFlowRequest{
|
||||
DepartmentID: flow.DepartmentID,
|
||||
Name: flow.Name,
|
||||
Description: flow.Description,
|
||||
IsActive: true,
|
||||
Steps: make([]contract.ApprovalFlowStepRequest, len(flow.Steps)),
|
||||
}
|
||||
|
||||
// Copy existing steps
|
||||
for i, step := range flow.Steps {
|
||||
req.Steps[i] = contract.ApprovalFlowStepRequest{
|
||||
StepOrder: step.StepOrder,
|
||||
ParallelGroup: step.ParallelGroup,
|
||||
ApproverRoleID: step.ApproverRoleID,
|
||||
ApproverUserID: step.ApproverUserID,
|
||||
Required: step.Required,
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.svc.UpdateApprovalFlow(c.Request.Context(), id, req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) DeactivateApprovalFlow(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
// Get the current flow
|
||||
flow, err := h.svc.GetApprovalFlow(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
// Update only the IsActive field
|
||||
req := &contract.ApprovalFlowRequest{
|
||||
DepartmentID: flow.DepartmentID,
|
||||
Name: flow.Name,
|
||||
Description: flow.Description,
|
||||
IsActive: false,
|
||||
Steps: make([]contract.ApprovalFlowStepRequest, len(flow.Steps)),
|
||||
}
|
||||
|
||||
// Copy existing steps
|
||||
for i, step := range flow.Steps {
|
||||
req.Steps[i] = contract.ApprovalFlowStepRequest{
|
||||
StepOrder: step.StepOrder,
|
||||
ParallelGroup: step.ParallelGroup,
|
||||
ApproverRoleID: step.ApproverRoleID,
|
||||
ApproverUserID: step.ApproverUserID,
|
||||
Required: step.Required,
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.svc.UpdateApprovalFlow(c.Request.Context(), id, req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *AdminApprovalFlowHandler) CloneApprovalFlow(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var cloneReq struct {
|
||||
DepartmentID uuid.UUID `json:"department_id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&cloneReq); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
// Get the source flow
|
||||
sourceFlow, err := h.svc.GetApprovalFlow(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
// Create new flow request with cloned data
|
||||
req := &contract.ApprovalFlowRequest{
|
||||
DepartmentID: cloneReq.DepartmentID,
|
||||
Name: cloneReq.Name,
|
||||
Description: sourceFlow.Description,
|
||||
IsActive: false, // New cloned flow starts as inactive
|
||||
Steps: make([]contract.ApprovalFlowStepRequest, len(sourceFlow.Steps)),
|
||||
}
|
||||
|
||||
// Copy steps from source flow
|
||||
for i, step := range sourceFlow.Steps {
|
||||
req.Steps[i] = contract.ApprovalFlowStepRequest{
|
||||
StepOrder: step.StepOrder,
|
||||
ParallelGroup: step.ParallelGroup,
|
||||
ApproverRoleID: step.ApproverRoleID,
|
||||
ApproverUserID: step.ApproverUserID,
|
||||
Required: step.Required,
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.svc.CreateApprovalFlow(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"eslogad-be/internal/contract"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type LetterOutgoingService interface {
|
||||
CreateOutgoingLetter(ctx context.Context, req *contract.CreateOutgoingLetterRequest) (*contract.OutgoingLetterResponse, error)
|
||||
GetOutgoingLetterByID(ctx context.Context, id uuid.UUID) (*contract.OutgoingLetterResponse, error)
|
||||
ListOutgoingLetters(ctx context.Context, req *contract.ListOutgoingLettersRequest) (*contract.ListOutgoingLettersResponse, error)
|
||||
UpdateOutgoingLetter(ctx context.Context, id uuid.UUID, req *contract.UpdateOutgoingLetterRequest) (*contract.OutgoingLetterResponse, error)
|
||||
DeleteOutgoingLetter(ctx context.Context, id uuid.UUID) error
|
||||
|
||||
SubmitForApproval(ctx context.Context, letterID uuid.UUID) error
|
||||
ApproveOutgoingLetter(ctx context.Context, letterID uuid.UUID, req *contract.ApproveLetterRequest) error
|
||||
RejectOutgoingLetter(ctx context.Context, letterID uuid.UUID, req *contract.RejectLetterRequest) error
|
||||
SendOutgoingLetter(ctx context.Context, letterID uuid.UUID) error
|
||||
ArchiveOutgoingLetter(ctx context.Context, letterID uuid.UUID) error
|
||||
|
||||
AddRecipients(ctx context.Context, letterID uuid.UUID, req *contract.AddRecipientsRequest) error
|
||||
UpdateRecipient(ctx context.Context, letterID uuid.UUID, recipientID uuid.UUID, req *contract.UpdateRecipientRequest) error
|
||||
RemoveRecipient(ctx context.Context, letterID uuid.UUID, recipientID uuid.UUID) error
|
||||
|
||||
AddAttachments(ctx context.Context, letterID uuid.UUID, req *contract.AddAttachmentsRequest) error
|
||||
RemoveAttachment(ctx context.Context, letterID uuid.UUID, attachmentID uuid.UUID) error
|
||||
|
||||
CreateDiscussion(ctx context.Context, letterID uuid.UUID, req *contract.CreateDiscussionRequest) (*contract.DiscussionResponse, error)
|
||||
UpdateDiscussion(ctx context.Context, discussionID uuid.UUID, req *contract.UpdateDiscussionRequest) error
|
||||
DeleteDiscussion(ctx context.Context, discussionID uuid.UUID) error
|
||||
}
|
||||
|
||||
type LetterOutgoingHandler struct {
|
||||
svc LetterOutgoingService
|
||||
}
|
||||
|
||||
func NewLetterOutgoingHandler(svc LetterOutgoingService) *LetterOutgoingHandler {
|
||||
return &LetterOutgoingHandler{svc: svc}
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) CreateOutgoingLetter(c *gin.Context) {
|
||||
var req contract.CreateOutgoingLetterRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.svc.CreateOutgoingLetter(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) GetOutgoingLetter(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.svc.GetOutgoingLetterByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) ListOutgoingLetters(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
offset := (page - 1) * limit
|
||||
|
||||
status := c.Query("status")
|
||||
query := c.Query("q")
|
||||
createdByStr := c.Query("created_by")
|
||||
receiverInstitutionStr := c.Query("receiver_institution_id")
|
||||
|
||||
var statusPtr *string
|
||||
var queryPtr *string
|
||||
var createdByPtr *uuid.UUID
|
||||
var receiverInstitutionPtr *uuid.UUID
|
||||
|
||||
if status != "" {
|
||||
statusPtr = &status
|
||||
}
|
||||
if query != "" {
|
||||
queryPtr = &query
|
||||
}
|
||||
if createdByStr != "" {
|
||||
if createdBy, err := uuid.Parse(createdByStr); err == nil {
|
||||
createdByPtr = &createdBy
|
||||
}
|
||||
}
|
||||
if receiverInstitutionStr != "" {
|
||||
if receiverInstitution, err := uuid.Parse(receiverInstitutionStr); err == nil {
|
||||
receiverInstitutionPtr = &receiverInstitution
|
||||
}
|
||||
}
|
||||
|
||||
req := &contract.ListOutgoingLettersRequest{
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
Status: statusPtr,
|
||||
Query: queryPtr,
|
||||
CreatedBy: createdByPtr,
|
||||
ReceiverInstitutionID: receiverInstitutionPtr,
|
||||
}
|
||||
|
||||
resp, err := h.svc.ListOutgoingLetters(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) UpdateOutgoingLetter(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateOutgoingLetterRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.svc.UpdateOutgoingLetter(c.Request.Context(), id, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) DeleteOutgoingLetter(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteOutgoingLetter(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "deleted"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) SubmitForApproval(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.SubmitForApproval(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "submitted for approval"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) ApproveOutgoingLetter(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.ApproveLetterRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.ApproveOutgoingLetter(c.Request.Context(), id, &req); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "approved"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) RejectOutgoingLetter(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.RejectLetterRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.RejectOutgoingLetter(c.Request.Context(), id, &req); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "rejected"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) SendOutgoingLetter(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.SendOutgoingLetter(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "sent"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) ArchiveOutgoingLetter(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.ArchiveOutgoingLetter(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "archived"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) AddRecipients(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.AddRecipientsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.AddRecipients(c.Request.Context(), id, &req); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "recipients added"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) UpdateRecipient(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid letter id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
recipientID, err := uuid.Parse(c.Param("recipient_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid recipient id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateRecipientRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.UpdateRecipient(c.Request.Context(), id, recipientID, &req); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "recipient updated"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) RemoveRecipient(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid letter id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
recipientID, err := uuid.Parse(c.Param("recipient_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid recipient id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.RemoveRecipient(c.Request.Context(), id, recipientID); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "recipient removed"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) AddAttachments(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.AddAttachmentsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.AddAttachments(c.Request.Context(), id, &req); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "attachments added"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) RemoveAttachment(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid letter id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
attachmentID, err := uuid.Parse(c.Param("attachment_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid attachment id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.RemoveAttachment(c.Request.Context(), id, attachmentID); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "attachment removed"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) CreateDiscussion(c *gin.Context) {
|
||||
id, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid letter id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.CreateDiscussionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.svc.CreateDiscussion(c.Request.Context(), id, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) UpdateDiscussion(c *gin.Context) {
|
||||
discussionID, err := uuid.Parse(c.Param("discussion_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid discussion id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateDiscussionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.UpdateDiscussion(c.Request.Context(), discussionID, &req); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "discussion updated"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) DeleteDiscussion(c *gin.Context) {
|
||||
discussionID, err := uuid.Parse(c.Param("discussion_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid discussion id", Code: http.StatusBadRequest})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteDiscussion(c.Request.Context(), discussionID); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "discussion deleted"})
|
||||
}
|
||||
@@ -296,6 +296,33 @@ func (h *UserHandler) ListTitles(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, titles)
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetUserProfile(c *gin.Context) {
|
||||
userIDStr := c.Param("id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::GetUserProfile -> Invalid user ID")
|
||||
h.sendValidationErrorResponse(c, "Invalid user ID", constants.MalformedFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateUserID(userID)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::GetUserProfile -> user ID validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
profile, err := h.userService.GetProfile(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::GetUserProfile -> Failed to get user profile from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Infof("UserHandler::GetUserProfile -> Successfully retrieved user profile for user ID = %s", userID)
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(profile))
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetActiveUsersForMention(c *gin.Context) {
|
||||
search := c.Query("search")
|
||||
limitStr := c.DefaultQuery("limit", "50")
|
||||
@@ -307,7 +334,7 @@ func (h *UserHandler) GetActiveUsersForMention(c *gin.Context) {
|
||||
if limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
|
||||
|
||||
var searchPtr *string
|
||||
if search != "" {
|
||||
searchPtr = &search
|
||||
|
||||
Reference in New Issue
Block a user