This repository has been archived by the owner on Apr 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
orders.go
122 lines (101 loc) · 2.91 KB
/
orders.go
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
116
117
118
119
120
121
122
package service
import (
"context"
"database/sql"
"errors"
"fmt"
"sync"
"time"
"github.com/jbpratt/tos/internal/models"
"github.com/jbpratt/tos/internal/pb"
"github.com/volatiletech/null/v8"
"github.com/volatiletech/sqlboiler/v4/boil"
"github.com/volatiletech/sqlboiler/v4/queries/qm"
)
// OrderDB is everything that interacts with the database involving the orders
type OrderDB interface {
GetOrders(context.Context) ([]*pb.Order, error)
CompleteOrder(context.Context, int64) error
SubmitOrder(context.Context, *pb.Order) error
}
// OrderService is the abstraction of the db layer
type OrderService interface {
OrderDB
}
var _ OrderDB = &orderService{}
type orderService struct {
OrderDB
}
type orderDB struct {
rw sync.RWMutex
db *sql.DB
}
// NewOrderService creates a new order service for interacting with the
// database
func NewOrderService(db *sql.DB) (OrderService, error) {
return &orderService{&orderDB{db: db}}, nil
}
func (o *orderDB) SubmitOrder(ctx context.Context, order *pb.Order) error {
o.rw.Lock()
defer o.rw.Unlock()
ord := models.Order{SubmittedAt: time.Now().UnixNano()}
if err := ord.InsertG(ctx, boil.Infer()); err != nil {
return fmt.Errorf("failed to insert order: %w", err)
}
for _, item := range order.GetItems() {
var itm *models.Item
itm, err := models.FindItemG(ctx, null.Int64From(item.ItemId))
if err != nil {
return fmt.Errorf("failed to find item: %w", err)
}
ordItm := models.OrderItem{
OrderID: ord.ID.Int64,
ItemID: itm.ID.Int64,
Price: null.Int64From(item.GetPrice()),
}
if err = ordItm.InsertG(ctx, boil.Infer()); err != nil {
return fmt.Errorf("failed to insert order_item: %w", err)
}
}
return nil
}
// GetOrders returns orders that are not yet marked as complete
func (o *orderDB) GetOrders(ctx context.Context) ([]*pb.Order, error) {
o.rw.RLock()
defer o.rw.RUnlock()
orders, err := models.Orders(
models.OrderWhere.CompletedAt.IsNull(),
qm.Load(models.OrderRels.OrderItems),
qm.Load(models.OrderRels.OrderItemOptions),
).AllG(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get orders that are not complete: %w", err)
}
output := make([]*pb.Order, 0, len(orders))
for _, order := range orders {
ord := &pb.Order{}
for _, it := range order.R.OrderItems {
item := &pb.OrderItem{
ItemId: it.ItemID,
Price: it.Price.Int64,
}
ord.Items = append(ord.Items, item)
// options...
}
output = append(output, ord)
}
return output, errors.New("unimplemented")
}
func (o *orderDB) CompleteOrder(ctx context.Context, id int64) error {
o.rw.Lock()
defer o.rw.Unlock()
order, err := models.FindOrderG(ctx, null.Int64From(id))
if err != nil {
return fmt.Errorf("failed to find order: %w", err)
}
order.CompletedAt = null.Int64From(time.Now().UnixNano())
if _, err = order.UpdateG(ctx, boil.Infer()); err != nil {
return fmt.Errorf("failed to update CompletedAt for order: %w", err)
}
return nil
}