Skip to content

Commit

Permalink
Merge branch 'week4' into feature/ISSUE-11
Browse files Browse the repository at this point in the history
  • Loading branch information
jjt4515 authored Sep 28, 2024
2 parents 530d5b1 + 9c6be8d commit 2dd5c8e
Show file tree
Hide file tree
Showing 13 changed files with 311 additions and 10 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ out/
### Mac OS ###
.DS_Store

application-secret.yml
## applicaion-secret
application-secret.yml

3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'

// mysql
implementation 'mysql:mysql-connector-java:8.0.33'

// Spring Security
implementation 'org.springframework.security:spring-security-crypto:5.7.1'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/poomasi/domain/farm/controller/FarmController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package poomasi.domain.farm.controller;

import lombok.AllArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import poomasi.domain.farm.service.FarmService;


@RestController
@AllArgsConstructor
@RequestMapping("/api/farm")
public class FarmController {
private final FarmService farmService;

@GetMapping("/{farmId}")
public ResponseEntity<?> getFarm(@RequestParam Long farmId) {
return ResponseEntity.ok(farmService.getFarmByFarmId(farmId));
}

@GetMapping("")
public ResponseEntity<?> getFarmList(Pageable pageable) {
return ResponseEntity.ok(farmService.getFarmList(pageable));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package poomasi.domain.farm.controller;

import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import poomasi.domain.farm.dto.FarmRegisterRequest;
import poomasi.domain.farm.dto.FarmUpdateRequest;
import poomasi.domain.farm.service.FarmFarmerService;

@RestController
@AllArgsConstructor
@RequestMapping("/api/farm")
public class FarmFarmerController {
private final FarmFarmerService farmFarmerService;

// TODO: 판매자만 접근가능하도록 인증/인가 annotation 추가
@PostMapping("")
public ResponseEntity<?> registerFarm(@RequestBody FarmRegisterRequest request) {
return ResponseEntity.ok(farmFarmerService.registerFarm(request));
}

@PostMapping("/update")
public ResponseEntity<?> updateFarm(@Valid @RequestBody FarmUpdateRequest request) {
// TODO: 판매자 ID(Spring Security Context)로 대체
Long farmerId = 1L;
return ResponseEntity.ok(farmFarmerService.updateFarm(farmerId, request));
}
}
26 changes: 26 additions & 0 deletions src/main/java/poomasi/domain/farm/dto/FarmRegisterRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package poomasi.domain.farm.dto;

import poomasi.domain.farm.entity.Farm;

public record FarmRegisterRequest(
String name,
Long ownerId,
String address,
String addressDetail,
Double latitude,
Double longitude,
String phoneNumber,
String description
) {
public Farm toEntity() {
return Farm.builder()
.name(name)
.ownerId(ownerId)
.address(address)
.addressDetail(addressDetail)
.latitude(latitude)
.longitude(longitude)
.description(description)
.build();
}
}
26 changes: 26 additions & 0 deletions src/main/java/poomasi/domain/farm/dto/FarmResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package poomasi.domain.farm.dto;

import poomasi.domain.farm.entity.Farm;


public record FarmResponse( // FIXME: 사용자 정보 추가 및 설명/전화번호 추가
Long id,
String name,
String address,
String addressDetail,
Double latitude,
Double longitude,
String description
) {
public static FarmResponse fromEntity(Farm farm) {
return new FarmResponse(
farm.getId(),
farm.getName(),
farm.getAddress(),
farm.getAddressDetail(),
farm.getLatitude(),
farm.getLongitude(),
farm.getDescription()
);
}
}
18 changes: 18 additions & 0 deletions src/main/java/poomasi/domain/farm/dto/FarmUpdateRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package poomasi.domain.farm.dto;

import jakarta.validation.constraints.NotNull;
import poomasi.domain.farm.entity.Farm;

public record FarmUpdateRequest(
@NotNull(message = "Farm ID는 필수 값입니다.") Long farmId,
String name,
String description,
String address,
String addressDetail,
Double latitude,
Double longitude
) {
public Farm toEntity(Farm farm) {
return farm.updateFarm(this);
}
}
73 changes: 73 additions & 0 deletions src/main/java/poomasi/domain/farm/entity/Farm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package poomasi.domain.farm.entity;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLSelect;
import org.hibernate.annotations.UpdateTimestamp;
import poomasi.domain.farm.dto.FarmUpdateRequest;

import java.time.LocalDateTime;

@Entity
@Getter
@Table(name = "farm")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SQLDelete(sql = "UPDATE farm SET deleted = true WHERE id = ?")
@SQLSelect(sql = "SELECT * FROM farm WHERE deleted = false")
public class Farm {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

// FIXME: owner_id는 Member의 id를 참조해야 합니다.
@Column(name = "owner_id")
private Long ownerId;

private String description;

private String address; // 도로명 주소
private String addressDetail; // 상세 주소

private Double latitude;
private Double longitude;

private FarmStatus status = FarmStatus.WAITING;

private boolean deleted = false;

@CreationTimestamp
@Column(name = "created_at")
private LocalDateTime createdAt = LocalDateTime.now();

@Column(name = "updated_at")
@UpdateTimestamp
private LocalDateTime updatedAt = LocalDateTime.now();

@Builder
public Farm(String name, Long ownerId, String address, String addressDetail, Double latitude, Double longitude, String description) {
this.name = name;
this.ownerId = ownerId;
this.address = address;
this.addressDetail = addressDetail;
this.latitude = latitude;
this.longitude = longitude;
this.description = description;
}

public Farm updateFarm(FarmUpdateRequest farmUpdateRequest) {
this.name = farmUpdateRequest.name();
this.address = farmUpdateRequest.address();
this.addressDetail = farmUpdateRequest.addressDetail();
this.latitude = farmUpdateRequest.latitude();
this.longitude = farmUpdateRequest.longitude();
this.description = farmUpdateRequest.description();
return this;
}
}
5 changes: 5 additions & 0 deletions src/main/java/poomasi/domain/farm/entity/FarmStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package poomasi.domain.farm.entity;

public enum FarmStatus {
OPEN, CLOSE, WAITING
}
12 changes: 12 additions & 0 deletions src/main/java/poomasi/domain/farm/repository/FarmRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package poomasi.domain.farm.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import poomasi.domain.farm.entity.Farm;

@Repository
public interface FarmRepository extends JpaRepository<Farm, Long> {
Page<Farm> findAll(Pageable pageable);
}
43 changes: 43 additions & 0 deletions src/main/java/poomasi/domain/farm/service/FarmFarmerService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package poomasi.domain.farm.service;

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import poomasi.domain.farm.dto.FarmRegisterRequest;
import poomasi.domain.farm.dto.FarmUpdateRequest;
import poomasi.domain.farm.entity.Farm;
import poomasi.domain.farm.repository.FarmRepository;
import poomasi.global.error.BusinessException;

import static poomasi.global.error.BusinessError.FARM_NOT_FOUND;
import static poomasi.global.error.BusinessError.FARM_OWNER_MISMATCH;

@Service
@AllArgsConstructor
public class FarmFarmerService {
private final FarmRepository farmRepository;

public Long registerFarm(FarmRegisterRequest request) {
// TODO: 판매자 인가?

// TODO: 이미 등록된 농장 인가?

return farmRepository.save(request.toEntity()).getId();

}

public Long updateFarm(Long farmerId, FarmUpdateRequest request) {
Farm farm = this.getFarmByFarmId(request.farmId());
if (!farm.getOwnerId().equals(farmerId)) {
throw new BusinessException(FARM_OWNER_MISMATCH);
}

// TODO: 변경 가능한 상태인가?

return farmRepository.save(request.toEntity(farm)).getId();
}

public Farm getFarmByFarmId(Long farmId) {
return farmRepository.findById(farmId).orElseThrow(() -> new BusinessException(FARM_NOT_FOUND));
}

}
31 changes: 31 additions & 0 deletions src/main/java/poomasi/domain/farm/service/FarmService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package poomasi.domain.farm.service;

import lombok.AllArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import poomasi.domain.farm.dto.FarmResponse;
import poomasi.domain.farm.repository.FarmRepository;
import poomasi.global.error.BusinessError;
import poomasi.global.error.BusinessException;

import java.util.List;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class FarmService {
private final FarmRepository farmRepository;

public FarmResponse getFarmByFarmId(Long farmId) {
return farmRepository.findById(farmId)
.map(FarmResponse::fromEntity)
.orElseThrow(() -> new BusinessException(BusinessError.FARM_NOT_FOUND));
}


public List<FarmResponse> getFarmList(Pageable pageable) {
return farmRepository.findAll(pageable).stream()
.map(FarmResponse::fromEntity)
.collect(Collectors.toList());
}
}
23 changes: 14 additions & 9 deletions src/main/java/poomasi/global/error/BusinessError.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@
@Getter
@AllArgsConstructor
public enum BusinessError {
//member
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "회원이 존재하지 않습니다."),
DUPLICATE_MEMBER_EMAIL(HttpStatus.CONFLICT, "중복된 이메일입니다."),
INVALID_FARMER_QUALIFICATION(HttpStatus.BAD_REQUEST, "농부 자격 증명이 필요합니다."),
//auth
INVALID_CREDENTIAL(HttpStatus.UNAUTHORIZED, "잘못된 비밀번호 입니다."),
REFRESH_TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "리프레시 토큰이 유효하지 않습니다.");
//member
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "회원이 존재하지 않습니다."),
DUPLICATE_MEMBER_EMAIL(HttpStatus.CONFLICT, "중복된 이메일입니다."),
INVALID_FARMER_QUALIFICATION(HttpStatus.BAD_REQUEST, "농부 자격 증명이 필요합니다."),
//auth
INVALID_CREDENTIAL(HttpStatus.UNAUTHORIZED, "잘못된 비밀번호 입니다."),
REFRESH_TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "리프레시 토큰이 유효하지 않습니다."),
// Farm
FARM_NOT_FOUND(HttpStatus.NOT_FOUND, "농장을 찾을 수 없습니다."),
FARM_OWNER_MISMATCH(HttpStatus.FORBIDDEN, "해당 농장의 소유자가 아닙니다.");


private final HttpStatus httpStatus;

private final String message;
private final HttpStatus httpStatus;

private final String message;
}

0 comments on commit 2dd5c8e

Please sign in to comment.