Compare commits
6 Commits
testing
...
feat/order
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ec07faab0 | |||
| c78021f520 | |||
| c429c1966e | |||
| 50e1ba32f3 | |||
| 85b0c53c0a | |||
| 366d80a9ee |
@@ -5,11 +5,12 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"terminalShop/pkg/bring"
|
"terminalShop/pkg/bring"
|
||||||
"terminalShop/pkg/notify"
|
"terminalShop/pkg/notify"
|
||||||
"terminalShop/pkg/shipping"
|
"terminalShop/pkg/shipping"
|
||||||
"terminalShop/pkg/shippo"
|
"terminalShop/pkg/shippo"
|
||||||
"time"
|
|
||||||
|
|
||||||
"terminalShop/api/middleware"
|
"terminalShop/api/middleware"
|
||||||
"terminalShop/pkg/audit"
|
"terminalShop/pkg/audit"
|
||||||
@@ -20,6 +21,7 @@ import (
|
|||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/stripe/stripe-go/v78"
|
"github.com/stripe/stripe-go/v78"
|
||||||
"github.com/stripe/stripe-go/v78/refund"
|
"github.com/stripe/stripe-go/v78/refund"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrderHandler struct {
|
type OrderHandler struct {
|
||||||
@@ -43,7 +45,10 @@ func (h *OrderHandler) GetOrders(w http.ResponseWriter, r *http.Request) {
|
|||||||
userID := middleware.UserIDFromContext(r.Context())
|
userID := middleware.UserIDFromContext(r.Context())
|
||||||
|
|
||||||
var orders []models.Order
|
var orders []models.Order
|
||||||
db.Where("user_id = ?", userID).Preload("Items").Order("created_at desc").Find(&orders)
|
db.Where("user_id = ?", userID).
|
||||||
|
Preload("Items").
|
||||||
|
Preload("Events", func(tx *gorm.DB) *gorm.DB { return tx.Order("created_at ASC") }).
|
||||||
|
Order("created_at desc").Find(&orders)
|
||||||
|
|
||||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||||
"orders": orders,
|
"orders": orders,
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"terminalShop/pkg/database"
|
"terminalShop/pkg/database"
|
||||||
"terminalShop/pkg/models"
|
"terminalShop/pkg/models"
|
||||||
"terminalShop/pkg/utils"
|
"terminalShop/pkg/utils"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ViewHandler struct{}
|
type ViewHandler struct{}
|
||||||
@@ -38,7 +40,10 @@ func (h *ViewHandler) GetViewInit(w http.ResponseWriter, r *http.Request) {
|
|||||||
db.Where("user_id = ?", userID).Find(&cards)
|
db.Where("user_id = ?", userID).Find(&cards)
|
||||||
|
|
||||||
var orders []models.Order
|
var orders []models.Order
|
||||||
db.Where("user_id = ?", userID).Preload("Items").Order("created_at DESC").Find(&orders)
|
db.Where("user_id = ?", userID).
|
||||||
|
Preload("Items").
|
||||||
|
Preload("Events", func(tx *gorm.DB) *gorm.DB { return tx.Order("created_at ASC") }).
|
||||||
|
Order("created_at DESC").Find(&orders)
|
||||||
var cartItems []models.CartItem
|
var cartItems []models.CartItem
|
||||||
if cart.ID != 0 {
|
if cart.ID != 0 {
|
||||||
db.Where("cart_id = ? AND quantity > 0", cart.ID).Preload("Coffee").Find(&cartItems)
|
db.Where("cart_id = ? AND quantity > 0", cart.ID).Preload("Coffee").Find(&cartItems)
|
||||||
|
|||||||
@@ -71,9 +71,10 @@ type Order struct {
|
|||||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` // GORM soft-delete sentinel
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` // GORM soft-delete sentinel
|
||||||
|
|
||||||
// Associations
|
// Associations
|
||||||
User User `gorm:"foreignKey:UserID" json:"-"`
|
User User `gorm:"foreignKey:UserID" json:"-"`
|
||||||
Card Card `gorm:"foreignKey:CardID" json:"-"`
|
Card Card `gorm:"foreignKey:CardID" json:"-"`
|
||||||
Items []OrderItem `gorm:"foreignKey:OrderID" json:"items"`
|
Items []OrderItem `gorm:"foreignKey:OrderID" json:"items"`
|
||||||
|
Events []OrderEvent `gorm:"foreignKey:OrderID" json:"events,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName specifies the table name for the Order model.
|
// TableName specifies the table name for the Order model.
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type OrderEvent struct {
|
type OrderEvent struct {
|
||||||
ID uint `gorm:"primaryKey" json:"id"`
|
ID uint `gorm:"primaryKey" json:"id"`
|
||||||
@@ -14,3 +17,47 @@ type OrderEvent struct {
|
|||||||
func (OrderEvent) TableName() string {
|
func (OrderEvent) TableName() string {
|
||||||
return "order_events"
|
return "order_events"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *OrderEvent) PayloadMap() map[string]any {
|
||||||
|
if e.Payload == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var m map[string]any
|
||||||
|
if err := json.Unmarshal([]byte(e.Payload), &m); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *OrderEvent) DisplayLabel() (string, bool) {
|
||||||
|
switch e.Type {
|
||||||
|
case "order_paid":
|
||||||
|
return "Paid", true
|
||||||
|
case "label_purchased":
|
||||||
|
return "Label created", true
|
||||||
|
case "order_delivered":
|
||||||
|
return "Delivered", true
|
||||||
|
case "order_refunded":
|
||||||
|
return "Refunded", true
|
||||||
|
case "order_failed":
|
||||||
|
return "Payment failed", true
|
||||||
|
case "tracking_updated":
|
||||||
|
status, _ := e.PayloadMap()["status"].(string)
|
||||||
|
return trackingLabel(status)
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func trackingLabel(status string) (string, bool) {
|
||||||
|
switch status {
|
||||||
|
case "transit":
|
||||||
|
return "In transit", true
|
||||||
|
case "failure":
|
||||||
|
return "Delivery issue", true
|
||||||
|
case "returned":
|
||||||
|
return "Returned to sender", true
|
||||||
|
case "pre_transit":
|
||||||
|
return "Label scanned by carrier", true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package notify provides a simple interface to send notifications to Slack.
|
||||||
package notify
|
package notify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -14,8 +15,10 @@ import (
|
|||||||
"terminalShop/pkg/models"
|
"terminalShop/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// slack client
|
||||||
var slackClient = &http.Client{Timeout: 5 * time.Second}
|
var slackClient = &http.Client{Timeout: 5 * time.Second}
|
||||||
|
|
||||||
|
// dollars converts cents to dollars
|
||||||
func dollars(cents int) string {
|
func dollars(cents int) string {
|
||||||
return fmt.Sprintf("$%.2f", float64(cents)/100)
|
return fmt.Sprintf("$%.2f", float64(cents)/100)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,6 +201,24 @@ func (m Model) buildOrderDetailView(order models.Order, _ int) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
visible := make([]models.OrderEvent, 0, len(order.Events))
|
||||||
|
for _, event := range order.Events {
|
||||||
|
if _, ok := event.DisplayLabel(); ok {
|
||||||
|
visible = append(visible, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(visible) > 0 {
|
||||||
|
b.WriteString(labelStyle.Render("Timeline"))
|
||||||
|
b.WriteString("\n")
|
||||||
|
for _, event := range visible {
|
||||||
|
label, _ := event.DisplayLabel()
|
||||||
|
when := event.CreatedAt.Format("Jan 02 3:04 PM")
|
||||||
|
b.WriteString(valueStyle.Render(fmt.Sprintf(" %-20s %s", label, dimStyle.Render(when))))
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
// Shipping address
|
// Shipping address
|
||||||
b.WriteString(labelStyle.Render("Ship To"))
|
b.WriteString(labelStyle.Render("Ship To"))
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
|
|||||||
Reference in New Issue
Block a user