Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/main/java/com/kuit/baemin/controller/AddressController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.kuit.baemin.controller;

import com.kuit.baemin.common.dto.ApiResponse;
import com.kuit.baemin.dto.request.CreateAddressReq;
import com.kuit.baemin.dto.request.UpdateAddressReq;
import com.kuit.baemin.dto.response.AddressListRes;
import com.kuit.baemin.dto.response.AddressRes;
import com.kuit.baemin.dto.response.DefaultAddressRes;
import com.kuit.baemin.dto.response.DeleteAddressRes;
import com.kuit.baemin.service.AddressService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
public class AddressController {
private final AddressService addressService;

@PostMapping("/users/{userId}/addresses")
public ApiResponse<AddressRes> createAddress(
@PathVariable Long userId,
@Valid @RequestBody CreateAddressReq req
){
return ApiResponse.of(addressService.createAddress(userId, req));
}
@GetMapping("/users/{userId}/addresses")
public ApiResponse<AddressListRes> getAddresses(
@PathVariable Long userId
){
return ApiResponse.of(addressService.getAddresses(userId));
}
@PatchMapping("/addresses/{addressId}")
public ApiResponse<AddressRes>updateAddress(
@PathVariable Long addressId,
@Valid @RequestBody UpdateAddressReq req
){
return ApiResponse.of(addressService.updateAddress(addressId, req));
}
@DeleteMapping("/addresses/{addressId}")
public ApiResponse<DeleteAddressRes> deleteAddress(
@PathVariable Long addressId
){
return ApiResponse.of(addressService.deleteAddress(addressId));
}
@PatchMapping("/addresses/{addressId}/default")
public ApiResponse<DefaultAddressRes> changeDefaultAddress(
@PathVariable Long addressId
){
return ApiResponse.of(addressService.changeDefaultAddress((addressId)));
}
}
18 changes: 17 additions & 1 deletion src/main/java/com/kuit/baemin/controller/MemberController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.kuit.baemin.common.dto.ApiResponse;
import com.kuit.baemin.dto.request.LoginReq;
import com.kuit.baemin.dto.request.SignUpReq;
import com.kuit.baemin.dto.request.UpdateMemberReq;
import com.kuit.baemin.dto.response.DeleteMemberRes;
import com.kuit.baemin.dto.response.MemberRes;
import com.kuit.baemin.service.MemberService;
import jakarta.validation.Valid;
Expand Down Expand Up @@ -30,7 +32,7 @@
* 8주차 커리큘럼(인증, 인가, JWT)을 학습한 후 직접 추가해보세요!
*/
@RestController
@RequestMapping("/members")
@RequestMapping("/users")
@RequiredArgsConstructor
public class MemberController {

Expand Down Expand Up @@ -59,4 +61,18 @@ public ApiResponse<Long> login(@Valid @RequestBody LoginReq req) {
public ApiResponse<MemberRes> getMember(@PathVariable Long memberId) {
return ApiResponse.of(memberService.getMember(memberId));
}

@PatchMapping("/{userId}")
public ApiResponse<MemberRes> updateMember(
@PathVariable Long userId,
@Valid @RequestBody UpdateMemberReq req
){
return ApiResponse.of(memberService.updateMember(userId, req));
}
@DeleteMapping("/{userId}")
public ApiResponse<DeleteMemberRes> deleteMember(
@PathVariable Long userId
){
return ApiResponse.of(memberService.deleteMember(userId));
}
}
22 changes: 22 additions & 0 deletions src/main/java/com/kuit/baemin/controller/MenuController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.kuit.baemin.controller;

import com.kuit.baemin.common.dto.ApiResponse;
import com.kuit.baemin.dto.response.MenuListRes;
import com.kuit.baemin.service.MenuService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class MenuController {
private final MenuService menuService;

@GetMapping("/stores/{storeId}/menus")
public ApiResponse<MenuListRes> getMenus(
@PathVariable Long storeId
){
return ApiResponse.of(menuService.getMenus(storeId));
}
}
24 changes: 24 additions & 0 deletions src/main/java/com/kuit/baemin/controller/OrderController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.kuit.baemin.controller;

import com.kuit.baemin.common.dto.ApiResponse;
import com.kuit.baemin.dto.request.CreateOrderReq;
import com.kuit.baemin.dto.response.CreateOrderRes;
import com.kuit.baemin.service.OrderService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;

@PostMapping("/orders")
public ApiResponse<CreateOrderRes> createOrder(
@Valid @RequestBody CreateOrderReq req
) {
return ApiResponse.of(orderService.createOrder(req));
}
}
24 changes: 24 additions & 0 deletions src/main/java/com/kuit/baemin/controller/RestaurantController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.kuit.baemin.controller;

import com.kuit.baemin.common.dto.ApiResponse;
import com.kuit.baemin.dto.response.RestaurantListRes;
import com.kuit.baemin.service.RestaurantService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequiredArgsConstructor
public class RestaurantController {
private final RestaurantService RestaurantService;

@GetMapping("/stores")
public ApiResponse<RestaurantListRes> getStores(
@PageableDefault(size=10) Pageable pageable

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

페이지 크기 상한을 강제해 주세요.

현재는 클라이언트가 매우 큰 size를 전달할 수 있어 대량 조회로 성능 저하/타임아웃 위험이 있습니다. spring.data.web.pageable.max-page-size 설정 또는 서비스 단 검증으로 상한을 두는 것이 필요합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/kuit/baemin/controller/RestaurantController.java` at line
20, The controller currently accepts a Pageable (parameter named pageable)
without enforcing a maximum page size, allowing clients to request arbitrarily
large pages; update RestaurantController to enforce a max page size by either
(A) reading spring.data.web.pageable.max-page-size from configuration and
applying it when resolving Pageable, or (B) validating and capping the incoming
Pageable.size in the controller/service method (e.g., in the method that accepts
Pageable pageable, check pageable.getPageSize() and replace it with
Math.min(requestedSize, MAX_PAGE_SIZE) before passing to the
repository/service). Use a single constant or config-backed value (e.g.,
MAX_PAGE_SIZE) and reference the pageable parameter and the controller method
handling restaurant listing to implement the cap.

){
return ApiResponse.of(RestaurantService.getStores(pageable));
}
}
33 changes: 31 additions & 2 deletions src/main/java/com/kuit/baemin/domain/Restaurant/Restaurant.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@
import jakarta.persistence.*;
import lombok.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

// TODO: 본인이 설계한 ERD에 맞게 수정
@Entity
@Getter
@Builder
@Table(name = "restaurants")
@Table(name = "stores")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

테이블명 변경에 대한 DB 마이그레이션이 필요합니다.

restaurants → stores 매핑 변경만으로는 기존 데이터가 자동 이관되지 않습니다. ddl-auto: update 환경에서는 신규 테이블 생성/스키마 불일치로 이어질 수 있어, 테이블 rename 또는 데이터 이관 마이그레이션 스크립트를 PR에 포함해 주세요.

As per coding guidelines spring.jpa.hibernate.ddl-auto: update ... 엔티티/테이블 변경이 자동으로 스키마 업데이트에 반영됨 ... 로컬 DB 스키마 상태와 충돌(컬럼 타입/제약 변경 등) 가능성을 확인한다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/kuit/baemin/domain/Restaurant/Restaurant.java` at line 15,
You changed the JPA mapping on the Restaurant entity (`@Table`(name = "stores"))
which does not migrate existing data; add a DB migration that either renames the
existing restaurants table to stores or copies data into a new stores table and
preserves constraints/indices. Specifically, create a migration script
(Flyway/Liquibase) that runs before app startup to perform ALTER TABLE RENAME
FROM restaurants TO stores or INSERT-SELECT with schema/constraint creation, and
include rollback steps; reference the Restaurant entity and its `@Table` mapping
so the schema and constraints match the entity fields.

@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Restaurant extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "store_id")
private Long id;

@Column(nullable = false, length = 100)
Expand All @@ -26,8 +28,35 @@ public class Restaurant extends BaseEntity {
@Column(nullable = false, length = 200)
private String address;

@Column(name = "category", length = 50, nullable = false)
private String category;

@Column(name = "phone", length = 20, nullable = false)
private String phone;

@Column(name = "min_order_price", nullable = false)
private Integer minOrderPrice = 0;

@Column(name = "delivery_fee", nullable = false)
private Integer deliveryFee = 0;
Comment on lines +37 to +41

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

금액 필드의 음수 방지 제약을 명시해 주세요.

minOrderPrice, deliveryFee가 nullable = false만으로는 음수 저장을 막지 못합니다. 도메인 무결성을 위해 DB 체크 제약(또는 검증 어노테이션 + 서비스 검증)을 추가하는 것이 안전합니다.

As per coding guidelines @Column(nullable = false) 등 제약조건이 ERD와 일치하는지 확인.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/kuit/baemin/domain/Restaurant/Restaurant.java` around lines
37 - 41, Add non-negative constraints to the Restaurant money fields: annotate
the fields minOrderPrice and deliveryFee with
javax.validation.constraints.@Min(0) for runtime/DTO validation and add a
DB-level CHECK to guarantee integrity (either via Hibernate's `@Check` at the
Restaurant class level or via Column(columnDefinition) with "check" expression)
ensuring min_order_price >= 0 and delivery_fee >= 0; update any service-side
setters/constructors that accept these values to validate/throw on negative
input so domain invariants are enforced before persistence.


@Column(name = "rating", precision = 2, scale = 1, nullable = false)
private BigDecimal rating;

@Column(name = "is_open", nullable = false)
private Boolean isOpen;

@Column(name = "latitude", precision = 10, scale = 7, nullable = false)
private BigDecimal latitude;

@Column(name="description", length = 255)
private String description;

@Column(name = "longitude", precision = 10, scale = 7, nullable = false)
private BigDecimal longitude;

@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 10)
private RestaurantStatus status;
private RestaurantStatus status = RestaurantStatus.ACTIVE;

}
100 changes: 100 additions & 0 deletions src/main/java/com/kuit/baemin/domain/address/Address.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.kuit.baemin.domain.address;

import com.kuit.baemin.domain.BaseEntity;
import com.kuit.baemin.domain.member.Member;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Entity
@Table(name="addresses")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Address extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "address_id")
private Long id;

@Column(name="address_name", length =50)
private String addressName;

@Column(name = "address", length = 255, nullable = false)
private String address;

@Column(name = "is_default", nullable = false)
private Boolean isDefault;

@Column(name = "latitude", nullable = false)
private Double latitude;

@Column(name = "longitude", nullable = false)
private Double longitude;

@Enumerated(EnumType.STRING)
@Column(name = "status", length = 20, nullable = false)
private AddressStatus status;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private Member member;

@Builder
public Address(
String addressName,
String address,
Boolean isDefault,
Double latitude,
Double longitude,
Member member
){
this.addressName = addressName;
this.address = address;
this.isDefault = isDefault !=null ? isDefault:false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

띄어쓰기를 수정하세요.

연산자 양쪽에 공백이 필요합니다.

✏️ 수정 제안
-        this.isDefault = isDefault !=null ? isDefault:false;
+        this.isDefault = isDefault != null ? isDefault : false;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.isDefault = isDefault !=null ? isDefault:false;
this.isDefault = isDefault != null ? isDefault : false;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/kuit/baemin/domain/address/Address.java` at line 56,
Whitespace around operators in the Address class assignment is incorrect; update
the expression in the Address constructor/initializer (the line using isDefault
!=null ? isDefault:false) to include spaces around operators so it reads:
isDefault != null ? isDefault : false; ensuring proper spacing around !=, ?: and
the colon.

this. latitude = latitude;
this. longitude = longitude;
Comment on lines +57 to +58

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

불필요한 공백을 제거하세요.

this.와 필드명 사이에 공백이 있습니다.

✏️ 수정 제안
-        this. latitude = latitude;
-        this. longitude = longitude;
+        this.latitude = latitude;
+        this.longitude = longitude;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this. latitude = latitude;
this. longitude = longitude;
this.latitude = latitude;
this.longitude = longitude;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/kuit/baemin/domain/address/Address.java` around lines 57 -
58, In class Address, remove the stray space between the "this." qualifier and
the field names so assignments use "this.latitude = latitude" and
"this.longitude = longitude"; update the constructor or any methods in Address
that contain "this. latitude" / "this. longitude" to remove the extra whitespace
so the field references are correct and consistent.

this.member = member;
this.status = AddressStatus.ACTIVE;
}
public void updateInfo(
String address,
String addressName,
Boolean isDefault,
Double latitude,
Double longitude
){
if(addressName!=null){
this.addressName = addressName;
}
if(address!=null){
this.address = address;
}
if(isDefault!=null){
this.isDefault = isDefault;
}
if(latitude !=null){
this.latitude = latitude;
}
if(longitude!=null) {
this.longitude = longitude;
}
}
public boolean isDeleted(){
return this.status == AddressStatus.DELETED;
}
public void delete(){
this.status = AddressStatus.DELETED;
}
public void setDefault(){
this.isDefault = true;
}
public void unsetDefault(){
this.isDefault = false;
}
public boolean isAlreadyDefault(){
return Boolean.TRUE.equals(this.isDefault);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.kuit.baemin.domain.address;

public enum AddressStatus {
ACTIVE,
DELETED
}
34 changes: 26 additions & 8 deletions src/main/java/com/kuit/baemin/domain/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Entity
@Getter
@Builder
@Table(name = "members")
@Table(name = "users")
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member extends BaseEntity {
Expand All @@ -17,23 +17,41 @@ public class Member extends BaseEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false, length = 50)
@Column(nullable = false, length = 100)
private String email;

@Column(nullable = false, length = 200)
@Column(nullable = false, length = 255)
private String password;

@Column(nullable = false, length = 20)
private String phoneNumber;
private String phone;

@Column(length = 25)
@Column(length = 50)
private String nickname;

@Column(length = 300)
private String profileImage;
@Column(length = 50)
private String name;

@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 10)
@Column(nullable = false, length = 20)
private MemberStatus status;

public void updateInfo(String name, String nickname, String phone){
if(name != null){
this.name = name;
}
if(name != null){
this.nickname = nickname;
}
Comment on lines +43 to +45

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

닉네임 갱신 조건이 잘못되어 부분 수정이 깨집니다.

nickname 갱신 분기에서 name != null을 검사하고 있어, 닉네임만 수정 요청 시 반영되지 않고 이름만 수정할 때 닉네임이 null로 덮일 수 있습니다.

수정 제안
-        if(name != null){
+        if(nickname != null){
             this.nickname = nickname;
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(name != null){
this.nickname = nickname;
}
if(nickname != null){
this.nickname = nickname;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/kuit/baemin/domain/member/Member.java` around lines 43 -
45, In Member.java the nickname update branch incorrectly checks name != null,
causing nickname updates to be skipped or overwritten; change the conditional to
check nickname != null before assigning this.nickname = nickname (inside the
method that updates member fields, e.g., the update/patch method in class
Member) so nickname is only updated when a new nickname is provided and other
fields remain unaffected.

if(phone!=null){
this.phone = phone;
}
}

public void delete(){
this.status = MemberStatus.DELETED;
}
public boolean isDeleted(){
return this.status == MemberStatus.DELETED;
}
}
Loading