Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.assu.server.domain.common.enums;

public enum ActivationStatus {
ACTIVE, INACTIVE, SUSPEND
ACTIVE, INACTIVE, SUSPEND, BLANK
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ public List<MapResponseDTO.StoreMapResponseDTO> getStores(MapRequestDTO.ViewOnMa
boolean hasPartner = (s.getPartner() != null);

PaperContent content = paperContentRepository.findTopByPaperStoreIdOrderByIdDesc(s.getId())
.orElseThrow(
() -> new GeneralException(ErrorStatus.NO_SUCH_CONTENT)
);
.orElseThrow(() -> new GeneralException(ErrorStatus.NO_SUCH_CONTENT));

String key = (s.getPartner() != null) ? s.getPartner().getMember().getProfileUrl() : null;
String url = amazonS3Manager.generatePresignedUrl(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,16 @@ public ResponseEntity<BaseResponse<Void>> finalPartnershipRequest(
return ResponseEntity.ok(BaseResponse.onSuccess(SuccessStatus.USER_PAPER_REQUEST_SUCCESS, null));
}


@PatchMapping("/proposal")
@Operation(
summary = "제휴 제안서 작성 API",
summary = "제휴 제안서 내용 수정 API",
description = "제공 서비스 종류(SERVICE, DISCOUNT), 서비스 제공 기준(PRICE, HEADCOUNT), 서비스 제공 항목, 카테고리, 할인율을 상황에 맞게 작성해주세요."
)
@PostMapping("/proposal")
public BaseResponse<PartnershipResponseDTO.WritePartnershipResponseDTO> writePartnership(
public BaseResponse<PartnershipResponseDTO.WritePartnershipResponseDTO> updatePartnership(
@RequestBody PartnershipRequestDTO.WritePartnershipRequestDTO request,
@AuthenticationPrincipal PrincipalDetails pd
){
Long memberId = pd.getMember().getId();
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.writePartnershipAsPartner(request, memberId));
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.updatePartnership(request, pd.getId()));
}

@Operation(
Expand All @@ -80,8 +78,7 @@ public BaseResponse<PartnershipResponseDTO.ManualPartnershipResponseDTO> createM
MultipartFile contractImage,
@AuthenticationPrincipal PrincipalDetails pd
) {
Long memberId = pd.getMember().getId();
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.createManualPartnership(request, memberId, contractImage));
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.createManualPartnership(request, pd.getId(), contractImage));
}

@Operation(
Expand All @@ -93,8 +90,7 @@ public BaseResponse<List<PartnershipResponseDTO.WritePartnershipResponseDTO>> li
@RequestParam(name = "all", defaultValue = "false") boolean all,
@AuthenticationPrincipal PrincipalDetails pd
) {
Long memberId = pd.getMember().getId();
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.listPartnershipsForAdmin(all, memberId));
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.listPartnershipsForAdmin(all, pd.getId()));
}

@Operation(
Expand All @@ -106,8 +102,7 @@ public BaseResponse<List<PartnershipResponseDTO.WritePartnershipResponseDTO>> li
@RequestParam(name = "all", defaultValue = "false") boolean all,
@AuthenticationPrincipal PrincipalDetails pd
) {
Long memberId = pd.getMember().getId();
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.listPartnershipsForPartner(all, memberId));
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.listPartnershipsForPartner(all, pd.getId()));
}

@Operation(
Expand All @@ -123,7 +118,7 @@ public BaseResponse<PartnershipResponseDTO.WritePartnershipResponseDTO> getPartn

@Operation(
summary = "제휴 상태 업데이트 API",
description = "제휴 ID와 바꾸고 싶은 상태를 입력하세요(SUSPEND/ACTIVE/INACTIVE)"
description = "제휴 ID와 바꾸고 싶은 상태를 입력하세요(SUSPEND/ACTIVE/INACTIVE/BLANK)"
)
@PatchMapping("/{partnershipId}/status")
public BaseResponse<PartnershipResponseDTO.UpdateResponseDTO> updatePartnershipStatus(
Expand All @@ -133,4 +128,62 @@ public BaseResponse<PartnershipResponseDTO.UpdateResponseDTO> updatePartnershipS
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.updatePartnershipStatus(partnershipId, request));
}

@PostMapping("/proposal/draft")
@Operation(
summary = "제휴 제안서 초안 생성 API",
description = "현재 로그인한 관리자(Admin)가 내용이 비어있는 제휴 제안서를 초안 상태로 생성합니다."
)
public BaseResponse<PartnershipResponseDTO.CreateDraftResponseDTO> createDraftPartnership(
@RequestBody PartnershipRequestDTO.CreateDraftRequestDTO request,
@AuthenticationPrincipal PrincipalDetails pd
) {
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.createDraftPartnership(request, pd.getId()));
}

@DeleteMapping("/proposal/delete/{paperId}")
@Operation(
summary = "제휴 제안서 삭제 API",
description = "특정 제휴 제안서(paperId)와 관련된 모든 데이터를 삭제합니다."
)
public BaseResponse<Void> deletePartnership(
@PathVariable Long paperId
) {
partnershipService.deletePartnership(paperId);
return BaseResponse.onSuccess(SuccessStatus._OK, null);
}

@GetMapping("/suspended")
@Operation(
summary = "대기 중인 제휴 계약서 조회 API",
description = "현재 로그인한 관리자(Admin)가 대기 중인 제휴 계약서를 모두 조회하여 리스트로 반환합니다."
)
public BaseResponse<List<PartnershipResponseDTO.SuspendedPaperDTO>> suspendPartnership(
@AuthenticationPrincipal PrincipalDetails pd
) {
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.getSuspendedPapers(pd.getId()));
}

@GetMapping("/check/admin")
@Operation(
summary = "관리자 채팅방 내 제휴 확인 API",
description = "현재 로그인한 관리자(Admin)가 파라미터로 받은 partnerId를 가진 상대 제휴업체(Partner)와 맺고 있는 제휴를 조회합니다. 비활성화되지 않은 가장 최근 제휴 1건을 조회합니다."
)
public BaseResponse<PartnershipResponseDTO.AdminPartnershipWithPartnerResponseDTO> checkAdminPartnership(
@RequestParam("partnerId") Long partnerId,
@AuthenticationPrincipal PrincipalDetails pd
) {
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.checkPartnershipWithPartner(pd.getId(), partnerId));
}

@GetMapping("/check/partner")
@Operation(
summary = "제휴업체 채팅방 내 제휴 확인 API",
description = "현재 로그인한 제휴업체(Partner)가 파라미터로 받은 AdminId를 가진 상대 관리자(Admin)과 맺고 있는 제휴를 조회합니다. 비활성화되지 않은 가장 최근 제휴 1건을 조회합니다."
)
public BaseResponse<PartnershipResponseDTO.PartnerPartnershipWithAdminResponseDTO> checkPartnerPartnership(
@RequestParam("adminId") Long adminId,
@AuthenticationPrincipal PrincipalDetails pd
) {
return BaseResponse.onSuccess(SuccessStatus._OK, partnershipService.checkPartnershipWithAdmin(pd.getId(), adminId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,36 @@ public static Paper toPaperEntity(
.build();
}

public static Paper toDraftPaperEntity(Admin admin, Partner partner, Store store) {
return Paper.builder()
.admin(admin)
.partner(partner)
.store(store)
.partnershipPeriodStart(null)
.partnershipPeriodEnd(null)
.isActivated(ActivationStatus.BLANK)
.contractImageKey(null)
.build();
}

public static List<PaperContent> toPaperContents(
PartnershipRequestDTO.WritePartnershipRequestDTO partnershipRequestDTO,
Paper paper
) {
if (partnershipRequestDTO.getOptions() == null || partnershipRequestDTO.getOptions().isEmpty()) {
return Collections.emptyList();
}
List<PaperContent> contents = new ArrayList<>(partnershipRequestDTO.getOptions().size());
for (var o : partnershipRequestDTO.getOptions()) {
PaperContent content = PaperContent.builder()
.paper(paper)
.criterionType(o.getCriterionType())
.optionType(o.getOptionType())
.people(o.getPeople())
.cost(o.getCost())
.category(o.getCategory())
.discount(o.getDiscountRate())
.build();
contents.add(content);
}
return contents;
return partnershipRequestDTO.getOptions().stream()
.map(optionDto -> PaperContent.builder()
.paper(paper) // 어떤 Paper에 속하는지 연결
.optionType(optionDto.getOptionType())
.criterionType(optionDto.getCriterionType())
.people(optionDto.getPeople())
.cost(optionDto.getCost())
.category(optionDto.getCategory())
.discount(optionDto.getDiscountRate()) // DTO의 discountRate를 Entity의 discount에 매핑
.build())
.toList();
}


Expand All @@ -84,22 +93,20 @@ public static List<List<Goods>> toGoodsBatches(
PartnershipRequestDTO.WritePartnershipRequestDTO partnershipRequestDTO
) {
if (partnershipRequestDTO == null || partnershipRequestDTO.getOptions().isEmpty()) {
return List.of();
}
List<List<Goods>> batches = new ArrayList<>(partnershipRequestDTO.getOptions().size());
for (var o : partnershipRequestDTO.getOptions()) {
if (o.getGoods() == null || o.getGoods().isEmpty()) {
batches.add(List.of());
continue;
}
List<Goods> goodsList = o.getGoods().stream()
.map(g -> Goods.builder()
.belonging(g.getGoodsName())
.build())
.collect(Collectors.toList());
batches.add(goodsList);
return Collections.emptyList();
}
return batches;
return partnershipRequestDTO.getOptions().stream()
.map(optionDto -> {
if (optionDto.getGoods() == null || optionDto.getGoods().isEmpty()) {
return Collections.<Goods>emptyList();
}
return optionDto.getGoods().stream()
.map(goodsDto -> Goods.builder()
.belonging(goodsDto.getGoodsName()) // DTO의 goodsName을 엔티티의 belonging에 매핑
.build())
.toList();
})
.toList();
}


Expand Down Expand Up @@ -272,6 +279,7 @@ public static PartnershipResponseDTO.WritePartnershipResponseDTO writePartnershi
.adminId(paper.getAdmin() != null ? paper.getAdmin().getId() : null)
.partnerId(paper.getPartner()!= null ? paper.getPartner().getId() : null) // 수동등록이면 null
.storeId(paper.getStore() != null ? paper.getStore().getId() : null)
.isActivated(paper.getIsActivated())
.options(optionDTOS)
.build();
}
Expand All @@ -285,4 +293,15 @@ public static List<PartnershipResponseDTO.PartnershipGoodsResponseDTO> goodsResu
.build())
.toList();
}

public static PartnershipResponseDTO.CreateDraftResponseDTO toCreateDraftResponseDTO(Paper paper) {
return PartnershipResponseDTO.CreateDraftResponseDTO.builder()
.paperId(paper.getId())
.build();
}

public static void updatePaperFromDto(Paper paper, PartnershipRequestDTO.WritePartnershipRequestDTO dto) {
paper.setPartnershipPeriodStart(dto.getPartnershipPeriodStart());
paper.setPartnershipPeriodEnd(dto.getPartnershipPeriodEnd());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ public static class finalRequest{
Long discount;
List<Long> userIds;
}

@Getter
public static class WritePartnershipRequestDTO {
private Long adminId; // 제안 학생회 아이디
private Long paperId; // 제휴 제안서 아이디
private LocalDate partnershipPeriodStart;
private LocalDate partnershipPeriodEnd;
private List<PartnershipOptionRequestDTO> options; // 동적으로 받는 제안 항목
Expand Down Expand Up @@ -66,4 +67,9 @@ public static class ManualPartnershipRequestDTO {
private LocalDate partnershipPeriodEnd;
private List<PartnershipOptionRequestDTO> options;
}

@Getter
public static class CreateDraftRequestDTO {
private Long partnerId; // 제안서를 보낼 제휴업체 ID
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.assu.server.domain.partnership.dto;


import com.assu.server.domain.common.enums.ActivationStatus;
import com.assu.server.domain.partnership.entity.enums.CriterionType;
import com.assu.server.domain.partnership.entity.enums.OptionType;
import lombok.*;
Expand All @@ -12,6 +13,7 @@
public class PartnershipResponseDTO {

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
Expand All @@ -22,6 +24,7 @@ public static class WritePartnershipResponseDTO {
private Long adminId;
private Long partnerId;
private Long storeId;
private ActivationStatus isActivated;
private List<PartnershipOptionResponseDTO> options;
}

Expand Down Expand Up @@ -76,4 +79,50 @@ public static class ManualPartnershipResponseDTO {
private String contractImageUrl;
private WritePartnershipResponseDTO partnership;
}

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class CreateDraftResponseDTO {
private Long paperId; // 생성된 빈 제안서의 ID
}

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class SuspendedPaperDTO {
private Long paperId;
private String partnerName;
private LocalDateTime createdAt;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class AdminPartnershipWithPartnerResponseDTO {
private Long paperId;
private boolean isPartnered; // 제휴 여부
private String status; // 제휴 상태
private Long partnerId;
private String partnerName;
private String partnerAddress;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class PartnerPartnershipWithAdminResponseDTO {
private Long paperId;
private boolean isPartnered; // 제휴 여부
private String status; // 제휴 상태
private Long adminId;
private String adminName;
private String adminAddress;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ public class Paper extends BaseEntity {
private Long id;


@Setter
private LocalDate partnershipPeriodStart; // LocalDate vs String

@Setter
private LocalDate partnershipPeriodEnd;

@Setter
@Enumerated(EnumType.STRING)
private ActivationStatus isActivated;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,19 @@

import com.assu.server.domain.partnership.entity.Goods;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface GoodsRepository extends JpaRepository<Goods, Long> {

List<Goods> findByContentId(Long contentId);

List<Goods> findByContentIdIn(List<Long> contentIds);

@Modifying
@Query("delete from Goods g where g.content.id in :contentIds")
void deleteAllByContentIds(@Param("contentIds") List<Long> contentIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ Optional<Paper> findTopByAdmin_IdAndPartner_IdAndIsActivatedOrderByIdDesc(
Long adminId, Long partnerId, ActivationStatus isActivated
);

boolean existsByAdmin_IdAndPartner_IdAndIsActivatedIn(Long adminId, Long partnerId, List<ActivationStatus> statuses);
Optional<Paper> findTopByAdmin_IdAndPartner_IdAndIsActivatedInOrderByIdDesc(Long adminId, Long partnerId, List<ActivationStatus> statuses);

// Admin 기준 (SUSPEND)
@Query("select p from Paper p join fetch p.partner where p.isActivated = :status order by p.createdAt desc")
List<Paper> findAllByIsActivatedWithPartner(@Param("status") ActivationStatus status);

// Partner 기준 (ACTIVE)
List<Paper> findByPartner_IdAndIsActivated(Long partnerId, ActivationStatus status, Sort sort);
Page<Paper> findByPartner_IdAndIsActivated(Long partnerId, ActivationStatus status, Pageable pageable);
Expand Down
Loading