Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ [FEATURE] 공고 조회, 삭제 기능 개발 #46

Merged
merged 8 commits into from
Jan 26, 2024
27 changes: 21 additions & 6 deletions http/test.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@accessToken = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZW1haWwiOiJzcG9udXNAZ21haWwuY29tIiwiYXV0aCI6IlNUVURFTlQiLCJpYXQiOjE3MDU4MzQ2MTksImV4cCI6MTcwNjgzNDYxOX0.XO8ydia0RB1eVGXrA7nBeP5AND2Ui4ivK26DEldZLnE
@matsterToken = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZW1haWwiOiJzcG9udXNAZ21haWwuY29tIiwiYXV0aCI6IlNUVURFTlQiLCJpYXQiOjE3MDU4MzQ2MTksImV4cCI6MTcwNjgzNDYxOX0.XO8ydia0RB1eVGXrA7nBeP5AND2Ui4ivK26DEldZLnE

### 회원가입
POST http://localhost:8080/api/v1/organizations/join
Expand All @@ -7,7 +7,7 @@ Content-Type: application/json
{
"name": "팀 스포너스",
"email": "[email protected]",
"password": "password12345",
"password": "password1234",
"location": "none",
"organizationType": "STUDENT",
"suborganizationType": "STUDENT_COUNCIL",
Expand All @@ -26,10 +26,25 @@ Content-Type: application/json

{
"email": "[email protected]",
"password": "password12345"
"password": "password1234"
}

### 공고 생성
POST http://localhost:8080/api/v1/announcement
Authorization: Bearer {{matsterToken}}
Content-Type: application/json

{
"title": "무신사 스폰서십",
"type": "SPONSORSHIP",
"category": "MARKETING",
"content": "무신사 스폰서십을 진행할 대학교 학생회를 모집합니다.",
"status": "POSTED"
}

### 상세 조회
GET http://localhost:8080/api/v1/announcement/1

### test
GET http://localhost:8080/api/v1/organizations/test
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZW1haWwiOiJzcG9udXNAZ21haWwuY29tIiwiYXV0aCI6IlNUVURFTlQiLCJpYXQiOjE3MDU4MzU3NzksImV4cCI6MTcwNjgzNTc3OX0.wWxNFDTXAWuRd4JbSQ5t7wKFJO3qnVvDsFHKskVnR1E
### 삭제 (생성한 단체만 삭제 가능)
DELETE http://localhost:8080/api/v1/announcement/1
Authorization: Bearer {{matsterToken}}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

import com.sponus.sponusbe.auth.user.CustomUserDetails;
import com.sponus.sponusbe.domain.organization.entity.Organization;
import com.sponus.sponusbe.domain.organization.exception.OrganizationErrorCode;
import com.sponus.sponusbe.domain.organization.exception.OrganizationException;
import com.sponus.sponusbe.domain.organization.repository.OrganizationRepository;
import com.sponus.sponusbe.global.common.code.OrganizationErrorCode;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import org.springframework.stereotype.Service;

import com.sponus.sponusbe.domain.organization.entity.Organization;
import com.sponus.sponusbe.domain.organization.exception.OrganizationErrorCode;
import com.sponus.sponusbe.domain.organization.exception.OrganizationException;
import com.sponus.sponusbe.domain.organization.repository.OrganizationRepository;
import com.sponus.sponusbe.global.common.code.OrganizationErrorCode;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package com.sponus.sponusbe.domain.announcement.controller;

import java.util.List;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.sponus.sponusbe.auth.annotation.AuthOrganization;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementBriefResponse;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementCreateRequest;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementCreateResponse;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementResponse;
Expand All @@ -19,47 +21,53 @@
import com.sponus.sponusbe.domain.organization.entity.Organization;
import com.sponus.sponusbe.global.common.ApiResponse;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequiredArgsConstructor
@RequestMapping("/api/v1/announcement")
@RequestMapping("/api/v1/announcements")
@RestController
public class AnnouncementController {

private final AnnouncementQueryService announcementQueryService;
private final AnnouncementService announcementService;

@GetMapping("/recommend")
public ApiResponse<?> getRecommendAnnouncement() {
public ApiResponse<Void> getRecommendAnnouncement() {
return null;
}

@GetMapping("/popular")
public ApiResponse<?> getAnnouncement() {
public ApiResponse<Void> getAnnouncement() {
return null;
}

@GetMapping("/{announcementId}")
public ApiResponse<AnnouncementResponse> getAnnouncement(@PathVariable Long announcementId) {
return ApiResponse.onSuccess(announcementQueryService.getAnnouncement(announcementId));
return ApiResponse.onSuccess(announcementService.getAnnouncement(announcementId));
}

@GetMapping
public ApiResponse<AnnouncementResponse> searchAnnouncement(@RequestParam String search) {
return ApiResponse.onSuccess(announcementQueryService.searchAnnouncement(search));
public ApiResponse<List<AnnouncementResponse>> searchAnnouncement(@RequestParam("search") String keyword) {
return ApiResponse.onSuccess(announcementQueryService.searchAnnouncement(keyword));
}

@PostMapping("/")
public ApiResponse<AnnouncementCreateResponse> createAnnouncement(@AuthOrganization Organization authOrganization,
AnnouncementCreateRequest request) {
@PostMapping
public ApiResponse<AnnouncementCreateResponse> createAnnouncement(
@AuthOrganization Organization authOrganization,
@RequestBody @Valid AnnouncementCreateRequest request
) {
return ApiResponse.onSuccess(announcementService.createAnnouncement(authOrganization, request));
}

@DeleteMapping("/{announcementId}")
public ApiResponse<AnnouncementBriefResponse> deleteAnnouncement(@PathVariable Long announcementId) {
return null;
public ApiResponse<Void> deleteAnnouncement(
@AuthOrganization Organization authOrganization,
@PathVariable Long announcementId) {
announcementService.deleteAnnouncement(authOrganization, announcementId);
return ApiResponse.onSuccess(null);
}

@PatchMapping("/{announcementId}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,8 @@ public class Announcement extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "organization_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Organization writer;

public void increaseViewCount() {
this.viewCount++;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
@Getter
@AllArgsConstructor
public enum AnnouncementErrorCode implements BaseErrorCode {
ANNOUNCEMENT_ERROR(HttpStatus.BAD_REQUEST, "4000", "공지사항 에러입니다.");
ANNOUNCEMENT_ERROR(HttpStatus.BAD_REQUEST, "ANC4000", "공지사항 관련 에러"),
ANNOUNCEMENT_ALREADY_DELETED(HttpStatus.BAD_REQUEST, "ANC4001", "이미 삭제된 공지사항입니다."),
ANNOUNCEMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "ANC4040", "해당 공지사항이 존재하지 않습니다.");

private HttpStatus httpStatus;
private String code;
private String message;
private final HttpStatus httpStatus;
private final String code;
private final String message;

@Override
public ApiResponse<Void> getErrorResponse() {
return null;
return ApiResponse.onFailure(code, message);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.sponus.sponusbe.domain.announcement.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import com.sponus.sponusbe.domain.announcement.entity.Announcement;

public interface AnnouncementRepository extends JpaRepository<Announcement, Long> {

List<Announcement> findByTitleContains(String title);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package com.sponus.sponusbe.domain.announcement.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sponus.sponusbe.domain.announcement.dto.AnnouncementBriefResponse;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementCreateRequest;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementResponse;
import com.sponus.sponusbe.domain.announcement.entity.Announcement;
import com.sponus.sponusbe.domain.announcement.exception.AnnouncementErrorCode;
import com.sponus.sponusbe.domain.announcement.exception.AnnouncementException;
import com.sponus.sponusbe.domain.announcement.repository.AnnouncementRepository;

import lombok.RequiredArgsConstructor;
Expand All @@ -22,14 +21,10 @@ public class AnnouncementQueryService {

private final AnnouncementRepository announcementRepository;

public AnnouncementResponse getAnnouncement(Long announcementId) {
Announcement announcement = announcementRepository.findById(announcementId)
.orElseThrow(() -> new AnnouncementException(AnnouncementErrorCode.ANNOUNCEMENT_ERROR));
return AnnouncementResponse.from(announcement);
}

public AnnouncementResponse searchAnnouncement(String search) {
return null;
public List<AnnouncementResponse> searchAnnouncement(String keyword) {
log.info("search announcement by keyword: {}", keyword);
return announcementRepository.findByTitleContains(keyword).stream()
.map(AnnouncementResponse::from).toList();
}

public AnnouncementBriefResponse createAnnouncement(AnnouncementCreateRequest request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

import com.sponus.sponusbe.domain.announcement.dto.AnnouncementCreateRequest;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementCreateResponse;
import com.sponus.sponusbe.domain.announcement.dto.AnnouncementResponse;
import com.sponus.sponusbe.domain.announcement.entity.Announcement;
import com.sponus.sponusbe.domain.announcement.exception.AnnouncementErrorCode;
import com.sponus.sponusbe.domain.announcement.exception.AnnouncementException;
import com.sponus.sponusbe.domain.announcement.repository.AnnouncementRepository;
import com.sponus.sponusbe.domain.organization.entity.Organization;

Expand All @@ -20,9 +23,27 @@ public class AnnouncementService {

private final AnnouncementRepository announcementRepository;

public AnnouncementCreateResponse createAnnouncement(Organization authOrganization,
public AnnouncementCreateResponse createAnnouncement(
Organization authOrganization,
AnnouncementCreateRequest request) {
final Announcement announcement = announcementRepository.save(request.toEntity(authOrganization));
return AnnouncementCreateResponse.from(announcement);
}

public AnnouncementResponse getAnnouncement(Long announcementId) {
Announcement announcement = announcementRepository.findById(announcementId)
.orElseThrow(() -> new AnnouncementException(AnnouncementErrorCode.ANNOUNCEMENT_NOT_FOUND));
announcement.increaseViewCount();
return AnnouncementResponse.from(announcement);
}

public void deleteAnnouncement(Organization organization, Long announcementId) {
final Announcement announcement = announcementRepository.findById(announcementId)
.orElseThrow(() -> new AnnouncementException(AnnouncementErrorCode.ANNOUNCEMENT_NOT_FOUND));
if (!announcement.getWriter().getId().equals(organization.getId())) {
throw new AnnouncementException(AnnouncementErrorCode.ANNOUNCEMENT_NOT_FOUND);
}
announcementRepository.delete(announcement);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.sponus.sponusbe.domain.organization.exception;

import org.springframework.http.HttpStatus;

import com.sponus.sponusbe.global.common.ApiResponse;
import com.sponus.sponusbe.global.common.BaseErrorCode;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum OrganizationErrorCode implements BaseErrorCode {
ORGANIZATION_ERROR(HttpStatus.BAD_REQUEST, "ORG4000", "단체 관련 에러"),
INVALID_FORMAT(HttpStatus.BAD_REQUEST, "ORG4001", "잘못된 형식입니다."),
ORGANIZATION_ALREADY_EXIST(HttpStatus.BAD_REQUEST, "ORG4002", "중복된 단체 이메일입니다."),
ORGANIZATION_NOT_FOUND(HttpStatus.NOT_FOUND, "ORG4040", "존재하지 않는 단체입니다.");

private final HttpStatus httpStatus;
private final String code;
private final String message;

@Override
public ApiResponse<Void> getErrorResponse() {
return ApiResponse.onFailure(code, message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,56 @@
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.sponus.sponusbe.auth.annotation.AuthOrganization;
import com.sponus.sponusbe.domain.organization.entity.Organization;
import com.sponus.sponusbe.domain.propose.controller.dto.request.ProposeCreateRequest;
import com.sponus.sponusbe.domain.propose.controller.dto.request.ProposeGetCondition;
import com.sponus.sponusbe.domain.propose.controller.dto.request.ProposeUpdateRequest;
import com.sponus.sponusbe.domain.propose.controller.dto.response.ProposeCreateResponse;
import com.sponus.sponusbe.domain.propose.controller.dto.response.ProposeDetailGetResponse;
import com.sponus.sponusbe.domain.propose.controller.dto.response.ProposeSummaryGetResponse;
import com.sponus.sponusbe.domain.propose.dto.request.ProposeCreateRequest;
import com.sponus.sponusbe.domain.propose.dto.request.ProposeGetCondition;
import com.sponus.sponusbe.domain.propose.dto.request.ProposeUpdateRequest;
import com.sponus.sponusbe.domain.propose.dto.response.ProposeCreateResponse;
import com.sponus.sponusbe.domain.propose.dto.response.ProposeDetailGetResponse;
import com.sponus.sponusbe.domain.propose.dto.response.ProposeSummaryGetResponse;
import com.sponus.sponusbe.domain.propose.service.ProposeQueryService;
import com.sponus.sponusbe.domain.propose.service.ProposeService;
import com.sponus.sponusbe.global.common.ApiResponse;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequiredArgsConstructor
@RequestMapping("/api/v1/proposes")
@RestController
public class ProposeController {

private final ProposeService proposeService;
private final ProposeQueryService proposeQueryService;

@PostMapping("/api/v1/propose")
@PostMapping
public ApiResponse<ProposeCreateResponse> createPropose(
@AuthOrganization Organization authOrganization,
@RequestBody @Valid ProposeCreateRequest request
) {
return ApiResponse.onSuccess(proposeService.createPropose(authOrganization, request));
}

@GetMapping("/api/v1/propose/me")
@GetMapping("/me")
public ApiResponse<List<ProposeSummaryGetResponse>> getMyProposes(
@AuthOrganization Organization authOrganization,
@ModelAttribute @Valid ProposeGetCondition condition
) {
return ApiResponse.onSuccess(proposeQueryService.getProposes(authOrganization, condition));
}

@GetMapping("/api/v1/propose/{proposeId}")
@GetMapping("/{proposeId}")
public ApiResponse<ProposeDetailGetResponse> getProposeDetail(@PathVariable Long proposeId) {
return ApiResponse.onSuccess(proposeQueryService.getProposeDetail(proposeId));
}

@PatchMapping("/api/v1/propose/{proposeId}")
@PatchMapping("/{proposeId}")
public ApiResponse<Void> updatePropose(
@AuthOrganization Organization authOrganization,
@PathVariable Long proposeId,
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.sponus.sponusbe.domain.propose.controller.dto.request;
package com.sponus.sponusbe.domain.propose.dto.request;

import com.sponus.sponusbe.domain.announcement.entity.Announcement;
import com.sponus.sponusbe.domain.organization.entity.Organization;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.sponus.sponusbe.domain.propose.controller.dto.request;
package com.sponus.sponusbe.domain.propose.dto.request;

import jakarta.validation.constraints.NotNull;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.sponus.sponusbe.domain.propose.dto.request;

public enum ProposeType {
SEND, RECEIVED;

}
Loading
Loading