Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
de77605
add/#12: 팀 entity 및 eum 파일 생성
EunHaSong May 13, 2026
783222f
chore/#12: entity 파일 포맷 수정
EunHaSong May 19, 2026
52c94e6
add/#12: 팀 service, controller 파일 생성
EunHaSong May 19, 2026
dd7f019
Merge branch 'main' into #12-teams/in-he
EunHaSong May 19, 2026
2123226
add/#12: entity 내 참조 id 추가
EunHaSong May 22, 2026
a018f8b
Merge remote-tracking branch 'origin/develop' into #12-teams/in-he
EunHaSong May 22, 2026
7ed3b4c
feat/#12: 팀 생성, 팀 조회, 팀 삭제 기능 구현
EunHaSong May 22, 2026
5ffa94c
Merge remote-tracking branch 'origin/develop' into #12-teams/in-he
EunHaSong May 22, 2026
cf36c27
fix/#12: Controller에 HttpStatus 값 body 추가
EunHaSong May 23, 2026
ecb0434
fix/#12: db 저장 이름 name 재지정 및 profile 사진 null값 허용
EunHaSong May 23, 2026
a41abec
fix/#12: BaseUpdatedTimeEntity로 createdAt, updatedAt 동시 지정
EunHaSong May 23, 2026
44db484
test/#12: team 관련 API 테스트를 위한 임시적 서버 접근 허용
EunHaSong May 23, 2026
c72d1b8
Merge branch 'develop' into #12-teams/in-he
EunHaSong May 24, 2026
9a5fa60
style/#12: team_name > name으로 지명 함수 변경
EunHaSong May 24, 2026
d94bc04
style/#12: BaseUpdatedTimeEntity() 적용
EunHaSong May 24, 2026
c2c7c25
style/#12: entity id 수정 및 update/delete 함수 추가
EunHaSong May 24, 2026
bea7734
feat/#12: 팀마다 권한/파트/링크 접근 Repository 추가
EunHaSong May 24, 2026
3475cff
style/#12: ENUM MANAGER 오타 수정
EunHaSong May 24, 2026
05ff93b
feat/#12: 팀 유저 ID 임시 연결 (이후, 모듈 수정 필요)
EunHaSong May 24, 2026
67a4b98
feat/#12: 팀 권한에 따라 삭제 및 수정 타당성 검증 로직 추가
EunHaSong May 24, 2026
56ef939
Feat/#12: 팀 상세조회 links, parts, memberCount 확인 로직 추가
EunHaSong May 24, 2026
fb28b2b
feat/#12: 팀 수정 시 변경된 사항 반영하는 조건 로직 추가
EunHaSong May 24, 2026
1381f4f
fix/#12: JPA Repository 코드 문제 해결을 위한 Repository/dto 간 타입 수정
EunHaSong May 25, 2026
f78ea49
feat/#12: team,user public key로 검색 및 활용
EunHaSong May 25, 2026
84336af
Style/#12: Link Response 방식 수정
EunHaSong May 25, 2026
607c7c6
feat/#12: 삭제된 팀을 찾을 수 없도록 처리함.
EunHaSong May 25, 2026
29f225f
feat/#12: 인증된 헤더 파라미터 숨기기
EunHaSong May 25, 2026
3f2e473
style/#12: @Repository 어노테이션 추가
EunHaSong May 27, 2026
50b744d
style/#12: Request/Response 카멜케이스로 수정
EunHaSong May 27, 2026
c07b861
style/#12: isNotChange 함수 형식 validate으로 통일
EunHaSong May 27, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class SecurityConfig(
.authorizeHttpRequests { auth ->
auth
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/teams/**").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.anyRequest().authenticated()
}
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/com/beat_it/global/error/ErrorCode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ enum class ErrorCode(
CALENDAR_START_TIME_REQUIRED(HttpStatus.BAD_REQUEST, "CALENDAR-008", "일정 시작 시각은 필수입니다."),
CALENDAR_END_TIME_REQUIRED(HttpStatus.BAD_REQUEST, "CALENDAR-009", "일정 종료 시각은 필수입니다."),

// --- 팀 관련 에러 (TEAM) ---
TEAM_NO_CONTENT_TO_UPDATE(HttpStatus.BAD_REQUEST, "TEAM-001", "팀에 대해 변경할 내용이 업습니다."),
TEAM_NO_PERMISSION(HttpStatus.FORBIDDEN, "TEAM-002", "팀 조회 권한이 없습니다."),
TEAM_NOT_FOUND(HttpStatus.NOT_FOUND, "TEAM-003", "팀을 찾을 수 없습니다."),
TEAM_NAME_REQUIRED(HttpStatus.BAD_REQUEST, "TEAM-004", "팀 이름은 필수입니다."),
TEAM_NAME_TOO_LONG(HttpStatus.BAD_REQUEST, "TEAM-005", "팀 이름은 100자 이하여야 합니다."),
TEAM_DESCRIPTION_TOO_LONG(HttpStatus.BAD_REQUEST, "TEAM-006", "팀 설명은 500자 이하여야 합니다."),
TEAM_NO_UPDATE_PERMISSION(HttpStatus.FORBIDDEN, "TEAM-007","팀 수정 권한이 없습니다."),


// --- 장소 관련 에러 ---
LOCATION_NOT_FOUND(HttpStatus.NOT_FOUND, "LOCATION-001", "장소를 찾을 수 없습니다."),

Expand Down
78 changes: 78 additions & 0 deletions src/main/kotlin/com/beat_it/team/controller/TeamController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.beat_it.team.controller

import com.beat_it.team.dto.TeamCreateRequest
import com.beat_it.team.dto.TeamCreateResponse
import com.beat_it.team.dto.TeamDetailResponse
import com.beat_it.team.dto.TeamDetailUpdateRequest
import com.beat_it.team.dto.TeamDetailUpdateResponse
import com.beat_it.team.service.TeamService
import com.beat_it.global.response.BasicResponse
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import java.util.UUID
import io.swagger.v3.oas.annotations.Parameter

@RestController
@RequestMapping("/teams")
class TeamController(
private val teamService: TeamService
) {

@PostMapping
fun createTeam(
@Parameter(hidden = true)
@RequestHeader("X-User-Public-Id") userPublicId: UUID,

@RequestBody request: TeamCreateRequest
): ResponseEntity<BasicResponse<TeamCreateResponse>> {

val responseData = teamService.createTeam(userPublicId, request)

return ResponseEntity
.status(HttpStatus.CREATED)
.body(BasicResponse.success(responseData, HttpStatus.CREATED, "팀 생성에 성공했습니다."))
}

@PatchMapping
fun updateTeamDetail(
@Parameter(hidden = true)
@RequestHeader("X-User-Public-Id") userPublicId: UUID,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

user id로 변경해주세요!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@AuthenticationPrincipal 어노테이션으로 JWT토큰 이용한 userId 가져오기 로직으로 해주세요!


@Parameter(hidden = true)
@RequestHeader("X-Team-Public-Id") teamPublicId: UUID,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

team id로 변경해주세요!


@RequestBody request: TeamDetailUpdateRequest,
): ResponseEntity<BasicResponse<TeamDetailUpdateResponse>> {
val responseData = teamService.updateTeamDetail(teamPublicId, userPublicId, request)
return ResponseEntity.ok(BasicResponse.success(responseData, HttpStatus.OK, "팀 상세 내용이 수정되었습니다."))
}

@DeleteMapping
fun deleteTeam(
@Parameter(hidden = true)
@RequestHeader("X-User-Public-Id") userPublicId: UUID,

@Parameter(hidden = true)
@RequestHeader("X-Team-Public-Id") teamPublicId: UUID,

): ResponseEntity<BasicResponse<Nothing>> {
teamService.deleteTeam(teamPublicId, userPublicId)
return ResponseEntity.ok(
BasicResponse.success(HttpStatus.OK,"팀이 성공적으로 삭제되었습니다.")
)
}

@GetMapping
fun getTeamDetail(
@Parameter(hidden = true)
@RequestHeader("X-Team-Public-Id") teamPublicId: UUID,

): ResponseEntity<BasicResponse<TeamDetailResponse>> {
val responseData = teamService.getTeamDetail(teamPublicId)
return ResponseEntity.ok(
BasicResponse.success(responseData, HttpStatus.OK,"팀 상세 내용 조회에 성공했습니다.")
)
}
}

15 changes: 15 additions & 0 deletions src/main/kotlin/com/beat_it/team/dto/TeamCreateRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.beat_it.team.dto

import com.beat_it.team.entity.enum.TeamType
import com.fasterxml.jackson.annotation.JsonProperty
import io.swagger.v3.oas.annotations.media.Schema
import java.time.LocalDate
import java.time.OffsetDateTime

data class TeamCreateRequest(
val teamName: String,
val description: String?,
val teamType: TeamType,
val establishedOn: LocalDate?,
val profileImageUrl: String?,
)
15 changes: 15 additions & 0 deletions src/main/kotlin/com/beat_it/team/dto/TeamCreateResponse.kt
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

JsonProperty로 invite_code 처럼 스네이크코드로 하면 responseBody를 스네이크코드로 받을텐데?!!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

아하 그러면 Response와 Request 모두 수정해둘게요!!

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.beat_it.team.dto

import com.beat_it.team.entity.enum.TeamType
import com.fasterxml.jackson.annotation.JsonProperty
import java.time.OffsetDateTime

data class TeamCreateResponse(
val teamId: Long,
val teamName: String,
val description: String?,
val inviteCode: String,
val teamType: TeamType,
val teamRole: String,
val createdAt: OffsetDateTime,
)
33 changes: 33 additions & 0 deletions src/main/kotlin/com/beat_it/team/dto/TeamDetailResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.beat_it.team.dto

import com.beat_it.team.entity.enum.PlatformCode
import java.time.LocalDate
import java.time.OffsetDateTime

data class TeamDetailResponse(
val teamId: Long? = null,
val profileImageUrl: String?,
val teamName: String,
val description: String?,
val establishedOn: LocalDate?,
val inviteCode: String,
val memberCount: Int,
val createdAt: OffsetDateTime,
val updatedAt: OffsetDateTime,
val links: List<LinksResponse>,
val parts: List<PartsResponse>,
val archiveCount: Int,
val cloudItemCount: Int,
)

data class LinksResponse(
val teamLinkId: Long,
val platformCode: PlatformCode,
val linkUrl: String,
)

data class PartsResponse(
val teamPartId: Long,
val partName: String,
val displayOrder: Int,
)
19 changes: 19 additions & 0 deletions src/main/kotlin/com/beat_it/team/dto/TeamDetailUpdateRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.beat_it.team.dto

import com.beat_it.team.entity.enum.PlatformCode
import com.beat_it.team.entity.enum.TeamType
import java.time.LocalDate

data class TeamDetailUpdateRequest(
val teamName: String? = null,
val description: String? = null,
val teamType: TeamType? = null,
val establishedOn: LocalDate? = null,
val profileImageUrl: String? = null,
val links: List<TeamLinksRequest>? = null,
)

data class TeamLinksRequest(
val platformCode: PlatformCode,
val linkUrl: String,
)
13 changes: 13 additions & 0 deletions src/main/kotlin/com/beat_it/team/dto/TeamDetailUpdateResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.beat_it.team.dto

import java.time.LocalDate
import java.time.OffsetDateTime

data class TeamDetailUpdateResponse(
val teamId: Long,
val teamName: String,
val description: String?,
val establishedOn: LocalDate?,
val updatedAt: OffsetDateTime,
val links: List<LinksResponse>? = null,
)
41 changes: 41 additions & 0 deletions src/main/kotlin/com/beat_it/team/entity/TeamLinks.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.beat_it.team.entity

import com.beat_it.global.entity.BaseUpdatedTimeEntity
import com.beat_it.team.entity.enum.PlatformCode
import com.beat_it.team.entity.enum.TeamRole
import io.swagger.v3.oas.annotations.links.Link
import jakarta.persistence.*
import java.time.OffsetDateTime

@Entity
@Table(name = "team_links")
class TeamLinks(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="team_link_id", nullable = false)
val teamLinkId: Long? = null,

//TODO: 팀 ID 연결하기
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id", nullable = false)
val team: Teams,

@Enumerated(EnumType.STRING)
@Column(name="platform_code",nullable = false)
var platformCode: PlatformCode = PlatformCode.CUSTOM,

@Column(name="link_url",nullable = false)
var linkUrl: String = "",

// @Column(name="update_at",nullable = false)
// var updateAt: OffsetDateTime = OffsetDateTime.now(),
//
// @Column(name="create_at",nullable = false)
// val createdAt: OffsetDateTime = OffsetDateTime.now(),

) : BaseUpdatedTimeEntity() {
fun updateLink(platformCode: PlatformCode, linkUrl: String) {
this.platformCode = platformCode
this.linkUrl = linkUrl
}
}
38 changes: 38 additions & 0 deletions src/main/kotlin/com/beat_it/team/entity/TeamMemberships.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.beat_it.team.entity

import com.beat_it.global.entity.BaseUpdatedTimeEntity
import com.beat_it.team.entity.enum.TeamRole
import jakarta.persistence.*
import java.time.OffsetDateTime

@Entity
@Table(name = "team_membership")
class TeamMemberships(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "team_membership_id")
val teamMembershipId: Long? = null,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id", nullable = false)
val team: Teams,

@Column(name = "user_id", nullable = false)
val userId: Long,

@Enumerated(EnumType.STRING)
@Column(name = "team_role", nullable = false)
var teamRole: TeamRole = TeamRole.MEMBER,

@Column(name = "left_at", nullable = true)
var leftAt: OffsetDateTime? = null,
) : BaseUpdatedTimeEntity() {

fun updateTeamRole(teamRole: TeamRole) {
this.teamRole = teamRole
}

fun leaveTeam() {
this.leftAt = OffsetDateTime.now()
}
}
50 changes: 50 additions & 0 deletions src/main/kotlin/com/beat_it/team/entity/TeamParts.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.beat_it.team.entity

import com.beat_it.global.entity.BaseUpdatedTimeEntity
import com.beat_it.team.entity.enum.TeamRole
import jakarta.persistence.*
import java.time.OffsetDateTime

@Entity
@Table(name = "team_parts")
class TeamParts(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="team_part_id", nullable = false)
val teamPartId: Long? = null,

//TODO: 팀 ID 연결하기
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id", nullable = false)
val team: Teams,

@Column(name="part_name", nullable = false)
var partName: String = "",

@Column(name="display_order", nullable = false)
var displayOrder: Int = 0,

@Column(name="is_active", nullable = false)
var isActive: Boolean = true,

// @Column(name="update_at", nullable = false)
// var updateAt: OffsetDateTime = OffsetDateTime.now(),
//
// @Column(name="create_at", nullable = false)
// val createdAt: OffsetDateTime = OffsetDateTime.now(),

) : BaseUpdatedTimeEntity() {
// TODO: 파트를 추가하는 함수를 넣어야 함.
fun updateTeamPart(
partName: String,
displayOrder: Int,
) {
this.partName = partName
this.displayOrder = displayOrder
}

fun deactivateTeamPart() {
this.isActive = false
}

}
27 changes: 27 additions & 0 deletions src/main/kotlin/com/beat_it/team/entity/TeamSettings.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.beat_it.team.entity

import jakarta.persistence.*
import java.time.OffsetDateTime

@Entity
@Table(name = "team_settings")
class TeamSettings(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="team_settings_id")
val teamSettingId: Long? = null,

//TODO: 팀 ID 연결하기
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id", nullable = false)
val team: Teams,

@Column(name="max_storage", nullable = false)
var maxStorage: Int = 10,

@Column(name="used_storage", nullable = false)
var usedStorage: Int = 0,

@Column(name="update_at", nullable = false)
var updateAt: OffsetDateTime = OffsetDateTime.now(),
)
Loading