Files
delivery-tracker/backend/internal/delivery/handler.go
2026-04-14 15:38:45 +06:00

193 lines
5.9 KiB
Go

package delivery
import (
"net/http"
"time"
sqlc "github.com/chedius/delivery-tracker/internal/db/sqlc"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
type Handler struct {
queries *sqlc.Queries
}
// DeliveryRequest represents the request body for creating or updating a delivery
type DeliveryRequest struct {
Date string `json:"date" binding:"required"` // DD-MM-YYYY
PickupLocation string `json:"pickup_location" binding:"required,oneof=warehouse symbat nursaya galaktika"`
ProductName string `json:"product_name" binding:"required"`
Address string `json:"address" binding:"required"`
Phone string `json:"phone" binding:"required"`
AdditionalPhone string `json:"additional_phone"`
HasElevator bool `json:"has_elevator"`
Comment string `json:"comment"`
}
func NewHandler(queries *sqlc.Queries) *Handler {
return &Handler{queries: queries}
}
// GET /api/deliveries/:id
func (h *Handler) GetDeliveryByID(c *gin.Context) {
id := c.Param("id")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"})
return
}
parsedID, err := uuid.Parse(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid UUID format", "details": err.Error()})
return
}
delivery, err := h.queries.GetDeliveryByID(c.Request.Context(), pgtype.UUID{Bytes: parsedID, Valid: true})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get delivery", "details": err.Error(), "id": id, "bytes": [16]byte([]byte(id))})
return
}
c.JSON(http.StatusOK, gin.H{"delivery": delivery})
}
// GET /api/deliveries?date=DD-MM-YYYY
func (h *Handler) GetDeliveries(c *gin.Context) {
t, err := parseDate(c.Query("date"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format", "details": err.Error()})
return
}
date := pgtype.Date{Time: t, Valid: true}
deliveries, err := h.queries.GetDeliveriesByDate(c.Request.Context(), date)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get deliveries", "details": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"deliveries": deliveries})
}
// GET /api/deliveries/count
func (h *Handler) GetDeliveryCount(c *gin.Context) {
counts, err := h.queries.GetDeliveryCount(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get delivery count", "details": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"counts": counts})
}
// POST /api/deliveries
func (h *Handler) CreateDelivery(c *gin.Context) {
var req DeliveryRequest = DeliveryRequest{}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
return
}
// Parse date from DD-MM-YYYY
t, err := parseDate(req.Date)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format", "details": err.Error()})
return
}
params := sqlc.CreateDeliveryParams{
Date: pgtype.Date{Time: t, Valid: true},
PickupLocation: req.PickupLocation,
ProductName: req.ProductName,
Address: req.Address,
Phone: req.Phone,
AdditionalPhone: pgtype.Text{String: req.AdditionalPhone, Valid: req.AdditionalPhone != ""},
HasElevator: req.HasElevator,
Comment: pgtype.Text{String: req.Comment, Valid: true},
}
res, err := h.queries.CreateDelivery(c.Request.Context(), params)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create delivery", "details": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Delivery created", "id": res.ID.String()})
}
// PATCH /api/deliveries/:id
func (h *Handler) UpdateDelivery(c *gin.Context) {
var req DeliveryRequest = DeliveryRequest{}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
return
}
id := c.Param("id")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"})
return
}
parsedID, err := uuid.Parse(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid UUID format", "details": err.Error()})
return
}
t, err := parseDate(req.Date)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format", "details": err.Error()})
return
}
if err := h.queries.UpdateDelivery(c.Request.Context(), sqlc.UpdateDeliveryParams{
ID: pgtype.UUID{Bytes: parsedID, Valid: true},
Date: pgtype.Date{Time: t, Valid: true},
PickupLocation: req.PickupLocation,
ProductName: req.ProductName,
Address: req.Address,
Phone: req.Phone,
AdditionalPhone: pgtype.Text{String: req.AdditionalPhone, Valid: req.AdditionalPhone != ""},
HasElevator: req.HasElevator,
Comment: pgtype.Text{String: req.Comment, Valid: true},
}); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update delivery", "details": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Delivery updated"})
}
// DELETE /api/deliveries/:id
func (h *Handler) DeleteDelivery(c *gin.Context) {
id := c.Param("id")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"})
return
}
parsedID, err := uuid.Parse(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid UUID format", "details": err.Error()})
return
}
if err := h.queries.DeleteDelivery(c.Request.Context(), pgtype.UUID{Bytes: parsedID, Valid: true}); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete delivery", "details": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Delivery deleted"})
}
func parseDate(dateStr string) (time.Time, error) {
t, err := time.Parse("02-01-2006", dateStr)
if err != nil {
return time.Time{}, err
}
return t, nil
}