Skip to content

Commit

Permalink
[Refactor] notice date #169 (#170)
Browse files Browse the repository at this point in the history
* feat: 날짜를 yyyy-MM-dd 형태로 반환하도록 변경

* feat: 경영학과 siteId 수정

* feat(KuisHomepageNoticeUpdater): save 과정에서 기존의 중요공지중 일반공지로 중요도가 변경된것이 있다면 저장에서 제외하고 중요도만 변경하도록 구현한다.

* docs(README): 리드미 사진 수정
  • Loading branch information
zbqmgldjfh authored Apr 1, 2024
1 parent 5adc4c0 commit 91a6ed5
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 62 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@
</div>

<p align="center">
<img src="https://user-images.githubusercontent.com/53814741/163469327-98af5c02-efc7-4c3e-8fec-9195ca6805ad.JPG" width="30%"/>
<img src="https://user-images.githubusercontent.com/53814741/163469357-aed6a78a-4b65-4a9a-bead-d541e7eee702.JPG" width="30%"/>
<img src="https://user-images.githubusercontent.com/53814741/163469345-503b6b50-b240-4c8d-9656-c719a5f3d9f2.JPG" width="30%"/>
<img src="https://github.com/ku-ring/ios-app/assets/53814741/73aae511-c6eb-4160-b666-2fafc7514c8b"/>

[//]: # ( <img src="https://user-images.githubusercontent.com/53814741/163469327-98af5c02-efc7-4c3e-8fec-9195ca6805ad.JPG" width="30%"/>)

[//]: # ( <img src="https://user-images.githubusercontent.com/53814741/163469357-aed6a78a-4b65-4a9a-bead-d541e7eee702.JPG" width="30%"/>)

[//]: # ( <img src="https://user-images.githubusercontent.com/53814741/163469345-503b6b50-b240-4c8d-9656-c719a5f3d9f2.JPG" width="30%"/>)
</p>

## 💌 프로젝트 소개
Expand Down Expand Up @@ -581,3 +585,7 @@ dev, local 환경에서는 단순히 ddl을 create-drop 또는 update 옵션을
</details>
## 문의
[![인스타그램](https://img.shields.io/badge/@kuring.konkuk-e4405f?style=for-the-badge&logo=instagram&logoColor=white)](https://bit.ly/3JyMWMi)
[![이메일](https://img.shields.io/badge/[email protected]?style=for-the-badge&logo=gmail&logoColor=white)](mailto:[email protected])
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public void deleteAllByIdsAndDepartment(DepartmentName departmentName, List<Stri
this.noticeRepository.deleteAllByIdsAndDepartment(departmentName, articleIds);
}

@Override
public void changeNoticeImportantToFalseByArticleId(CategoryName categoryName, List<String> articleIds) {
this.noticeRepository.changeNoticeImportantByArticleId(categoryName, articleIds, false);
}

@Override
public List<NoticeDto> findNoticesByCategoryWithOffset(CategoryName categoryName, Pageable pageable) {
return this.noticeRepository.findNoticesByCategoryWithOffset(categoryName, pageable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ interface NoticeQueryRepository {
void deleteAllByIdsAndDepartment(DepartmentName departmentName, List<String> articleIds);

List<BookmarkDto> findAllByBookmarkIds(List<String> ids);

void changeNoticeImportantByArticleId(CategoryName categoryName, List<String> articleIds, boolean important);
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,18 @@ public List<BookmarkDto> findAllByBookmarkIds(List<String> ids) {
.fetch();
}

@Transactional
@Override
public void changeNoticeImportantByArticleId(CategoryName categoryName, List<String> articleIds, boolean important) {
queryFactory
.update(notice)
.set(notice.important, important)
.where(
notice.categoryName.eq(categoryName)
.and(notice.articleId.in(articleIds))
).execute();
}

private static BooleanBuilder isContainSubject(List<String> keywords) {
BooleanBuilder booleanBuilder = new BooleanBuilder();
for (String containedName : keywords) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public interface NoticeCommandPort {
void saveAllDepartmentNotices(List<DepartmentNotice> departmentNotices);
void deleteAllByIdsAndCategory(CategoryName categoryName, List<String> articleIds);
void deleteAllByIdsAndDepartment(DepartmentName departmentName, List<String> articleIds);
void changeNoticeImportantToFalseByArticleId(CategoryName categoryName, List<String> articleIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.querydsl.core.annotations.QueryProjection;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.util.Assert;
Expand All @@ -11,6 +10,9 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class NoticeDto {

private static final String SPACE = " ";
private static final int DATE_INDEX = 0;

private String articleId;

private String postedDate;
Expand All @@ -23,7 +25,6 @@ public class NoticeDto {

private Boolean important;

@Builder
@QueryProjection
public NoticeDto(String articleId, String postedDate, String url, String subject, String category, Boolean important) {
Assert.notNull(articleId, "articleId must not be null");
Expand All @@ -34,7 +35,7 @@ public NoticeDto(String articleId, String postedDate, String url, String subject
Assert.notNull(important, "important must not be null");

this.articleId = articleId;
this.postedDate = postedDate;
this.postedDate = postedDate.split(SPACE)[DATE_INDEX];
this.url = url;
this.subject = subject;
this.category = category;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public class NoticeDateTime {
private static final Pattern compiledDateDotPattern = Pattern.compile(REGEX_DATE_DOT_SPLIT);
private static final Pattern compiledDateTimePattern = Pattern.compile(REGEX_DATE_TIME);
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withLocale(Locale.KOREA);
private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withLocale(Locale.KOREA);
private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(" HH:mm:ss").withLocale(Locale.KOREA);

@Getter(AccessLevel.PUBLIC)
@Getter
@Column(name = "posted_dt", length = 32, nullable = false)
private LocalDateTime postedDate;

@Getter(AccessLevel.PUBLIC)
@Column(name = "updated_dt", length = 32)
private LocalDateTime updatedDate;

Expand Down Expand Up @@ -65,12 +65,10 @@ public NoticeDateTime(String postedDate, String updatedDate) {
throw new InternalLogicException(ErrorCode.DOMAIN_CANNOT_CREATE);
}

public String postedDateStr() {
return this.postedDate.format(dateTimeFormatter);
}
public String postedDateStr() { return this.postedDate.format(dateFormatter); }

public String updatedDateStr() {
return this.updatedDate.format(dateTimeFormatter);
return this.updatedDate.format(dateFormatter);
}

private void initDateTime(String postedDate, String updatedDate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.util.Assert;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class BookmarkDto {

private static final String SPACE = " ";
private static final int DATE_INDEX = 0;

private String articleId;

private String postedDate;
Expand All @@ -21,8 +25,14 @@ public class BookmarkDto {

@QueryProjection
public BookmarkDto(String articleId, String postedDate, String subject, String category, String baseUrl) {
Assert.notNull(articleId, "articleId must not be null");
Assert.notNull(postedDate, "postedDate must not be null");
Assert.notNull(subject, "subject must not be null");
Assert.notNull(category, "category must not be null");
Assert.notNull(baseUrl, "baseUrl must not be null");

this.articleId = articleId;
this.postedDate = postedDate;
this.postedDate = postedDate.split(SPACE)[DATE_INDEX];
this.subject = subject;
this.category = category;
this.baseUrl = baseUrl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public BusinessAdministrationDept(

List<String> professorForumIds = List.of("10499");
this.staffScrapInfo = new StaffScrapInfo(professorForumIds);
this.noticeScrapInfo = new NoticeScrapInfo(BUIS_ADMIN.getKorName(), 441);
this.noticeScrapInfo = new NoticeScrapInfo(BUIS_ADMIN.getKorName(), 437);
this.departmentName = BUIS_ADMIN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private List<Notice> synchronizationWithLibraryDb(List<CommonNoticeFormatDto> sc
return newNotices;
}

// 여기부터는 kUIS 공지
// 여기부터는 KUIS 공지
private List<ComplexNoticeFormatDto> updateKuisNoticeAsync(KuisHomepageNoticeInfo deptInfo, Function<KuisHomepageNoticeInfo, List<ScrapingResultDto>> decisionMaker) {
return scrapperTemplate.scrap(deptInfo, decisionMaker);
}
Expand Down Expand Up @@ -136,7 +136,7 @@ private List<Notice> compareLatestAndUpdateDB(List<ComplexNoticeFormatDto> scrap
return newNoticeList;
}

private void compareAllAndUpdateDB(List<ComplexNoticeFormatDto> scrapResults, CategoryName categoryName) {
public void compareAllAndUpdateDB(List<ComplexNoticeFormatDto> scrapResults, CategoryName categoryName) {
if (scrapResults.isEmpty()) {
return;
}
Expand All @@ -157,12 +157,39 @@ private void compareAllAndUpdateDB(List<ComplexNoticeFormatDto> scrapResults, Ca
}
}

private List<Notice> saveNewNotices(List<CommonNoticeFormatDto> scrapResults, List<String> savedArticleIds, CategoryName categoryName, boolean important) {
List<Notice> newNotices = noticeUpdateSupport.filteringSoonSaveNotices(scrapResults, savedArticleIds, categoryName, important);
private List<Notice> saveNewNotices(
List<CommonNoticeFormatDto> scrapResults,
List<String> savedArticleIds,
CategoryName categoryName,
boolean important
) {
List<Notice> newNotices = noticeUpdateSupport.
filteringSoonSaveNotices(scrapResults, savedArticleIds, categoryName, important);

if(!important) {
updateNoticesByImportantToNormal(savedArticleIds, newNotices, categoryName);
}

noticeCommandPort.saveAllCategoryNotices(newNotices);
return newNotices;
}

private void updateNoticesByImportantToNormal(
List<String> savedImportantArticleIds,
List<Notice> newNormalNotices,
CategoryName categoryName
) {
List<String> changedImportantArticleIds = new ArrayList<>();
for (Notice notice : newNormalNotices) {
if (Collections.binarySearch(savedImportantArticleIds, notice.getArticleId()) >= 0) { // 정렬되어있다, 이진탐색으로 O(logN)안에 수행
changedImportantArticleIds.add(notice.getArticleId());
newNormalNotices.remove(notice);
}
}

noticeCommandPort.changeNoticeImportantToFalseByArticleId(categoryName, changedImportantArticleIds);
}

private void synchronizationWithDb(List<CommonNoticeFormatDto> scrapResults, List<String> savedArticleIds, CategoryName categoryName, boolean important) {
List<Notice> newNotices = noticeUpdateSupport.filteringSoonSaveNotices(scrapResults, savedArticleIds, categoryName, important);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,31 @@ void lookupAllNoticeByIds() {
assertThat(bookmarks).hasSize(4)
.extracting("articleId", "postedDate", "subject")
.containsExactly(
tuple("4", "2024-01-24 17:27:05", "departmentNotice2"),
tuple("3", "2024-01-22 17:27:05", "departmentNotice1"),
tuple("2", "2024-01-20 17:27:05", "notice2"),
tuple("1", "2024-01-19 17:27:05", "notice1")
tuple("4", "2024-01-24", "departmentNotice2"),
tuple("3", "2024-01-22", "departmentNotice1"),
tuple("2", "2024-01-20", "notice2"),
tuple("1", "2024-01-19", "notice1")
);
}

@DisplayName("공지 중요도를 변경할 수 있다")
@Test
void notice_change_important() {
// given
Notice notice1 = new Notice("1", "2024-01-19 17:27:05", "2023-04-03 17:27:05",
"notice1", CategoryName.BACHELOR, true, "https://www.example.com");
Notice notice2 = new Notice("2", "2024-01-20 17:27:05", "2023-04-03 17:27:05",
"notice2", CategoryName.BACHELOR, true, "https://www.example.com");
Notice notice3 = new Notice("3", "2024-01-20 17:27:05", "2023-04-03 17:27:05",
"notice3", CategoryName.BACHELOR, true, "https://www.example.com");

noticeCommandPort.saveAllCategoryNotices(List.of(notice1, notice2, notice3));

// when
noticeCommandPort.changeNoticeImportantToFalseByArticleId(CategoryName.BACHELOR, List.of("1", "2"));

// then
List<String> normalArticleIds = noticeQueryPort.findNormalArticleIdsByCategoryName(CategoryName.BACHELOR);
assertThat(normalArticleIds).containsExactly("1", "2");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,30 @@
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.NullAndEmptySource;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;

class NoticeDateTimeTest {

@DisplayName("날짜 시간이 있는 경우 yyyy-MM-dd HH:mm:ss 형태를 생성한다")
@DisplayName("날짜 시간이 있는 경우 내부적으로 yyyy-MM-dd HH:mm:ss 형태를 생성하고 반환시에는 yyyy-MM-dd 형태로 반환한다")
@Test
void date_time_test() {
// given
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse("2023-04-03 00:00:12", formatter);
String postedDate = "2023-04-03 00:00:12";
String updatedDate = "2023-04-04 00:00:12";

// when
NoticeDateTime postDateTime =
new NoticeDateTime("2023-04-03 00:00:12", "2023-04-03 00:00:12");
NoticeDateTime postDateTime = new NoticeDateTime(postedDate, updatedDate);

// then
assertAll(
() -> assertThat(dateTime.format(formatter)).isEqualTo(postDateTime.postedDateStr()),
() -> assertThat(dateTime.format(formatter)).isEqualTo(postDateTime.updatedDateStr())
() -> assertThat(postDateTime.postedDateStr()).isEqualTo("2023-04-03"),
() -> assertThat(postDateTime.updatedDateStr()).isEqualTo("2023-04-04")
);
}

@DisplayName("날짜만 있는 경우에도 시간을 현재 시분초로 설정하여 yyyy-MM-dd HH:mm:ss 형태를 생성한다")
@DisplayName("날짜만 있는 경우에도 시간을 현재 시분초로 설정하여 내부적으로 yyyy-MM-dd HH:mm:ss 형태를 생성하고 반환시 yyyy-MM-dd 형태로 반환한다")
@Test
void date_test() {
// when
Expand All @@ -44,13 +40,13 @@ void date_test() {
// then
assertAll(
() -> assertThat(postDateTime.postedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$"),
.containsPattern("^\\d{4}-\\d{2}-\\d{2}"),
() -> assertThat(postDateTime.updatedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$")
.containsPattern("^\\d{4}-\\d{2}-\\d{2}")
);
}

@DisplayName("날짜만 yyyy.MM.dd 처럼 있는 경우에도 yyyy-MM-dd HH:mm:ss 형태를 생성한다")
@DisplayName("날짜만 yyyy.MM.dd 처럼 있는 경우에도 내부적으로 yyyy-MM-dd HH:mm:ss 형태를 생성하고 반환시 yyyy-MM-dd 형태로 반환한다")
@Test
void date_dot_test() {
// when
Expand All @@ -59,13 +55,13 @@ void date_dot_test() {
// then
assertAll(
() -> assertThat(postDateTime.postedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$"),
.containsPattern("^\\d{4}-\\d{2}-\\d{2}"),
() -> assertThat(postDateTime.updatedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$")
.containsPattern("^\\d{4}-\\d{2}-\\d{2}")
);
}

@DisplayName("업데이트 날자가 공지에 없어 null인 경우에도 yyyy-MM-dd HH:mm:ss 형태를 생성한다")
@DisplayName("업데이트 날자가 공지에 없어 null인 경우에도 내부적으로 yyyy-MM-dd HH:mm:ss 형태를 생성하고 반환시 yyyy-MM-dd 형태로 반환한다")
@NullAndEmptySource
@ParameterizedTest
void date_both_null_test(String dateTime) {
Expand All @@ -75,13 +71,13 @@ void date_both_null_test(String dateTime) {
// then
assertAll(
() -> assertThat(postDateTime.postedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$"),
.containsPattern("^\\d{4}-\\d{2}-\\d{2}"),
() -> assertThat(postDateTime.updatedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$")
.containsPattern("^\\d{4}-\\d{2}-\\d{2}")
);
}

@DisplayName("업데이트 날자가 공지에 없어 null인 경우에도 yyyy-MM-dd HH:mm:ss 형태를 생성한다")
@DisplayName("업데이트 날자가 공지에 없어 null인 경우에도 내부적으로 yyyy-MM-dd HH:mm:ss 형태를 생성하고 반환시 yyyy-MM-dd 형태로 반환한다")
@Test
void update_date_null_test() {
// when
Expand All @@ -90,9 +86,9 @@ void update_date_null_test() {
// then
assertAll(
() -> assertThat(postDateTime.postedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$"),
.containsPattern("^\\d{4}-\\d{2}-\\d{2}"),
() -> assertThat(postDateTime.updatedDateStr())
.containsPattern("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$")
.containsPattern("^\\d{4}-\\d{2}-\\d{2}")
);
}

Expand Down
Loading

0 comments on commit 91a6ed5

Please sign in to comment.