2025-10-30 12:40:32 +07:00

316 lines
14 KiB
Go

package router
import (
"eslogad-be/config"
"eslogad-be/internal/middleware"
"github.com/gin-gonic/gin"
)
type Router struct {
config *config.Config
authHandler AuthHandler
healthHandler HealthHandler
authMiddleware AuthMiddleware
userHandler UserHandler
fileHandler FileHandler
rbacHandler RBACHandler
masterHandler MasterHandler
letterHandler LetterHandler
letterOutgoingHandler LetterOutgoingHandler
adminApprovalFlowHandler AdminApprovalFlowHandler
dispRouteHandler DispositionRouteHandler
onlyOfficeHandler OnlyOfficeHandler
analyticsHandler AnalyticsHandler
notificationHandler NotificationHandler
repositoryAttachmentHandler RepositoryAttachmentHandler
}
func NewRouter(
cfg *config.Config,
authHandler AuthHandler,
authMiddleware AuthMiddleware,
healthHandler HealthHandler,
userHandler UserHandler,
fileHandler FileHandler,
rbacHandler RBACHandler,
masterHandler MasterHandler,
letterHandler LetterHandler,
letterOutgoingHandler LetterOutgoingHandler,
adminApprovalFlowHandler AdminApprovalFlowHandler,
dispRouteHandler DispositionRouteHandler,
onlyOfficeHandler OnlyOfficeHandler,
analyticsHandler AnalyticsHandler,
notificationHandler NotificationHandler,
repositoryAttachmentHandler RepositoryAttachmentHandler,
) *Router {
return &Router{
config: cfg,
authHandler: authHandler,
authMiddleware: authMiddleware,
healthHandler: healthHandler,
userHandler: userHandler,
fileHandler: fileHandler,
rbacHandler: rbacHandler,
masterHandler: masterHandler,
letterHandler: letterHandler,
letterOutgoingHandler: letterOutgoingHandler,
adminApprovalFlowHandler: adminApprovalFlowHandler,
dispRouteHandler: dispRouteHandler,
onlyOfficeHandler: onlyOfficeHandler,
analyticsHandler: analyticsHandler,
notificationHandler: notificationHandler,
repositoryAttachmentHandler: repositoryAttachmentHandler,
}
}
func (r *Router) Init() *gin.Engine {
gin.SetMode(gin.ReleaseMode)
engine := gin.New()
engine.Use(
middleware.JsonAPI(),
middleware.CorrelationID(),
middleware.Recover(),
middleware.HTTPStatLogger(),
middleware.PopulateContext(),
middleware.CORS(),
)
r.addAppRoutes(engine)
return engine
}
func (r *Router) addAppRoutes(rg *gin.Engine) {
rg.GET("/health", r.healthHandler.HealthCheck)
v1 := rg.Group("/api/v1")
{
auth := v1.Group("/auth")
{
auth.POST("/login", r.authHandler.Login)
auth.POST("/refresh", r.authHandler.RefreshToken)
auth.GET("/profile", r.authHandler.GetProfile)
}
users := v1.Group("/users")
users.Use(r.authMiddleware.RequireAuth())
{
users.POST("", r.userHandler.CreateUser)
users.GET("", r.userHandler.ListUsers)
users.PUT("/:id", r.userHandler.UpdateUser)
users.DELETE("/:id", r.userHandler.DeleteUser)
users.GET("/profile", r.userHandler.GetProfile)
users.GET("/:id/profile", r.userHandler.GetUserProfile)
users.PUT("/profile", r.userHandler.UpdateProfile)
users.PUT("/:id/password", r.userHandler.ChangePassword)
users.GET("/titles", r.userHandler.ListTitles)
users.GET("/mention", r.userHandler.GetActiveUsersForMention)
users.POST("/profile/avatar", r.fileHandler.UploadProfileAvatar)
}
files := v1.Group("/files")
files.Use(r.authMiddleware.RequireAuth())
{
files.POST("/documents", r.fileHandler.UploadDocument)
}
rbac := v1.Group("/rbac")
rbac.Use(r.authMiddleware.RequireAuth())
{
rbac.GET("/permissions", r.rbacHandler.ListPermissions)
rbac.POST("/permissions", r.rbacHandler.CreatePermission)
rbac.PUT("/permissions/:id", r.rbacHandler.UpdatePermission)
rbac.DELETE("/permissions/:id", r.rbacHandler.DeletePermission)
rbac.GET("/roles", r.rbacHandler.ListRoles)
rbac.POST("/roles", r.rbacHandler.CreateRole)
rbac.PUT("/roles/:id", r.rbacHandler.UpdateRole)
rbac.DELETE("/roles/:id", r.rbacHandler.DeleteRole)
}
roles := v1.Group("/roles")
roles.Use(r.authMiddleware.RequireAuth())
{
roles.POST("", r.rbacHandler.CreateOrUpdateRole)
roles.GET("/permissions", r.rbacHandler.GetPermissionsGrouped)
roles.GET("/:id", r.rbacHandler.GetRoleDetail)
}
master := v1.Group("/master")
master.Use(r.authMiddleware.RequireAuth())
{
master.GET("/labels", r.masterHandler.ListLabels)
master.POST("/labels", r.masterHandler.CreateLabel)
master.PUT("/labels/:id", r.masterHandler.UpdateLabel)
master.DELETE("/labels/:id", r.masterHandler.DeleteLabel)
master.GET("/priorities", r.masterHandler.ListPriorities)
master.POST("/priorities", r.masterHandler.CreatePriority)
master.PUT("/priorities/:id", r.masterHandler.UpdatePriority)
master.DELETE("/priorities/:id", r.masterHandler.DeletePriority)
master.GET("/institutions", r.masterHandler.ListInstitutions)
master.POST("/institutions", r.masterHandler.CreateInstitution)
master.PUT("/institutions/:id", r.masterHandler.UpdateInstitution)
master.DELETE("/institutions/:id", r.masterHandler.DeleteInstitution)
master.GET("/disposition-actions", r.masterHandler.ListDispositionActions)
master.POST("/disposition-actions", r.masterHandler.CreateDispositionAction)
master.PUT("/disposition-actions/:id", r.masterHandler.UpdateDispositionAction)
master.DELETE("/disposition-actions/:id", r.masterHandler.DeleteDispositionAction)
master.POST("/departments", r.masterHandler.CreateDepartment)
master.GET("/departments", r.masterHandler.ListDepartments)
master.GET("/departments/chart", r.masterHandler.GetOrganizationalChart)
master.GET("/departments/:id", r.masterHandler.GetDepartment)
master.GET("/departments/:id/chart", r.masterHandler.GetOrganizationalChartByID)
master.PUT("/departments/:id", r.masterHandler.UpdateDepartment)
master.DELETE("/departments/:id", r.masterHandler.DeleteDepartment)
}
lettersch := v1.Group("/letters")
lettersch.Use(r.authMiddleware.RequireAuth())
{
lettersch.GET("/unread-counts", r.letterHandler.GetLetterUnreadCounts)
lettersch.GET("/incoming", r.letterHandler.ListIncomingLetters)
lettersch.GET("/incoming/search", r.letterHandler.SearchIncomingLetters)
lettersch.POST("/incoming", r.letterHandler.CreateIncomingLetter)
lettersch.GET("/incoming/cta/:letter_id", r.letterHandler.GetLetterCTA)
lettersch.GET("/incoming/:id", r.letterHandler.GetIncomingLetter)
lettersch.PUT("/incoming/:id", r.letterHandler.UpdateIncomingLetter)
lettersch.PUT("/incoming/:id/read", r.letterHandler.MarkIncomingLetterAsRead)
lettersch.DELETE("/incoming/:id", r.letterHandler.DeleteIncomingLetter)
lettersch.DELETE("/incoming/delete", r.letterHandler.BulkDeleteIncomingLetters)
lettersch.POST("/incoming/archive", r.letterHandler.BulkArchiveIncomingLetters)
lettersch.PUT("/incoming/:id/archive", r.letterHandler.ArchiveIncomingLetter)
lettersch.POST("/outgoing", r.letterOutgoingHandler.CreateOutgoingLetter)
lettersch.GET("/outgoing/search", r.letterOutgoingHandler.SearchOutgoingLetters)
lettersch.GET("/outgoing/:id", r.letterOutgoingHandler.GetOutgoingLetter)
lettersch.GET("/outgoing", r.letterOutgoingHandler.ListOutgoingLetters)
lettersch.PUT("/outgoing/:id", r.letterOutgoingHandler.UpdateOutgoingLetter)
lettersch.PUT("/outgoing/:id/read", r.letterHandler.MarkOutgoingLetterAsRead)
lettersch.DELETE("/outgoing/:id", r.letterOutgoingHandler.DeleteOutgoingLetter)
lettersch.DELETE("/outgoing/delete", r.letterOutgoingHandler.BulkDeleteOutgoingLetters)
lettersch.POST("/outgoing/:id/submit", r.letterOutgoingHandler.SubmitForApproval)
lettersch.POST("/outgoing/:id/approve", r.letterOutgoingHandler.ApproveOutgoingLetter)
lettersch.POST("/outgoing/:id/reject", r.letterOutgoingHandler.RejectOutgoingLetter)
lettersch.POST("/outgoing/:id/revise", r.letterOutgoingHandler.ReviseOutgoingLetter)
lettersch.POST("/outgoing/:id/send", r.letterOutgoingHandler.SendOutgoingLetter)
lettersch.POST("/outgoing/:id/archive", r.letterOutgoingHandler.ArchiveOutgoingLetter)
lettersch.POST("/outgoing/archive", r.letterOutgoingHandler.BulkArchiveOutgoingLetters)
lettersch.GET("/outgoing/:id/cta", r.letterOutgoingHandler.GetLetterApprovalInfo)
lettersch.GET("/outgoing/:id/approvals", r.letterOutgoingHandler.GetLetterApprovals)
lettersch.POST("/outgoing/:id/recipients", r.letterOutgoingHandler.AddRecipients)
lettersch.PUT("/outgoing/:id/recipients/:recipient_id", r.letterOutgoingHandler.UpdateRecipient)
lettersch.DELETE("/outgoing/:id/recipients/:recipient_id", r.letterOutgoingHandler.RemoveRecipient)
lettersch.POST("/outgoing/:id/attachments", r.letterOutgoingHandler.AddAttachments)
lettersch.DELETE("/outgoing/:id/attachments/:attachment_id", r.letterOutgoingHandler.RemoveAttachment)
lettersch.POST("/outgoing/:id/discussions", r.letterOutgoingHandler.CreateDiscussion)
lettersch.PUT("/outgoing/discussions/:discussion_id", r.letterOutgoingHandler.UpdateDiscussion)
lettersch.DELETE("/outgoing/discussions/:discussion_id", r.letterOutgoingHandler.DeleteDiscussion)
lettersch.GET("/outgoing/:id/approval-discussions", r.letterOutgoingHandler.GetApprovalDiscussions)
lettersch.GET("/outgoing/:id/timeline", r.letterOutgoingHandler.GetApprovalTimeline)
lettersch.POST("/dispositions/:letter_id", r.letterHandler.CreateDispositions)
lettersch.GET("/dispositions/:letter_id", r.letterHandler.GetEnhancedDispositionsByLetter)
lettersch.GET("/dispositions/:letter_id/department/status", r.letterHandler.GetDepartmentDispositionStatus)
lettersch.PUT("/dispositions/:letter_id/status", r.letterHandler.UpdateDispositionStatus)
lettersch.POST("/discussions/:letter_id", r.letterHandler.CreateDiscussion)
lettersch.PUT("/discussions/:letter_id/:discussion_id", r.letterHandler.UpdateDiscussion)
}
droutes := v1.Group("/disposition-routes")
droutes.Use(r.authMiddleware.RequireAuth())
{
droutes.POST("", r.dispRouteHandler.Create) // Create with upsert logic
droutes.PUT("/bulk", r.dispRouteHandler.BulkCreateOrUpdate) // Explicit bulk create/update
droutes.GET("", r.dispRouteHandler.ListAll) // List all routes with details
droutes.GET("/grouped", r.dispRouteHandler.ListGrouped) // List grouped by from_department_id
droutes.GET("/department", r.dispRouteHandler.ListByFromDept)
droutes.GET("/:id", r.dispRouteHandler.Get)
droutes.PUT("/:id", r.dispRouteHandler.Update)
droutes.PUT("/:id/active", r.dispRouteHandler.SetActive)
}
repoattachsch := v1.Group("/repository-attachments")
repoattachsch.Use(r.authMiddleware.RequireAuth())
{
repoattachsch.POST("", r.repositoryAttachmentHandler.CreateAttachment)
repoattachsch.GET("", r.repositoryAttachmentHandler.ListAttachment)
repoattachsch.DELETE("/:id", r.repositoryAttachmentHandler.DeleteAttachment)
repoattachsch.GET("/:id", r.repositoryAttachmentHandler.GetAttachment)
}
admin := v1.Group("/setting")
admin.Use(r.authMiddleware.RequireAuth())
{
approvalFlows := admin.Group("/approval-flows")
{
approvalFlows.POST("", r.adminApprovalFlowHandler.CreateApprovalFlow)
approvalFlows.GET("", r.adminApprovalFlowHandler.ListApprovalFlows)
approvalFlows.GET("/department", r.adminApprovalFlowHandler.ListApprovalFlowsByDepartment)
approvalFlows.GET("/:id", r.adminApprovalFlowHandler.GetApprovalFlow)
approvalFlows.GET("/department/:department_id", r.adminApprovalFlowHandler.GetApprovalFlowByDepartment)
approvalFlows.PUT("/:id", r.adminApprovalFlowHandler.UpdateApprovalFlow)
approvalFlows.DELETE("/:id", r.adminApprovalFlowHandler.DeleteApprovalFlow)
approvalFlows.POST("/:id/activate", r.adminApprovalFlowHandler.ActivateApprovalFlow)
approvalFlows.POST("/:id/deactivate", r.adminApprovalFlowHandler.DeactivateApprovalFlow)
approvalFlows.POST("/:id/clone", r.adminApprovalFlowHandler.CloneApprovalFlow)
}
}
onlyoffice := v1.Group("/onlyoffice")
{
onlyoffice.POST("/callback/:key", r.onlyOfficeHandler.ProcessCallback)
onlyofficeAuth := onlyoffice.Group("")
onlyofficeAuth.Use(r.authMiddleware.RequireAuth())
{
onlyofficeAuth.POST("/config", r.onlyOfficeHandler.GetEditorConfig)
onlyofficeAuth.GET("/settings", r.onlyOfficeHandler.GetOnlyOfficeConfig)
onlyofficeAuth.POST("/lock/:id", r.onlyOfficeHandler.LockDocument)
onlyofficeAuth.POST("/unlock/:id", r.onlyOfficeHandler.UnlockDocument)
onlyofficeAuth.GET("/session/:key", r.onlyOfficeHandler.GetDocumentSession)
}
}
analytics := v1.Group("/analytics")
analytics.Use(r.authMiddleware.RequireAuth())
{
analytics.GET("/dashboard", r.analyticsHandler.GetDashboard)
analytics.GET("/volume", r.analyticsHandler.GetLetterVolume)
analytics.GET("/status-distribution", r.analyticsHandler.GetStatusDistribution)
analytics.GET("/priority-distribution", r.analyticsHandler.GetPriorityDistribution)
analytics.GET("/department-stats", r.analyticsHandler.GetDepartmentStats)
analytics.GET("/monthly-trend", r.analyticsHandler.GetMonthlyTrend)
analytics.GET("/approval-metrics", r.analyticsHandler.GetApprovalMetrics)
}
notifications := v1.Group("/notifications")
notifications.Use(r.authMiddleware.RequireAuth())
{
notifications.POST("/me/trigger", r.notificationHandler.TriggerNotificationForCurrentUser)
notifications.GET("/me/subscriber", r.notificationHandler.GetCurrentUserSubscriber)
notifications.PUT("/me/channel", r.notificationHandler.UpdateCurrentUserSubscriberChannel)
notifAdmin := notifications.Group("")
notifAdmin.Use(r.authMiddleware.RequirePermissions("notification.admin"))
{
notifAdmin.POST("/trigger", r.notificationHandler.TriggerNotification)
notifAdmin.POST("/bulk-trigger", r.notificationHandler.BulkTriggerNotification)
notifAdmin.GET("/subscribers/:userId", r.notificationHandler.GetSubscriber)
notifAdmin.PUT("/subscribers/channel", r.notificationHandler.UpdateSubscriberChannel)
}
}
}
}