[
  {
    "pr_no": 405,
    "file_path": "src/reviews/reviews.service.ts",
    "status": "modified",
    "patch": "@@ -9,6 +9,10 @@ import { MeetReview } from './schemas/meet-review.schema';\n export class ReviewsService {\n   constructor(@InjectModel(MeetReview.name) private reviewModel: Model<MeetReview>) {}\n \n+  reviewDeadlineAt(meetAt: Date): Date {\n+    return new Date(meetAt.getTime() + 72 * 60 * 60 * 1000);\n+  }\n+\n   async create(dto: CreateMeetReviewDto, appointment: Appointment) {\n     return this.reviewModel.create({ ...dto, appointmentId: appointment.id });\n   }"
  },
  {
    "pr_no": 412,
    "file_path": "src/notifications/templates/review-reminder.ts",
    "status": "modified",
    "patch": "@@ -1,4 +1,4 @@\n export const reviewReminder = {\n-  title: '만남 후기를 남겨 주세요',\n-  body: '오늘 만남은 어떠셨나요? 후기를 남기면 다음 매칭에 반영됩니다.',\n+  title: '오늘 만남, 어떠셨어요?',\n+  body: '후기를 남겨 주시면 다음 소개에 반영합니다.',\n };"
  },
  {
    "pr_no": 413,
    "file_path": "src/reviews/reviews.service.ts",
    "status": "modified",
    "patch": "@@ -14,6 +14,9 @@ export class ReviewsService {\n   }\n \n   async create(dto: CreateMeetReviewDto, appointment: Appointment) {\n+    if (Date.now() > this.reviewDeadlineAt(appointment.meetAt).getTime()) {\n+      throw new ForbiddenException('후기 작성 기한이 지났습니다.');\n+    }\n     return this.reviewModel.create({ ...dto, appointmentId: appointment.id });\n   }\n }"
  },
  {
    "pr_no": 415,
    "file_path": "migrations/20261006091500-rename-job-title.js",
    "status": "added",
    "patch": "@@ -0,0 +1,15 @@\n+module.exports = {\n+  async up(db) {\n+    await db.collection('members').updateMany(\n+      { jobTitle: { $exists: true } },\n+      { $rename: { jobTitle: 'occupation' } },\n+    );\n+  },\n+\n+  async down(db) {\n+    await db.collection('members').updateMany(\n+      { occupation: { $exists: true } },\n+      { $rename: { occupation: 'jobTitle' } },\n+    );\n+  },\n+};"
  },
  {
    "pr_no": 415,
    "file_path": "src/members/members.service.ts",
    "status": "modified",
    "patch": "@@ -9,6 +9,6 @@ export class MembersService {\n \n   async profileCard(memberId: string) {\n     const member = await this.memberModel.findById(memberId).lean();\n-    return { nickname: member.nickname, jobTitle: member.jobTitle };\n+    return { nickname: member.nickname, occupation: member.occupation };\n   }\n }"
  },
  {
    "pr_no": 415,
    "file_path": "src/members/schemas/member.schema.ts",
    "status": "modified",
    "patch": "@@ -6,7 +6,7 @@ export class Member {\n   nickname: string;\n \n   @Prop()\n-  jobTitle?: string;\n+  occupation?: string;\n \n   @Prop({ default: false })\n   incomeVerified: boolean;"
  },
  {
    "pr_no": 416,
    "file_path": "src/reviews/dto/create-meet-review.dto.ts",
    "status": "modified",
    "patch": "@@ -10,4 +10,9 @@ export class CreateMeetReviewDto {\n   @IsOptional()\n   @IsString()\n   comment?: string;\n+\n+  @ApiPropertyOptional({ description: '만남 평가의 늦게 옴 항목에 남긴 이유' })\n+  @IsOptional()\n+  @IsString()\n+  lateReason?: string;\n }"
  },
  {
    "pr_no": 416,
    "file_path": "src/reviews/schemas/meet-review.schema.ts",
    "status": "modified",
    "patch": "@@ -13,6 +13,9 @@ export class MeetReview {\n \n   @Prop()\n   comment?: string;\n+\n+  @Prop()\n+  lateReason?: string;\n }\n \n export const MeetReviewSchema = SchemaFactory.createForClass(MeetReview);"
  },
  {
    "pr_no": 417,
    "file_path": "src/notifications/appointment-confirmed.ts",
    "status": "modified",
    "patch": "@@ -4,6 +4,7 @@ import { Member } from '../members/schemas/member.schema';\n export function appointmentConfirmedLines(appointment: Appointment, partner: Member): string[] {\n   const lines = [\n     `${partner.nickname}님과의 약속이 확정됐습니다.`,\n+    `상대 직업: ${partner.occupation ?? '비공개'}`,\n     `장소: ${appointment.placeName}`,\n   ];\n   return lines;"
  },
  {
    "pr_no": 418,
    "file_path": "src/appointments/appointments.service.ts",
    "status": "modified",
    "patch": "@@ -14,4 +14,10 @@ export class AppointmentsService {\n   async upcoming(memberId: string) {\n     return this.appointmentModel.find({ memberIds: memberId, meetAt: { $gte: new Date() } });\n   }\n+\n+  async lateNotice(lastAppointmentId: string): Promise<string | null> {\n+    const review = await this.reviewModel.findOne({ appointmentId: lastAppointmentId });\n+    if (!review?.lateReason) return null;\n+    return `지난 만남에 늦게 왔다는 평가가 있었습니다: ${review.lateReason}`;\n+  }\n }"
  },
  {
    "pr_no": 421,
    "file_path": "openapi.json",
    "status": "modified",
    "patch": "@@ -1,106 +1,121 @@\n {\n   \"openapi\": \"3.0.0\",\n   \"info\": {\n     \"title\": \"W Club API\",\n     \"version\": \"2.10.0\"\n   },\n   \"paths\": {\n     \"/appointments\": {\n       \"get\": {\n         \"operationId\": \"AppointmentsController_list\",\n         \"responses\": {\n           \"200\": {\n             \"description\": \"\",\n             \"content\": {\n               \"application/json\": {\n                 \"schema\": {\n                   \"type\": \"array\",\n                   \"items\": {\n                     \"$ref\": \"#/components/schemas/AppointmentDto\"\n                   }\n                 }\n               }\n             }\n           }\n         }\n       }\n     },\n     \"/appointments/{id}\": {\n       \"get\": {\n         \"operationId\": \"AppointmentsController_get\",\n         \"responses\": {\n           \"200\": {\n             \"description\": \"\",\n             \"content\": {\n               \"application/json\": {\n                 \"schema\": {\n                   \"$ref\": \"#/components/schemas/AppointmentDto\"\n                 }\n               }\n             }\n           }\n         }\n       }\n     },\n     \"/me/badges\": {\n       \"get\": {\n         \"operationId\": \"BadgesController_mine\",\n         \"responses\": {\n           \"200\": {\n             \"description\": \"\",\n             \"content\": {\n               \"application/json\": {\n                 \"schema\": {\n                   \"type\": \"array\",\n                   \"items\": {\n                     \"$ref\": \"#/components/schemas/BadgeDto\"\n                   }\n                 }\n               }\n             }\n           }\n         }\n       }\n     }\n   },\n   \"components\": {\n     \"schemas\": {\n       \"AppointmentDto\": {\n         \"type\": \"object\",\n         \"properties\": {\n           \"id\": {\n             \"type\": \"string\"\n           },\n           \"meetAt\": {\n             \"type\": \"string\",\n             \"format\": \"date-time\"\n           },\n-          \"placeName\": {\n-            \"type\": \"string\"\n+          \"place\": {\n+            \"$ref\": \"#/components/schemas/PlaceDto\"\n           }\n         },\n         \"required\": [\n           \"id\",\n           \"meetAt\",\n-          \"placeName\"\n+          \"place\"\n+        ]\n+      },\n+      \"PlaceDto\": {\n+        \"type\": \"object\",\n+        \"properties\": {\n+          \"name\": {\n+            \"type\": \"string\"\n+          },\n+          \"address\": {\n+            \"type\": \"string\"\n+          }\n+        },\n+        \"required\": [\n+          \"name\",\n+          \"address\"\n         ]\n       },\n       \"BadgeDto\": {\n         \"type\": \"object\",\n         \"properties\": {\n           \"code\": {\n             \"type\": \"string\"\n           },\n           \"earnedAt\": {\n             \"type\": \"string\",\n             \"format\": \"date\"\n           }\n         },\n         \"required\": [\n           \"code\",\n           \"earnedAt\"\n         ]\n       }\n     }\n   }\n }"
  },
  {
    "pr_no": 421,
    "file_path": "src/appointments/dto/appointment.dto.ts",
    "status": "modified",
    "patch": "@@ -1,5 +1,13 @@\n import { ApiProperty } from '@nestjs/swagger';\n \n+export class PlaceDto {\n+  @ApiProperty()\n+  name: string;\n+\n+  @ApiProperty()\n+  address: string;\n+}\n+\n export class AppointmentDto {\n   @ApiProperty()\n   id: string;\n@@ -7,6 +15,6 @@ export class AppointmentDto {\n   @ApiProperty({ format: 'date-time' })\n   meetAt: string;\n \n-  @ApiProperty()\n-  placeName: string;\n+  @ApiProperty({ type: () => PlaceDto })\n+  place: PlaceDto;\n }"
  },
  {
    "pr_no": 422,
    "file_path": "openapi.json",
    "status": "modified",
    "patch": "@@ -1,106 +1,106 @@\n {\n   \"openapi\": \"3.0.0\",\n   \"info\": {\n     \"title\": \"W Club API\",\n     \"version\": \"2.10.0\"\n   },\n   \"paths\": {\n     \"/appointments\": {\n       \"get\": {\n         \"operationId\": \"AppointmentsController_list\",\n         \"responses\": {\n           \"200\": {\n             \"description\": \"\",\n             \"content\": {\n               \"application/json\": {\n                 \"schema\": {\n                   \"type\": \"array\",\n                   \"items\": {\n                     \"$ref\": \"#/components/schemas/AppointmentDto\"\n                   }\n                 }\n               }\n             }\n           }\n         }\n       }\n     },\n     \"/appointments/{id}\": {\n       \"get\": {\n         \"operationId\": \"AppointmentsController_get\",\n         \"responses\": {\n           \"200\": {\n             \"description\": \"\",\n             \"content\": {\n               \"application/json\": {\n                 \"schema\": {\n                   \"$ref\": \"#/components/schemas/AppointmentDto\"\n                 }\n               }\n             }\n           }\n         }\n       }\n     },\n     \"/me/badges\": {\n       \"get\": {\n         \"operationId\": \"BadgesController_mine\",\n         \"responses\": {\n           \"200\": {\n             \"description\": \"\",\n             \"content\": {\n               \"application/json\": {\n                 \"schema\": {\n                   \"type\": \"array\",\n                   \"items\": {\n                     \"$ref\": \"#/components/schemas/BadgeDto\"\n                   }\n                 }\n               }\n             }\n           }\n         }\n       }\n     }\n   },\n   \"components\": {\n     \"schemas\": {\n       \"AppointmentDto\": {\n         \"type\": \"object\",\n         \"properties\": {\n           \"id\": {\n             \"type\": \"string\"\n           },\n           \"meetAt\": {\n             \"type\": \"string\",\n             \"format\": \"date-time\"\n           },\n           \"placeName\": {\n             \"type\": \"string\"\n           }\n         },\n         \"required\": [\n           \"id\",\n           \"meetAt\",\n           \"placeName\"\n         ]\n       },\n       \"BadgeDto\": {\n         \"type\": \"object\",\n         \"properties\": {\n           \"code\": {\n             \"type\": \"string\"\n           },\n           \"earnedAt\": {\n             \"type\": \"string\",\n-            \"format\": \"date\"\n+            \"format\": \"date-time\"\n           }\n         },\n         \"required\": [\n           \"code\",\n           \"earnedAt\"\n         ]\n       }\n     }\n   }\n }"
  },
  {
    "pr_no": 422,
    "file_path": "src/badges/dto/badge.dto.ts",
    "status": "modified",
    "patch": "@@ -4,6 +4,6 @@ export class BadgeDto {\n   @ApiProperty()\n   code: string;\n \n-  @ApiProperty({ format: 'date' })\n+  @ApiProperty({ format: 'date-time' })\n   earnedAt: string;\n }"
  },
  {
    "pr_no": 423,
    "file_path": "assets/badges/photo-verified-v2@3x.png",
    "status": "added",
    "patch": null
  },
  {
    "pr_no": 423,
    "file_path": "src/badges/badge-images.ts",
    "status": "modified",
    "patch": "@@ -1,4 +1,4 @@\n export const badgeImages = {\n   incomeVerified: 'assets/badges/income-verified@3x.png',\n-  photoVerified: 'assets/badges/photo-verified@3x.png',\n+  photoVerified: 'assets/badges/photo-verified-v2@3x.png',\n };"
  }
]