17ab1098ec
PayInstallmentStep(Step 4.5): 1200%룰로 이연된 분급(installment_plan SCHEDULED)을 도래월(settle_month=정산월)에 recruit_ledger로 편입해 실제 지급. 이전엔 이연만 되고 도래월 지급 절차가 없어 차액이 영구 미지급되던 갭을 메움. - BatchConfig job flow에 step4b(calcRecruit→payInstallment→calcMaintain) 등록 - InstallmentPlanMapper.resetPaidToScheduledByMonth(+XML)로 재실행 멱등 (진입 시 PAID→SCHEDULED 역산, Step4 deleteBySettleMonth가 원장 정리) - RecruitLedgerMapper insert에 reconcile_status 컬럼, SettlementContext.installmentPaidCount - 단위테스트 3건(정상지급/멱등/계약미존재) GREEN 신입교육 주석: 컨트롤러/서비스/공통/프론트 전반에 도메인·코드 설명 주석 추가 (동작 변경 없음 — 빌드/테스트/타입체크 전부 GREEN으로 무회귀 확인). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
75 lines
2.9 KiB
Java
75 lines
2.9 KiB
Java
package com.ga.common.notification;
|
|
|
|
import com.ga.common.exception.BizException;
|
|
import com.ga.common.exception.ErrorCode;
|
|
import com.ga.common.util.SecurityUtil;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.util.List;
|
|
|
|
/**
|
|
* 앱 내(in-app) 알림 서비스.
|
|
* <p>
|
|
* 신입 메모: 이건 화면 종(벨) 아이콘에 쌓이는 "사내 알림"을 DB에 적재/조회하는 기능이다.
|
|
* 외부로 나가는 SMS/알림톡/푸시(adapter 패키지)와는 별개이며, 보통 업무 이벤트가 나면
|
|
* {@link #send}로 알림을 한 건 적재하고, 사용자는 목록/안읽음 개수를 조회하고 읽음 처리한다.
|
|
* 대부분의 메서드는 {@link SecurityUtil}로 현재 로그인 사용자를 기준으로 동작한다.
|
|
*/
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
public class NotificationService {
|
|
|
|
private final NotificationMapper mapper;
|
|
|
|
/** 현재 사용자의 알림 목록. 미로그인 시 UNAUTHORIZED. */
|
|
public List<NotificationVO> myNotifications() {
|
|
Long userId = SecurityUtil.getCurrentUserId();
|
|
if (userId == null) throw new BizException(ErrorCode.UNAUTHORIZED);
|
|
return mapper.selectByUser(userId);
|
|
}
|
|
|
|
/** 현재 사용자의 안읽음 알림 개수 (벨 배지용). 미로그인 시 0. */
|
|
public int unreadCount() {
|
|
Long userId = SecurityUtil.getCurrentUserId();
|
|
if (userId == null) return 0;
|
|
return mapper.countUnread(userId);
|
|
}
|
|
|
|
/** 특정 알림 1건을 읽음 처리 (본인 알림만). */
|
|
@Transactional
|
|
public void markRead(Long notiId) {
|
|
Long userId = SecurityUtil.getCurrentUserId();
|
|
if (userId == null) throw new BizException(ErrorCode.UNAUTHORIZED);
|
|
mapper.markRead(notiId, userId);
|
|
}
|
|
|
|
/** 현재 사용자의 모든 알림을 읽음 처리. */
|
|
@Transactional
|
|
public void markAllRead() {
|
|
Long userId = SecurityUtil.getCurrentUserId();
|
|
if (userId == null) throw new BizException(ErrorCode.UNAUTHORIZED);
|
|
mapper.markAllRead(userId);
|
|
}
|
|
|
|
/** 알림 1건 적재(발송). 다른 도메인이 업무 이벤트 발생 시 호출한다. linkUrl은 클릭 시 이동 경로. */
|
|
@Transactional
|
|
public void send(Long userId, String type, String title, String content, String linkUrl) {
|
|
NotificationVO vo = new NotificationVO();
|
|
vo.setUserId(userId);
|
|
vo.setNotiType(type);
|
|
vo.setTitle(title);
|
|
vo.setContent(content);
|
|
vo.setLinkUrl(linkUrl);
|
|
mapper.insert(vo);
|
|
}
|
|
|
|
/** 여러 사용자에게 한 번에 알림 적재 (정산 완료 등 대량 발송용). 빈 목록은 무시. */
|
|
@Transactional
|
|
public void sendBatch(List<NotificationVO> list) {
|
|
if (list == null || list.isEmpty()) return;
|
|
mapper.insertBatch(list);
|
|
}
|
|
}
|