From f351973fe8408960a2008259bf06311b4f7f774a Mon Sep 17 00:00:00 2001 From: Edison Zhuang Date: Thu, 9 Mar 2023 20:54:47 +0800 Subject: [PATCH] complete lesson --- README.md | 68 +++++++++++++----- assets/erd.png | Bin 0 -> 53453 bytes .../cart_api/controller/CartController.java | 13 ++-- .../java/sg/edu/ntu/cart_api/entity/Cart.java | 10 +++ .../sg/edu/ntu/cart_api/entity/Product.java | 2 +- .../java/sg/edu/ntu/cart_api/entity/User.java | 49 +++++++++++++ .../cart_api/repository/CartRepository.java | 5 +- .../edu/ntu/cart_api/service/CartService.java | 9 +-- 8 files changed, 128 insertions(+), 28 deletions(-) create mode 100644 assets/erd.png create mode 100644 cart_api/src/main/java/sg/edu/ntu/cart_api/entity/User.java diff --git a/README.md b/README.md index 7cc01a7..6b3bae1 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,58 @@ Step 1: CD to the project root directory `cart_api` Step 2: Run `./mvnw spring-boot:run` command -## Lesson Overview (6 Mar 2023, Mon) +## Lesson Overview (9 Mar 2023, Fri) Lesson Coverage: -- Use of `@OneToOne` and `@JoinColumn` annotation -- Start implementing new set of APIs - -## New APIs - -|URL|Status|Response| -|-|-|-| -|GET /carts|200|A list of records in cart table| -||404|When no records are found in cart table| -|POST /carts/add/{productId}?quantity=1|200|

If `productId` does not exist, create a new record with `quantity` set to 1.

When `quantity` is provided, set the quantity of the specified `productId` to the specified value.

When `quantity` is not provided, increment the quantity of the specified `productId` by 1.

| -||400|When the specified `productId` does not exist in the product table. -|POST /carts/decrement/{productId}|200|

If the specified `productId` exist and the quantity is 1, delete the record from cart table.

If the specified `productId` exist and the quantity is greater than 1, decrement the quantity by 1.

| -||400|When the specified `productId` does not exist in the `cart` table| -|POST /carts/clear|200|If there are records in the cart table, delete all records in the cart table| -||304|If there are no records in the cart table, do nothing.| +1. Move complex logics in `/carts` to a `@Service` class +2. Adding `User` entity +3. Use of `UserID` header as a mock authentication header + +> Firebase SDK has a major shift and no longer support `signInWithEmailAndPassword` from the backend `Firebase Admin SDK` using Java. + +## 1. Move complex logics to @Service class + +Refer to the `add` and `decrement` methods in [CartService.java](./cart_api/src/main/java/sg/edu/ntu/cart_api/service/CartService.java) where complex logics is moved into. + +Refer to [CartController.java](./cart_api/src/main/java/sg/edu/ntu/cart_api/controller/CartController.java) where the code mainly focuses on handling http request and response (status). + +A custom exception called [NotFoundException.java](./cart_api/src/main/java/sg/edu/ntu/cart_api/exception/NotFoundException.java) is created to help us identify scenario where the `productId` is not found. + +## 2. Adding the `User` Entity + +Let's refer to our ERD again while creating our `User` Entity class. + + + +The SQL Statements required to generate the `user` table: + +```sql +create table user ( + id int not null auto_increment, + email varchar(255) not null, + created_at timestamp not null default current_timestamp, + primary key (id) +); + +alter table cart add column user_id int; +alter table cart add constraint fk_cart_user foreign key (user_id) references user(id); +``` + +If you need to check all foreign keys in the DB, use the following command: + +```sql +SELECT TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA = 'cartdb'; +``` + +## 3. Using `@RequestHeader` to capture value from HTTP Header + +```java +public ResponseEntity> findAll(@RequestHeader("user-id") int userId) +``` + +See [CartController.java](./cart_api/src/main/java/sg/edu/ntu/cart_api/controller/CartController.java) for full details. + +We should also implement this for every methods in `CartController.java`. This will eventually affect `CartService.java` as well. All request to `/carts` must contains a `user-id` header. + +End \ No newline at end of file diff --git a/assets/erd.png b/assets/erd.png new file mode 100644 index 0000000000000000000000000000000000000000..3288370a33140f9bb3e7161327cd1022050eefe8 GIT binary patch literal 53453 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∨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 o3b`D%nkW97r67}S%kW1Z{~Es?Ir#4SF8I&> findAll(){ - List cartItems = (List)repo.findAll(); + public ResponseEntity> findAll(@RequestHeader("user-id") int userId){ + List cartItems = (List)repo.findByUserId(userId); if(cartItems.size() > 0) return ResponseEntity.ok().body(cartItems); return ResponseEntity.notFound().build(); } @RequestMapping(value="/add/{productId}", method=RequestMethod.POST) - public ResponseEntity add(@PathVariable int productId, @RequestParam Optional quantity){ + public ResponseEntity add(@PathVariable int productId, @RequestParam Optional quantity, @RequestHeader("user-id") int userId){ try{ - service.add(productId, quantity); + service.add(productId, quantity, userId); return ResponseEntity.ok().build(); // When no exception is thrown means operation is successful. }catch(NotFoundException nfe){ nfe.printStackTrace(); @@ -56,10 +57,10 @@ public ResponseEntity add(@PathVariable int productId, @RequestParam Optional { - Optional findByProductId(int productId); + Optional findByProductIdAndUserId(int productId, int userId); + + List findByUserId(int userId); } diff --git a/cart_api/src/main/java/sg/edu/ntu/cart_api/service/CartService.java b/cart_api/src/main/java/sg/edu/ntu/cart_api/service/CartService.java index fa81f22..f4d22e2 100644 --- a/cart_api/src/main/java/sg/edu/ntu/cart_api/service/CartService.java +++ b/cart_api/src/main/java/sg/edu/ntu/cart_api/service/CartService.java @@ -19,8 +19,8 @@ public class CartService { @Autowired ProductRepository productRepo; - public void add(int productId, Optional quantity) throws NotFoundException { - Optional optionalCartItem = repo.findByProductId(productId); + public void add(int productId, Optional quantity, int userId) throws NotFoundException { + Optional optionalCartItem = repo.findByProductIdAndUserId(productId, userId); if(optionalCartItem.isPresent()){ @@ -39,6 +39,7 @@ public void add(int productId, Optional quantity) throws NotFoundExcept Cart cartItem = new Cart(); cartItem.setProduct(product); cartItem.setQuantity(quantity.orElseGet(() -> 1)); + cartItem.setUserId(userId); repo.save(cartItem); }else{ throw new NotFoundException("Product ID not found"); @@ -46,8 +47,8 @@ public void add(int productId, Optional quantity) throws NotFoundExcept } } - public void decrement(int productId) throws NotFoundException{ - Optional optionalCartItem = repo.findByProductId(productId); + public void decrement(int productId, int userId) throws NotFoundException{ + Optional optionalCartItem = repo.findByProductIdAndUserId(productId, userId); if(optionalCartItem.isPresent()){ int currentQuantity = 0;