Skip to content

Commit 920500b

Browse files
authored
Merge pull request #169 from Kusitms32th-KuCheck/dev
메인 1차 배포
2 parents 3fe0bd8 + 2c7c0bf commit 920500b

226 files changed

Lines changed: 11067 additions & 330 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/deploy.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,17 @@ jobs:
4646
env:
4747
APPLICATION_PROPERTIES: ${{ secrets.ONKU_APP_DEV_YML }}
4848
TEST_APPLICATION_PROPERTIES: ${{ secrets.ONKU_APP_TEST_YML }}
49+
FCM_JSON: ${{ secrets.ONKU_FCM_JSON }}
4950

5051
run: |
5152
cd ./src
5253
rm -rf main/resources/application.yml
5354
mkdir -p main/resources
5455
mkdir -p test/resources
56+
mkdir -p main/resources/firebase
5557
echo "$APPLICATION_PROPERTIES" > main/resources/application.yml
5658
echo "$TEST_APPLICATION_PROPERTIES" > test/resources/application.yml
59+
echo "$FCM_JSON" > main/resources/firebase/fcm.json
5760
5861
- name: gradlew 권한 부여
5962
run: chmod +x gradlew
@@ -126,14 +129,17 @@ jobs:
126129
env:
127130
APPLICATION_PROPERTIES: ${{ secrets.ONKU_APP_PROD_YML }}
128131
TEST_APPLICATION_PROPERTIES: ${{ secrets.ONKU_APP_TEST_YML }}
132+
FCM_JSON: ${{ secrets.ONKU_FCM_JSON }}
129133

130134
run: |
131135
cd ./src
132136
rm -rf main/resources/application.yml
133137
mkdir -p main/resources
134138
mkdir -p test/resources
139+
mkdir -p main/resources/firebase
135140
echo "$APPLICATION_PROPERTIES" > main/resources/application.yml
136141
echo "$TEST_APPLICATION_PROPERTIES" > test/resources/application.yml
142+
echo "$FCM_JSON" > main/resources/firebase/fcm.json
137143
138144
- name: gradlew 권한 부여
139145
run: chmod +x gradlew
@@ -186,4 +192,4 @@ jobs:
186192
export REDIS_PASSWORD=${{ secrets.PROD_REDIS_PASSWORD }}
187193
export GITHUB_SHA=${{ github.sha }}
188194
sudo chmod +x ./deploy.sh
189-
./deploy.sh
195+
./deploy.sh

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,5 @@ out/
4141

4242
### YAML ###
4343
application.yml
44-
src/main/resources/*
44+
#src/main/resources/*
45+
src/main/resources/firebase/*

build.gradle.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
kotlin("jvm") version "1.9.25"
33
kotlin("plugin.spring") version "1.9.25"
4+
kotlin("plugin.serialization") version "2.1.0"
45
id("org.springframework.boot") version "3.5.6"
56
id("io.spring.dependency-management") version "1.1.7"
67
kotlin("plugin.jpa") version "1.9.25"
@@ -45,6 +46,15 @@ dependencies {
4546
implementation("software.amazon.awssdk:s3:2.25.34")
4647
implementation("software.amazon.awssdk:auth:2.25.34")
4748
implementation("software.amazon.awssdk:regions:2.25.34")
49+
implementation("software.amazon.awssdk:url-connection-client:2.25.30")
50+
//serializable
51+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")
52+
//okhttp3
53+
implementation("com.squareup.okhttp3:okhttp:4.12.0")
54+
//google auth
55+
implementation("com.google.auth:google-auth-library-oauth2-http:1.33.1")
56+
//test
57+
testImplementation("io.mockk:mockk:1.13.5")
4858
}
4959

5060
kotlin {
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package onku.backend.domain.absence
2+
3+
import jakarta.persistence.*
4+
import onku.backend.domain.absence.dto.request.SubmitAbsenceReportRequest
5+
import onku.backend.domain.absence.enums.AbsenceReportApproval
6+
import onku.backend.domain.absence.enums.AbsenceApprovedType
7+
import onku.backend.domain.absence.enums.AbsenceSubmitType
8+
import onku.backend.domain.member.Member
9+
import onku.backend.domain.session.Session
10+
import onku.backend.global.entity.BaseEntity
11+
import java.time.LocalDateTime
12+
13+
@Entity
14+
@Table(
15+
name = "absence_report",
16+
uniqueConstraints = [
17+
UniqueConstraint(
18+
name = "uk_absence_member_session",
19+
columnNames = ["member_id", "session_id"]
20+
)
21+
]
22+
)
23+
class AbsenceReport(
24+
@Id
25+
@GeneratedValue(strategy = GenerationType.IDENTITY)
26+
@Column(name = "absence_report_id")
27+
val id: Long? = null,
28+
29+
@ManyToOne(fetch = FetchType.LAZY)
30+
@JoinColumn(name = "session_id")
31+
var session : Session,
32+
33+
@ManyToOne(fetch = FetchType.LAZY)
34+
@JoinColumn(name = "member_id")
35+
val member : Member,
36+
37+
@Column(name = "url")
38+
var url : String,
39+
40+
@Column(name = "submit_type")
41+
@Enumerated(EnumType.STRING) // 사용자가 제출한 사유서 type
42+
var submitType : AbsenceSubmitType = AbsenceSubmitType.ABSENT,
43+
44+
@Column(name = "approved_type")
45+
@Enumerated(EnumType.STRING) // 운영진이 승인한 사유서 type
46+
var approvedType: AbsenceApprovedType = AbsenceApprovedType.ABSENT,
47+
48+
@Column(name = "reason")
49+
var reason : String,
50+
51+
@Column(name = "approval")
52+
@Enumerated(EnumType.STRING)
53+
var approval : AbsenceReportApproval,
54+
55+
@Column(name = "lateDateTime")
56+
var lateDateTime: LocalDateTime?,
57+
58+
@Column(name = "leaveDateTime")
59+
var leaveDateTime: LocalDateTime?
60+
) : BaseEntity() {
61+
companion object {
62+
fun createAbsenceReport(
63+
member: Member,
64+
session : Session,
65+
submitAbsenceReportRequest: SubmitAbsenceReportRequest,
66+
fileKey : String,
67+
): AbsenceReport {
68+
return AbsenceReport(
69+
member = member,
70+
session = session,
71+
url = fileKey,
72+
submitType = submitAbsenceReportRequest.submitType,
73+
approvedType = AbsenceApprovedType.ABSENT,
74+
reason = submitAbsenceReportRequest.reason,
75+
approval = AbsenceReportApproval.SUBMIT,
76+
leaveDateTime = submitAbsenceReportRequest.leaveDateTime,
77+
lateDateTime = submitAbsenceReportRequest.lateDateTime
78+
)
79+
}
80+
}
81+
82+
fun updateAbsenceReport(
83+
submitAbsenceReportRequest: SubmitAbsenceReportRequest,
84+
fileKey: String,
85+
session: Session
86+
) {
87+
this.session = session
88+
this.reason = submitAbsenceReportRequest.reason
89+
this.url = fileKey
90+
this.submitType = submitAbsenceReportRequest.submitType
91+
this.updatedAt = LocalDateTime.now()
92+
this.leaveDateTime = submitAbsenceReportRequest.leaveDateTime
93+
this.lateDateTime = submitAbsenceReportRequest.lateDateTime
94+
}
95+
96+
fun updateApprovedType(
97+
approvedType: AbsenceApprovedType
98+
) {
99+
this.approvedType = approvedType;
100+
}
101+
102+
fun updateApproval(
103+
approval: AbsenceReportApproval
104+
) {
105+
this.approval = approval
106+
}
107+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package onku.backend.domain.absence
2+
3+
import onku.backend.global.exception.ApiErrorCode
4+
import org.springframework.http.HttpStatus
5+
6+
enum class AbsenceReportErrorCode(
7+
override val errorCode: String,
8+
override val message: String,
9+
override val status: HttpStatus
10+
) : ApiErrorCode {
11+
ABSENCE_REPORT_NOT_FOUND("ABSENCE404", "해당하는 불참사유서를 찾을 수 없습니다.", HttpStatus.NOT_FOUND),
12+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package onku.backend.domain.absence.controller.manager
2+
3+
import io.swagger.v3.oas.annotations.Operation
4+
import io.swagger.v3.oas.annotations.tags.Tag
5+
import onku.backend.domain.absence.dto.request.EstimateAbsenceReportRequest
6+
import onku.backend.domain.absence.dto.response.GetMemberAbsenceReportResponse
7+
import onku.backend.domain.absence.facade.AbsenceFacade
8+
import onku.backend.global.response.SuccessResponse
9+
import org.springframework.http.ResponseEntity
10+
import org.springframework.web.bind.annotation.*
11+
12+
@RestController
13+
@RequestMapping("/api/v1/absence/manage")
14+
@Tag(name = "[관리자용] 불참사유서 관련 API")
15+
class AbsenceManagerController(
16+
private val absenceFacade : AbsenceFacade
17+
) {
18+
@GetMapping("/{sessionId}")
19+
@Operation(summary = "세션 별 불참 사유서 제출내역 조회", description = "세션 별로 학회원들이 낸 불참사유서 내역을 조회합니다.")
20+
fun getMemberAbsenceReports(@PathVariable(name = "sessionId") sessionId: Long)
21+
: ResponseEntity<SuccessResponse<List<GetMemberAbsenceReportResponse>>> {
22+
return ResponseEntity.ok(SuccessResponse.ok(absenceFacade.getMemberAbsenceReport(sessionId)))
23+
}
24+
25+
@PatchMapping("/{absenceReportId}")
26+
@Operation(summary = "불참 사유서 벌점 매기기", description = "제출한 불참 사유서에 대해서 벌점을 매긴다.")
27+
fun estimateAbsenceReport(@PathVariable(name = "absenceReportId") absenceReportId : Long,
28+
@RequestBody estimateAbsenceReportRequest: EstimateAbsenceReportRequest)
29+
: ResponseEntity<SuccessResponse<Boolean>> {
30+
return ResponseEntity.ok(SuccessResponse.ok(absenceFacade.estimateAbsenceReport(absenceReportId, estimateAbsenceReportRequest)))
31+
}
32+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package onku.backend.domain.absence.controller.user
2+
3+
import io.swagger.v3.oas.annotations.Operation
4+
import io.swagger.v3.oas.annotations.tags.Tag
5+
import jakarta.validation.Valid
6+
import onku.backend.domain.absence.dto.request.SubmitAbsenceReportRequest
7+
import onku.backend.domain.absence.dto.response.GetMyAbsenceReportResponse
8+
import onku.backend.domain.absence.facade.AbsenceFacade
9+
import onku.backend.domain.member.Member
10+
import onku.backend.global.annotation.CurrentMember
11+
import onku.backend.global.response.SuccessResponse
12+
import onku.backend.global.s3.dto.GetPreSignedUrlDto
13+
import org.springframework.http.ResponseEntity
14+
import org.springframework.web.bind.annotation.*
15+
16+
@RestController
17+
@RequestMapping("/api/v1/absence")
18+
@Tag(name = "불참사유서 관련 API")
19+
class AbsenceController(
20+
private val absenceFacade : AbsenceFacade
21+
) {
22+
@PostMapping("")
23+
@Operation(summary = "불참 사유서 제출", description = "불참 사유서 제출하는 API 입니다")
24+
fun submitAbsenceReport(@CurrentMember member: Member,
25+
@RequestBody @Valid submitAbsenceReportRequest: SubmitAbsenceReportRequest): ResponseEntity<SuccessResponse<GetPreSignedUrlDto>> {
26+
return ResponseEntity.ok(SuccessResponse.ok(absenceFacade.submitAbsenceReport(member, submitAbsenceReportRequest)))
27+
}
28+
29+
@GetMapping("")
30+
@Operation(summary = "불참 사유서 제출내역 조회", description = "내가 낸 불참 사유서 제출내역을 조회합니다.")
31+
fun getMyAbsenceReport(@CurrentMember member: Member)
32+
: ResponseEntity<SuccessResponse<List<GetMyAbsenceReportResponse>>> {
33+
return ResponseEntity.ok(SuccessResponse.ok(absenceFacade.getMyAbsenceReport(member)))
34+
}
35+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package onku.backend.domain.absence.dto.annotation
2+
3+
import jakarta.validation.Constraint
4+
import jakarta.validation.Payload
5+
import onku.backend.domain.absence.validator.AbsenceReportValidator
6+
import kotlin.reflect.KClass
7+
8+
@Target(AnnotationTarget.CLASS)
9+
@Retention(AnnotationRetention.RUNTIME)
10+
@Constraint(validatedBy = [AbsenceReportValidator::class])
11+
annotation class ValidAbsenceReport(
12+
val message: String = "Invalid absence report combination",
13+
val groups: Array<KClass<*>> = [],
14+
val payload: Array<KClass<out Payload>> = []
15+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package onku.backend.domain.absence.dto.request
2+
3+
import io.swagger.v3.oas.annotations.media.Schema
4+
import onku.backend.domain.absence.enums.AbsenceApprovedType
5+
6+
data class EstimateAbsenceReportRequest(
7+
@Schema(description = "승인 타입", example = "EXCUSED / ABSENT / ABSENT_WITH_DOC / ABSENT_WITH_CAUSE / LATE / EARLY_LEAVE")
8+
val approvedType: AbsenceApprovedType
9+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package onku.backend.domain.absence.dto.request
2+
3+
import jakarta.validation.constraints.NotNull
4+
import onku.backend.domain.absence.dto.annotation.ValidAbsenceReport
5+
import onku.backend.domain.absence.enums.AbsenceSubmitType
6+
import java.time.LocalDateTime
7+
@ValidAbsenceReport
8+
data class SubmitAbsenceReportRequest(
9+
val absenceReportId : Long?,
10+
@field:NotNull val sessionId : Long,
11+
val submitType : AbsenceSubmitType,
12+
val reason : String,
13+
val fileName : String?,
14+
val lateDateTime : LocalDateTime?,
15+
val leaveDateTime : LocalDateTime?
16+
)

0 commit comments

Comments
 (0)