From 9e88eb0c5f7a9e92b76578b77f1f28f4cdbc2a02 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sat, 1 Apr 2023 16:48:08 +0900 Subject: [PATCH 01/14] =?UTF-8?q?chore:=20excel=20=EA=B0=92=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20row=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/thirdparty/parser/ExcelAdapter.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt index 15a32ad78..a7213bd7a 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt @@ -1,7 +1,11 @@ package team.aliens.dms.thirdparty.parser import com.fasterxml.uuid.Generators +import java.io.ByteArrayOutputStream +import java.io.File +import java.time.format.DateTimeFormatter import org.apache.poi.hssf.usermodel.HSSFWorkbook +import org.apache.poi.ss.usermodel.Cell import org.apache.poi.ss.usermodel.CellStyle import org.apache.poi.ss.usermodel.HorizontalAlignment import org.apache.poi.ss.usermodel.IndexedColors @@ -28,9 +32,6 @@ import team.aliens.dms.domain.studyroom.spi.vo.StudentSeatInfo import team.aliens.dms.domain.user.exception.UserNotFoundException import team.aliens.dms.thirdparty.parser.exception.ExcelExtensionMismatchException import team.aliens.dms.thirdparty.parser.exception.ExcelInvalidFileException -import java.io.ByteArrayOutputStream -import java.io.File -import java.time.format.DateTimeFormatter @Component class ExcelAdapter : ParseFilePort, WriteFilePort { @@ -43,7 +44,10 @@ class ExcelAdapter : ParseFilePort, WriteFilePort { try { val worksheet = workbook.getSheetAt(0) for (i in 1..worksheet.lastRowNum) { - val excelData = worksheet.getRow(i).run { + val row = worksheet.getRow(i) + if (row.cellIterator().next().cellType == Cell.CELL_TYPE_BLANK) continue + + val excelData = row.run { VerifiedStudent( id = Generators.timeBasedGenerator().generate(), schoolName = schoolName, @@ -151,6 +155,7 @@ class ExcelAdapter : ParseFilePort, WriteFilePort { for (i in 1..worksheet.lastRowNum) { val row = worksheet.getRow(i) + if (row.cellIterator().next().cellType == Cell.CELL_TYPE_BLANK) continue val studentSeat = row.run { try { studentSeatsMap[ From 6977081dedd1312a1a097e984c4ff39a6375ed01 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sat, 1 Apr 2023 20:31:37 +0900 Subject: [PATCH 02/14] =?UTF-8?q?chore:=20=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/thirdparty/parser/ExcelAdapter.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt index a7213bd7a..d2b80b89c 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt @@ -45,7 +45,7 @@ class ExcelAdapter : ParseFilePort, WriteFilePort { val worksheet = workbook.getSheetAt(0) for (i in 1..worksheet.lastRowNum) { val row = worksheet.getRow(i) - if (row.cellIterator().next().cellType == Cell.CELL_TYPE_BLANK) continue + if (row.isFirstCellBlank()) continue val excelData = row.run { VerifiedStudent( @@ -74,6 +74,8 @@ class ExcelAdapter : ParseFilePort, WriteFilePort { return verifiedStudents } + private fun Row.isFirstCellBlank() = cellIterator().next().cellType == Cell.CELL_TYPE_BLANK + private fun Row.getStringValue(idx: Int) = getCell(idx, CREATE_NULL_AS_BLANK).stringCellValue private fun Row.getIntValue(idx: Int) = getCell(idx, CREATE_NULL_AS_BLANK).numericCellValue.toInt() @@ -155,7 +157,8 @@ class ExcelAdapter : ParseFilePort, WriteFilePort { for (i in 1..worksheet.lastRowNum) { val row = worksheet.getRow(i) - if (row.cellIterator().next().cellType == Cell.CELL_TYPE_BLANK) continue + if (row.isFirstCellBlank()) continue + val studentSeat = row.run { try { studentSeatsMap[ From 0d04c515cf26045ac4104e90404d7e5a301ef9c9 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sat, 1 Apr 2023 22:02:22 +0900 Subject: [PATCH 03/14] =?UTF-8?q?chore:=20(#411)=20=ED=95=99=EC=83=9D=20ta?= =?UTF-8?q?g=20filter=20=EC=A1=B0=EA=B1=B4=EB=AC=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../student/StudentPersistenceAdapter.kt | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt index 8bf8e4983..816fcc4f7 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt @@ -11,6 +11,7 @@ import com.querydsl.core.types.dsl.CaseBuilder import com.querydsl.core.types.dsl.Expressions import com.querydsl.jpa.JPAExpressions.select import com.querydsl.jpa.impl.JPAQueryFactory +import java.util.UUID import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component import team.aliens.dms.domain.manager.dto.PointFilter @@ -35,7 +36,6 @@ import team.aliens.dms.persistence.tag.entity.QStudentTagJpaEntity.studentTagJpa import team.aliens.dms.persistence.tag.entity.QTagJpaEntity.tagJpaEntity import team.aliens.dms.persistence.tag.mapper.TagMapper import team.aliens.dms.persistence.user.entity.QUserJpaEntity.userJpaEntity -import java.util.UUID @Component class StudentPersistenceAdapter( @@ -127,16 +127,16 @@ class StudentPersistenceAdapter( .join(studentJpaEntity.user, userJpaEntity) .join(userJpaEntity.school, schoolJpaEntity) .leftJoin(studentTagJpaEntity) - .on(studentTagJpaEntity.student.id.eq(studentJpaEntity.id)) - .leftJoin(tagJpaEntity).distinct() - .on(eqTag()) + .on(studentJpaEntity.id.eq(studentTagJpaEntity.student.id)).fetchJoin() + .leftJoin(tagJpaEntity) + .on(studentTagJpaEntity.tag.id.eq(tagJpaEntity.id)) .leftJoin(pointHistoryJpaEntity) - .on(eqStudentRecentPointHistory()) + .on(eqStudentRecentPointHistory()) .where( + userJpaEntity.school.id.eq(schoolId), nameContains(name), pointTotalBetween(pointFilter), - schoolEq(schoolId), - tagIdsIn(tagIds) + hasAllTags(tagIds) ) .orderBy( sortFilter(sort), @@ -171,25 +171,13 @@ class StudentPersistenceAdapter( profileImageUrl = it.profileImageUrl, sex = it.sex, tags = it.tags - .map { - tag -> + .map { tag -> tagMapper.toDomain(tag)!! } ) } } - private fun tagIdsIn(tagIds: List?) = - tagIds?.run { studentTagJpaEntity.tag.id.`in`(tagIds) } - - private fun eqTag(): BooleanExpression? { - return tagJpaEntity.id.`in`( - select(studentTagJpaEntity.tag.id) - .from(studentTagJpaEntity) - .where(studentTagJpaEntity.student.id.eq(studentJpaEntity.id)) - ) - } - private fun nameContains(name: String?) = name?.run { studentJpaEntity.name.contains(this) } private fun pointTotalBetween(pointFilter: PointFilter): BooleanExpression? { @@ -221,7 +209,16 @@ class StudentPersistenceAdapter( } } - private fun schoolEq(schoolId: UUID) = userJpaEntity.school.id.eq(schoolId) + private fun hasAllTags(tagIds: List?): BooleanExpression? = + tagIds?.run { + studentJpaEntity.id.`in`( + select(studentTagJpaEntity.student.id) + .from(studentTagJpaEntity) + .where(studentTagJpaEntity.tag.id.`in`(tagIds)) + .groupBy(studentTagJpaEntity.student) + .having(studentTagJpaEntity.count().eq(tagIds.size.toLong())) + ) + } private fun sortFilter(sort: Sort): OrderSpecifier<*>? { return when (sort) { From 7b23225a8f25157845672ca85933d54d7a775821 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sat, 1 Apr 2023 22:14:54 +0900 Subject: [PATCH 04/14] chore: stacktrace --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9c22fb62d..12a31a513 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,7 +32,7 @@ jobs: run: chmod +x gradlew - name: codecov gradle - run: ./gradlew test jacocoRootReport + run: ./gradlew test jacocoRootReport --stacktrace - name: Upload coverage to Codecov uses: codecov/codecov-action@v2 From 1c9189002b362b39fdb6b5907cc1fe4629da575f Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sat, 1 Apr 2023 22:28:30 +0900 Subject: [PATCH 05/14] =?UTF-8?q?chore:=20(#403)=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=9A=A9=EB=8F=84=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FileExtension.kt} | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) rename dms-presentation/src/main/kotlin/team/aliens/dms/common/{util/FileUtil.kt => extension/FileExtension.kt} (58%) diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/common/util/FileUtil.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/common/extension/FileExtension.kt similarity index 58% rename from dms-presentation/src/main/kotlin/team/aliens/dms/common/util/FileUtil.kt rename to dms-presentation/src/main/kotlin/team/aliens/dms/common/extension/FileExtension.kt index 106e56874..a9bdf5d2a 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/common/util/FileUtil.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/common/extension/FileExtension.kt @@ -1,24 +1,21 @@ -package team.aliens.dms.common.util +package team.aliens.dms.common.extension -import org.springframework.http.HttpHeaders -import org.springframework.web.multipart.MultipartFile import java.io.File import java.io.FileOutputStream import java.net.URLEncoder import java.util.UUID import javax.servlet.http.HttpServletResponse +import org.springframework.http.HttpHeaders +import org.springframework.web.multipart.MultipartFile -object FileUtil { - val transferFile = { multipartFile: MultipartFile -> - File("${UUID.randomUUID()}||${multipartFile.originalFilename}").let { - FileOutputStream(it).run { - this.write(multipartFile.bytes) - this.close() - } - it +fun MultipartFile.toFile() = + File("${UUID.randomUUID()}||${originalFilename}").let { + FileOutputStream(it).run { + this.write(bytes) + this.close() } + it } -} fun HttpServletResponse.setExcelContentDisposition(fileName: String) { setHeader( From 7bbec2f7562da5e1257413020b369315f2bedd6c Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sat, 1 Apr 2023 22:28:43 +0900 Subject: [PATCH 06/14] =?UTF-8?q?chore:=20(#403)=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/team/aliens/dms/domain/file/FileWebAdapter.kt | 8 ++++---- .../team/aliens/dms/domain/point/PointWebAdapter.kt | 2 +- .../team/aliens/dms/domain/remain/RemainWebAdapter.kt | 2 +- .../aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/file/FileWebAdapter.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/file/FileWebAdapter.kt index fb39627b4..fc56efc25 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/file/FileWebAdapter.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/file/FileWebAdapter.kt @@ -1,5 +1,6 @@ package team.aliens.dms.domain.file +import javax.validation.constraints.NotNull import org.springframework.http.HttpStatus import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.GetMapping @@ -10,13 +11,12 @@ import org.springframework.web.bind.annotation.RequestPart import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController import org.springframework.web.multipart.MultipartFile -import team.aliens.dms.common.util.FileUtil +import team.aliens.dms.common.extension.toFile import team.aliens.dms.domain.file.dto.GetFileUploadUrlResponse import team.aliens.dms.domain.file.dto.response.UploadFileResponse import team.aliens.dms.domain.file.usecase.GetFileUploadUrlUseCase import team.aliens.dms.domain.file.usecase.ImportVerifiedStudentUseCase import team.aliens.dms.domain.file.usecase.UploadFileUseCase -import javax.validation.constraints.NotNull @Validated @RequestMapping("/files") @@ -30,7 +30,7 @@ class FileWebAdapter( @PostMapping fun uploadFile(@RequestPart @NotNull file: MultipartFile?): UploadFileResponse { val result = uploadFileUseCase.execute( - file!!.let(FileUtil.transferFile) + file!!.toFile() ) return UploadFileResponse(result) } @@ -46,7 +46,7 @@ class FileWebAdapter( @PostMapping("/verified-student") fun importVerifiedStudentFromExcel(@RequestPart @NotNull file: MultipartFile?) { importVerifiedStudentUseCase.execute( - file!!.let(FileUtil.transferFile) + file!!.toFile() ) } } diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/point/PointWebAdapter.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/point/PointWebAdapter.kt index c2bcff8f2..d3c8fba93 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/point/PointWebAdapter.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/point/PointWebAdapter.kt @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController import team.aliens.dms.common.dto.PageData import team.aliens.dms.common.dto.PageWebData -import team.aliens.dms.common.util.setExcelContentDisposition +import team.aliens.dms.common.extension.setExcelContentDisposition import team.aliens.dms.domain.point.dto.CreatePointOptionRequest import team.aliens.dms.domain.point.dto.CreatePointOptionResponse import team.aliens.dms.domain.point.dto.GrantPointRequest diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/remain/RemainWebAdapter.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/remain/RemainWebAdapter.kt index 2edacf946..041b1b6f1 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/remain/RemainWebAdapter.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/remain/RemainWebAdapter.kt @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController -import team.aliens.dms.common.util.setExcelContentDisposition +import team.aliens.dms.common.extension.setExcelContentDisposition import team.aliens.dms.domain.remain.dto.QueryCurrentAppliedRemainOptionResponse import team.aliens.dms.domain.remain.dto.QueryRemainAvailableTimeResponse import team.aliens.dms.domain.remain.dto.QueryRemainOptionsResponse diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt index e4bd8e5d0..92b22aba9 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt @@ -19,8 +19,8 @@ import org.springframework.web.bind.annotation.RequestPart import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController import org.springframework.web.multipart.MultipartFile -import team.aliens.dms.common.util.FileUtil -import team.aliens.dms.common.util.setExcelContentDisposition +import team.aliens.dms.common.extension.setExcelContentDisposition +import team.aliens.dms.common.extension.toFile import team.aliens.dms.domain.studyroom.dto.CreateSeatTypeWebRequest import team.aliens.dms.domain.studyroom.dto.CreateStudyRoomRequest import team.aliens.dms.domain.studyroom.dto.CreateStudyRoomResponse @@ -288,7 +288,7 @@ class StudyRoomWebAdapter( httpResponse: HttpServletResponse ): ByteArray { val response = exportStudyRoomApplicationStatusUseCase.execute( - file = file?.let(FileUtil.transferFile) + file = file?.toFile() ) httpResponse.setExcelContentDisposition(response.fileName) return response.file From c216d9ef308bbf7dad6a500ee58663f45411fd89 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sat, 1 Apr 2023 22:29:28 +0900 Subject: [PATCH 07/14] =?UTF-8?q?chore:=20(#403)=20stacktrace=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 12a31a513..9c22fb62d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,7 +32,7 @@ jobs: run: chmod +x gradlew - name: codecov gradle - run: ./gradlew test jacocoRootReport --stacktrace + run: ./gradlew test jacocoRootReport - name: Upload coverage to Codecov uses: codecov/codecov-action@v2 From 74915af36a8570cbcc5b45d395bc2c39f0fadf4c Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sun, 2 Apr 2023 16:02:20 +0900 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20(#414)=20studyRoomId=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt | 2 +- .../team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt b/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt index bc4df316c..85eb0e4ee 100644 --- a/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt +++ b/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt @@ -15,7 +15,7 @@ class QuerySeatTypesUseCase( private val querySeatTypePort: QuerySeatTypePort ) { - fun execute(): QuerySeatTypesResponse { + fun execute(studyRoomId: UUID?): QuerySeatTypesResponse { val currentUserId = securityPort.getCurrentUserId() val user = queryUserPort.queryUserById(currentUserId) ?: throw UserNotFoundException diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt index 92b22aba9..3e6978263 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt @@ -101,8 +101,8 @@ class StudyRoomWebAdapter( } @GetMapping("/types") - fun getSeatTypes(): QuerySeatTypesResponse { - return querySeatTypesUseCase.execute() + fun getSeatTypes(@RequestParam(name = "study_room_id") studyRoomId: UUID?): QuerySeatTypesResponse { + return querySeatTypesUseCase.execute(studyRoomId) } @ResponseStatus(HttpStatus.CREATED) From 08851294ef8d1ceb914ab3489dfb59e073259735 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sun, 2 Apr 2023 16:02:58 +0900 Subject: [PATCH 09/14] feat: (#414) queryAllSeatTypeByStudyRoomId --- .../domain/studyroom/spi/QuerySeatTypePort.kt | 4 +++- .../usecase/QuerySeatTypesUseCase.kt | 12 +++++++---- .../studyroom/SeatTypePersistenceAdapter.kt | 21 +++++++++++++++++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/spi/QuerySeatTypePort.kt b/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/spi/QuerySeatTypePort.kt index bd12a12e2..434917571 100644 --- a/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/spi/QuerySeatTypePort.kt +++ b/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/spi/QuerySeatTypePort.kt @@ -1,12 +1,14 @@ package team.aliens.dms.domain.studyroom.spi -import team.aliens.dms.domain.studyroom.model.SeatType import java.util.UUID +import team.aliens.dms.domain.studyroom.model.SeatType interface QuerySeatTypePort { fun queryAllSeatTypeBySchoolId(schoolId: UUID): List + fun queryAllSeatTypeByStudyRoomId(studyRoomId: UUID): List + fun existsSeatTypeByName(name: String): Boolean fun querySeatTypeById(seatTypeId: UUID): SeatType? diff --git a/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt b/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt index 85eb0e4ee..a7265a61a 100644 --- a/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt +++ b/dms-application/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCase.kt @@ -1,5 +1,6 @@ package team.aliens.dms.domain.studyroom.usecase +import java.util.UUID import team.aliens.dms.common.annotation.ReadOnlyUseCase import team.aliens.dms.domain.studyroom.dto.QuerySeatTypesResponse import team.aliens.dms.domain.studyroom.dto.QuerySeatTypesResponse.TypeElement @@ -19,15 +20,18 @@ class QuerySeatTypesUseCase( val currentUserId = securityPort.getCurrentUserId() val user = queryUserPort.queryUserById(currentUserId) ?: throw UserNotFoundException - val seatTypes = querySeatTypePort - .queryAllSeatTypeBySchoolId(user.schoolId).map { + val seatTypes = studyRoomId?.let { + querySeatTypePort.queryAllSeatTypeByStudyRoomId(studyRoomId) + } ?: querySeatTypePort.queryAllSeatTypeBySchoolId(user.schoolId) + + return QuerySeatTypesResponse( + seatTypes.map { TypeElement( id = it.id, name = it.name, color = it.color ) } - - return QuerySeatTypesResponse(seatTypes) + ) } } diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/studyroom/SeatTypePersistenceAdapter.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/studyroom/SeatTypePersistenceAdapter.kt index df75df5df..5dc5bba63 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/studyroom/SeatTypePersistenceAdapter.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/studyroom/SeatTypePersistenceAdapter.kt @@ -1,17 +1,22 @@ package team.aliens.dms.persistence.studyroom +import com.querydsl.jpa.impl.JPAQueryFactory +import java.util.UUID import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component import team.aliens.dms.domain.studyroom.model.SeatType import team.aliens.dms.domain.studyroom.spi.SeatTypePort +import team.aliens.dms.persistence.studyroom.entity.QSeatJpaEntity.seatJpaEntity +import team.aliens.dms.persistence.studyroom.entity.QSeatTypeJpaEntity.seatTypeJpaEntity +import team.aliens.dms.persistence.studyroom.entity.QStudyRoomJpaEntity.studyRoomJpaEntity import team.aliens.dms.persistence.studyroom.mapper.SeatTypeMapper import team.aliens.dms.persistence.studyroom.repository.SeatTypeJpaRepository -import java.util.UUID @Component class SeatTypePersistenceAdapter( private val seatTypeMapper: SeatTypeMapper, - private val seatTypeRepository: SeatTypeJpaRepository + private val seatTypeRepository: SeatTypeJpaRepository, + private val queryFactory: JPAQueryFactory, ) : SeatTypePort { override fun queryAllSeatTypeBySchoolId(schoolId: UUID) = seatTypeRepository @@ -19,6 +24,18 @@ class SeatTypePersistenceAdapter( seatTypeMapper.toDomain(it)!! } + override fun queryAllSeatTypeByStudyRoomId(studyRoomId: UUID) = + queryFactory + .select(seatTypeJpaEntity).distinct() + .from(studyRoomJpaEntity) + .join(seatJpaEntity).on(studyRoomJpaEntity.id.eq(seatJpaEntity.studyRoom.id)) + .join(seatJpaEntity.type, seatTypeJpaEntity) + .where(studyRoomJpaEntity.id.eq(studyRoomId)) + .fetch() + .map { + seatTypeMapper.toDomain(it)!! + } + override fun existsSeatTypeByName(name: String) = seatTypeRepository.existsByName(name) override fun querySeatTypeById(seatTypeId: UUID) = seatTypeMapper.toDomain( From b58a80f7c986663995eeadf6b24b184a34eed5ba Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sun, 2 Apr 2023 16:15:13 +0900 Subject: [PATCH 10/14] test: (#414) createSeatTypeStub --- .../dms/domain/studyroom/stub/StudyRoomStub.kt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt b/dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt index 73fd47bcc..943eada46 100644 --- a/dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt +++ b/dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt @@ -1,13 +1,14 @@ package team.aliens.dms.domain.studyroom.stub +import java.time.LocalTime +import java.util.UUID import team.aliens.dms.domain.student.model.Sex import team.aliens.dms.domain.studyroom.model.Seat import team.aliens.dms.domain.studyroom.model.SeatApplication import team.aliens.dms.domain.studyroom.model.SeatStatus +import team.aliens.dms.domain.studyroom.model.SeatType import team.aliens.dms.domain.studyroom.model.StudyRoom import team.aliens.dms.domain.studyroom.model.TimeSlot -import java.time.LocalTime -import java.util.UUID internal fun createStudyRoomStub( id: UUID = UUID.randomUUID(), @@ -78,3 +79,15 @@ internal fun createSeatApplicationStub( timeSlotId = timeSlotId, studentId = studentId ) + +internal fun createSeatTypeStub( + id: UUID = UUID.randomUUID(), + schoolId: UUID = UUID.randomUUID(), + name: String = "자리", + color: String = "#FFFFFF", +) = SeatType( + id = id, + schoolId = schoolId, + name = name, + color = color +) \ No newline at end of file From 4b6e4ece216ff12f87ad83c2df04d843cb5eba6c Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sun, 2 Apr 2023 16:15:33 +0900 Subject: [PATCH 11/14] test: (#414) QuerySeatTypesUseCaseTests --- .../usecase/QuerySeatTypesUseCaseTests.kt | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCaseTests.kt diff --git a/dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCaseTests.kt b/dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCaseTests.kt new file mode 100644 index 000000000..d587d4a39 --- /dev/null +++ b/dms-application/src/test/kotlin/team/aliens/dms/domain/studyroom/usecase/QuerySeatTypesUseCaseTests.kt @@ -0,0 +1,88 @@ +package team.aliens.dms.domain.studyroom.usecase + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import java.util.UUID +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertAll +import org.junit.jupiter.api.assertThrows +import team.aliens.dms.domain.studyroom.spi.QuerySeatTypePort +import team.aliens.dms.domain.studyroom.spi.StudyRoomQueryUserPort +import team.aliens.dms.domain.studyroom.spi.StudyRoomSecurityPort +import team.aliens.dms.domain.studyroom.stub.createSeatTypeStub +import team.aliens.dms.domain.user.exception.UserNotFoundException +import team.aliens.dms.domain.user.stub.createUserStub + +class QuerySeatTypesUseCaseTests { + + private val securityPort: StudyRoomSecurityPort = mockk(relaxed = true) + private val queryUserPort: StudyRoomQueryUserPort = mockk(relaxed = true) + private val querySeatTypePort: QuerySeatTypePort = mockk(relaxed = true) + + private val querySeatTypesUseCase = QuerySeatTypesUseCase( + securityPort, queryUserPort, querySeatTypePort + ) + + private val userId = UUID.randomUUID() + private val schoolId = UUID.randomUUID() + private val studyRoomId = UUID.randomUUID() + + private val userStub by lazy { + createUserStub( + id = userId, + schoolId = schoolId + ) + } + + private val seatTypesStub by lazy { + listOf(createSeatTypeStub()) + } + + @Test + fun `자리 종류 조회 성공 (studyRoomId가 null인 경우)`() { + // given + every { securityPort.getCurrentUserId() } returns userId + every { queryUserPort.queryUserById(userId) } returns userStub + every { querySeatTypePort.queryAllSeatTypeBySchoolId(schoolId) } returns seatTypesStub + + // when + val response = querySeatTypesUseCase.execute(null) + + // then + assertAll( + { verify(exactly = 1) { querySeatTypePort.queryAllSeatTypeBySchoolId(schoolId) } }, + { assertEquals(response.types.size, seatTypesStub.size) } + ) + } + + @Test + fun `자리 종류 조회 성공 (studyRoomId가 null이 아닌 경우)`() { + // given + every { securityPort.getCurrentUserId() } returns userId + every { queryUserPort.queryUserById(userId) } returns userStub + every { querySeatTypePort.queryAllSeatTypeByStudyRoomId(studyRoomId) } returns seatTypesStub + + // when + val response = querySeatTypesUseCase.execute(studyRoomId) + + // then + assertAll( + { verify(exactly = 1) { querySeatTypePort.queryAllSeatTypeByStudyRoomId(studyRoomId) } }, + { assertEquals(response.types.size, seatTypesStub.size) } + ) + } + + @Test + fun `유저가 존재하지 않음`() { + // given + every { securityPort.getCurrentUserId() } returns userId + every { queryUserPort.queryUserById(userId) } returns null + + // when + assertThrows { + querySeatTypesUseCase.execute(null) + } + } +} \ No newline at end of file From ac21a46641298b3b40d491d3804b308f323dd316 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Sun, 2 Apr 2023 17:41:02 +0900 Subject: [PATCH 12/14] chore: (#414) required false --- .../team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt index 3e6978263..046192f51 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/studyroom/StudyRoomWebAdapter.kt @@ -101,7 +101,7 @@ class StudyRoomWebAdapter( } @GetMapping("/types") - fun getSeatTypes(@RequestParam(name = "study_room_id") studyRoomId: UUID?): QuerySeatTypesResponse { + fun getSeatTypes(@RequestParam(name = "study_room_id", required = false) studyRoomId: UUID?): QuerySeatTypesResponse { return querySeatTypesUseCase.execute(studyRoomId) } From 80b70096869ebd815cebfe32fbddb397e969fad2 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Mon, 3 Apr 2023 09:12:25 +0900 Subject: [PATCH 13/14] =?UTF-8?q?feat:=20(#416)=20=EA=B3=B5=EC=A7=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20id=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/domain/notice/dto/QueryNoticeDetailsResponse.kt | 2 ++ .../dms/domain/notice/usecase/QueryNoticeDetailsUseCase.kt | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/dto/QueryNoticeDetailsResponse.kt b/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/dto/QueryNoticeDetailsResponse.kt index 72f086bfe..c19593393 100644 --- a/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/dto/QueryNoticeDetailsResponse.kt +++ b/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/dto/QueryNoticeDetailsResponse.kt @@ -1,8 +1,10 @@ package team.aliens.dms.domain.notice.dto import java.time.LocalDateTime +import java.util.UUID data class QueryNoticeDetailsResponse( + val id: UUID, val title: String, val content: String, val createdAt: LocalDateTime diff --git a/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCase.kt b/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCase.kt index 8bd0ddfb4..8d8e21f71 100644 --- a/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCase.kt +++ b/dms-application/src/main/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCase.kt @@ -1,5 +1,6 @@ package team.aliens.dms.domain.notice.usecase +import java.util.UUID import team.aliens.dms.common.annotation.ReadOnlyUseCase import team.aliens.dms.domain.manager.exception.ManagerNotFoundException import team.aliens.dms.domain.notice.dto.QueryNoticeDetailsResponse @@ -9,7 +10,6 @@ import team.aliens.dms.domain.notice.spi.NoticeSecurityPort import team.aliens.dms.domain.notice.spi.QueryNoticePort import team.aliens.dms.domain.school.validateSameSchool import team.aliens.dms.domain.user.exception.UserNotFoundException -import java.util.UUID @ReadOnlyUseCase class QueryNoticeDetailsUseCase( @@ -28,6 +28,7 @@ class QueryNoticeDetailsUseCase( validateSameSchool(writer.schoolId, viewer.schoolId) return QueryNoticeDetailsResponse( + id = notice.id, title = notice.title, content = notice.content, createdAt = notice.createdAt!! From 271fac2109c6b13e96ca74bf7bbdd0c1eace2000 Mon Sep 17 00:00:00 2001 From: rlaisqls Date: Mon, 3 Apr 2023 09:33:02 +0900 Subject: [PATCH 14/14] =?UTF-8?q?test:=20(#416)=20id=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/domain/notice/usecase/QueryNoticeDetailsUseCaseTests.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/dms-application/src/test/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCaseTests.kt b/dms-application/src/test/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCaseTests.kt index 0a1f7b0e8..f0408e49f 100644 --- a/dms-application/src/test/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCaseTests.kt +++ b/dms-application/src/test/kotlin/team/aliens/dms/domain/notice/usecase/QueryNoticeDetailsUseCaseTests.kt @@ -70,6 +70,7 @@ class QueryNoticeDetailsUseCaseTests { private val queryNoticeDetailsResponseStub by lazy { QueryNoticeDetailsResponse( + id = noticeStub.id, title = noticeStub.title, content = noticeStub.content, createdAt = createdAt