diff --git a/src/modules/estimate/estimate.repository.ts b/src/modules/estimate/estimate.repository.ts index c72b49aa..bcd1cd0e 100644 --- a/src/modules/estimate/estimate.repository.ts +++ b/src/modules/estimate/estimate.repository.ts @@ -600,6 +600,7 @@ export const receivedEstimateRepository = { select: { id: true, customerId: true, + moveDate: true, status: true, confirmedEstimateId: true, }, diff --git a/src/modules/estimate/estimate.service.ts b/src/modules/estimate/estimate.service.ts index 5b5ed74c..0b2b72dd 100644 --- a/src/modules/estimate/estimate.service.ts +++ b/src/modules/estimate/estimate.service.ts @@ -3,6 +3,7 @@ import { AppError } from "../../lib/app-error"; import { buildPagination } from "../../utils/pagination.util"; import { runTransaction } from "../../utils/transaction"; +import { notificationService } from "../notification/notification.service"; import { moverEstimateRequestRepository, receivedEstimateRepository } from "./estimate.repository"; import type { ConfirmReceivedEstimateParams, @@ -24,17 +25,35 @@ import type { -DB 결과 API 응답 형태로 가공 */ -/* +/* 2026.07.23 add 김성현 - 받은 견적 목록 비즈니스 로직 - 받은 견적 상세 비즈니스 로직 - 받은 견적 확정 비즈니스 로직 */ +const KST_OFFSET_MS = 9 * 60 * 60 * 1000; + // ============================================================================= // 기사: 고객의 견적 요청 목록 조회 // ============================================================================= +function getKstEndOfDay(date: Date): Date { + const kstDate = new Date(date.getTime() + KST_OFFSET_MS); + + return new Date( + Date.UTC( + kstDate.getUTCFullYear(), + kstDate.getUTCMonth(), + kstDate.getUTCDate(), + 14, + 59, + 59, + 999, + ), + ); +} + function getCursorId(cursor: string | undefined) { if (!cursor) { return undefined; @@ -601,7 +620,7 @@ export const receivedEstimateService = { estimateId, customerId, }: ConfirmReceivedEstimateParams) { - return runTransaction(async (tx) => { + const result = await runTransaction(async (tx) => { //확정 대상 견적 조회 const estimate = await receivedEstimateRepository.findReceivedEstimateForConfirm( estimateRequestId, @@ -702,6 +721,7 @@ export const receivedEstimateService = { //확정 응답 형태 가공 return { estimateRequest: confirmedEstimateRequest, + moveDate: estimate.estimateRequest.moveDate, estimate: { id: confirmedEstimate.id, price: confirmedEstimate.price, @@ -717,5 +737,16 @@ export const receivedEstimateService = { expiredEstimateCount: expiredEstimates.count, }; }); + + await notificationService.createNotification({ + userId: result.estimate.mover.id, + type: "ESTIMATE_CONFIRMED", + title: "견적 확정", + content: "고객님이 회원님의 견적을 확정했습니다.", + linkUrl: "/estimate/received-requests", + expiresAt: getKstEndOfDay(result.moveDate), + }); + + return result; }, }; diff --git a/src/modules/review/review.service.ts b/src/modules/review/review.service.ts index 79e1be81..a0e4ea26 100644 --- a/src/modules/review/review.service.ts +++ b/src/modules/review/review.service.ts @@ -3,6 +3,7 @@ import { EstimateRequestStatus, EstimateStatus, Prisma } from "@prisma/client"; import { AppError } from "../../lib/app-error"; import { buildPagination } from "../../utils/pagination.util"; import { runTransaction } from "../../utils/transaction"; +import { notificationService } from "../notification/notification.service"; import { reviewRepository } from "./review.repository"; type GetMyReviewListParams = { @@ -260,6 +261,15 @@ export const reviewService = { }, ); + await notificationService.createNotification({ + userId: estimate.moverId, + type: "REVIEW_RECEIVED", + title: "리뷰 도착", + content: "고객님이 회원님에게 리뷰를 작성했습니다.", + linkUrl: null, + expiresAt: null, + }); + return { review, };