-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathproducts.go
135 lines (118 loc) · 3.47 KB
/
products.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
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
type Product struct {
SKU string `json:"sku"`
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Stock int `json:"stock"`
Cost int `json:"cost"`
SellingPrice int `json:"selling_price"`
Sold int `json:"sold,omitempty"`
TypeID int `json:"type_id,omitempty"`
TypeName string `json:"type_name,omitempty"`
}
type ProductType struct {
ID int `json:"id"`
Name string `json:"name"`
}
func getProducts(ctx context.Context, db *sqlx.DB) ([]Product, error) {
return queryProducts(ctx, db, nil)
}
func getTopProducts(ctx context.Context, db *sqlx.DB) ([]Product, error) {
const limit = 3 // top 3 best-selling products
queryString := `SELECT
id, sku, name, stock, SUM(order_lines.amount) AS sold
FROM products JOIN order_lines ON id=product_id GROUP BY products.id ORDER BY sold DESC
`
queryString += fmt.Sprintf("LIMIT %d\n", limit)
rows, err := db.QueryContext(ctx, queryString)
if err != nil {
return nil, errors.Wrap(err, "querying top products")
}
defer rows.Close()
var products []Product
for rows.Next() {
var p Product
if err := rows.Scan(&p.ID, &p.SKU, &p.Name, &p.Stock, &p.Sold); err != nil {
return nil, err
}
products = append(products, p)
}
return products, rows.Err()
}
func getProduct(ctx context.Context, db *sqlx.DB, id int) (*Product, error) {
products, err := queryProducts(ctx, db, &id)
if err != nil || len(products) == 0 {
return nil, err
}
return &products[0], nil
}
func queryProducts(ctx context.Context, db *sqlx.DB, id *int) ([]Product, error) {
var args []interface{}
queryString := `SELECT
products.id, products.sku, products.name, products.description,
products.stock, products.cost, products.selling_price,
products.type_id, product_types.name
FROM products JOIN product_types ON type_id=product_types.id
`
if id != nil {
queryString += "WHERE products.id=?\n"
args = append(args, *id)
}
rows, err := db.QueryContext(ctx, db.Rebind(queryString), args...)
if err != nil {
return nil, errors.Wrap(err, "querying products")
}
defer rows.Close()
var products []Product
for rows.Next() {
var p Product
if err := rows.Scan(
&p.ID, &p.SKU, &p.Name, &p.Description,
&p.Stock, &p.Cost, &p.SellingPrice,
&p.TypeID, &p.TypeName,
); err != nil {
return nil, err
}
products = append(products, p)
}
return products, rows.Err()
}
func getProductTypes(ctx context.Context, db *sqlx.DB) ([]ProductType, error) {
return queryProductTypes(ctx, db, nil)
}
func getProductType(ctx context.Context, db *sqlx.DB, id int) (*ProductType, error) {
productTypes, err := queryProductTypes(ctx, db, &id)
if err != nil || len(productTypes) == 0 {
return nil, err
}
return &productTypes[0], nil
}
func queryProductTypes(ctx context.Context, db *sqlx.DB, id *int) ([]ProductType, error) {
var args []interface{}
queryString := "SELECT id, name FROM product_types"
if id != nil {
queryString += " WHERE id=?"
args = append(args, *id)
}
rows, err := db.QueryContext(ctx, db.Rebind(queryString), args...)
if err != nil {
return nil, errors.Wrap(err, "querying product types")
}
defer rows.Close()
var productTypes []ProductType
for rows.Next() {
var pt ProductType
if err := rows.Scan(&pt.ID, &pt.Name); err != nil {
return nil, err
}
productTypes = append(productTypes, pt)
}
return productTypes, rows.Err()
}