Move database code to store package

This commit is contained in:
bronku 2025-03-21 23:35:55 +01:00
parent d1c393736a
commit e75468ce55
7 changed files with 79 additions and 75 deletions

View file

@ -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

View file

@ -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

View file

@ -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)
}

View file

@ -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
}

View file

@ -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 = "

View file

@ -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
}