234 lines
6.9 KiB
Go
234 lines
6.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"})
|
|
}
|
|
|
|
// PATCH /api/deliveries/:id/status
|
|
func (h *Handler) UpdateDeliveryStatus(c *gin.Context) {
|
|
var req struct {
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
status := req.Status
|
|
if status == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Status is required"})
|
|
return
|
|
}
|
|
|
|
if err := h.queries.UpdateDeliveryStatus(c.Request.Context(), sqlc.UpdateDeliveryStatusParams{
|
|
ID: pgtype.UUID{Bytes: parsedID, Valid: true},
|
|
Status: status,
|
|
}); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update delivery status", "details": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Delivery status 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
|
|
}
|