diff --git a/TODO.md b/TODO.md index 2c4b2c9..4d0cb07 100644 --- a/TODO.md +++ b/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 diff --git a/handler.go b/handler.go index f9227da..eb518bf 100644 --- a/handler.go +++ b/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 diff --git a/main.go b/main.go index 9a988a0..62bc27c 100644 --- a/main.go +++ b/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) } diff --git a/model.go b/store/model.go similarity index 77% rename from model.go rename to store/model.go index b0c038d..6884bc2 100644 --- a/model.go +++ b/store/model.go @@ -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 } diff --git a/schema.sql b/store/schema.sql similarity index 100% rename from schema.sql rename to store/schema.sql diff --git a/store.go b/store/store.go similarity index 85% rename from store.go rename to store/store.go index e913a4e..723a1da 100644 --- a/store.go +++ b/store/store.go @@ -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 = " diff --git a/store_test.go b/store/store_test.go similarity index 86% rename from store_test.go rename to store/store_test.go index 97060bf..61aea9f 100644 --- a/store_test.go +++ b/store/store_test.go @@ -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 }