Skip to content
Merged
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
38 changes: 19 additions & 19 deletions src/main/java/com/umc/timeto/block/controller/BlockController.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.util.List;

Expand Down Expand Up @@ -77,24 +76,25 @@ public ResponseEntity<ResponseDTO<List<BlockResponseNumDTO>>> getBlockNumByMonth
}


@PatchMapping("/{blockId}/duration")
@Override
public ResponseEntity<ResponseDTO<Void>> updateDuration(
@PathVariable Long blockId,
@RequestParam LocalTime duration,
Authentication authentication
) {

blockService.updateBlockDuration(
blockId,
getMemberId(authentication),
duration
);

return ResponseEntity.ok(
new ResponseDTO<>(ResponseCode.SUCCESS_UPDATE_BLOCK, null)
);
}
// @PatchMapping("/{blockId}/duration")
// @Override
// public ResponseEntity<ResponseDTO<Void>> updateDuration(
// @PathVariable Long blockId,
// @DateTimeFormat(pattern = "HH:mm:ss")
// @RequestParam LocalTime duration,
// Authentication authentication
// ) {
//
// blockService.updateBlockDuration(
// blockId,
// getMemberId(authentication),
// duration
// );
//
// return ResponseEntity.ok(
// new ResponseDTO<>(ResponseCode.SUCCESS_UPDATE_BLOCK, null)
// );
// }



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.util.List;

public interface BlockControllerDocs {
@Operation(summary = "타임블럭 저장", description = "할 일 시작 시간을 받아서 블록을 저장합니다. 블록에는 일정 겹침 검사가 존재합니다." +
"(ex: 일정 1이 7:30~8:30 일떄, 일정2의 생성/이동은 8:30분 이상부터 가능)")
"(ex: 일정 1이 7:30~8:30 일떄, 일정2의 생성/이동은 8:30분 이상부터 가능)" +
"추가: startAt이 해당하는 날짜(당일 05시~다음날 05시 사이) 에 블록이 하나도 없을 경우에는 startAt의 값을 입력받아 생성됩니다." +
"하나라도 블록이 존재하면 가장 하단 블록의 endAt 시간대를 startAt으로 하여 생성됩니다. " +
"startAt의 날짜 부분에는 선택한 날짜를, 시간에는 현재 시간대나 default로 설정하고 싶은 시간을 입력해주세요. " )
@ApiResponses({
@ApiResponse(
responseCode = "201",
Expand Down Expand Up @@ -82,35 +84,35 @@ ResponseEntity<ResponseDTO<List<BlockResponseNumDTO>>> getBlockNumByMonth(
Authentication authentication
);

@Operation(summary = "블록 소요시간 변경",
description = "블록 소요시간 변경 시 사용합니다. 할 일 내부에서만 소요시간 변경이 가능하다면 사용하지 않아도 됩니다. ")
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "블록을 성공적으로 업데이트했습니다"
),
@ApiResponse(
responseCode = "404",
description = "해당 아이디를 가진 블록이 존재하지 않습니다.",
content = @Content(schema = @Schema(hidden = true))
),
@ApiResponse(
responseCode = "400",
description = "이미 해당 시간에 블록이 존재합니다."
,content = @Content(schema = @Schema(hidden = true))
)

})
@PatchMapping("/{blockId}/duration")
ResponseEntity<ResponseDTO<Void>> updateDuration(
@PathVariable Long blockId,
@RequestParam LocalTime duration,
Authentication authentication
);
// @Operation(summary = "블록 소요시간 변경",
// description = "블록 소요시간 변경 시 사용합니다. 할 일 내부에서만 소요시간 변경이 가능하다면 사용하지 않아도 됩니다. ")
// @ApiResponses({
// @ApiResponse(
// responseCode = "200",
// description = "블록을 성공적으로 업데이트했습니다"
// ),
// @ApiResponse(
// responseCode = "404",
// description = "해당 아이디를 가진 블록이 존재하지 않습니다.",
// content = @Content(schema = @Schema(hidden = true))
// ),
// @ApiResponse(
// responseCode = "400",
// description = "이미 해당 시간에 블록이 존재합니다."
// ,content = @Content(schema = @Schema(hidden = true))
// )
//
// })
// @PatchMapping("/{blockId}/duration")
// ResponseEntity<ResponseDTO<Void>> updateDuration(
// @PathVariable Long blockId,
// @RequestParam LocalTime duration,
// Authentication authentication
// );

@Operation(summary = "블록 이동",
description = "블록을 드래그&드롭으로 이동했을 때 정보를 갱신합니다. 변경된 시작 시간을 입력으로 받습니다. " +
"이동된 시간이 다른 일정과 겹칠 경우 갱신되지 않습니다. startAt format: yyyy-MM-dd'T'HH:mm")
"이동된 시간이 다른 일정과 겹칠 경우 갱신되지 않습니다. startAt format: yyyy-MM-dd'T'HH:mm(ex: 2026-02-14T:02:14) ")
@ApiResponses({
@ApiResponse(
responseCode = "200",
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/umc/timeto/block/repository/BlockRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.umc.timeto.block.entity.Block;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.time.LocalDateTime;
import java.util.List;
Expand Down Expand Up @@ -37,4 +38,20 @@ List<Block> findByTodo_Folder_Goal_Member_MemberIdAndBlockIdNotAndStartAtLessTha
);

Optional<Block> findByBlockIdAndTodo_Folder_Goal_Member_MemberId(Long blockId, Long memberId);

@Query("""
select b
from Block b
join fetch b.todo t
join fetch t.folder f
join fetch f.goal g
where g.member.memberId = :memberId
and b.startAt between :start and :end
""")
List<Block> findBlocksWithTodo(
Long memberId,
LocalDateTime start,
LocalDateTime end
);

}
69 changes: 47 additions & 22 deletions src/main/java/com/umc/timeto/block/service/BlockServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
Expand All @@ -29,36 +30,59 @@ public class BlockServiceImpl implements BlockService {

private final TodoRepository todoRepository;
private final BlockRepository blockRepository;
private final BusinessDayPolicy businessDayPolicy;

@Override
public BlockResponseDTO createBlock(Long todoId, BlockAddDTO req, Long memberId) {

Todo todo = todoRepository.findByTodoIdAndFolder_Goal_Member_MemberId(todoId,memberId)
.orElseThrow(() -> new GlobalException(ErrorCode.TODO_NOT_FOUND));


// 블록 겹침 조회
LocalDateTime startAt = req.getStartAt();
LocalTime duration = todo.getDuration();

LocalDateTime endAt = startAt
.plusHours(duration.getHour())
.plusMinutes(duration.getMinute())
.plusSeconds(duration.getSecond());
System.out.println("시작시간" +startAt + "끝나는시간" +endAt);
// Todo당 Block 1개 보장
blockRepository.findByTodo_TodoId(todoId)
.ifPresent(b -> {
throw new GlobalException(ErrorCode.BAD_REQUEST);
});

List<Block> overlaps =

// 05:00 기준 startAt에서 입력받은 날짜 범위
LocalDateTime dayStart = businessDayPolicy.startOfBusinessDay(startAt);
LocalDateTime dayEnd = businessDayPolicy.endOfBusinessDay(startAt);



List<Block> todayBlocks =
blockRepository
.findByTodo_Folder_Goal_Member_MemberIdAndStartAtLessThanAndEndAtGreaterThan(
.findByTodo_Folder_Goal_Member_MemberIdAndStartAtGreaterThanEqualAndStartAtLessThan(
memberId,
endAt,
startAt
dayStart,
dayEnd
);

if (!overlaps.isEmpty()) {
throw new GlobalException(ErrorCode.BLOCK_TIME_CONFLICT);

System.out.println("dayStart = " + dayStart);
System.out.println("dayEnd = " + dayEnd);
System.out.println("todayBlocks size = " + todayBlocks.size());




if (todayBlocks.isEmpty()) {
// 오늘 블록 없으면 입력받은 시간에 생성
startAt = req.getStartAt();
} else {
// 가장 늦게 끝나는 블록 아래 배치
Block lastBlock = todayBlocks.stream()
.max(Comparator.comparing(Block::getEndAt))
.orElseThrow();

startAt = lastBlock.getEndAt();
}

//생성 시 시작시간 추가되도록
todo.updateStartAt(startAt);

//블록 저장
Block block = new Block(todo, startAt);
Expand All @@ -76,16 +100,17 @@ public BlockResponseDTO createBlock(Long todoId, BlockAddDTO req, Long memberId)
@Override
public List<BlockResponseDetailDTO> getBlockByDay(LocalDate date, Long memberId) {

LocalDateTime start = date.atStartOfDay();
LocalDateTime end = date.atTime(23, 59, 59);
LocalDateTime time_standard = date.atTime(5, 0);

LocalDateTime start = businessDayPolicy.startOfBusinessDay(time_standard);
LocalDateTime end = businessDayPolicy.endOfBusinessDay(time_standard);

List<Block> blocks =
blockRepository
.findByTodo_Folder_Goal_Member_MemberIdAndStartAtBetween(
memberId,
start,
end
);
blockRepository.findBlocksWithTodo(
memberId,
start,
end
);


return blocks.stream()
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/umc/timeto/block/service/BusinessDayPolicy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.umc.timeto.block.service;

import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

@Component
public class BusinessDayPolicy {

private static final LocalTime DAY_START = LocalTime.of(5, 0);

public LocalDateTime startOfBusinessDay(LocalDateTime base) {
LocalDate date = base.toLocalDate();

if (base.toLocalTime().isBefore(DAY_START)) {
date = date.minusDays(1);
}

return date.atTime(DAY_START);
}

public LocalDateTime endOfBusinessDay(LocalDateTime base) {
return startOfBusinessDay(base).plusDays(1);
}
}

2 changes: 2 additions & 0 deletions src/main/java/com/umc/timeto/todo/domain/Todo.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicUpdate;

import java.time.LocalDateTime;
import java.time.LocalTime;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DynamicUpdate
@Table(name = "todo")
public class Todo {
@Id
Expand Down