Add document saved
This commit is contained in:
@@ -120,6 +120,9 @@ func (h *LetterHandler) ListIncomingLetters(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *LetterHandler) parseListRequest(c *gin.Context) *contract.ListIncomingLettersRequest {
|
||||
//appCtx := appcontext.FromGinContext(c)
|
||||
//departmentID := appCtx.DepartmentID
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
|
||||
@@ -139,7 +142,6 @@ func (h *LetterHandler) parseListRequest(c *gin.Context) *contract.ListIncomingL
|
||||
Limit: limit,
|
||||
}
|
||||
|
||||
// Handle optional query parameters
|
||||
if status := c.Query("status"); status != "" {
|
||||
req.Status = &status
|
||||
}
|
||||
@@ -147,6 +149,8 @@ func (h *LetterHandler) parseListRequest(c *gin.Context) *contract.ListIncomingL
|
||||
req.Query = &query
|
||||
}
|
||||
|
||||
//req.DepartmentID = &departmentID
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type LetterOutgoingService interface {
|
||||
@@ -35,6 +36,9 @@ type LetterOutgoingService interface {
|
||||
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
|
||||
|
||||
GetLetterApprovalInfo(ctx context.Context, letterID uuid.UUID) (*contract.LetterApprovalInfoResponse, error)
|
||||
GetApprovalDiscussions(ctx context.Context, letterID uuid.UUID) (*contract.OutgoingLetterApprovalDiscussionsResponse, error)
|
||||
}
|
||||
|
||||
type LetterOutgoingHandler struct {
|
||||
@@ -420,4 +424,41 @@ func (h *LetterOutgoingHandler) DeleteDiscussion(c *gin.Context) {
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "discussion deleted"})
|
||||
}
|
||||
|
||||
func (h *LetterOutgoingHandler) GetLetterApprovalInfo(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.GetLetterApprovalInfo(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))
|
||||
}
|
||||
|
||||
// GetApprovalDiscussions returns both approvals and discussions for an outgoing letter
|
||||
func (h *LetterOutgoingHandler) GetApprovalDiscussions(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.GetApprovalDiscussions(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
c.JSON(http.StatusNotFound, &contract.ErrorResponse{Error: "letter not found", Code: http.StatusNotFound})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: http.StatusInternalServerError})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(resp))
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"eslogad-be/internal/contract"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type OnlyOfficeService interface {
|
||||
ProcessCallback(ctx context.Context, documentKey string, req *contract.OnlyOfficeCallbackRequest) (*contract.OnlyOfficeCallbackResponse, error)
|
||||
GetEditorConfig(ctx context.Context, req *contract.GetEditorConfigRequest) (*contract.GetEditorConfigResponse, error)
|
||||
LockDocument(ctx context.Context, documentID uuid.UUID, userID uuid.UUID) error
|
||||
UnlockDocument(ctx context.Context, documentID uuid.UUID, userID uuid.UUID) error
|
||||
GetDocumentSession(ctx context.Context, documentKey string) (*contract.DocumentSession, error)
|
||||
GetOnlyOfficeConfig(ctx context.Context) (*contract.OnlyOfficeConfigInfo, error)
|
||||
}
|
||||
|
||||
type OnlyOfficeHandler struct {
|
||||
svc OnlyOfficeService
|
||||
}
|
||||
|
||||
func NewOnlyOfficeHandler(svc OnlyOfficeService) *OnlyOfficeHandler {
|
||||
return &OnlyOfficeHandler{
|
||||
svc: svc,
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessCallback handles OnlyOffice document server callbacks
|
||||
// POST /api/v1/onlyoffice/callback/:key
|
||||
func (h *OnlyOfficeHandler) ProcessCallback(c *gin.Context) {
|
||||
documentKey := c.Param("key")
|
||||
if documentKey == "" {
|
||||
c.JSON(http.StatusBadRequest, &contract.OnlyOfficeCallbackResponse{Error: 1})
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.OnlyOfficeCallbackRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.OnlyOfficeCallbackResponse{Error: 2})
|
||||
return
|
||||
}
|
||||
|
||||
// Extract JWT token from Authorization header if not in request body
|
||||
if req.Token == "" {
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader != "" {
|
||||
// Remove "Bearer " prefix if present
|
||||
if len(authHeader) > 7 && authHeader[:7] == "Bearer " {
|
||||
req.Token = authHeader[7:]
|
||||
} else {
|
||||
req.Token = authHeader
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyOffice requires the key in the request to match the URL
|
||||
if req.Key != "" && req.Key != documentKey {
|
||||
c.JSON(http.StatusBadRequest, &contract.OnlyOfficeCallbackResponse{Error: 1})
|
||||
return
|
||||
}
|
||||
req.Key = documentKey
|
||||
|
||||
resp, err := h.svc.ProcessCallback(c.Request.Context(), documentKey, &req)
|
||||
if err != nil {
|
||||
// Log the error for debugging but return appropriate OnlyOffice error code
|
||||
// OnlyOffice expects specific error codes, not standard HTTP errors
|
||||
c.JSON(http.StatusOK, &contract.OnlyOfficeCallbackResponse{Error: 0})
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyOffice expects 200 OK with error field in response
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
func (h *OnlyOfficeHandler) GetEditorConfig(c *gin.Context) {
|
||||
var req contract.GetEditorConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: fmt.Sprintf("invalid request body: %v", err),
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.svc.GetEditorConfig(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))
|
||||
}
|
||||
|
||||
// LockDocument locks a document for editing
|
||||
// POST /api/v1/onlyoffice/lock/:id
|
||||
func (h *OnlyOfficeHandler) LockDocument(c *gin.Context) {
|
||||
documentID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "invalid document id",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Get user ID from context
|
||||
userCtx := c.MustGet("user").(map[string]interface{})
|
||||
userID, err := uuid.Parse(userCtx["user_id"].(string))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "invalid user context",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.LockDocument(c.Request.Context(), documentID, userID); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{
|
||||
Error: err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "document locked"})
|
||||
}
|
||||
|
||||
// UnlockDocument unlocks a document
|
||||
// POST /api/v1/onlyoffice/unlock/:id
|
||||
func (h *OnlyOfficeHandler) UnlockDocument(c *gin.Context) {
|
||||
documentID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "invalid document id",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Get user ID from context
|
||||
userCtx := c.MustGet("user").(map[string]interface{})
|
||||
userID, err := uuid.Parse(userCtx["user_id"].(string))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "invalid user context",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.UnlockDocument(c.Request.Context(), documentID, userID); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{
|
||||
Error: err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, &contract.SuccessResponse{Message: "document unlocked"})
|
||||
}
|
||||
|
||||
// GetDocumentSession gets document session information
|
||||
// GET /api/v1/onlyoffice/session/:key
|
||||
func (h *OnlyOfficeHandler) GetDocumentSession(c *gin.Context) {
|
||||
documentKey := c.Param("key")
|
||||
if documentKey == "" {
|
||||
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
||||
Error: "document key is required",
|
||||
Code: http.StatusBadRequest,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
session, err := h.svc.GetDocumentSession(c.Request.Context(), documentKey)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{
|
||||
Error: err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(session))
|
||||
}
|
||||
|
||||
// GetOnlyOfficeConfig returns the OnlyOffice configuration
|
||||
// GET /api/v1/onlyoffice/config
|
||||
func (h *OnlyOfficeHandler) GetOnlyOfficeConfig(c *gin.Context) {
|
||||
config, err := h.svc.GetOnlyOfficeConfig(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{
|
||||
Error: err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(config))
|
||||
}
|
||||
Reference in New Issue
Block a user