@@ -34,6 +34,79 @@ const verifyPassword = (password, storedPassword) => {
3434 return timingSafeEqual ( candidateHash , expectedHash ) ;
3535} ;
3636
37+ db . exec ( `
38+ CREATE TABLE IF NOT EXISTS users (
39+ id TEXT PRIMARY KEY,
40+ username TEXT NOT NULL UNIQUE,
41+ password TEXT NOT NULL,
42+ name TEXT NOT NULL,
43+ role TEXT NOT NULL
44+ );
45+
46+ CREATE TABLE IF NOT EXISTS spots (
47+ id TEXT PRIMARY KEY,
48+ location TEXT NOT NULL,
49+ date TEXT NOT NULL,
50+ host_user_id TEXT NOT NULL,
51+ FOREIGN KEY (host_user_id) REFERENCES users(id) ON DELETE CASCADE
52+ );
53+
54+ CREATE TABLE IF NOT EXISTS catalog_items (
55+ id TEXT PRIMARY KEY,
56+ category TEXT NOT NULL,
57+ name TEXT NOT NULL,
58+ price REAL NOT NULL
59+ );
60+
61+ CREATE TABLE IF NOT EXISTS orders (
62+ id TEXT PRIMARY KEY,
63+ spot_id TEXT NOT NULL,
64+ user_id TEXT NOT NULL,
65+ total_amount REAL NOT NULL,
66+ created_at TEXT NOT NULL,
67+ FOREIGN KEY (spot_id) REFERENCES spots(id),
68+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
69+ );
70+
71+ CREATE TABLE IF NOT EXISTS order_items (
72+ id INTEGER PRIMARY KEY AUTOINCREMENT,
73+ order_id TEXT NOT NULL,
74+ product_id TEXT NOT NULL,
75+ name TEXT NOT NULL,
76+ quantity INTEGER NOT NULL,
77+ unit_price REAL NOT NULL,
78+ total REAL NOT NULL,
79+ FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE
80+ );
81+ ` ) ;
82+
83+ const hasUsers = db . prepare ( 'SELECT COUNT(*) AS count FROM users' ) . get ( ) . count > 0 ;
84+
85+ if ( ! hasUsers ) {
86+ const insertUser = db . prepare ( 'INSERT INTO users (id, username, password, name, role) VALUES (?, ?, ?, ?, ?)' ) ;
87+ insertUser . run ( 'u-1' , 'brocode' , hashPassword ( 'changeme' ) , 'Ram' , 'admin' ) ;
88+ insertUser . run ( 'u-2' , 'dhanush' , hashPassword ( 'changeme' ) , 'Dhanush' , 'user' ) ;
89+
90+ const insertSpot = db . prepare ( 'INSERT INTO spots (id, location, date, host_user_id) VALUES (?, ?, ?, ?)' ) ;
91+ insertSpot . run ( 'spot-2025-07-26' , 'Attibele Toll Plaza' , '2025-07-26T10:00:00.000Z' , 'u-1' ) ;
92+
93+ const insertCatalogItem = db . prepare ( 'INSERT INTO catalog_items (id, category, name, price) VALUES (?, ?, ?, ?)' ) ;
94+ insertCatalogItem . run ( 'd-1' , 'drinks' , 'Brocode Beer' , 180 ) ;
95+ insertCatalogItem . run ( 'd-2' , 'drinks' , 'Kingfisher Beer' , 170 ) ;
96+ insertCatalogItem . run ( 'f-1' , 'food' , 'Beef Biriyani' , 220 ) ;
97+ insertCatalogItem . run ( 'f-2' , 'food' , 'Parotta' , 30 ) ;
98+ insertCatalogItem . run ( 'c-1' , 'cigarettes' , 'Marlboro' , 25 ) ;
99+ insertCatalogItem . run ( 'c-2' , 'cigarettes' , 'Classic' , 20 ) ;
100+
101+ db . prepare (
102+ 'INSERT INTO orders (id, spot_id, user_id, total_amount, created_at) VALUES (?, ?, ?, ?, ?)'
103+ ) . run ( 'ord-1' , 'spot-2025-07-26' , 'u-2' , 360 , '2025-07-26T10:30:00.000Z' ) ;
104+
105+ db . prepare (
106+ `INSERT INTO order_items (order_id, product_id, name, quantity, unit_price, total)
107+ VALUES (?, ?, ?, ?, ?, ?)`
108+ ) . run ( 'ord-1' , 'd-1' , 'Brocode Beer' , 2 , 180 , 360 ) ;
109+ }
37110const seedData = ( ) => ( {
38111 users : [
39112 { id : 'u-1' , username : 'brocode' , password : hashPassword ( 'changeme' ) , name : 'Ram' , role : 'admin' } ,
@@ -123,6 +196,42 @@ const mapOrder = (order, items) => ({
123196 } ) ) ,
124197} ) ;
125198
199+ const fetchOrderItemsByOrderIds = ( orderIds ) => {
200+ if ( orderIds . length === 0 ) return new Map ( ) ;
201+
202+ const placeholders = orderIds . map ( ( ) => '?' ) . join ( ',' ) ;
203+ const rows = db
204+ . prepare (
205+ `SELECT order_id, product_id, name, quantity, unit_price, total
206+ FROM order_items
207+ WHERE order_id IN (${ placeholders } )
208+ ORDER BY id ASC`
209+ )
210+ . all ( ...orderIds ) ;
211+
212+ const itemsByOrderId = new Map ( ) ;
213+ rows . forEach ( ( row ) => {
214+ if ( ! itemsByOrderId . has ( row . order_id ) ) {
215+ itemsByOrderId . set ( row . order_id , [ ] ) ;
216+ }
217+ itemsByOrderId . get ( row . order_id ) . push ( row ) ;
218+ } ) ;
219+
220+ return itemsByOrderId ;
221+ } ;
222+
223+ const getCatalogItemByIdStatement = db . prepare (
224+ 'SELECT id, category, name, price FROM catalog_items WHERE id = ?'
225+ ) ;
226+
227+ const userExistsStatement = db . prepare ( 'SELECT 1 AS found FROM users WHERE id = ? LIMIT 1' ) ;
228+ const spotExistsStatement = db . prepare ( 'SELECT 1 AS found FROM spots WHERE id = ? LIMIT 1' ) ;
229+ const getUserByUsernameStatement = db . prepare ( 'SELECT id, username, password, name, role FROM users WHERE username = ?' ) ;
230+ const updateUserPasswordStatement = db . prepare ( 'UPDATE users SET password = ? WHERE id = ?' ) ;
231+ const deleteUserByIdStatement = db . prepare ( 'DELETE FROM users WHERE id = ?' ) ;
232+ const deleteOrdersByUserIdStatement = db . prepare ( 'DELETE FROM orders WHERE user_id = ?' ) ;
233+ const deleteSpotsByHostUserIdStatement = db . prepare ( 'DELETE FROM spots WHERE host_user_id = ?' ) ;
234+
126235export const database = {
127236 getUserByCredentials ( username , password ) {
128237 const user = state . users . find ( ( entry ) => entry . username === username ) ;
@@ -251,6 +360,21 @@ export const database = {
251360 } ;
252361 } ,
253362
363+ deleteUserCompletely ( userId ) {
364+ db . exec ( 'BEGIN' ) ;
365+
366+ try {
367+ deleteOrdersByUserIdStatement . run ( userId ) ;
368+ deleteSpotsByHostUserIdStatement . run ( userId ) ;
369+ deleteUserByIdStatement . run ( userId ) ;
370+
371+ db . exec ( 'COMMIT' ) ;
372+ } catch ( error ) {
373+ db . exec ( 'ROLLBACK' ) ;
374+ throw error ;
375+ }
376+ } ,
377+
254378 getBillBySpotId ( spotId ) {
255379 const summaryRows = state . orders . filter ( ( order ) => order . spot_id === spotId ) ;
256380
0 commit comments