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 0000000..3288370 Binary files /dev/null and b/assets/erd.png differ diff --git a/cart_api/src/main/java/sg/edu/ntu/cart_api/controller/CartController.java b/cart_api/src/main/java/sg/edu/ntu/cart_api/controller/CartController.java index 882af3f..7e62183 100644 --- a/cart_api/src/main/java/sg/edu/ntu/cart_api/controller/CartController.java +++ b/cart_api/src/main/java/sg/edu/ntu/cart_api/controller/CartController.java @@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -34,16 +35,16 @@ public class CartController { CartService service; @RequestMapping(method=RequestMethod.GET) - public ResponseEntity> 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;