Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ services:
image: ghcr.io/2024-ajouchong/2024-ajouchong/ajouchong:a9cab46
container_name: ajouchong-backend
environment:
SPRING_DATASOURCE_URL: ${SPRING_DATASOURCE_URL}
SPRING_DATASOURCE_URL: jdbc:postgresql://database:5432/ajouchong
SPRING_DATASOURCE_USERNAME: ${SPRING_DATASOURCE_USERNAME}
SPRING_DATASOURCE_PASSWORD: ${SPRING_DATASOURCE_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
DIR: ${DIR}
CLIENT_ID: ${CLIENT_ID}
CLIENT_SECRET: ${CLIENT_SECRET}
TOKEN_URI: ${TOKEN_URI}
RESOURCE_URI: ${RESOURCE_URI]
RESOURCE_URI: ${RESOURCE_URI}
URI: ${URI}
depends_on:
- database
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/ajouchong/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/favicon.ico", "/img/**").permitAll()
.requestMatchers("/api/admin").hasRole(MemberRole.ADMIN.name()) // ADMIN 권한 필요
.requestMatchers("/api/admin/**").hasRole(MemberRole.ADMIN.name()) // ADMIN 권한 필요
// .requestMatchers("/api/auth/profile").authenticated() // 인증 필요
.anyRequest().permitAll() // 그 외 요청 허용
);
Expand All @@ -60,7 +60,7 @@ public CorsConfigurationSource corsConfigurationSource() {
"https://admin.ajouchong.com"
));

configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setExposedHeaders(List.of("Authorization", "Set-Cookie")); // 쿠키 반환 허용
configuration.setAllowCredentials(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.ajouchong.controller.admin;

import com.ajouchong.common.ApiResponse;
import com.ajouchong.dto.request.PromotionPartnerRequestDto;
import com.ajouchong.dto.response.PromotionPartnerResponseDto;
import com.ajouchong.service.PromotionPartnerService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/admin/promotion")
@RequiredArgsConstructor
public class PromotionAdminController {

private final PromotionPartnerService promotionPartnerService;

@GetMapping
public ApiResponse<List<PromotionPartnerResponseDto>> getAllPromotionPartners() {
List<PromotionPartnerResponseDto> partners = promotionPartnerService.getAllPartnersForAdmin();
return new ApiResponse<>(1, "제휴 항목 목록 조회 성공", partners);
}

@PostMapping
public ApiResponse<PromotionPartnerResponseDto> createPromotionPartner(
@Valid @RequestBody PromotionPartnerRequestDto requestDto) {
PromotionPartnerResponseDto response = promotionPartnerService.createPartner(requestDto);
return new ApiResponse<>(1, "제휴 항목 생성 성공", response);
}

@PutMapping("/{id}")
public ApiResponse<PromotionPartnerResponseDto> updatePromotionPartner(
@PathVariable Long id,
@Valid @RequestBody PromotionPartnerRequestDto requestDto) {
PromotionPartnerResponseDto response = promotionPartnerService.updatePartner(id, requestDto);
return new ApiResponse<>(1, "제휴 항목 수정 성공", response);
}

@DeleteMapping("/{id}")
public ApiResponse<Void> deletePromotionPartner(@PathVariable Long id) {
promotionPartnerService.deletePartner(id);
return new ApiResponse<>(1, "제휴 항목 삭제 성공", null);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.ajouchong.controller.admin;

import com.ajouchong.common.ApiResponse;
import com.ajouchong.dto.request.RentalItemRequestDto;
import com.ajouchong.dto.request.RentalRecordCreateRequestDto;
import com.ajouchong.dto.request.RentalRecordReturnRequestDto;
import com.ajouchong.dto.response.RentalItemResponseDto;
import com.ajouchong.dto.response.RentalRecordResponseDto;
import com.ajouchong.service.RentalService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/admin/rental")
@RequiredArgsConstructor
public class RentalAdminController {

private final RentalService rentalService;

@GetMapping("/items")
public ApiResponse<List<RentalItemResponseDto>> getAllItems() {
return new ApiResponse<>(1, "대여 품목 목록 조회 성공", rentalService.getAllItemsForAdmin());
}

@PostMapping("/items")
public ApiResponse<RentalItemResponseDto> createItem(@Valid @RequestBody RentalItemRequestDto requestDto) {
return new ApiResponse<>(1, "대여 품목 등록 성공", rentalService.createItem(requestDto));
}

@PutMapping("/items/{id}")
public ApiResponse<RentalItemResponseDto> updateItem(
@PathVariable Long id,
@Valid @RequestBody RentalItemRequestDto requestDto) {
return new ApiResponse<>(1, "대여 품목 수정 성공", rentalService.updateItem(id, requestDto));
}

@DeleteMapping("/items/{id}")
public ApiResponse<Void> deleteItem(@PathVariable Long id) {
rentalService.deleteItem(id);
return new ApiResponse<>(1, "대여 품목 삭제 성공", null);
}

@PatchMapping("/items/{id}/quantity")
public ApiResponse<RentalItemResponseDto> adjustItemQuantity(
@PathVariable Long id,
@RequestParam Integer delta) {
return new ApiResponse<>(1, "현재 수량 조정 성공", rentalService.adjustCurrentQuantity(id, delta));
}

@PostMapping("/items/upload-image")
public ApiResponse<Map<String, String>> uploadItemImage(@RequestPart("file") MultipartFile file) {
String imageUrl = rentalService.uploadRentalItemImage(file);
return new ApiResponse<>(1, "이미지 업로드 성공", Map.of("imageUrl", imageUrl));
}

@GetMapping("/records")
public ApiResponse<List<RentalRecordResponseDto>> getAllRecords() {
return new ApiResponse<>(1, "대여 명부 조회 성공", rentalService.getAllRecordsForAdmin());
}

@PostMapping("/records")
public ApiResponse<RentalRecordResponseDto> createRecord(
@Valid @RequestBody RentalRecordCreateRequestDto requestDto) {
return new ApiResponse<>(1, "대여 기록 등록 성공", rentalService.createRecord(requestDto));
}

@PatchMapping("/records/{id}/return")
public ApiResponse<RentalRecordResponseDto> returnRecord(
@PathVariable Long id,
@Valid @RequestBody RentalRecordReturnRequestDto requestDto) {
return new ApiResponse<>(1, "반납 처리 성공", rentalService.markAsReturned(id, requestDto));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.ajouchong.controller.user;

import com.ajouchong.common.ApiResponse;
import com.ajouchong.dto.response.PromotionPartnerResponseDto;
import com.ajouchong.service.PromotionPartnerService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/promotion")
@RequiredArgsConstructor
public class PromotionUserController {

private final PromotionPartnerService promotionPartnerService;

@GetMapping
public ApiResponse<List<PromotionPartnerResponseDto>> getActivePromotionPartners() {
List<PromotionPartnerResponseDto> partners = promotionPartnerService.getActivePartners();
return new ApiResponse<>(1, "제휴 항목 조회 성공", partners);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.ajouchong.controller.user;

import com.ajouchong.common.ApiResponse;
import com.ajouchong.dto.response.RentalItemResponseDto;
import com.ajouchong.service.RentalService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/rental")
@RequiredArgsConstructor
public class RentalUserController {

private final RentalService rentalService;

@GetMapping("/items")
public ApiResponse<List<RentalItemResponseDto>> getRentalItems() {
return new ApiResponse<>(1, "대여 품목 조회 성공", rentalService.getActiveItems());
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.ajouchong.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

@Data
public class PromotionPartnerRequestDto {

@NotBlank(message = "업체명은 필수입니다.")
private String name;

@NotBlank(message = "카테고리는 필수입니다.")
private String category;

@NotBlank(message = "혜택 내용은 필수입니다.")
private String benefit;

@NotBlank(message = "위치는 필수입니다.")
private String location;

private String homepageUrl;
private String note;

@NotNull(message = "노출 순서는 필수입니다.")
private Integer displayOrder;

@NotNull(message = "활성 상태는 필수입니다.")
private Boolean active;
}

35 changes: 35 additions & 0 deletions src/main/java/com/ajouchong/dto/request/RentalItemRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.ajouchong.dto.request;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

@Data
public class RentalItemRequestDto {

@NotBlank(message = "품목명은 필수입니다.")
private String name;

@NotBlank(message = "카테고리는 필수입니다.")
private String category;

@NotNull(message = "총 수량은 필수입니다.")
@Min(value = 0, message = "총 수량은 0 이상이어야 합니다.")
private Integer totalQuantity;

@NotNull(message = "현재 수량은 필수입니다.")
@Min(value = 0, message = "현재 수량은 0 이상이어야 합니다.")
private Integer currentQuantity;

private String imageUrl;
private String note;

@NotNull(message = "노출 순서는 필수입니다.")
@Min(value = 1, message = "노출 순서는 1 이상이어야 합니다.")
private Integer displayOrder;

@NotNull(message = "활성 상태는 필수입니다.")
private Boolean active;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.ajouchong.dto.request;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

import java.time.LocalDate;

@Data
public class RentalRecordCreateRequestDto {

@NotNull(message = "대여 품목은 필수입니다.")
private Long rentalItemId;

@NotNull(message = "대여 수량은 필수입니다.")
@Min(value = 1, message = "대여 수량은 1 이상이어야 합니다.")
private Integer quantity;

@NotBlank(message = "담당자 이름은 필수입니다.")
private String managerName;

@NotNull(message = "대여 일자는 필수입니다.")
private LocalDate rentalDate;

@NotBlank(message = "대여자 이름은 필수입니다.")
private String borrowerName;

@NotBlank(message = "대여자 학과는 필수입니다.")
private String borrowerDepartment;

@NotBlank(message = "대여자 학번은 필수입니다.")
private String borrowerStudentId;

@NotBlank(message = "대여자 전화번호는 필수입니다.")
private String borrowerPhone;

@NotBlank(message = "손해 배상 동의 서명은 필수입니다.")
private String borrowerSignature;

private String note;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ajouchong.dto.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Data;

@Data
public class RentalRecordReturnRequestDto {

@NotBlank(message = "담당자 확인은 필수입니다.")
private String managerConfirmation;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.ajouchong.dto.response;

import lombok.Builder;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@Builder
public class PromotionPartnerResponseDto {
private Long id;
private String name;
private String category;
private String benefit;
private String location;
private String homepageUrl;
private String note;
private Integer displayOrder;
private Boolean active;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.ajouchong.dto.response;

import lombok.Builder;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@Builder
public class RentalItemResponseDto {
private Long id;
private String name;
private String category;
private Integer totalQuantity;
private Integer currentQuantity;
private String imageUrl;
private String note;
private Integer displayOrder;
private Boolean active;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}

Loading
Loading