-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathorders.go
More file actions
115 lines (99 loc) · 2.8 KB
/
Copy pathorders.go
File metadata and controls
115 lines (99 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package orders
import (
"context"
"errors"
"fmt"
"time"
"example.com/orders-api/gen/serverhttp"
"github.com/devctllabs/go-libs/postgresdb"
"github.com/jackc/pgx/v5"
)
var ErrNotFound = errors.New("order not found")
type Order struct {
ID int64
CustomerName string
TotalCents int64
CreatedAt time.Time
}
type Store interface {
Create(ctx context.Context, customerName string, totalCents int64) (Order, error)
Get(ctx context.Context, id int64) (Order, error)
}
type PostgresStore struct {
reader *postgresdb.Endpoint
writer *postgresdb.Endpoint
}
func NewPostgresStore(reader, writer *postgresdb.Endpoint) *PostgresStore {
return &PostgresStore{reader: reader, writer: writer}
}
func (s *PostgresStore) Create(ctx context.Context, customerName string, totalCents int64) (Order, error) {
const query = `
INSERT INTO orders (customer_name, total_cents)
VALUES ($1, $2)
RETURNING id, customer_name, total_cents, created_at`
var order Order
err := s.writer.QueryRow(ctx, query, customerName, totalCents).Scan(
&order.ID,
&order.CustomerName,
&order.TotalCents,
&order.CreatedAt,
)
if err != nil {
return Order{}, fmt.Errorf("insert order: %w", err)
}
return order, nil
}
func (s *PostgresStore) Get(ctx context.Context, id int64) (Order, error) {
const query = `
SELECT id, customer_name, total_cents, created_at
FROM orders
WHERE id = $1`
var order Order
err := s.reader.QueryRow(ctx, query, id).Scan(
&order.ID,
&order.CustomerName,
&order.TotalCents,
&order.CreatedAt,
)
if errors.Is(err, pgx.ErrNoRows) {
return Order{}, ErrNotFound
}
if err != nil {
return Order{}, fmt.Errorf("select order: %w", err)
}
return order, nil
}
type Handler struct {
store Store
}
func NewHandler(store Store) *Handler {
return &Handler{store: store}
}
func (h *Handler) CreateOrder(ctx context.Context, request serverhttp.CreateOrderRequestObject) (serverhttp.CreateOrderResponseObject, error) {
if request.Body == nil {
return nil, errors.New("create order body is required")
}
order, err := h.store.Create(ctx, request.Body.CustomerName, request.Body.TotalCents)
if err != nil {
return nil, err
}
return serverhttp.CreateOrder201JSONResponse(toAPIOrder(order)), nil
}
func (h *Handler) GetOrder(ctx context.Context, request serverhttp.GetOrderRequestObject) (serverhttp.GetOrderResponseObject, error) {
order, err := h.store.Get(ctx, request.Id)
if errors.Is(err, ErrNotFound) {
return serverhttp.GetOrder404JSONResponse{Message: "order not found"}, nil
}
if err != nil {
return nil, err
}
return serverhttp.GetOrder200JSONResponse(toAPIOrder(order)), nil
}
func toAPIOrder(order Order) serverhttp.Order {
return serverhttp.Order{
Id: order.ID,
CustomerName: order.CustomerName,
TotalCents: order.TotalCents,
CreatedAt: order.CreatedAt,
}
}