Move database code to store package
This commit is contained in:
parent
d1c393736a
commit
e75468ce55
7 changed files with 79 additions and 75 deletions
4
TODO.md
4
TODO.md
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
## Critical Features
|
||||
|
||||
- [ ] Database Implementation
|
||||
- [x] Database Implementation
|
||||
|
||||
- [ ] Init mode to create a new db
|
||||
- [x] Init mode to create a new db
|
||||
- [x] Set up SQLite database
|
||||
- [x] Create proper schemas
|
||||
- [x] Implement data persistence
|
||||
|
|
|
|||
26
handler.go
26
handler.go
|
|
@ -7,38 +7,40 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Bronku/iroon/store"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
tmpl *template.Template
|
||||
s *store
|
||||
s *store.Store
|
||||
}
|
||||
|
||||
func (h *handler) close() {
|
||||
if h.s != nil {
|
||||
h.s.close()
|
||||
h.s.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) form(w http.ResponseWriter, r *http.Request) {
|
||||
url := strings.Split(r.URL.String(), "/")
|
||||
o := order{
|
||||
o := store.Order{
|
||||
ID: -1,
|
||||
Date: time.Now(),
|
||||
}
|
||||
id, err := strconv.Atoi(url[2])
|
||||
if err == nil {
|
||||
newOrder, err := h.s.getOrder(id)
|
||||
newOrder, err := h.s.GetOrder(id)
|
||||
if err == nil {
|
||||
o = newOrder
|
||||
}
|
||||
}
|
||||
type formData struct {
|
||||
Order order
|
||||
Catalogue []cake
|
||||
Order store.Order
|
||||
Catalogue []store.Cake
|
||||
}
|
||||
|
||||
cakes, err := h.s.getCakes()
|
||||
cakes, err := h.s.GetCakes()
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "server side error getting available cakes: ", err)
|
||||
return
|
||||
|
|
@ -62,7 +64,7 @@ func (h *handler) addOrder(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
fmt.Println("received form: ", r.Form)
|
||||
|
||||
var n order
|
||||
var n store.Order
|
||||
n.ID, err = strconv.Atoi(r.FormValue("id"))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
|
@ -96,8 +98,8 @@ func (h *handler) addOrder(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
n.Accepted = time.Now()
|
||||
|
||||
n.Cakes = make([]cake, 0)
|
||||
cakes, err := h.s.getCakes()
|
||||
n.Cakes = make([]store.Cake, 0)
|
||||
cakes, err := h.s.GetCakes()
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "server side error getting available cakes: ", err)
|
||||
return
|
||||
|
|
@ -117,7 +119,7 @@ func (h *handler) addOrder(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
fmt.Println("parsed order: ", n)
|
||||
|
||||
h.s.saveOrder(n)
|
||||
h.s.SaveOrder(n)
|
||||
|
||||
w.Header().Set("content-type", "text/html")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
|
|
@ -126,7 +128,7 @@ func (h *handler) addOrder(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func (h *handler) index(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("content-type", "text/html")
|
||||
orders, err := h.s.getOrders()
|
||||
orders, err := h.s.GetOrders()
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "server side error getting orders: ", err)
|
||||
return
|
||||
|
|
|
|||
4
main.go
4
main.go
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/Bronku/iroon/auth"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/Bronku/iroon/store"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
@ -20,7 +20,7 @@ func main() {
|
|||
log.Fatal("can't parse templates: ", err)
|
||||
}
|
||||
|
||||
h.s, err = openStore("./foo.db")
|
||||
h.s, err = store.OpenStore("./foo.db")
|
||||
if err != nil {
|
||||
log.Fatal("can't open the databse", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
package main
|
||||
package store
|
||||
|
||||
import "time"
|
||||
|
||||
type cake struct {
|
||||
type Cake struct {
|
||||
Name string
|
||||
ID int
|
||||
Price int
|
||||
Amount int
|
||||
}
|
||||
|
||||
type order struct {
|
||||
type Order struct {
|
||||
ID int
|
||||
Name string
|
||||
Surname string
|
||||
|
|
@ -19,5 +19,5 @@ type order struct {
|
|||
Accepted time.Time
|
||||
Status string
|
||||
Paid int // increments of 0.01
|
||||
Cakes []cake
|
||||
Cakes []Cake
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package store
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
|
@ -7,17 +7,19 @@ import (
|
|||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
//go:embed schema.sql
|
||||
var schema string
|
||||
|
||||
type store struct {
|
||||
type Store struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func openStore(filename string) (*store, error) {
|
||||
var out store
|
||||
func OpenStore(filename string) (*Store, error) {
|
||||
var out Store
|
||||
var err error
|
||||
_, err = os.Stat(filename)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
|
|
@ -27,13 +29,13 @@ func openStore(filename string) (*store, error) {
|
|||
return &out, err
|
||||
}
|
||||
|
||||
func (s *store) close() {
|
||||
func (s *Store) Close() {
|
||||
if s.db != nil {
|
||||
s.db.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) loadSchema() error {
|
||||
func (s *Store) loadSchema() error {
|
||||
if s.db == nil {
|
||||
return errors.New("database doesn't exist")
|
||||
}
|
||||
|
|
@ -41,8 +43,8 @@ func (s *store) loadSchema() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (s *store) getCake(id int) (cake, error) {
|
||||
out := cake{ID: id}
|
||||
func (s *Store) GetCake(id int) (Cake, error) {
|
||||
out := Cake{ID: id}
|
||||
row, err := s.db.Query("select name, price from cake where id = ?;", id)
|
||||
if err != nil {
|
||||
return out, err
|
||||
|
|
@ -53,15 +55,15 @@ func (s *store) getCake(id int) (cake, error) {
|
|||
return out, err
|
||||
}
|
||||
|
||||
func (s *store) getCakes() ([]cake, error) {
|
||||
func (s *Store) GetCakes() ([]Cake, error) {
|
||||
rows, err := s.db.Query("select id, name, price from cake")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
cakes := make([]cake, 0)
|
||||
cakes := make([]Cake, 0)
|
||||
for rows.Next() {
|
||||
var c cake
|
||||
var c Cake
|
||||
c.Amount = 0
|
||||
err = rows.Scan(&c.ID, &c.Name, &c.Price)
|
||||
if err != nil {
|
||||
|
|
@ -72,7 +74,7 @@ func (s *store) getCakes() ([]cake, error) {
|
|||
return cakes, err
|
||||
}
|
||||
|
||||
func (s *store) saveCake(newCake cake) (int, error) {
|
||||
func (s *Store) SaveCake(newCake Cake) (int, error) {
|
||||
query := "insert into cake(name, price) values (?, ?) returning id;"
|
||||
if newCake.ID != -1 {
|
||||
query = "update cake set name = ? , price = ? where id = "
|
||||
|
|
@ -90,8 +92,8 @@ func (s *store) saveCake(newCake cake) (int, error) {
|
|||
return newCake.ID, err
|
||||
}
|
||||
|
||||
func (s *store) getOrder(id int) (order, error) {
|
||||
var out order
|
||||
func (s *Store) GetOrder(id int) (Order, error) {
|
||||
var out Order
|
||||
row, err := s.db.Query("select id, name, surname, phone, location, order_date, delivery_date, status, paid from customer_order where id = ?;", id)
|
||||
defer row.Close()
|
||||
if err != nil {
|
||||
|
|
@ -107,19 +109,19 @@ func (s *store) getOrder(id int) (order, error) {
|
|||
out.Accepted, _ = time.Parse("2006-01-02 15:04", order_date)
|
||||
out.Date, _ = time.Parse("2006-01-02 15:04", delivery_date)
|
||||
|
||||
out.Cakes = make([]cake, 0)
|
||||
out.Cakes = make([]Cake, 0)
|
||||
rows, err := s.db.Query("select cake, amount from ordered_cake where customer_order = ?;", id)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var newCake cake
|
||||
var newCake Cake
|
||||
err = rows.Scan(&newCake.ID, &newCake.Amount)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
cakeData, err := s.getCake(newCake.ID)
|
||||
cakeData, err := s.GetCake(newCake.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
@ -131,8 +133,8 @@ func (s *store) getOrder(id int) (order, error) {
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (s *store) getOrders() ([]order, error) {
|
||||
var out []order
|
||||
func (s *Store) GetOrders() ([]Order, error) {
|
||||
var out []Order
|
||||
rows, err := s.db.Query("select id, name, surname, phone, location, order_date, delivery_date, status, paid from customer_order;")
|
||||
if err != nil {
|
||||
return out, err
|
||||
|
|
@ -140,7 +142,7 @@ func (s *store) getOrders() ([]order, error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var o order
|
||||
var o Order
|
||||
var order_date, delivery_date string
|
||||
err = rows.Scan(&o.ID, &o.Name, &o.Surname, &o.Phone, &o.Location, &order_date, &delivery_date, &o.Status, &o.Paid)
|
||||
if err != nil {
|
||||
|
|
@ -149,7 +151,7 @@ func (s *store) getOrders() ([]order, error) {
|
|||
o.Accepted, _ = time.Parse("2006-01-02 15:04", order_date)
|
||||
o.Date, _ = time.Parse("2006-01-02 15:04", delivery_date)
|
||||
|
||||
o.Cakes = make([]cake, 0)
|
||||
o.Cakes = make([]Cake, 0)
|
||||
rows, err := s.db.Query("select cake, amount from ordered_cake where customer_order = ?;", o.ID)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -157,12 +159,12 @@ func (s *store) getOrders() ([]order, error) {
|
|||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var newCake cake
|
||||
var newCake Cake
|
||||
err = rows.Scan(&newCake.ID, &newCake.Amount)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
cakeData, err := s.getCake(newCake.ID)
|
||||
cakeData, err := s.GetCake(newCake.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
@ -177,7 +179,7 @@ func (s *store) getOrders() ([]order, error) {
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (s *store) saveOrder(newOrder order) (int, error) {
|
||||
func (s *Store) SaveOrder(newOrder Order) (int, error) {
|
||||
query := "insert into customer_order(name, surname, phone, location, order_date, delivery_date, status, paid) values (?, ?, ?, ?, ?, ?, ?, ?) returning id;"
|
||||
if newOrder.ID != -1 {
|
||||
query = "update customer_order set name = ?, surname = ?, phone = ?, location = ?, order_date = ?, delivery_date = ?, status = ?, paid = ? where id = "
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package store
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
@ -6,21 +6,21 @@ import (
|
|||
)
|
||||
|
||||
func TestStore(t *testing.T) {
|
||||
s, err := openStore("file:memdb1?mode=memory&cache=shared")
|
||||
s, err := OpenStore("file:memdb1?mode=memory&cache=shared")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create store: %v", err)
|
||||
}
|
||||
defer s.close()
|
||||
defer s.Close()
|
||||
|
||||
// ensure db is empty
|
||||
cakes, err := s.getCakes()
|
||||
cakes, err := s.GetCakes()
|
||||
if err != nil {
|
||||
t.Errorf("Error getting cakes: %v", err)
|
||||
}
|
||||
if len(cakes) != 0 {
|
||||
t.Errorf("Expected empty cakes list, got: %v", cakes)
|
||||
}
|
||||
orders, err := s.getOrders()
|
||||
orders, err := s.GetOrders()
|
||||
if err != nil {
|
||||
t.Errorf("Error getting orders: %v", err)
|
||||
}
|
||||
|
|
@ -29,8 +29,8 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
|
||||
// create new cake
|
||||
newCake := cake{Name: "Chocolate Cake", ID: -1, Price: 2500, Amount: -1}
|
||||
newCake.ID, err = s.saveCake(newCake)
|
||||
newCake := Cake{Name: "Chocolate Cake", ID: -1, Price: 2500, Amount: -1}
|
||||
newCake.ID, err = s.SaveCake(newCake)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save new cake: %v", err)
|
||||
}
|
||||
|
|
@ -39,8 +39,8 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
|
||||
// create another cake
|
||||
anotherCake := cake{Name: "Another Cake", ID: -1, Price: 3000, Amount: -1}
|
||||
anotherCake.ID, err = s.saveCake(anotherCake)
|
||||
anotherCake := Cake{Name: "Another Cake", ID: -1, Price: 3000, Amount: -1}
|
||||
anotherCake.ID, err = s.SaveCake(anotherCake)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save new cake: %v", err)
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ func TestStore(t *testing.T) {
|
|||
// Update Existing Cake
|
||||
newCake.Name = "Updated Cake"
|
||||
newCake.Price = 100
|
||||
newID, err := s.saveCake(newCake)
|
||||
newID, err := s.SaveCake(newCake)
|
||||
if newID != newCake.ID {
|
||||
t.Error("wrong id")
|
||||
}
|
||||
|
|
@ -60,15 +60,15 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
|
||||
// Update Non-existing Cake
|
||||
var updatedCake cake
|
||||
var updatedCake Cake
|
||||
updatedCake.ID = 10
|
||||
_, err = s.saveCake(updatedCake)
|
||||
_, err = s.SaveCake(updatedCake)
|
||||
if err == nil {
|
||||
t.Error("did not return an error when attempted to update non existant cake")
|
||||
}
|
||||
|
||||
// get cakes
|
||||
cakes, err = s.getCakes()
|
||||
cakes, err = s.GetCakes()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get all cakes after creation: %v", err)
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ func TestStore(t *testing.T) {
|
|||
t.Errorf("Want %v\nGot %v", anotherCake, cakes)
|
||||
}
|
||||
|
||||
selectedCake, err := s.getCake(newCake.ID)
|
||||
selectedCake, err := s.GetCake(newCake.ID)
|
||||
if err != nil {
|
||||
t.Error("error getting a cake", err)
|
||||
}
|
||||
|
|
@ -104,14 +104,14 @@ func TestStore(t *testing.T) {
|
|||
t.Errorf("Want %v\nGot %v", newCake, selectedCake)
|
||||
}
|
||||
|
||||
selectedCake, err = s.getCake(-1)
|
||||
selectedCake, err = s.GetCake(-1)
|
||||
if err == nil {
|
||||
t.Error("no error getting a non-existant cake")
|
||||
}
|
||||
|
||||
// create new order
|
||||
now := time.Now()
|
||||
newOrder := order{
|
||||
newOrder := Order{
|
||||
ID: -1,
|
||||
Name: "John",
|
||||
Surname: "Doe",
|
||||
|
|
@ -121,9 +121,9 @@ func TestStore(t *testing.T) {
|
|||
Date: now.Add(time.Hour * 24),
|
||||
Status: "Pending",
|
||||
Paid: 1000,
|
||||
Cakes: []cake{{ID: newCake.ID, Amount: 2}, {ID: anotherCake.ID, Amount: 10}},
|
||||
Cakes: []Cake{{ID: newCake.ID, Amount: 2}, {ID: anotherCake.ID, Amount: 10}},
|
||||
}
|
||||
newOrder.ID, err = s.saveOrder(newOrder)
|
||||
newOrder.ID, err = s.SaveOrder(newOrder)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save new order: %v", err)
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
|
||||
// create another order
|
||||
anotherOrder := order{
|
||||
anotherOrder := Order{
|
||||
ID: -1,
|
||||
Name: "Jane",
|
||||
Surname: "Doe",
|
||||
|
|
@ -142,9 +142,9 @@ func TestStore(t *testing.T) {
|
|||
Date: now.Add(time.Hour * 192),
|
||||
Status: "Accepted",
|
||||
Paid: 1500,
|
||||
Cakes: []cake{{ID: newCake.ID, Amount: 100}},
|
||||
Cakes: []Cake{{ID: newCake.ID, Amount: 100}},
|
||||
}
|
||||
anotherOrder.ID, err = s.saveOrder(anotherOrder)
|
||||
anotherOrder.ID, err = s.SaveOrder(anotherOrder)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save new order: %v", err)
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ func TestStore(t *testing.T) {
|
|||
newOrder.Name = "James"
|
||||
newOrder.Status = "Done"
|
||||
newOrder.Cakes = newOrder.Cakes[1:]
|
||||
newID, err = s.saveOrder(newOrder)
|
||||
newID, err = s.SaveOrder(newOrder)
|
||||
if newID != newOrder.ID {
|
||||
t.Error("wrong id")
|
||||
}
|
||||
|
|
@ -165,15 +165,15 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
|
||||
// update non existing order
|
||||
var updatedOrder order
|
||||
var updatedOrder Order
|
||||
updatedOrder.ID = 10
|
||||
_, err = s.saveOrder(updatedOrder)
|
||||
_, err = s.SaveOrder(updatedOrder)
|
||||
if err == nil {
|
||||
t.Error("did not return an error when attempted to update non existant cake")
|
||||
}
|
||||
|
||||
// get orders
|
||||
orders, err = s.getOrders()
|
||||
orders, err = s.GetOrders()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get all orders after creation: %v", err)
|
||||
}
|
||||
|
|
@ -223,7 +223,7 @@ func TestStore(t *testing.T) {
|
|||
t.Errorf("Want %v\nGot %v", anotherOrder.Cakes, orders[anotherOrderPos].Cakes)
|
||||
}
|
||||
|
||||
selectedOrder, err := s.getOrder(newOrder.ID)
|
||||
selectedOrder, err := s.GetOrder(newOrder.ID)
|
||||
if err != nil {
|
||||
t.Error("error getting an order by id ", err)
|
||||
}
|
||||
|
|
@ -241,20 +241,20 @@ func TestStore(t *testing.T) {
|
|||
t.Errorf("Want %v\nGot %v", newOrder.Cakes, selectedOrder.Cakes)
|
||||
}
|
||||
|
||||
_, err = s.getOrder(-1)
|
||||
_, err = s.GetOrder(-1)
|
||||
if err == nil {
|
||||
t.Error("no error getting invalid order")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSliceComparison(t *testing.T) {
|
||||
a := []cake{
|
||||
a := []Cake{
|
||||
{Name: "ok", Price: 100, ID: 12, Amount: 10},
|
||||
{Name: "ok", Price: 11, ID: 13, Amount: 1},
|
||||
{Name: "ok", Price: 100, ID: 10, Amount: 11},
|
||||
}
|
||||
|
||||
b := []cake{
|
||||
b := []Cake{
|
||||
{Name: "okas", Price: 110, ID: 12, Amount: 10},
|
||||
{Name: "oksa", Price: 11, ID: 13, Amount: 1},
|
||||
{Name: "oasdk", Price: 101, ID: 10, Amount: 11},
|
||||
|
|
@ -264,11 +264,11 @@ func TestSliceComparison(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func areCakesEqual(a, b cake) bool {
|
||||
func areCakesEqual(a, b Cake) bool {
|
||||
return a.ID == b.ID && a.Amount == b.Amount
|
||||
}
|
||||
|
||||
func areCakeSlicesEqual(a, b []cake) bool {
|
||||
func areCakeSlicesEqual(a, b []Cake) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue