Files
Tomas Dvorak 3cb40adb23 first commit
2026-04-10 12:04:09 +02:00

214 lines
6.1 KiB
Go

package httpapi
import (
"net/http"
"github.com/gin-gonic/gin"
"productier/apps/backend/internal/store"
)
func (s *Server) registerCRMRoutes(group *gin.RouterGroup) {
// Contacts
group.GET("/contacts", func(c *gin.Context) {
workspaceSlug := c.Query("workspaceSlug")
if _, ok := s.requireWorkspaceMember(c, workspaceSlug); !ok {
return
}
c.JSON(http.StatusOK, gin.H{"data": s.store.ListContacts(workspaceSlug)})
})
group.GET("/contacts/:contactId", func(c *gin.Context) {
contact, err := s.store.GetContactByID(c.Param("contactId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
return
}
c.JSON(http.StatusOK, gin.H{"data": contact})
})
group.POST("/contacts", func(c *gin.Context) {
var input store.CreateContactInput
if err := c.ShouldBindJSON(&input); err != nil {
s.writeStatusError(c, http.StatusBadRequest, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, input.WorkspaceSlug); !ok {
return
}
contact := s.store.CreateContact(input)
c.JSON(http.StatusCreated, gin.H{"data": contact})
})
group.PATCH("/contacts/:contactId", func(c *gin.Context) {
contact, err := s.store.GetContactByID(c.Param("contactId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
return
}
var input store.UpdateContactInput
if err := c.ShouldBindJSON(&input); err != nil {
s.writeStatusError(c, http.StatusBadRequest, err.Error())
return
}
updated, err := s.store.UpdateContact(c.Param("contactId"), input)
if err != nil {
s.writeStatusError(c, http.StatusInternalServerError, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{"data": updated})
})
group.DELETE("/contacts/:contactId", func(c *gin.Context) {
contact, err := s.store.GetContactByID(c.Param("contactId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
return
}
if err := s.store.DeleteContact(c.Param("contactId")); err != nil {
s.writeStatusError(c, http.StatusInternalServerError, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
})
// Companies
group.GET("/companies", func(c *gin.Context) {
workspaceSlug := c.Query("workspaceSlug")
if _, ok := s.requireWorkspaceMember(c, workspaceSlug); !ok {
return
}
c.JSON(http.StatusOK, gin.H{"data": s.store.ListCompanies(workspaceSlug)})
})
group.GET("/companies/:companyId", func(c *gin.Context) {
company, err := s.store.GetCompanyByID(c.Param("companyId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, company.WorkspaceSlug); !ok {
return
}
c.JSON(http.StatusOK, gin.H{"data": company})
})
group.POST("/companies", func(c *gin.Context) {
var input store.CreateCompanyInput
if err := c.ShouldBindJSON(&input); err != nil {
s.writeStatusError(c, http.StatusBadRequest, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, input.WorkspaceSlug); !ok {
return
}
company := s.store.CreateCompany(input)
c.JSON(http.StatusCreated, gin.H{"data": company})
})
group.PATCH("/companies/:companyId", func(c *gin.Context) {
company, err := s.store.GetCompanyByID(c.Param("companyId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, company.WorkspaceSlug); !ok {
return
}
var input store.UpdateCompanyInput
if err := c.ShouldBindJSON(&input); err != nil {
s.writeStatusError(c, http.StatusBadRequest, err.Error())
return
}
updated, err := s.store.UpdateCompany(c.Param("companyId"), input)
if err != nil {
s.writeStatusError(c, http.StatusInternalServerError, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{"data": updated})
})
group.DELETE("/companies/:companyId", func(c *gin.Context) {
company, err := s.store.GetCompanyByID(c.Param("companyId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, company.WorkspaceSlug); !ok {
return
}
if err := s.store.DeleteCompany(c.Param("companyId")); err != nil {
s.writeStatusError(c, http.StatusInternalServerError, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
})
// Contact-Task linking
group.POST("/contacts/:contactId/tasks/:taskId", func(c *gin.Context) {
contact, err := s.store.GetContactByID(c.Param("contactId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
return
}
if err := s.store.LinkContactToTask(c.Param("contactId"), c.Param("taskId")); err != nil {
s.writeStatusError(c, http.StatusInternalServerError, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
})
group.DELETE("/contacts/:contactId/tasks/:taskId", func(c *gin.Context) {
contact, err := s.store.GetContactByID(c.Param("contactId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
return
}
if err := s.store.UnlinkContactFromTask(c.Param("contactId"), c.Param("taskId")); err != nil {
s.writeStatusError(c, http.StatusInternalServerError, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
})
// Contact-Event linking
group.POST("/contacts/:contactId/events/:eventId", func(c *gin.Context) {
contact, err := s.store.GetContactByID(c.Param("contactId"))
if err != nil {
s.writeStatusError(c, http.StatusNotFound, err.Error())
return
}
if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
return
}
if err := s.store.LinkContactToEvent(c.Param("contactId"), c.Param("eventId")); err != nil {
s.writeStatusError(c, http.StatusInternalServerError, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
})
}