Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.dreamteam.alter.adapter.inbound.general.file.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.dreamteam.alter.adapter.inbound.common.dto.CommonApiResponse;
import com.dreamteam.alter.adapter.inbound.common.dto.FilePresignedUrlResponseDto;
import com.dreamteam.alter.adapter.inbound.general.file.dto.AppUploadFileResponseDto;
import com.dreamteam.alter.application.aop.AppActionContext;
import com.dreamteam.alter.domain.file.port.inbound.AppDeleteFileUseCase;
import com.dreamteam.alter.domain.file.port.inbound.AppGetPresignedUrlUseCase;
import com.dreamteam.alter.domain.file.port.inbound.AppUploadFileUseCase;
import com.dreamteam.alter.domain.file.type.BucketType;
import com.dreamteam.alter.domain.file.type.FileTargetType;
import com.dreamteam.alter.domain.user.context.AppActor;

import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;


@RestController
@RequestMapping("/app/files")
@RequiredArgsConstructor
public class AppFileController implements AppFileControllerSpec {

@Resource(name = "appUploadFile")
private final AppUploadFileUseCase appUploadFile;

@Resource(name = "appGetPresignedUrl")
private final AppGetPresignedUrlUseCase appGetPresignedUrl;

@Resource(name = "appDeleteFile")
private final AppDeleteFileUseCase appDeleteFile;

@Override
@PostMapping
public ResponseEntity<CommonApiResponse<AppUploadFileResponseDto>> uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam("targetType") FileTargetType targetType,
@RequestParam("bucketType") BucketType bucketType
) {
AppActor actor = AppActionContext.getInstance().getActor();
return ResponseEntity.ok(CommonApiResponse.of(appUploadFile.execute(actor, file, targetType, bucketType)));
}

@Override
@GetMapping("/{fileId}/presigned-url")
public ResponseEntity<CommonApiResponse<FilePresignedUrlResponseDto>> getPresignedUrl(
@PathVariable String fileId
) {
AppActor actor = AppActionContext.getInstance().getActor();
return ResponseEntity.ok(CommonApiResponse.of(appGetPresignedUrl.execute(actor, fileId)));
}

@Override
@DeleteMapping("/{fileId}")
public ResponseEntity<CommonApiResponse<Void>> deleteFile(
@PathVariable String fileId
) {
AppActor actor = AppActionContext.getInstance().getActor();
appDeleteFile.execute(actor, fileId);
return ResponseEntity.ok(CommonApiResponse.empty());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.dreamteam.alter.adapter.inbound.general.file.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.dreamteam.alter.adapter.inbound.common.dto.CommonApiResponse;
import com.dreamteam.alter.adapter.inbound.common.dto.ErrorResponse;
import com.dreamteam.alter.adapter.inbound.common.dto.FilePresignedUrlResponseDto;
import com.dreamteam.alter.adapter.inbound.general.file.dto.AppUploadFileResponseDto;
import com.dreamteam.alter.domain.file.type.BucketType;
import com.dreamteam.alter.domain.file.type.FileTargetType;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;


@Tag(name = "APP - 파일 API")
public interface AppFileControllerSpec {

@Operation(summary = "파일 업로드", description = "파일을 S3에 업로드하고 PENDING 상태로 저장합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "파일 업로드 성공"),
@ApiResponse(responseCode = "400", description = "실패 케이스",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(name = "유효하지 않은 파일", value = "{\"code\" : \"B022\"}"),
@ExampleObject(name = "허용되지 않는 파일 형식", value = "{\"code\" : \"B023\"}"),
@ExampleObject(name = "파일 크기 초과", value = "{\"code\" : \"B024\"}")
}))
})
ResponseEntity<CommonApiResponse<AppUploadFileResponseDto>> uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam("targetType") FileTargetType targetType,
@RequestParam("bucketType") BucketType bucketType
);

@Operation(summary = "Presigned URL 조회", description = "본인이 업로드한 Private 파일 접근을 위한 Presigned URL을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Presigned URL 조회 성공"),
@ApiResponse(responseCode = "403", description = "권한 없음",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(name = "본인 파일 아님", value = "{\"code\" : \"A005\"}")
})),
@ApiResponse(responseCode = "404", description = "존재하지 않는 파일",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(name = "파일 없음", value = "{\"code\" : \"B021\"}")
}))
})
ResponseEntity<CommonApiResponse<FilePresignedUrlResponseDto>> getPresignedUrl(
@PathVariable String fileId
);

@Operation(summary = "파일 삭제", description = "본인이 업로드한 파일을 S3에서 삭제하고 DELETED 상태로 변경합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "파일 삭제 성공"),
@ApiResponse(responseCode = "403", description = "권한 없음",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(name = "본인 파일 아님", value = "{\"code\" : \"A005\"}")
})),
@ApiResponse(responseCode = "404", description = "존재하지 않는 파일",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(name = "파일 없음", value = "{\"code\" : \"B021\"}")
}))
})
ResponseEntity<CommonApiResponse<Void>> deleteFile(
@PathVariable String fileId
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.dreamteam.alter.adapter.inbound.general.file.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Schema(description = "파일 업로드 응답 DTO")
public class AppUploadFileResponseDto {

@Schema(description = "파일 ID", example = "01959b4e-4e5f-7c3a-8d9e-0f1a2b3c4d5e")
private String fileId;

public static AppUploadFileResponseDto of(String fileId) {
return new AppUploadFileResponseDto(fileId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.dreamteam.alter.adapter.inbound.general.workspace.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.dreamteam.alter.adapter.inbound.common.dto.CommonApiResponse;
import com.dreamteam.alter.adapter.inbound.general.workspace.dto.CreateWorkspaceRequestDto;
import com.dreamteam.alter.application.aop.AppActionContext;
import com.dreamteam.alter.domain.user.context.AppActor;
import com.dreamteam.alter.domain.workspace.port.inbound.CreateWorkspaceUseCase;

import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/app/workspaces")
@RequiredArgsConstructor
@Validated
public class UserWorkspaceController implements UserWorkspaceControllerSpec {

@Resource(name = "createWorkspace")
private final CreateWorkspaceUseCase createWorkspace;

@Override
@PostMapping
public ResponseEntity<CommonApiResponse<Void>> createWorkspace(
@RequestBody @Valid CreateWorkspaceRequestDto request
) {
AppActor actor = AppActionContext.getInstance().getActor();
createWorkspace.execute(actor, request);
return ResponseEntity.ok(CommonApiResponse.empty());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.dreamteam.alter.adapter.inbound.general.workspace.controller;

import com.dreamteam.alter.adapter.inbound.common.dto.CommonApiResponse;
import com.dreamteam.alter.adapter.inbound.general.workspace.dto.CreateWorkspaceRequestDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;

@Tag(name = "APP - 업장 API")
public interface UserWorkspaceControllerSpec {

@Operation(summary = "업장 등록 신청")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "업장 등록 신청 성공"),
@ApiResponse(responseCode = "400", description = "유효하지 않은 파일입니다. (INVALID_FILE)"),
@ApiResponse(responseCode = "403", description = "접근 권한이 없습니다. (FORBIDDEN)"),
@ApiResponse(responseCode = "404", description = "존재하지 않는 파일입니다. (FILE_NOT_FOUND)"),
@ApiResponse(responseCode = "409", description = "이미 연결된 파일입니다. (FILE_ALREADY_ATTACHED)")
})
ResponseEntity<CommonApiResponse<Void>> createWorkspace(
@RequestBody @Valid CreateWorkspaceRequestDto request
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.dreamteam.alter.adapter.inbound.general.workspace.dto;

import java.math.BigDecimal;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "업장 등록 신청 DTO")
public class CreateWorkspaceRequestDto {

@NotBlank
@Schema(description = "업장 이름", example = "세븐일레븐")
private String bizName;

@NotBlank
@Schema(description = "사업자 등록번호", example = "123-45-12345")
private String brn;

@NotBlank
@Schema(description = "풀주소", example = "서울특별시 구로구 고척동 123")
private String address;

@NotBlank
@Schema(description = "시/도", example = "서울특별시")
private String province;

@NotBlank
@Schema(description = "구", example = "구로구")
private String district;

@NotBlank
@Schema(description = "동", example = "고척동")
private String town;

@NotNull
@Schema(description = "위도", example = "35.150485")
private BigDecimal latitude;

@NotNull
@Schema(description = "경도", example = "129.115717")
private BigDecimal longitude;

@NotBlank
@Schema(description = "업장 형태", example = "음식점")
private String type;

@NotBlank
@Schema(description = "업장 연락처", example = "02-1234-5678")
private String contact;

@NotBlank
@Schema(description = "사업자등록증명원 파일 ID", example = "01959b4e-4e5f-7c3a-8d9e-0f1a2b3c4d5e")
private String workspaceCertFileId;

@NotBlank
@Schema(description = "대표자 신분증 사본 파일 ID", example = "01959b4e-4e5f-7c3a-8d9e-0f1a2b3c4d5e")
private String workspaceOwnIdentityFileId;

@Schema(description = "위임 확인서 파일 ID", example = "01959b4e-4e5f-7c3a-8d9e-0f1a2b3c4d5e")
private String workspaceWarrantFileId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.dreamteam.alter.adapter.inbound.manager.workspace.controller;

import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.dreamteam.alter.adapter.inbound.common.dto.CommonApiResponse;
import com.dreamteam.alter.adapter.inbound.manager.workspace.dto.CreateWorkspaceReasonCommentRequestDto;
import com.dreamteam.alter.adapter.inbound.manager.workspace.dto.WorkspaceReasonCommentResponseDto;
import com.dreamteam.alter.application.aop.ManagerActionContext;
import com.dreamteam.alter.domain.user.context.ManagerActor;
import com.dreamteam.alter.domain.workspace.port.inbound.CreateWorkspaceReasonCommentUseCase;
import com.dreamteam.alter.domain.workspace.port.inbound.GetWorkspaceReasonCommentsUseCase;

import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/manager/workspaces/{workspaceId}/reasons/{reasonId}/comments")
@PreAuthorize("hasAnyRole('MANAGER')")
@RequiredArgsConstructor
@Validated
public class ManagerWorkspaceReasonCommentController implements ManagerWorkspaceReasonCommentControllerSpec {

@Resource(name = "createWorkspaceReasonComment")
private final CreateWorkspaceReasonCommentUseCase createWorkspaceReasonComment;

@Resource(name = "getWorkspaceReasonComments")
private final GetWorkspaceReasonCommentsUseCase getWorkspaceReasonComments;

@Override
@PostMapping
public ResponseEntity<CommonApiResponse<Void>> createWorkspaceReasonComment(
@PathVariable Long workspaceId,
@PathVariable Long reasonId,
@Valid @RequestBody CreateWorkspaceReasonCommentRequestDto request
) {
ManagerActor actor = ManagerActionContext.getInstance().getActor();
createWorkspaceReasonComment.execute(actor, workspaceId, reasonId, request);
return ResponseEntity.ok(CommonApiResponse.empty());
}

@Override
@GetMapping
public ResponseEntity<CommonApiResponse<List<WorkspaceReasonCommentResponseDto>>> getWorkspaceReasonComments(
@PathVariable Long workspaceId,
@PathVariable Long reasonId
) {
ManagerActor actor = ManagerActionContext.getInstance().getActor();
return ResponseEntity.ok(CommonApiResponse.of(getWorkspaceReasonComments.execute(actor, workspaceId, reasonId)));
}

}
Loading
Loading