Skip to content

Commit 3ce37d8

Browse files
committed
feat: 자격증 제출 API
1 parent 0c38f98 commit 3ce37d8

File tree

11 files changed

+178
-1
lines changed

11 files changed

+178
-1
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package kgu.developers.api.certificate.presentation;
2+
3+
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
4+
5+
import org.springframework.http.ResponseEntity;
6+
import org.springframework.web.bind.annotation.RequestPart;
7+
import org.springframework.web.multipart.MultipartFile;
8+
9+
import io.swagger.v3.oas.annotations.Operation;
10+
import io.swagger.v3.oas.annotations.Parameter;
11+
import io.swagger.v3.oas.annotations.media.Content;
12+
import io.swagger.v3.oas.annotations.media.Schema;
13+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
14+
import io.swagger.v3.oas.annotations.tags.Tag;
15+
import kgu.developers.api.certificate.presentation.request.CertificateSubmitRequest;
16+
import kgu.developers.api.certificate.presentation.response.CertificatePersistResponse;
17+
18+
@Tag(name = "Certificate", description = "자격증 관련 API")
19+
public interface CertificateController {
20+
21+
@Operation(
22+
summary = "자격증 파일 제출 API", description = """
23+
- Description : 이 API는 자격증 파일을 제출합니다.
24+
- Assignee : 이한음
25+
"""
26+
)
27+
@ApiResponse(
28+
responseCode = "201", content = @Content(schema = @Schema(implementation = CertificatePersistResponse.class))
29+
)
30+
ResponseEntity<CertificatePersistResponse> submitCertificateAndSaveFile(
31+
@Parameter(
32+
description = "자격증 첨부 파일",
33+
content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE),
34+
required = true
35+
) @RequestPart(value = "file") MultipartFile file,
36+
@RequestPart CertificateSubmitRequest request
37+
);
38+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package kgu.developers.api.certificate.presentation;
2+
3+
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
4+
5+
import org.springframework.http.ResponseEntity;
6+
import org.springframework.web.bind.annotation.PostMapping;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RequestPart;
9+
import org.springframework.web.bind.annotation.RestController;
10+
import org.springframework.web.multipart.MultipartFile;
11+
12+
import kgu.developers.api.certificate.presentation.request.CertificateSubmitRequest;
13+
import kgu.developers.api.certificate.presentation.response.CertificatePersistResponse;
14+
import kgu.developers.domain.certificate.application.command.CertificateCommandService;
15+
import lombok.RequiredArgsConstructor;
16+
17+
@RestController
18+
@RequestMapping("/api/v1/certificate")
19+
@RequiredArgsConstructor
20+
public class CertificateControllerImpl implements CertificateController {
21+
private final CertificateCommandService certificateCommandService;
22+
23+
@Override
24+
@PostMapping(consumes = MULTIPART_FORM_DATA_VALUE)
25+
public ResponseEntity<CertificatePersistResponse> submitCertificateAndSaveFile(
26+
@RequestPart(value = "file") MultipartFile file,
27+
@RequestPart CertificateSubmitRequest request
28+
) {
29+
Long id = certificateCommandService.submitCertificate(file, request.scheduleId());
30+
return ResponseEntity.ok(
31+
CertificatePersistResponse.of(id)
32+
);
33+
}
34+
35+
36+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package kgu.developers.api.certificate.presentation.request;
2+
3+
public record CertificateSubmitRequest(
4+
Long scheduleId
5+
) {
6+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package kgu.developers.api.certificate.presentation.response;
2+
3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
4+
5+
import io.swagger.v3.oas.annotations.media.Schema;
6+
import lombok.Builder;
7+
8+
@Builder
9+
public record CertificatePersistResponse(
10+
@Schema(description = "자격증 객체 id", example = "1", requiredMode = REQUIRED)
11+
Long id
12+
) {
13+
public static CertificatePersistResponse of(Long id) {
14+
return CertificatePersistResponse.builder().id(id).build();
15+
}
16+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package kgu.developers.domain.certificate.application.command;
2+
3+
import org.springframework.stereotype.Service;
4+
import org.springframework.web.multipart.MultipartFile;
5+
6+
import kgu.developers.domain.certificate.domain.Certificate;
7+
import kgu.developers.domain.certificate.domain.CertificateRepository;
8+
import kgu.developers.domain.file.application.command.FileCommandService;
9+
import kgu.developers.domain.file.domain.FileDomain;
10+
import kgu.developers.domain.file.infrastructure.repository.FileStorageService;
11+
import kgu.developers.domain.schedule.application.query.ScheduleQueryService;
12+
import lombok.RequiredArgsConstructor;
13+
14+
@Service
15+
@RequiredArgsConstructor
16+
public class CertificateCommandService {
17+
private final CertificateRepository certificateRepository;
18+
private final FileStorageService fileStorageService;
19+
private final FileCommandService fileCommandService;
20+
private final ScheduleQueryService scheduleQueryService;
21+
22+
public Long submitCertificate(MultipartFile file, Long scheduleId) {
23+
String storedPath = fileStorageService.store(file, FileDomain.CERTIFICATE);
24+
Long fileId = fileCommandService.saveFile(file, storedPath).getId();
25+
scheduleQueryService.checkExistsOrThrow(scheduleId);
26+
27+
Certificate certificate = Certificate.create(scheduleId, fileId);
28+
return certificateRepository.save(certificate);
29+
}
30+
31+
}

aics-domain/src/main/java/kgu/developers/domain/certificate/domain/Certificate.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
import java.time.LocalDateTime;
44

55
import lombok.AccessLevel;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Builder;
68
import lombok.Getter;
79
import lombok.NoArgsConstructor;
810

11+
@Builder
912
@Getter
1013
@NoArgsConstructor(access = AccessLevel.PRIVATE)
14+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
1115
public class Certificate {
1216
private Long id;
1317
private Long scheduleId;
@@ -17,6 +21,17 @@ public class Certificate {
1721
private LocalDateTime updatedAt;
1822
private LocalDateTime deletedAt;
1923

24+
public static Certificate create(
25+
Long scheduleId,
26+
Long certificateFileId
27+
) {
28+
return Certificate.builder()
29+
.scheduleId(scheduleId)
30+
.certificateFileId(certificateFileId)
31+
.approval(false)
32+
.build();
33+
}
34+
2035
public static Certificate of(
2136
Long id,
2237
Long scheduleId,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package kgu.developers.domain.certificate.domain;
2+
3+
public interface CertificateRepository {
4+
Long save(Certificate certificate);
5+
}

aics-domain/src/main/java/kgu/developers/domain/certificate/infrastructure/entity/CertificateJpaEntity.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
import kgu.developers.domain.certificate.domain.Certificate;
1515
import lombok.AllArgsConstructor;
1616
import lombok.Builder;
17+
import lombok.Getter;
1718
import lombok.NoArgsConstructor;
1819

20+
@Getter
1921
@Builder
2022
@Entity
2123
@Table(
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package kgu.developers.domain.certificate.infrastructure.repository;
2+
3+
import org.springframework.stereotype.Repository;
4+
5+
import kgu.developers.domain.certificate.domain.Certificate;
6+
import kgu.developers.domain.certificate.domain.CertificateRepository;
7+
import kgu.developers.domain.certificate.infrastructure.entity.CertificateJpaEntity;
8+
import lombok.RequiredArgsConstructor;
9+
10+
@Repository
11+
@RequiredArgsConstructor
12+
public class CertificateRepositoryImpl implements CertificateRepository {
13+
private final JpaCertificateRepository jpaCertificateRepository;
14+
15+
@Override
16+
public Long save(Certificate certificate) {
17+
return jpaCertificateRepository.save(CertificateJpaEntity.toEntity(certificate)).getId();
18+
}
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package kgu.developers.domain.certificate.infrastructure.repository;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
5+
import kgu.developers.domain.certificate.infrastructure.entity.CertificateJpaEntity;
6+
7+
public interface JpaCertificateRepository extends JpaRepository<CertificateJpaEntity, Long> {
8+
}

0 commit comments

Comments
 (0)