Files
Mini-ERP-app/core-service/internal/api/handlers/operations.go
Andrey Epifantsev a846a2dce4 feat: завершён этап 3 - API структура Core Service
- Созданы репозитории для locations, items, operations
- Реализованы сервисы с бизнес-логикой
- Созданы HTTP handlers для всех API endpoints
- Добавлена функция GetClaims в middleware
- Обновлён server.go для интеграции всех компонентов
- Поддержка JSON полей в PostgreSQL
- Organization-scope фильтрация во всех операциях
- Валидация запросов через validator

Готово для этапа 4 - Шаблоны помещений
2025-08-27 15:17:12 +04:00

228 lines
6.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handlers
import (
"net/http"
"erp-mvp/core-service/internal/api/middleware"
"erp-mvp/core-service/internal/models"
"erp-mvp/core-service/internal/service"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
)
type OperationsHandler struct {
operationsService service.OperationsService
validate *validator.Validate
}
func NewOperationsHandler(operationsService service.OperationsService) *OperationsHandler {
return &OperationsHandler{
operationsService: operationsService,
validate: validator.New(),
}
}
// PlaceItem размещает товар в месте хранения
func (h *OperationsHandler) PlaceItem(c *gin.Context) {
claims := middleware.GetClaims(c)
if claims == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
var req models.PlaceItemRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
return
}
if err := h.validate.Struct(req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Validation failed", "details": err.Error()})
return
}
placement, err := h.operationsService.PlaceItem(c.Request.Context(), claims.OrganizationID, &req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to place item"})
return
}
c.JSON(http.StatusCreated, placement)
}
// MoveItem перемещает товар в другое место хранения
func (h *OperationsHandler) MoveItem(c *gin.Context) {
claims := middleware.GetClaims(c)
if claims == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
placementIDStr := c.Param("id")
placementID, err := uuid.Parse(placementIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid placement ID"})
return
}
var req struct {
NewLocationID uuid.UUID `json:"new_location_id" validate:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
return
}
if err := h.validate.Struct(req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Validation failed", "details": err.Error()})
return
}
if err := h.operationsService.MoveItem(c.Request.Context(), placementID, req.NewLocationID, claims.OrganizationID); err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Placement not found"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Item moved successfully"})
}
// GetItemPlacements получает все размещения товара
func (h *OperationsHandler) GetItemPlacements(c *gin.Context) {
claims := middleware.GetClaims(c)
if claims == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
itemIDStr := c.Param("item_id")
itemID, err := uuid.Parse(itemIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid item ID"})
return
}
placements, err := h.operationsService.GetItemPlacements(c.Request.Context(), itemID, claims.OrganizationID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Item not found"})
return
}
c.JSON(http.StatusOK, placements)
}
// GetLocationPlacements получает все товары в месте хранения
func (h *OperationsHandler) GetLocationPlacements(c *gin.Context) {
claims := middleware.GetClaims(c)
if claims == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
locationIDStr := c.Param("location_id")
locationID, err := uuid.Parse(locationIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid location ID"})
return
}
placements, err := h.operationsService.GetLocationPlacements(c.Request.Context(), locationID, claims.OrganizationID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Location not found"})
return
}
c.JSON(http.StatusOK, placements)
}
// UpdateQuantity обновляет количество товара в размещении
func (h *OperationsHandler) UpdateQuantity(c *gin.Context) {
claims := middleware.GetClaims(c)
if claims == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
placementIDStr := c.Param("id")
placementID, err := uuid.Parse(placementIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid placement ID"})
return
}
var req struct {
Quantity int `json:"quantity" validate:"required,min=1"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
return
}
if err := h.validate.Struct(req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Validation failed", "details": err.Error()})
return
}
if err := h.operationsService.UpdateQuantity(c.Request.Context(), placementID, req.Quantity, claims.OrganizationID); err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Placement not found"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Quantity updated successfully"})
}
// DeletePlacement удаляет размещение товара
func (h *OperationsHandler) DeletePlacement(c *gin.Context) {
claims := middleware.GetClaims(c)
if claims == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
placementIDStr := c.Param("id")
placementID, err := uuid.Parse(placementIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid placement ID"})
return
}
if err := h.operationsService.DeletePlacement(c.Request.Context(), placementID, claims.OrganizationID); err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Placement not found"})
return
}
c.JSON(http.StatusNoContent, nil)
}
// Search выполняет поиск товаров с местами размещения
func (h *OperationsHandler) Search(c *gin.Context) {
claims := middleware.GetClaims(c)
if claims == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
var req models.SearchRequest
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid query parameters"})
return
}
// Устанавливаем значения по умолчанию
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 20
}
response, err := h.operationsService.Search(c.Request.Context(), claims.OrganizationID, &req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to search"})
return
}
c.JSON(http.StatusOK, response)
}