Files
MyClub/internal/controllers/eshop/shipping_controller.go
T
Tomas Dvorak dfc079288f hot fix #1
2026-01-26 08:13:18 +01:00

171 lines
4.6 KiB
Go

package eshop
import (
"encoding/json"
"fmt"
"net/http"
"fotbal-club/internal/config"
"fotbal-club/internal/models"
"fotbal-club/internal/services"
"fotbal-club/pkg/database"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ShippingController struct {
Config *config.Config
PacketaService *services.PacketaService
}
func NewShippingController(cfg *config.Config) *ShippingController {
return &ShippingController{
Config: cfg,
PacketaService: services.NewPacketaService(cfg),
}
}
// GetPacketaWidgetConfig returns the configuration for the Packeta widget
func (c *ShippingController) GetPacketaWidgetConfig(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"api_key": c.Config.PacketaWidgetAPIKey,
"env": c.Config.PacketaEnv,
})
}
// DownloadLabel handles the download of a shipping label PDF
// GET /api/v1/eshop/shipping/labels/:packet_id
func (c *ShippingController) DownloadLabel(ctx *gin.Context) {
packetID := ctx.Param("packet_id")
if packetID == "" {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Missing packet ID"})
return
}
// In MVP, we might not have label download implemented in service yet
// pdfData, err := c.PacketaService.GetPacketLabel(packetID)
// Placeholder
pdfData, err := c.PacketaService.GetPacketLabel(packetID)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to download label"})
return
}
ctx.Header("Content-Type", "application/pdf")
ctx.Header("Content-Disposition", fmt.Sprintf(`attachment; filename="label_%s.pdf"`, packetID))
ctx.Data(http.StatusOK, "application/pdf", pdfData)
}
// CreatePacket creates a shipment in Packeta system from an order
func (c *ShippingController) CreatePacket(ctx *gin.Context) {
id := ctx.Param("id")
// Use a new DB connection or pass it via struct if possible.
// For now, InitDB (cached instance)
db, _ := database.InitDB()
var order models.EshopOrder
if err := db.First(&order, id).Error; err != nil {
ctx.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
return
}
if order.ShippingMethod != "packeta" {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Not a Packeta order"})
return
}
// Parse shipping address JSON to get point ID
// Format: {"id":"123", "name":"Z-Point..."}
var pointData struct {
ID interface{} `json:"id"`
}
if err := json.Unmarshal([]byte(order.ShippingAddressJSON), &pointData); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to parse shipping address"})
return
}
addressID := fmt.Sprintf("%v", pointData.ID)
if addressID == "" {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Missing Packeta point ID"})
return
}
packetID, err := c.PacketaService.CreatePacket(&order, addressID)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Packeta API error: " + err.Error()})
return
}
// Create Label record
label := models.EshopShippingLabel{
OrderID: order.ID,
PacketaPacketID: packetID,
Carrier: "packeta",
Status: "created",
}
db.Create(&label)
// Update order status
order.Status = "ready_to_ship"
db.Save(&order)
ctx.JSON(http.StatusOK, gin.H{
"packet_id": packetID,
"status": "created",
})
}
// Background job
func (c *ShippingController) UpdatePacketStatuses(db *gorm.DB) {
var labels []models.EshopShippingLabel
// Check active shipments
if err := db.Where("status NOT IN ?", []string{"delivered", "cancelled", "returned"}).Find(&labels).Error; err != nil {
return
}
for _, label := range labels {
status, err := c.PacketaService.GetPacketStatus(label.PacketaPacketID)
if err != nil {
continue
}
if label.Status != status {
// Update label status
label.Status = status
if err := db.Save(&label).Error; err != nil {
continue
}
// Update order status based on shipping status
c.updateOrderStatusFromShipping(db, label.OrderID, status)
}
}
}
// updateOrderStatusFromShipping updates order status based on shipping status
func (c *ShippingController) updateOrderStatusFromShipping(db *gorm.DB, orderID uint, shippingStatus string) {
var newOrderStatus string
switch shippingStatus {
case "ready_to_ship", "collected":
newOrderStatus = "processing"
case "in_transit", "out_for_delivery":
newOrderStatus = "shipped"
case "delivered":
newOrderStatus = "completed"
case "cancelled", "returned":
newOrderStatus = shippingStatus
default:
return // No status change needed
}
if err := db.Model(&models.EshopOrder{}).
Where("id = ?", orderID).
Update("status", newOrderStatus).Error; err != nil {
// Log error but don't fail the entire process
return
}
}