Skip to content

Commit d278bf3

Browse files
committed
Merge branch 'v2.0'
2 parents 9128827 + 6decd3e commit d278bf3

17 files changed

+756
-59
lines changed

.idea/dataSources.xml

Lines changed: 0 additions & 14 deletions
This file was deleted.

.idea/sqlDataSources.xml

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db.sql

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,17 @@ CREATE TABLE Shop
4343
DROP TABLE IF EXISTS User;
4444
CREATE TABLE User
4545
(
46-
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
47-
name VARCHAR(255) NOT NULL,
48-
surname VARCHAR(255) NOT NULL,
46+
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
47+
name VARCHAR(255) NOT NULL,
48+
surname VARCHAR(255) NOT NULL,
4949
-- It can be a commercial email address for operators
50-
email VARCHAR(255) NOT NULL,
51-
active BOOLEAN NOT NULL DEFAULT FALSE,
50+
email VARCHAR(255) NOT NULL,
51+
active BOOLEAN NOT NULL DEFAULT FALSE,
5252
-- BCrypt hash length
53-
password VARCHAR(60) NOT NULL,
54-
roleId INT NOT NULL DEFAULT 1,
55-
shopId INT DEFAULT NULL,
53+
password VARCHAR(60) NOT NULL,
54+
roleId INT NOT NULL DEFAULT 1,
55+
shopId INT DEFAULT NULL,
56+
signupDate DATETIME NOT NULL DEFAULT NOW(),
5657
-- Email verification code
5758
verificationCode VARCHAR(64),
5859
UNIQUE (email),
@@ -69,8 +70,7 @@ CREATE TABLE Booking
6970
userId INT NOT NULL,
7071
shopId INT NOT NULL,
7172
createdAt DATETIME NOT NULL DEFAULT NOW(),
72-
-- Ensure a user can only have one booking per shop
73-
UNIQUE (userId, shopId),
73+
finished BOOLEAN NOT NULL DEFAULT FALSE,
7474
FOREIGN KEY (userId) REFERENCES User (id)
7575
ON UPDATE CASCADE ON DELETE CASCADE,
7676
FOREIGN KEY (shopId) REFERENCES Shop (id)
@@ -85,6 +85,7 @@ CREATE TABLE Session
8585
accessToken VARCHAR(88) BINARY NOT NULL,
8686
loginDate DATETIME NOT NULL DEFAULT NOW(),
8787
lastUsageDate DATETIME NOT NULL DEFAULT NOW(),
88+
active BOOLEAN NOT NULL DEFAULT TRUE,
8889
-- Ensure a token cannot be used by more than 1 user,
8990
-- even if that's almost impossible, but not 100% impossible
9091
UNIQUE (accessToken),
@@ -114,13 +115,54 @@ CREATE TABLE FcmToken
114115
ON UPDATE CASCADE ON DELETE CASCADE
115116
);
116117

118+
DROP TABLE IF EXISTS Product;
119+
CREATE TABLE Product
120+
(
121+
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
122+
name VARCHAR(255) NOT NULL,
123+
ean VARCHAR(13) NOT NULL,
124+
price FLOAT(10, 2) UNSIGNED NOT NULL,
125+
shopId INT NOT NULL,
126+
-- A shop can only use an EAN once
127+
UNIQUE (shopId, ean),
128+
FOREIGN KEY (shopId) REFERENCES Shop (id)
129+
ON UPDATE CASCADE ON DELETE CASCADE
130+
);
131+
132+
DROP TABLE IF EXISTS ShoppingList;
133+
CREATE TABLE ShoppingList
134+
(
135+
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
136+
userId INT NOT NULL,
137+
createdAt DATETIME NOT NULL DEFAULT NOW(),
138+
isReady BOOLEAN NOT NULL DEFAULT FALSE
139+
);
140+
141+
DROP TABLE IF EXISTS ShoppingList_Products;
142+
CREATE TABLE ShoppingList_Products
143+
(
144+
shoppingListId INT NOT NULL,
145+
productId INT NOT NULL,
146+
PRIMARY KEY (shoppingListId, productId),
147+
FOREIGN KEY (shoppingListId) REFERENCES ShoppingList (id)
148+
ON UPDATE CASCADE ON DELETE CASCADE,
149+
FOREIGN KEY (productId) REFERENCES Product (id)
150+
ON UPDATE CASCADE ON DELETE CASCADE
151+
);
152+
117153
SET FOREIGN_KEY_CHECKS = 1;
118154

155+
DROP VIEW IF EXISTS PendingBooking;
156+
CREATE VIEW PendingBooking AS
157+
SELECT *
158+
FROM Booking
159+
WHERE finished = FALSE;
160+
119161
DROP VIEW IF EXISTS ShopWithCount;
120162
CREATE VIEW ShopWithCount AS
121-
SELECT Shop.*, COUNT(Booking.userId) AS count
163+
SELECT Shop.*, COUNT(PendingBooking.userId) AS count
122164
FROM Shop
123-
LEFT JOIN Booking ON Shop.id = Booking.shopId
165+
LEFT JOIN PendingBooking ON Shop.id = PendingBooking.shopId
124166
GROUP BY Shop.id;
125167

126168
DROP VIEW IF EXISTS UserWithRole;
@@ -144,48 +186,68 @@ FROM UserWithRole
144186

145187
DROP VIEW IF EXISTS BookingDetail;
146188
CREATE VIEW BookingDetail AS
147-
SELECT Booking.id AS bookingId,
189+
SELECT PendingBooking.id AS bookingId,
148190
ShopWithCount.id AS bookingShopId,
149191
UserWithRole.id AS userId,
150192
UserWithRole.name,
151193
UserWithRole.surname,
152194
UserWithRole.role,
153195
UserWithRole.email,
154-
Booking.createdAt,
196+
PendingBooking.createdAt,
155197
ShopWithCount.name AS shopName,
156198
ShopWithCount.latitude,
157199
ShopWithCount.longitude,
158200
ShopWithCount.address,
159201
ShopWithCount.count
160-
FROM Booking
161-
JOIN UserWithRole ON Booking.userId = UserWithRole.id
162-
JOIN ShopWithCount ON Booking.shopId = ShopWithCount.id
163-
ORDER BY Booking.createdAt;
202+
FROM PendingBooking
203+
JOIN UserWithRole ON PendingBooking.userId = UserWithRole.id
204+
JOIN ShopWithCount ON PendingBooking.shopId = ShopWithCount.id
205+
ORDER BY PendingBooking.createdAt;
164206

165207
DROP VIEW IF EXISTS BookingDetailQueueCount;
166208
CREATE VIEW BookingDetailQueueCount AS
167209
SELECT BookingDetail.*, COALESCE(BookingQueueCount.queueCount, 0) AS queueCount
168210
FROM BookingDetail
169-
LEFT JOIN (SELECT Booking.userId, Booking.shopId, COUNT(*) AS queueCount
170-
FROM Booking,
171-
(SELECT createdAt, shopId, userId FROM Booking) Booking2
172-
WHERE Booking.shopId = Booking2.shopId
173-
AND Booking.createdAt > Booking2.createdAt
174-
GROUP BY Booking.userId, Booking.shopId) BookingQueueCount
211+
LEFT JOIN (SELECT PendingBooking.userId, PendingBooking.shopId, COUNT(*) AS queueCount
212+
FROM PendingBooking,
213+
(SELECT createdAt, shopId, userId FROM PendingBooking) Booking2
214+
WHERE PendingBooking.shopId = Booking2.shopId
215+
AND PendingBooking.createdAt > Booking2.createdAt
216+
GROUP BY PendingBooking.userId, PendingBooking.shopId) BookingQueueCount
175217
ON BookingQueueCount.shopId = BookingDetail.bookingShopId
176218
AND BookingQueueCount.userId = BookingDetail.userId
177219
ORDER BY queueCount;
178220

179221
DROP VIEW IF EXISTS SessionDetail;
180222
CREATE VIEW SessionDetail AS
181-
SELECT Session.id AS sessionId,
223+
SELECT Session.id AS sessionId,
182224
Session.accessToken,
183225
Session.lastUsageDate,
184226
Session.loginDate,
227+
Session.active AS sessionActive,
185228
UserDetails.*
186229
FROM Session
187230
JOIN UserDetails ON Session.userId = UserDetails.id;
188231

232+
DROP VIEW IF EXISTS ShoppingListDetail;
233+
CREATE VIEW ShoppingListDetail AS
234+
SELECT ShoppingList.id AS shoppingListId,
235+
ShoppingList.createdAt,
236+
ShoppingList.userId,
237+
ShoppingList.isReady,
238+
Product.shopId,
239+
Product.id AS productId,
240+
Product.price,
241+
Product.ean,
242+
Product.name AS productName,
243+
ShopWithCount.*,
244+
UserWithRole.name AS userName
245+
FROM ShoppingList
246+
JOIN ShoppingList_Products ON ShoppingList.id = ShoppingList_Products.shoppingListId
247+
JOIN Product ON ShoppingList_Products.productId = Product.id
248+
JOIN ShopWithCount ON ShopWithCount.id = Product.shopId
249+
JOIN UserWithRole ON UserWithRole.id = ShoppingList.userId;
250+
189251
-- Apply the haversine formula to calculate
190252
-- the distance between 2 points on Earth in KMs
191253
DROP FUNCTION IF EXISTS DISTANCE_KM;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* Copyright 2020 Simone Sestito
4+
* This file is part of Shops Queue.
5+
*
6+
* Shops Queue is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* Shops Queue is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with Shops Queue. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
class ProductController extends BaseController {
21+
private $productDao;
22+
23+
public function __construct(ProductDao $productDao) {
24+
$this->productDao = $productDao;
25+
$this->registerRoute('/shops/:id/products', 'GET', '*', 'getShopProducts');
26+
$this->registerRoute('/products', 'POST', 'OWNER', 'addShopProduct');
27+
$this->registerRoute('/products/:id', 'GET', '*', 'getProduct');
28+
$this->registerRoute('/products/:id', 'PUT', 'OWNER', 'editProduct');
29+
$this->registerRoute('/products/:id', 'DELETE', 'OWNER', 'deleteProduct');
30+
}
31+
32+
/**
33+
* @param int $shopId
34+
* @return Product[]
35+
*/
36+
public function getShopProducts(int $shopId): array {
37+
$entities = $this->productDao->getProductsByShopId($shopId);
38+
return array_map(function ($entity) {
39+
return new Product($entity);
40+
}, $entities);
41+
}
42+
43+
/**
44+
* @param NewProduct $newProduct
45+
* @return Product
46+
*/
47+
public function addShopProduct(NewProduct $newProduct): Product {
48+
$shopId = AuthService::getAuthContext()['shopId'];
49+
$id = $this->productDao->addProduct($shopId, $newProduct);
50+
$entity = $this->productDao->getProductById($id);
51+
return new Product($entity);
52+
}
53+
54+
/**
55+
* @param int $id
56+
* @return Product
57+
* @throws AppHttpException
58+
*/
59+
public function getProduct(int $id) {
60+
$entity = $this->productDao->getProductById($id);
61+
if ($entity == null)
62+
throw new AppHttpException(HTTP_NOT_FOUND);
63+
return new Product($entity);
64+
}
65+
66+
/**
67+
* @param int $id
68+
* @param NewProduct $newProduct
69+
* @return Product
70+
* @throws AppHttpException
71+
*/
72+
public function editProduct(int $id, NewProduct $newProduct): Product {
73+
$shopId = AuthService::getAuthContext()['shopId'];
74+
$this->productDao->editProduct($id, $shopId, $newProduct);
75+
$newEntity = $this->productDao->getProductById($id);
76+
if ($newEntity == null) {
77+
throw new AppHttpException(HTTP_NOT_FOUND);
78+
}
79+
return new Product($newEntity);
80+
}
81+
82+
/**
83+
* @param int $id
84+
*/
85+
public function deleteProduct(int $id) {
86+
$shopId = AuthService::getAuthContext()['shopId'];
87+
$this->productDao->deleteProduct($id, $shopId);
88+
}
89+
}
90+
91+
onInit(function () {
92+
registerController(ProductController::class);
93+
});

0 commit comments

Comments
 (0)