From 34e2d8c01af8a27e069716718e15333d6b34e90f Mon Sep 17 00:00:00 2001 From: bronku Date: Thu, 20 Mar 2025 07:41:27 +0100 Subject: [PATCH] Implement order items --- schema.sql | 2 +- store.go | 118 +++++++++++++++++++++++++++++++++++++++++++++----- store_test.go | 25 +++++++++++ 3 files changed, 134 insertions(+), 11 deletions(-) diff --git a/schema.sql b/schema.sql index c707e86..c4f85a7 100644 --- a/schema.sql +++ b/schema.sql @@ -21,4 +21,4 @@ create table ordered_cake ( cake integer references cake (id) not null, amount integer not null, primary key (customer_order, cake) -) +); diff --git a/store.go b/store.go index 82afd8a..ae160af 100644 --- a/store.go +++ b/store.go @@ -4,6 +4,7 @@ package main import ( "database/sql" _ "embed" + "fmt" "os" "strconv" "time" @@ -83,10 +84,14 @@ func (s *store) saveCake(newCake cake) (int, error) { // #todo: retrieve and save order contents func (s *store) getOrder(id int) (order, error) { var out order - // #todo: error handling - row, err := s.db.Query("select id, name, surname, phone, location, order_date, delivery_date, status, paid from customer_order where id = ?;", id) + tx, err := s.db.Begin() + if err != nil { + return out, nil + } + row, err := tx.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 { + tx.Rollback() return out, err } @@ -96,14 +101,37 @@ func (s *store) getOrder(id int) (order, error) { // #todo: error handling 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) + rows, err := tx.Query("select cake, amount from ordered_cake where customer_order = ?;", id) + if err != nil { + tx.Rollback() + return out, err + } + defer rows.Close() + for rows.Next() { + var newCake cake + err = rows.Scan(&newCake.ID, &newCake.Amount) + if err != nil { + tx.Rollback() + return out, err + } + out.Cakes = append(out.Cakes, newCake) + } + + tx.Commit() return out, nil } -// #todo: should return an error 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;") + tx, err := s.db.Begin() if err != nil { + return nil, err + } + rows, err := tx.Query("select id, name, surname, phone, location, order_date, delivery_date, status, paid from customer_order;") + if err != nil { + tx.Rollback() return out, err } defer rows.Close() @@ -113,15 +141,34 @@ func (s *store) getOrders() ([]order, error) { 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 { + tx.Rollback() return nil, err } - // #todo: error handling - // figure out what to do with errors, as they shouldn't really crash the app, but there should probably be an indication that something went wrong 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) + rows, err := tx.Query("select cake, amount from ordered_cake where customer_order = ?;", o.ID) + + if err != nil { + tx.Rollback() + return out, err + } + defer rows.Close() + for rows.Next() { + var newCake cake + err = rows.Scan(&newCake.ID, &newCake.Amount) + if err != nil { + tx.Rollback() + return out, err + } + o.Cakes = append(o.Cakes, newCake) + } + out = append(out, o) } + tx.Commit() return out, nil } @@ -131,19 +178,70 @@ func (s *store) saveOrder(newOrder order) (int, error) { query = "update customer_order set name = ?, surname = ?, phone = ?, location = ?, order_date = ?, delivery_date = ?, status = ?, paid = ? where id = " query += strconv.Itoa(newOrder.ID) + " returning id;" } + tx, err := s.db.Begin() + if err != nil { + return -1, nil + } - // #todo: error handling - // #todo: date format accepted := newOrder.Accepted.Format("2006-01-02 15:04") date := newOrder.Date.Format("2006-01-02 15:04") - row, err := s.db.Query(query, newOrder.Name, newOrder.Surname, newOrder.Phone, newOrder.Location, accepted, date, newOrder.Status, newOrder.Paid) + row, err := tx.Query(query, newOrder.Name, newOrder.Surname, newOrder.Phone, newOrder.Location, accepted, date, newOrder.Status, newOrder.Paid) if err != nil { + tx.Rollback() return -1, err } defer row.Close() - // #todo: see if next is required or not to get the first element row.Next() err = row.Scan(&newOrder.ID) + if err != nil { + tx.Rollback() + return newOrder.ID, err + } + + // remove all ordered_cakes associated with this order before inserting + query = "delete from ordered_cake where customer_order = ?;" + _, err = tx.Exec(query, newOrder.ID) + if err != nil { + tx.Rollback() + return newOrder.ID, err + } + + // add all ordered_cakes for this order + query = "insert into ordered_cake(customer_order, cake, amount) values (?,?,?);" + for _, e := range newOrder.Cakes { + _, err := tx.Exec(query, newOrder.ID, e.ID, e.Amount) + if err != nil { + tx.Rollback() + return newOrder.ID, err + } + } + + err = tx.Commit() + return newOrder.ID, err + +} + +func listTables(db *sql.DB) error { + rows, err := db.Query("SELECT name FROM sqlite_master WHERE type='table';") + if err != nil { + return fmt.Errorf("error querying sqlite_master: %w", err) + } + defer rows.Close() + + fmt.Println("Tables in the database:") + for rows.Next() { + var tableName string + if err := rows.Scan(&tableName); err != nil { + return fmt.Errorf("error scanning table name: %w", err) + } + fmt.Println("-", tableName) + } + + if err := rows.Err(); err != nil { + return fmt.Errorf("error iterating through rows: %w", err) + } + + return nil } diff --git a/store_test.go b/store_test.go index 7e5a33a..087ecfa 100644 --- a/store_test.go +++ b/store_test.go @@ -189,6 +189,9 @@ func TestStore(t *testing.T) { newOrder.Date.Format("2006-01-02 15:04") != newOrder.Date.Format("2006-01-02 15:04") { t.Errorf("Want %v\nGot %v", newOrder, orders[newOrderPos]) } + if !areCakeSlicesEqual(newOrder.Cakes, orders[newOrderPos].Cakes) { + t.Errorf("Want %v\nGot %v", newOrder.Cakes, orders[newOrderPos].Cakes) + } if anotherOrderPos == -1 { t.Error("not found anotherOrder") @@ -202,6 +205,28 @@ func TestStore(t *testing.T) { anotherOrder.Date.Format("2006-01-02 15:04") != anotherOrder.Date.Format("2006-01-02 15:04") { t.Errorf("Want %v\nGot %v", anotherOrder, orders[anotherOrderPos]) } + + if !areCakeSlicesEqual(anotherOrder.Cakes, orders[anotherOrderPos].Cakes) { + t.Errorf("Want %v\nGot %v", anotherOrder.Cakes, orders[anotherOrderPos].Cakes) + } + + selectedOrder, err := s.getOrder(newOrder.ID) + if err != nil { + t.Error("error getting an order by id ", err) + } + if newOrder.Name != selectedOrder.Name || + newOrder.Surname != selectedOrder.Surname || + newOrder.Phone != selectedOrder.Phone || + newOrder.Status != selectedOrder.Status || + newOrder.Location != selectedOrder.Location || + newOrder.Accepted.Format("2006-01-02 15:04") != newOrder.Accepted.Format("2006-01-02 15:04") || + newOrder.Date.Format("2006-01-02 15:04") != newOrder.Date.Format("2006-01-02 15:04") { + t.Errorf("Want %v\nGot %v", newOrder, selectedOrder) + } + + if !areCakeSlicesEqual(newOrder.Cakes, selectedOrder.Cakes) { + t.Errorf("Want %v\nGot %v", newOrder.Cakes, selectedOrder.Cakes) + } } func TestSliceComparison(t *testing.T) {