mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools
Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
* GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
* GET /api/v1/users/me/organizations - User organizations
* POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue
API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules
Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
236 lines
6.8 KiB
Go
236 lines
6.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"bugulma/backend/internal/service"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// AIHandler handles AI-powered functionality
|
|
type AIHandler struct {
|
|
service *service.AIService
|
|
}
|
|
|
|
// NewAIHandler creates a new AI handler
|
|
func NewAIHandler(service *service.AIService) *AIHandler {
|
|
return &AIHandler{service: service}
|
|
}
|
|
|
|
// ExtractFromText extracts organization data from text
|
|
// @Summary Extract organization data from text
|
|
// @Tags ai
|
|
// @Accept multipart/form-data
|
|
// @Produce json
|
|
// @Param text formData string true "Text to extract from"
|
|
// @Success 200 {object} map[string]interface{}
|
|
// @Router /ai/extract/text [post]
|
|
func (h *AIHandler) ExtractFromText(c *gin.Context) {
|
|
text := c.PostForm("text")
|
|
if text == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "text parameter is required"})
|
|
return
|
|
}
|
|
|
|
result, err := h.service.ExtractDataFromText(c.Request.Context(), text)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// ExtractFromFile extracts organization data from file
|
|
// @Summary Extract organization data from file
|
|
// @Tags ai
|
|
// @Accept multipart/form-data
|
|
// @Produce json
|
|
// @Param file formData file true "File to extract from"
|
|
// @Success 200 {object} map[string]interface{}
|
|
// @Router /ai/extract/file [post]
|
|
func (h *AIHandler) ExtractFromFile(c *gin.Context) {
|
|
file, header, err := c.Request.FormFile("file")
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "file parameter is required"})
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
// Read file data
|
|
fileData := make([]byte, header.Size)
|
|
_, err = file.Read(fileData)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to read file"})
|
|
return
|
|
}
|
|
|
|
result, err := h.service.ExtractDataFromFile(c.Request.Context(), fileData, header.Filename)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// AnalyzeSymbiosis analyzes symbiotic relationships
|
|
// @Summary Analyze symbiotic relationships
|
|
// @Tags ai
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body map[string]interface{} true "Analysis request"
|
|
// @Success 200 {array} map[string]interface{}
|
|
// @Router /ai/analyze/symbiosis [post]
|
|
func (h *AIHandler) AnalyzeSymbiosis(c *gin.Context) {
|
|
var request map[string]interface{}
|
|
if err := c.ShouldBindJSON(&request); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
orgID, _ := request["organization_id"].(string)
|
|
result, err := h.service.AnalyzeSymbiosis(c.Request.Context(), orgID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// GetWebIntelligence gets web intelligence
|
|
// @Summary Get web intelligence
|
|
// @Tags ai
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body map[string]interface{} true "Web intelligence request"
|
|
// @Success 200 {object} map[string]interface{}
|
|
// @Router /ai/web-intelligence [post]
|
|
func (h *AIHandler) GetWebIntelligence(c *gin.Context) {
|
|
var request map[string]interface{}
|
|
if err := c.ShouldBindJSON(&request); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
orgName, _ := request["organization_name"].(string)
|
|
result, err := h.service.GetWebIntelligence(c.Request.Context(), orgName)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// GetSearchSuggestions gets search suggestions
|
|
// @Summary Get search suggestions
|
|
// @Tags ai
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body map[string]interface{} true "Search suggestions request"
|
|
// @Success 200 {array} string
|
|
// @Router /ai/search-suggestions [post]
|
|
func (h *AIHandler) GetSearchSuggestions(c *gin.Context) {
|
|
var request map[string]interface{}
|
|
if err := c.ShouldBindJSON(&request); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
query, _ := request["query"].(string)
|
|
result, err := h.service.GetSearchSuggestions(c.Request.Context(), query)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// GenerateDescription generates organization description
|
|
// @Summary Generate organization description
|
|
// @Tags ai
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body map[string]interface{} true "Description generation request"
|
|
// @Success 200 {string} string
|
|
// @Router /ai/generate/description [post]
|
|
func (h *AIHandler) GenerateDescription(c *gin.Context) {
|
|
var request map[string]interface{}
|
|
if err := c.ShouldBindJSON(&request); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
name, _ := request["name"].(string)
|
|
sector, _ := request["sector"].(string)
|
|
keywords, _ := request["keywords"].(string)
|
|
|
|
result, err := h.service.GenerateDescription(c.Request.Context(), name, sector, keywords)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// GenerateHistoricalContext generates historical context
|
|
// @Summary Generate historical context
|
|
// @Tags ai
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body map[string]interface{} true "Historical context request"
|
|
// @Success 200 {string} string
|
|
// @Router /ai/generate/historical-context [post]
|
|
func (h *AIHandler) GenerateHistoricalContext(c *gin.Context) {
|
|
var request map[string]interface{}
|
|
if err := c.ShouldBindJSON(&request); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
landmarkName, _ := request["landmark_name"].(string)
|
|
period, _ := request["period"].(string)
|
|
originalPurpose, _ := request["original_purpose"].(string)
|
|
currentStatus, _ := request["current_status"].(string)
|
|
|
|
result, err := h.service.GenerateHistoricalContext(c.Request.Context(), landmarkName, period, originalPurpose, currentStatus)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// SendMessage sends a chat message
|
|
// @Summary Send chat message
|
|
// @Tags ai
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body map[string]interface{} true "Chat message request"
|
|
// @Success 200 {string} string
|
|
// @Router /ai/chat [post]
|
|
func (h *AIHandler) SendMessage(c *gin.Context) {
|
|
var request map[string]interface{}
|
|
if err := c.ShouldBindJSON(&request); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
message, _ := request["message"].(string)
|
|
systemInstruction, _ := request["system_instruction"].(string)
|
|
|
|
result, err := h.service.SendMessage(c.Request.Context(), message, systemInstruction)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|