diff --git a/src/main/java/poomasi/domain/farm/_schedule/controller/FarmScheduleController.java b/src/main/java/poomasi/domain/farm/_schedule/controller/FarmScheduleController.java new file mode 100644 index 00000000..dec48e68 --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/controller/FarmScheduleController.java @@ -0,0 +1,22 @@ +package poomasi.domain.farm._schedule.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import poomasi.domain.farm._schedule.dto.FarmScheduleRequest; +import poomasi.domain.farm._schedule.service.FarmScheduleService; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/farm") +public class FarmScheduleController { + private final FarmScheduleService farmScheduleService; + + @GetMapping("/schedule") + public ResponseEntity getFarmSchedule(@RequestParam Long farmId, @RequestParam Integer year, @RequestParam Integer month) { + return ResponseEntity.ok(farmScheduleService.getFarmSchedulesByYearAndMonth(new FarmScheduleRequest(farmId, year, month))); + } +} diff --git a/src/main/java/poomasi/domain/farm/_schedule/controller/FarmScheduleFarmerController.java b/src/main/java/poomasi/domain/farm/_schedule/controller/FarmScheduleFarmerController.java new file mode 100644 index 00000000..d0308f17 --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/controller/FarmScheduleFarmerController.java @@ -0,0 +1,25 @@ +package poomasi.domain.farm._schedule.controller; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +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._schedule.dto.FarmScheduleUpdateRequest; +import poomasi.domain.farm._schedule.service.FarmScheduleService; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/farm") +public class FarmScheduleFarmerController { + private final FarmScheduleService farmScheduleService; + + @PostMapping("/schedule") + public ResponseEntity addFarmSchedule(@Valid @RequestBody FarmScheduleUpdateRequest request) { + farmScheduleService.addFarmSchedule(request); + return ResponseEntity.ok().build(); + } + +} diff --git a/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleRequest.java b/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleRequest.java new file mode 100644 index 00000000..335e2535 --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleRequest.java @@ -0,0 +1,9 @@ +package poomasi.domain.farm._schedule.dto; + +public record FarmScheduleRequest( + Long farmId, + Integer year, + Integer month +) { +} + diff --git a/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleResponse.java b/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleResponse.java new file mode 100644 index 00000000..4fa4f13d --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleResponse.java @@ -0,0 +1,20 @@ +package poomasi.domain.farm._schedule.dto; + +import lombok.Builder; +import poomasi.domain.farm._schedule.entity.FarmSchedule; +import poomasi.domain.farm._schedule.entity.ScheduleStatus; + +import java.time.LocalDate; + +@Builder +public record FarmScheduleResponse( + LocalDate date, + ScheduleStatus status +) { + public static FarmScheduleResponse fromEntity(FarmSchedule farmSchedule) { + return FarmScheduleResponse.builder() + .date(farmSchedule.getDate()) + .status(farmSchedule.getStatus()) + .build(); + } +} diff --git a/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleUpdateRequest.java b/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleUpdateRequest.java new file mode 100644 index 00000000..40e6bdd0 --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/dto/FarmScheduleUpdateRequest.java @@ -0,0 +1,29 @@ +package poomasi.domain.farm._schedule.dto; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import poomasi.domain.farm._schedule.entity.FarmSchedule; +import poomasi.domain.farm._schedule.entity.ScheduleStatus; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.List; + +public record FarmScheduleUpdateRequest( + Long farmId, + @NotNull(message = "시작 날짜는 필수 값입니다.") + LocalDate startDate, + @NotNull(message = "종료 날짜는 필수 값입니다.") + LocalDate endDate, + ScheduleStatus status, + @NotEmpty(message = "예약 가능한 요일은 필수 값입니다.") + List availableDays // 예약 가능한 요일 리스트 +) { + public FarmSchedule toEntity(LocalDate date) { + return FarmSchedule.builder() + .farmId(farmId) + .date(date) + .status(status) + .build(); + } +} diff --git a/src/main/java/poomasi/domain/farm/_schedule/entity/FarmSchedule.java b/src/main/java/poomasi/domain/farm/_schedule/entity/FarmSchedule.java new file mode 100644 index 00000000..3f043335 --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/entity/FarmSchedule.java @@ -0,0 +1,41 @@ +package poomasi.domain.farm._schedule.entity; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Comment; + +import java.time.LocalDate; + +@Entity +@Getter +@Table(name = "farm_schedule") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class FarmSchedule { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Comment("농장") + private Long farmId; + + @Comment("예약 가능 날짜") + private LocalDate date; + + @Comment("예약 가능 여부") + @Enumerated(EnumType.STRING) + private ScheduleStatus status; + + @Builder + public FarmSchedule(Long farmId, LocalDate date, ScheduleStatus status) { + this.farmId = farmId; + this.date = date; + this.status = status; + } + + public void updateStatus(ScheduleStatus status) { + this.status = status; + } +} diff --git a/src/main/java/poomasi/domain/farm/_schedule/entity/ScheduleStatus.java b/src/main/java/poomasi/domain/farm/_schedule/entity/ScheduleStatus.java new file mode 100644 index 00000000..dae5b8ae --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/entity/ScheduleStatus.java @@ -0,0 +1,15 @@ +package poomasi.domain.farm._schedule.entity; + +public enum ScheduleStatus { + PENDING, + RESERVED, + ; + + public boolean isAvailable() { + return this == PENDING; + } + + public boolean isReserved() { + return this == RESERVED; + } +} diff --git a/src/main/java/poomasi/domain/farm/_schedule/repository/FarmScheduleRepository.java b/src/main/java/poomasi/domain/farm/_schedule/repository/FarmScheduleRepository.java new file mode 100644 index 00000000..1bc64247 --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/repository/FarmScheduleRepository.java @@ -0,0 +1,19 @@ +package poomasi.domain.farm._schedule.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import poomasi.domain.farm._schedule.entity.FarmSchedule; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +@Repository +public interface FarmScheduleRepository extends JpaRepository { + @Query("SELECT f FROM FarmSchedule f WHERE f.farmId = :farmId AND f.date BETWEEN :startDate AND :endDate") + List findByFarmIdAndDateRange(Long farmId, LocalDate startDate, LocalDate endDate); + + Optional findByFarmIdAndDate(Long aLong, LocalDate date); + +} diff --git a/src/main/java/poomasi/domain/farm/_schedule/service/FarmScheduleService.java b/src/main/java/poomasi/domain/farm/_schedule/service/FarmScheduleService.java new file mode 100644 index 00000000..61c8658d --- /dev/null +++ b/src/main/java/poomasi/domain/farm/_schedule/service/FarmScheduleService.java @@ -0,0 +1,58 @@ +package poomasi.domain.farm._schedule.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import poomasi.domain.farm._schedule.dto.FarmScheduleRequest; +import poomasi.domain.farm._schedule.dto.FarmScheduleResponse; +import poomasi.domain.farm._schedule.dto.FarmScheduleUpdateRequest; +import poomasi.domain.farm._schedule.entity.FarmSchedule; +import poomasi.domain.farm._schedule.repository.FarmScheduleRepository; +import poomasi.global.error.BusinessException; + +import java.time.LocalDate; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static poomasi.global.error.BusinessError.FARM_SCHEDULE_ALREADY_EXISTS; +import static poomasi.global.error.BusinessError.START_DATE_SHOULD_BE_BEFORE_END_DATE; + +@Service +@RequiredArgsConstructor +public class FarmScheduleService { + private final FarmScheduleRepository farmScheduleRepository; + + public void addFarmSchedule(FarmScheduleUpdateRequest request) { + List existingSchedules = farmScheduleRepository.findByFarmIdAndDateRange(request.farmId(), request.startDate(), request.endDate()); + + if (request.startDate().isAfter(request.endDate())) { + throw new BusinessException(START_DATE_SHOULD_BE_BEFORE_END_DATE); + } + + Set existingDates = existingSchedules.stream() + .map(FarmSchedule::getDate) + .collect(Collectors.toSet()); + + for (LocalDate date = request.startDate(); !date.isAfter(request.endDate()); date = date.plusDays(1)) { + if (request.availableDays().contains(date.getDayOfWeek())) { + if (existingDates.contains(date)) { + throw new BusinessException(FARM_SCHEDULE_ALREADY_EXISTS); + } + + FarmSchedule newSchedule = request.toEntity(date); + farmScheduleRepository.save(newSchedule); + } + } + } + + public List getFarmSchedulesByYearAndMonth(FarmScheduleRequest request) { + LocalDate startDate = LocalDate.of(request.year(), request.month(), 1); + LocalDate endDate = startDate.withDayOfMonth(startDate.lengthOfMonth()); + + return farmScheduleRepository.findByFarmIdAndDateRange(request.farmId(), startDate, endDate).stream() + .map(FarmScheduleResponse::fromEntity) + .toList(); + } + + +} diff --git a/src/main/java/poomasi/domain/farm/controller/FarmController.java b/src/main/java/poomasi/domain/farm/controller/FarmController.java index 9c7c1b27..cd2899f2 100644 --- a/src/main/java/poomasi/domain/farm/controller/FarmController.java +++ b/src/main/java/poomasi/domain/farm/controller/FarmController.java @@ -4,8 +4,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import poomasi.domain.farm.service.FarmService; @@ -17,7 +17,7 @@ public class FarmController { private final FarmService farmService; @GetMapping("/{farmId}") - public ResponseEntity getFarm(@RequestParam Long farmId) { + public ResponseEntity getFarm(@PathVariable Long farmId) { return ResponseEntity.ok(farmService.getFarmByFarmId(farmId)); } diff --git a/src/main/java/poomasi/domain/farm/controller/FarmFarmerController.java b/src/main/java/poomasi/domain/farm/controller/FarmFarmerController.java index 71a3aa33..eed59cd3 100644 --- a/src/main/java/poomasi/domain/farm/controller/FarmFarmerController.java +++ b/src/main/java/poomasi/domain/farm/controller/FarmFarmerController.java @@ -1,21 +1,20 @@ package poomasi.domain.farm.controller; import jakarta.validation.Valid; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; 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 org.springframework.web.bind.annotation.*; import poomasi.domain.farm.dto.FarmRegisterRequest; import poomasi.domain.farm.dto.FarmUpdateRequest; import poomasi.domain.farm.service.FarmFarmerService; +import poomasi.domain.farm._schedule.service.FarmScheduleService; @RestController -@AllArgsConstructor +@RequiredArgsConstructor @RequestMapping("/api/farm") public class FarmFarmerController { private final FarmFarmerService farmFarmerService; + private final FarmScheduleService farmScheduleService; // TODO: 판매자만 접근가능하도록 인증/인가 annotation 추가 @PostMapping("") @@ -29,4 +28,14 @@ public ResponseEntity updateFarm(@Valid @RequestBody FarmUpdateRequest reques Long farmerId = 1L; return ResponseEntity.ok(farmFarmerService.updateFarm(farmerId, request)); } + + @DeleteMapping("/{farmId}") + public ResponseEntity deleteFarm(@PathVariable Long farmId) { + // TODO: 판매자 ID + Long farmerId = 1L; + + farmFarmerService.deleteFarm(farmerId, farmId); + return ResponseEntity.ok().build(); + } + } diff --git a/src/main/java/poomasi/domain/farm/dto/FarmRegisterRequest.java b/src/main/java/poomasi/domain/farm/dto/FarmRegisterRequest.java index 2f60d40a..49447af8 100644 --- a/src/main/java/poomasi/domain/farm/dto/FarmRegisterRequest.java +++ b/src/main/java/poomasi/domain/farm/dto/FarmRegisterRequest.java @@ -4,23 +4,25 @@ public record FarmRegisterRequest( String name, - Long ownerId, + Long memberId, String address, String addressDetail, Double latitude, Double longitude, String phoneNumber, - String description + String description, + Long experiencePrice ) { public Farm toEntity() { return Farm.builder() .name(name) - .ownerId(ownerId) + .ownerId(memberId) .address(address) .addressDetail(addressDetail) .latitude(latitude) .longitude(longitude) .description(description) + .experiencePrice(experiencePrice) .build(); } } diff --git a/src/main/java/poomasi/domain/farm/dto/FarmResponse.java b/src/main/java/poomasi/domain/farm/dto/FarmResponse.java index 74021c34..632957e3 100644 --- a/src/main/java/poomasi/domain/farm/dto/FarmResponse.java +++ b/src/main/java/poomasi/domain/farm/dto/FarmResponse.java @@ -10,8 +10,9 @@ public record FarmResponse( // FIXME: 사용자 정보 추가 및 설명/전화 String addressDetail, Double latitude, Double longitude, - String description - ) { + String description, + Long experiencePrice +) { public static FarmResponse fromEntity(Farm farm) { return new FarmResponse( farm.getId(), @@ -20,7 +21,8 @@ public static FarmResponse fromEntity(Farm farm) { farm.getAddressDetail(), farm.getLatitude(), farm.getLongitude(), - farm.getDescription() + farm.getDescription(), + farm.getExperiencePrice() ); } } diff --git a/src/main/java/poomasi/domain/farm/entity/Farm.java b/src/main/java/poomasi/domain/farm/entity/Farm.java index e89db2bf..62335214 100644 --- a/src/main/java/poomasi/domain/farm/entity/Farm.java +++ b/src/main/java/poomasi/domain/farm/entity/Farm.java @@ -1,13 +1,14 @@ package poomasi.domain.farm.entity; +import jakarta.annotation.Nullable; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.Comment; 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; @@ -17,8 +18,7 @@ @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") +@SQLDelete(sql = "UPDATE farm SET deleted_at=current_timestamp WHERE id = ?") public class Farm { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -27,20 +27,34 @@ public class Farm { private String name; // FIXME: owner_id는 Member의 id를 참조해야 합니다. + @Comment("농장 소유자 ID") @Column(name = "owner_id") private Long ownerId; + @Comment("농장 간단 설명") private String description; - private String address; // 도로명 주소 - private String addressDetail; // 상세 주소 + @Comment("도로명 주소") + private String address; + @Comment("상세 주소") + private String addressDetail; + + @Comment("위도") private Double latitude; + + @Comment("경도") private Double longitude; - private FarmStatus status = FarmStatus.WAITING; + @Comment("농장 상태") + @Enumerated(EnumType.STRING) + private FarmStatus status = FarmStatus.OPEN; + + @Comment("체험 비용") + private Long experiencePrice; - private boolean deleted = false; + @Comment("삭제 일시") + private LocalDateTime deletedAt; @CreationTimestamp @Column(name = "created_at") @@ -51,7 +65,7 @@ public class Farm { private LocalDateTime updatedAt = LocalDateTime.now(); @Builder - public Farm(String name, Long ownerId, String address, String addressDetail, Double latitude, Double longitude, String description) { + public Farm(String name, Long ownerId, String address, String addressDetail, Double latitude, Double longitude, String description, Long experiencePrice) { this.name = name; this.ownerId = ownerId; this.address = address; @@ -59,6 +73,7 @@ public Farm(String name, Long ownerId, String address, String addressDetail, Dou this.latitude = latitude; this.longitude = longitude; this.description = description; + this.experiencePrice = experiencePrice; } public Farm updateFarm(FarmUpdateRequest farmUpdateRequest) { diff --git a/src/main/java/poomasi/domain/farm/repository/FarmRepository.java b/src/main/java/poomasi/domain/farm/repository/FarmRepository.java index 7c4c6e9b..96b40c67 100644 --- a/src/main/java/poomasi/domain/farm/repository/FarmRepository.java +++ b/src/main/java/poomasi/domain/farm/repository/FarmRepository.java @@ -6,7 +6,15 @@ import org.springframework.stereotype.Repository; import poomasi.domain.farm.entity.Farm; +import java.util.Optional; + @Repository public interface FarmRepository extends JpaRepository { Page findAll(Pageable pageable); + + Page findByDeletedAtIsNull(Pageable pageable); + + Optional getFarmByOwnerIdAndDeletedAtIsNull(Long ownerId); + + Optional findByIdAndDeletedAtIsNull(Long id); } diff --git a/src/main/java/poomasi/domain/farm/service/FarmFarmerService.java b/src/main/java/poomasi/domain/farm/service/FarmFarmerService.java index 7a967eb8..5eec83fd 100644 --- a/src/main/java/poomasi/domain/farm/service/FarmFarmerService.java +++ b/src/main/java/poomasi/domain/farm/service/FarmFarmerService.java @@ -1,6 +1,5 @@ package poomasi.domain.farm.service; -import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import poomasi.domain.farm.dto.FarmRegisterRequest; @@ -9,8 +8,7 @@ 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; +import static poomasi.global.error.BusinessError.*; @Service @RequiredArgsConstructor @@ -20,7 +18,9 @@ public class FarmFarmerService { public Long registerFarm(FarmRegisterRequest request) { // TODO: 판매자 인가? - // TODO: 이미 등록된 농장 인가? + farmRepository.getFarmByOwnerIdAndDeletedAtIsNull(request.memberId()).ifPresent(farm -> { + throw new BusinessException(FARM_ALREADY_EXISTS); + }); return farmRepository.save(request.toEntity()).getId(); @@ -28,17 +28,23 @@ public Long registerFarm(FarmRegisterRequest request) { 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)); + return farmRepository.findByIdAndDeletedAtIsNull(farmId).orElseThrow(() -> new BusinessException(FARM_NOT_FOUND)); } + public void deleteFarm(Long farmerId, Long farmId) { + Farm farm = this.getFarmByFarmId(farmId); + if (!farm.getOwnerId().equals(farmerId)) { + throw new BusinessException(FARM_OWNER_MISMATCH); + } + farmRepository.delete(farm); + } } diff --git a/src/main/java/poomasi/domain/farm/service/FarmService.java b/src/main/java/poomasi/domain/farm/service/FarmService.java index 99e1bc1d..8ef71096 100644 --- a/src/main/java/poomasi/domain/farm/service/FarmService.java +++ b/src/main/java/poomasi/domain/farm/service/FarmService.java @@ -1,6 +1,5 @@ package poomasi.domain.farm.service; -import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -18,14 +17,14 @@ public class FarmService { private final FarmRepository farmRepository; public FarmResponse getFarmByFarmId(Long farmId) { - return farmRepository.findById(farmId) + return farmRepository.findByIdAndDeletedAtIsNull(farmId) .map(FarmResponse::fromEntity) .orElseThrow(() -> new BusinessException(BusinessError.FARM_NOT_FOUND)); } public List getFarmList(Pageable pageable) { - return farmRepository.findAll(pageable).stream() + return farmRepository.findByDeletedAtIsNull(pageable).stream() .map(FarmResponse::fromEntity) .collect(Collectors.toList()); } diff --git a/src/main/java/poomasi/global/error/BusinessError.java b/src/main/java/poomasi/global/error/BusinessError.java index 240b2bb4..3d1ba525 100644 --- a/src/main/java/poomasi/global/error/BusinessError.java +++ b/src/main/java/poomasi/global/error/BusinessError.java @@ -1,14 +1,13 @@ package poomasi.global.error; +import org.springframework.http.HttpStatus; + import lombok.AllArgsConstructor; import lombok.Getter; -import org.springframework.http.HttpStatus; @Getter @AllArgsConstructor public enum BusinessError { - EXAMPLE_ERROR(HttpStatus.BAD_REQUEST, "에러 예시입니다."), - // Product PRODUCT_NOT_FOUND(HttpStatus.NOT_FOUND, "상품을 찾을 수 없습니다."), @@ -19,13 +18,23 @@ public enum BusinessError { 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.NOT_FOUND, "리프레시 토큰이 없습니다."), REFRESH_TOKEN_NOT_VALID(HttpStatus.UNAUTHORIZED, "리프레시 토큰이 유효하지 않습니다."), // Farm FARM_NOT_FOUND(HttpStatus.NOT_FOUND, "농장을 찾을 수 없습니다."), - FARM_OWNER_MISMATCH(HttpStatus.FORBIDDEN, "해당 농장의 소유자가 아닙니다."); + FARM_OWNER_MISMATCH(HttpStatus.FORBIDDEN, "해당 농장의 소유자가 아닙니다."), + FARM_ALREADY_EXISTS(HttpStatus.CONFLICT, "이미 농장이 존재합니다."), + + // FarmSchedule + FARM_SCHEDULE_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 날짜의 스케줄을 찾을 수 없습니다."), + FARM_SCHEDULE_ALREADY_EXISTS(HttpStatus.CONFLICT, "이미 스케줄이 존재합니다."), + + // ETC + START_DATE_SHOULD_BE_BEFORE_END_DATE(HttpStatus.BAD_REQUEST, "시작 날짜는 종료 날짜보다 이전이어야 합니다."), + ; private final HttpStatus httpStatus;