Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import com.campus.campus.domain.councilpost.domain.entity.PostCategory;
import com.campus.campus.domain.councilpost.domain.entity.ThumbnailIcon;
import com.campus.campus.domain.place.application.dto.response.SavedPlaceInfo;
import com.fasterxml.jackson.annotation.JsonFormat;

import io.swagger.v3.oas.annotations.media.Schema;
Expand All @@ -22,7 +23,24 @@ public record PostRequest(
@NotBlank
String content,

String place,
@Schema(example =
"""
"placeName": "숙명여자대학교",
"placeKey": "string",
"address": "서울특별시 용산구 청파로47길 99",
"category": "교육,학문>대학교",
"link": "https://map.naver.com/v5/search/%EC%88%99%EB%AA%85%EC%97%AC%EC%9E%90%EB%8C%80%ED%95%99%EA%B5%90+%EC%A0%9C1%EC%BA%A0%ED%8D%BC%EC%8A%A4?c=37.545947,126.964578,15,0,0,0,dh",
"telephone": "010-1234-1234",
"coordinate": {
"latitude": 0.1,
"longitude": 0.1
},
"imgUrls": [
"string"
]
""",
description = "/search API에서 반환된 결과 중 하나를 선택")
SavedPlaceInfo place,

@Schema(example = "2025-04-10T18:00")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public record GetPostResponse(
PostCategory category,
String title,
String content,
String place,
String placeName,
LocalDate startDate,
LocalDate endDate,
LocalDateTime startDateTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public record PostListItemResponse(
Long id,
PostCategory category,
String title,
String place,
Long placeId,
LocalDateTime endDateTime,
String thumbnailImageUrl,
ThumbnailIcon thumbnailIcon,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@
import org.springframework.stereotype.Component;

import com.campus.campus.domain.council.domain.entity.StudentCouncil;
import com.campus.campus.domain.councilpost.application.dto.request.PostRequest;
import com.campus.campus.domain.councilpost.application.dto.response.GetActivePartnershipListForUserResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetLikedPostResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetPostResponse;
import com.campus.campus.domain.councilpost.application.dto.response.LikePostResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetPostForUserResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetPostListForCouncilResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetPostResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetUpcomingEventListForCouncilResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetActivePartnershipListForUserResponse;
import com.campus.campus.domain.councilpost.application.dto.response.LikePostResponse;
import com.campus.campus.domain.councilpost.application.dto.response.PostListItemResponse;
import com.campus.campus.domain.councilpost.application.dto.request.PostRequest;
import com.campus.campus.domain.councilpost.application.dto.response.GetPostForUserResponse;
import com.campus.campus.domain.councilpost.domain.entity.LikePost;
import com.campus.campus.domain.councilpost.domain.entity.PostImage;
import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost;
import com.campus.campus.domain.place.domain.entity.Place;
import com.campus.campus.domain.user.domain.entity.User;

import lombok.RequiredArgsConstructor;
Expand All @@ -31,8 +32,10 @@ public PostListItemResponse toPostListItemResponse(StudentCouncilPost post, bool
post.getId(),
post.getCategory(),
post.getTitle(),
post.getPlace(),
post.isEvent() ? post.getStartDateTime() : post.getEndDateTime(),
post.getPlace().getPlaceId(),
post.isEvent()
? post.getStartDateTime()
: post.getEndDateTime(),
post.getThumbnailImageUrl(),
post.getThumbnailIcon(),
isLiked
Expand All @@ -44,7 +47,7 @@ public GetPostListForCouncilResponse toGetPostListForCouncilResponse(StudentCoun
post.getId(),
post.getCategory(),
post.getTitle(),
post.getPlace(),
post.getPlace().getPlaceName(),
post.isEvent() ? post.getStartDateTime() : post.getEndDateTime(),
post.getThumbnailImageUrl(),
post.getThumbnailIcon()
Expand All @@ -56,7 +59,7 @@ public GetUpcomingEventListForCouncilResponse toGetUpcomingEventListForCouncilRe
post.getId(),
post.getCategory(),
post.getTitle(),
post.getPlace(),
post.getPlace().getPlaceName(),
post.getStartDateTime(),
post.getThumbnailIcon()
);
Expand All @@ -66,7 +69,7 @@ public GetActivePartnershipListForUserResponse toGetActivePartnershipListForUser
return new GetActivePartnershipListForUserResponse(
post.getId(),
post.getTitle(),
post.getPlace(),
post.getPlace().getPlaceName(),
post.getThumbnailImageUrl()
);
}
Expand All @@ -81,7 +84,7 @@ public GetPostResponse toGetPostResponse(StudentCouncilPost post, List<String> i
.category(post.getCategory())
.title(post.getTitle())
.content(post.getContent())
.place(post.getPlace())
.placeName(post.getPlace().getPlaceName())
.thumbnailImageUrl(post.getThumbnailImageUrl())
.thumbnailIcon(post.getThumbnailIcon())
.images(images != null ? images : Collections.emptyList());
Expand All @@ -96,6 +99,9 @@ public GetPostResponse toGetPostResponse(StudentCouncilPost post, List<String> i
return builder.build();
}

//
// public StudentCouncilPost createStudentCouncilPost(StudentCouncil writer, PostRequest dto,
// LocalDateTime startDateTime, LocalDateTime endDateTime, Place place) {
public GetPostForUserResponse toGetPostForUserResponse(StudentCouncilPost post, List<String> images,
Long currentUserId, boolean isLiked) {
var writer = post.getWriter();
Expand All @@ -106,7 +112,7 @@ public GetPostForUserResponse toGetPostForUserResponse(StudentCouncilPost post,
.category(post.getCategory())
.title(post.getTitle())
.content(post.getContent())
.place(post.getPlace())
.place(post.getPlace().getPlaceName())
.thumbnailImageUrl(post.getThumbnailImageUrl())
.thumbnailIcon(post.getThumbnailIcon())
.isLiked(isLiked)
Expand Down Expand Up @@ -134,20 +140,20 @@ public GetLikedPostResponse toGetLikedPostResponse(StudentCouncilPost post) {
return new GetLikedPostResponse(
post.getId(),
post.getTitle(),
post.getPlace(),
post.getPlace().getPlaceName(),
post.isEvent() ? post.getStartDateTime() : post.getEndDateTime(),
post.getThumbnailImageUrl()
);
}

public StudentCouncilPost createStudentCouncilPost(StudentCouncil writer, PostRequest dto,
public StudentCouncilPost createStudentCouncilPost(StudentCouncil writer, Place place, PostRequest dto,
LocalDateTime startDateTime, LocalDateTime endDateTime) {
return StudentCouncilPost.builder()
.writer(writer)
.category(dto.category())
.title(dto.title())
.content(dto.content())
.place(dto.place())
.place(place)
.startDateTime(startDateTime)
.endDateTime(endDateTime)
.thumbnailImageUrl(dto.thumbnailImageUrl())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
import com.campus.campus.domain.council.application.exception.StudentCouncilNotFoundException;
import com.campus.campus.domain.council.domain.entity.StudentCouncil;
import com.campus.campus.domain.council.domain.repository.StudentCouncilRepository;
import com.campus.campus.domain.councilpost.application.dto.request.PostRequest;
import com.campus.campus.domain.councilpost.application.dto.response.GetPostListForCouncilResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetPostResponse;
import com.campus.campus.domain.councilpost.application.dto.response.GetUpcomingEventListForCouncilResponse;
import com.campus.campus.domain.councilpost.application.dto.response.NormalizedDateTime;
import com.campus.campus.domain.councilpost.application.dto.request.PostRequest;
import com.campus.campus.domain.councilpost.application.exception.NotPostWriterException;
import com.campus.campus.domain.councilpost.application.exception.PostImageLimitExceededException;
import com.campus.campus.domain.councilpost.application.exception.PostNotFoundException;
Expand All @@ -30,6 +30,9 @@
import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost;
import com.campus.campus.domain.councilpost.domain.repository.PostImageRepository;
import com.campus.campus.domain.councilpost.domain.repository.StudentCouncilPostRepository;
import com.campus.campus.domain.partnership.application.service.PartnershipService;
import com.campus.campus.domain.place.application.service.PlaceService;
import com.campus.campus.domain.place.domain.entity.Place;
import com.campus.campus.global.oci.application.service.PresignedUrlService;

import lombok.RequiredArgsConstructor;
Expand All @@ -48,6 +51,9 @@ public class StudentCouncilPostService {

private static final int MAX_IMAGE_COUNT = 10;
private static final long UPCOMING_EVENT_WINDOW_HOURS = 72L;
private final PlaceService placeService;
private final StudentCouncilPostRepository studentCouncilPostRepository;
private final PartnershipService partnershipService;

@Transactional
public GetPostResponse create(Long councilId, PostRequest dto) {
Expand All @@ -65,12 +71,18 @@ public GetPostResponse create(Long councilId, PostRequest dto) {

NormalizedDateTime normalized = dto.category().validateAndNormalize(dto);

//Place 객체 생성
Place place = placeService.findOrCreatePlace(dto);

StudentCouncilPost post = studentCouncilPostMapper.createStudentCouncilPost(
writer, dto, normalized.startDateTime(), normalized.endDateTime()
writer, place, dto, normalized.startDateTime(), normalized.endDateTime()
);

postRepository.save(post);

//제휴 엔티티 생성
partnershipService.create(post, place);

if (dto.imageUrls() != null) {
for (String imageUrl : dto.imageUrls()) {
postImageRepository.save(studentCouncilPostMapper.createPostImage(post, imageUrl));
Expand Down Expand Up @@ -203,10 +215,15 @@ public GetPostResponse update(Long councilId, Long postId, PostRequest dto) {
String oldThumbnailUrl = post.getThumbnailImageUrl();
List<PostImage> oldImages = postImageRepository.findAllByPost(post);

Place place = post.getPlace();
if (!dto.place().placeName().equals(place.getPlaceName())) {
place = placeService.findOrCreatePlace(dto);
}

post.update(
dto.title(),
dto.content(),
dto.place(),
place,
normalized.startDateTime(),
normalized.endDateTime(),
dto.thumbnailImageUrl(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.time.LocalDateTime;

import com.campus.campus.domain.council.domain.entity.StudentCouncil;
import com.campus.campus.domain.place.domain.entity.Place;
import com.campus.campus.global.entity.BaseEntity;

import jakarta.persistence.Column;
Expand Down Expand Up @@ -45,7 +46,9 @@ public class StudentCouncilPost extends BaseEntity {
@Column(columnDefinition = "TEXT")
private String content;

private String place;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "place_id")
private Place place;

private LocalDateTime startDateTime;
private LocalDateTime endDateTime;
Expand All @@ -58,7 +61,7 @@ public class StudentCouncilPost extends BaseEntity {
public void update(
String title,
String content,
String place,
Place place,
LocalDateTime startDateTime,
LocalDateTime endDateTime,
String thumbnailImageUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.campus.campus.domain.councilpost.domain.entity.PostImage;
import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost;
import com.campus.campus.domain.place.application.dto.response.partnership.PostImageSummary;

public interface PostImageRepository extends JpaRepository<PostImage, Long> {

Expand All @@ -14,4 +17,26 @@ public interface PostImageRepository extends JpaRepository<PostImage, Long> {
void deleteByPost(StudentCouncilPost post);

List<PostImage> findAllByPostOrderByIdAsc(StudentCouncilPost post);

@Query("""
SELECT NEW com.campus.campus.domain.place.application.dto.response.partnership.PostImageSummary
(post.place.placeId,
img.imageUrl)
FROM PostImage img
JOIN img.post post
WHERE post.category='PARTNERSHIP'
AND post.place.placeId in :placeIds
ORDER BY img.id asc
""")
List<PostImageSummary> findPartnershipImagesByPlaceIds(
@Param("placeIds") List<Long> placeIds
);

@Query("""
select pi.imageUrl
from PostImage pi
where pi.post = :post
order by pi.id asc
""")
List<String> findImageUrlsByPost(@Param("post") StudentCouncilPost post);
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,87 @@ Page<StudentCouncilPost> findUpcomingMajorEvents(
@Param("limit") LocalDateTime limit,
Pageable pageable
);

@Query("""
SELECT p
FROM StudentCouncilPost p
WHERE p.place.placeId=:placeId
and p.writer.id=:councilId
and p.category='PARTNERSHIP'
order by p.createdAt desc
""")
Optional<StudentCouncilPost> findByCouncilIdAndPlaceId(
@Param("placeId") Long placeId,
@Param("councilId") Long councilId
);

@EntityGraph(attributePaths = {"writer", "writer.school", "writer.college", "writer.major", "place"})
@Query("""
SELECT p
FROM StudentCouncilPost p
JOIN p.writer w
LEFT JOIN w.school s
LEFT JOIN w.college c
LEFT JOIN w.major m
WHERE w.deletedAt IS NULL
AND p.category = :category
AND p.startDateTime <= :now
AND p.endDateTime >= :now
AND (
(w.councilType = :majorType AND m.majorId = :majorId)
OR (w.councilType = :collegeType AND c.collegeId = :collegeId)
OR (w.councilType = :schoolType AND s.schoolId = :schoolId)
)
AND (:cursor IS NULL OR p.id < :cursor)
ORDER BY p.id DESC
""")
List<StudentCouncilPost> findByUserScopeWithCursor(
@Param("majorId") Long majorId,
@Param("collegeId") Long collegeId,
@Param("schoolId") Long schoolId,
@Param("category") PostCategory category,
@Param("majorType") CouncilType majorType,
@Param("collegeType") CouncilType collegeType,
@Param("schoolType") CouncilType schoolType,
@Param("cursor") Long cursor,
@Param("now") LocalDateTime now,
Pageable pageable
);

@Query("""
SELECT p
FROM StudentCouncilPost p
JOIN p.writer w
JOIN p.place pl
LEFT JOIN w.school s
LEFT JOIN w.college c
LEFT JOIN w.major m
WHERE w.deletedAt IS NULL
AND p.category = :category
AND p.startDateTime <= :now
AND p.endDateTime >= :now
AND pl.coordinate.latitude BETWEEN :minLat AND :maxLat
AND pl.coordinate.longitude BETWEEN :minLng AND :maxLng
AND (
(w.councilType = :majorType AND m.majorId = :majorId)
OR (w.councilType = :collegeType AND c.collegeId = :collegeId)
OR (w.councilType = :schoolType AND s.schoolId = :schoolId)
)
ORDER BY p.id DESC
""")
List<StudentCouncilPost> findPinsInBounds(
@Param("majorId") Long majorId,
@Param("collegeId") Long collegeId,
@Param("schoolId") Long schoolId,
@Param("category") PostCategory category,
@Param("majorType") CouncilType majorType,
@Param("collegeType") CouncilType collegeType,
@Param("schoolType") CouncilType schoolType,
@Param("minLat") Double minLat,
@Param("maxLat") Double maxLat,
@Param("minLng") Double minLng,
@Param("maxLng") Double maxLng,
@Param("now") LocalDateTime now
);

}
Loading
Loading