turash/bugulma/backend/internal/handler/shared_asset_handler.go
Damir Mukimov 000eab4740
Major repository reorganization and missing backend endpoints implementation
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)
2025-11-25 06:01:16 +01:00

197 lines
6.3 KiB
Go

package handler
import (
"bugulma/backend/internal/service"
"net/http"
"github.com/gin-gonic/gin"
)
// SharedAssetHandler handles HTTP requests for shared assets
type SharedAssetHandler struct {
service *service.SharedAssetService
}
// NewSharedAssetHandler creates a new shared asset handler
func NewSharedAssetHandler(service *service.SharedAssetService) *SharedAssetHandler {
return &SharedAssetHandler{service: service}
}
// CreateRequest represents the request to create a shared asset
type CreateSharedAssetRequest struct {
OwnerBusinessID string `json:"owner_business_id" binding:"required"`
SiteID string `json:"site_id" binding:"required"`
Type string `json:"type" binding:"required"`
Description string `json:"description"`
Capacity float64 `json:"capacity"`
CapacityUnit string `json:"capacity_unit"`
UtilizationRate float64 `json:"utilization_rate"`
AvailabilityPeriod string `json:"availability_period"`
OperationalStatus string `json:"operational_status"`
CostSharingModel string `json:"cost_sharing_model"`
MaintenanceSchedule string `json:"maintenance_schedule"`
}
// Create creates a new shared asset
// @Summary Create a shared asset
// @Tags shared-assets
// @Accept json
// @Produce json
// @Param asset body CreateSharedAssetRequest true "Shared Asset"
// @Success 201 {object} domain.SharedAsset
// @Router /api/shared-assets [post]
func (h *SharedAssetHandler) Create(c *gin.Context) {
var req CreateSharedAssetRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
asset, err := h.service.Create(c.Request.Context(), service.CreateSharedAssetRequest{
OwnerBusinessID: req.OwnerBusinessID,
SiteID: req.SiteID,
Type: service.AssetTypeFromString(req.Type),
Description: req.Description,
Capacity: req.Capacity,
CapacityUnit: req.CapacityUnit,
UtilizationRate: req.UtilizationRate,
AvailabilityPeriod: req.AvailabilityPeriod,
OperationalStatus: service.OperationalStatusFromString(req.OperationalStatus),
CostSharingModel: req.CostSharingModel,
MaintenanceSchedule: req.MaintenanceSchedule,
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, asset)
}
// GetByID retrieves a shared asset by ID
// @Summary Get shared asset by ID
// @Tags shared-assets
// @Produce json
// @Param id path string true "Asset ID"
// @Success 200 {object} domain.SharedAsset
// @Router /api/shared-assets/{id} [get]
func (h *SharedAssetHandler) GetByID(c *gin.Context) {
id := c.Param("id")
asset, err := h.service.GetByID(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Shared asset not found"})
return
}
c.JSON(http.StatusOK, asset)
}
// GetBySite retrieves shared assets at a specific site
// @Summary Get shared assets by site
// @Tags shared-assets
// @Produce json
// @Param siteId path string true "Site ID"
// @Success 200 {array} domain.SharedAsset
// @Router /api/shared-assets/site/{siteId} [get]
func (h *SharedAssetHandler) GetBySite(c *gin.Context) {
siteID := c.Param("siteId")
assets, err := h.service.GetBySiteID(c.Request.Context(), siteID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, assets)
}
// GetByOwner retrieves shared assets owned by a specific organization
// @Summary Get shared assets by owner
// @Tags shared-assets
// @Produce json
// @Param organizationId path string true "Organization ID"
// @Success 200 {array} domain.SharedAsset
// @Router /api/shared-assets/owner/{organizationId} [get]
func (h *SharedAssetHandler) GetByOwner(c *gin.Context) {
ownerID := c.Param("organizationId")
assets, err := h.service.GetByOwnerBusinessID(c.Request.Context(), ownerID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, assets)
}
// GetAvailable retrieves shared assets with available capacity
// @Summary Get available shared assets
// @Tags shared-assets
// @Produce json
// @Success 200 {array} domain.SharedAsset
// @Router /api/shared-assets/available [get]
func (h *SharedAssetHandler) GetAvailable(c *gin.Context) {
assets, err := h.service.GetAvailableAssets(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, assets)
}
// Update updates a shared asset
// @Summary Update a shared asset
// @Tags shared-assets
// @Accept json
// @Produce json
// @Param id path string true "Asset ID"
// @Param asset body CreateSharedAssetRequest true "Shared Asset"
// @Success 200 {object} domain.SharedAsset
// @Router /api/shared-assets/{id} [put]
func (h *SharedAssetHandler) Update(c *gin.Context) {
id := c.Param("id")
asset, err := h.service.GetByID(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Shared asset not found"})
return
}
var req CreateSharedAssetRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Update fields
asset.OwnerBusinessID = req.OwnerBusinessID
asset.SiteID = req.SiteID
asset.Type = service.AssetTypeFromString(req.Type)
asset.Description = req.Description
asset.Capacity = req.Capacity
asset.CapacityUnit = req.CapacityUnit
asset.UtilizationRate = req.UtilizationRate
asset.AvailabilityPeriod = req.AvailabilityPeriod
asset.OperationalStatus = service.OperationalStatusFromString(req.OperationalStatus)
asset.CostSharingModel = req.CostSharingModel
asset.MaintenanceSchedule = req.MaintenanceSchedule
if err := h.service.Update(c.Request.Context(), asset); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, asset)
}
// Delete deletes a shared asset
// @Summary Delete a shared asset
// @Tags shared-assets
// @Param id path string true "Asset ID"
// @Success 204
// @Router /api/shared-assets/{id} [delete]
func (h *SharedAssetHandler) Delete(c *gin.Context) {
id := c.Param("id")
if err := h.service.Delete(c.Request.Context(), id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.Status(http.StatusNoContent)
}