|
|
# backend/app/seed_mail.py — mail-data.js / notify-data.js 이식
|
|
|
from sqlmodel import Session
|
|
|
|
|
|
from .models import (
|
|
|
Digest,
|
|
|
Notification,
|
|
|
NotificationGuard,
|
|
|
NotifyBucket,
|
|
|
NotifyStats,
|
|
|
Person,
|
|
|
SenderRule,
|
|
|
)
|
|
|
|
|
|
# ---- 메일 전용 추가 발신자 (mail-data.js people) ----
|
|
|
# (id, name, initial, color, email, role)
|
|
|
MAIL_PEOPLE = [
|
|
|
("daepyo", "서지원 대표", "서", "var(--coral)", "jiwon@lumi.co", "대표이사"),
|
|
|
("bank", "우리카드", "우", "oklch(0.6 0.12 250)", "no-reply@wooricard.com", "카드 명세"),
|
|
|
("book", "수요 독서모임", "독", "oklch(0.62 0.1 150)", "club@bookwed.kr", "모임 운영"),
|
|
|
("stripe", "Stripe", "S", "oklch(0.6 0.15 285)", "receipts@stripe.com", "결제 영수증"),
|
|
|
(
|
|
|
"recruit",
|
|
|
"박서연 (지원자)",
|
|
|
"박",
|
|
|
"oklch(0.64 0.12 30)",
|
|
|
"seoyeon.p@gmail.com",
|
|
|
"프로덕트 디자이너 지원",
|
|
|
),
|
|
|
]
|
|
|
# 기존 person(현우/민서/수아/재호)에 메일 email/role 보강
|
|
|
PEOPLE_MAIL_INFO = {
|
|
|
"hyunwoo": ("hyunwoo@lumi.co", "프로덕트 디자이너"),
|
|
|
"minseo": ("minseo@lumi.co", "팀 리드"),
|
|
|
"sua": ("sua@lumi.co", "UX 리서처"),
|
|
|
"jaeho": ("jaeho@lumi.co", "데이터 분석"),
|
|
|
"jiwoo": ("jiwoo@lumi.co", "PM"),
|
|
|
}
|
|
|
|
|
|
MAIL_ACCOUNTS = [
|
|
|
("work", "회사", "jiwoo@lumi.co", "coral", "Lumi Workspace", 3),
|
|
|
("personal", "개인", "jiwoo.kim@gmail.com", "blue", "Google", 2),
|
|
|
("side", "사이드", "jiwoo@hey.com", "violet", "HEY", 1),
|
|
|
]
|
|
|
MAIL_FOLDERS = [
|
|
|
("inbox", "받은편지함", "inbox", 0),
|
|
|
("starred", "별표", "star", 1),
|
|
|
("sent", "보낸편지함", "send", 2),
|
|
|
("drafts", "임시보관함", "file", 3),
|
|
|
("archive", "보관함", "archive", 4),
|
|
|
]
|
|
|
|
|
|
|
|
|
def _P(s: str) -> list:
|
|
|
return [t.strip() for t in s.split("\n") if t.strip()]
|
|
|
|
|
|
|
|
|
EMAILS = [
|
|
|
{
|
|
|
"id": "m1",
|
|
|
"account": "work",
|
|
|
"from_key": "hyunwoo",
|
|
|
"to": "나",
|
|
|
"subject": "온보딩 시안 v3 — 금요일까지 피드백 부탁드려요",
|
|
|
"time": "8분 전",
|
|
|
"date": "오늘 09:12",
|
|
|
"read": False,
|
|
|
"starred": False,
|
|
|
"has_attach": True,
|
|
|
"attachments": [
|
|
|
{"name": "온보딩_v3.fig", "size": "4.2MB"},
|
|
|
{"name": "변경사항_요약.pdf", "size": "320KB"},
|
|
|
],
|
|
|
"labels": ["디자인"],
|
|
|
"preview": "지우님, 리뷰에서 나온 코멘트 반영해서 v3 정리했어요. 환영·권한요청·음성안내 3개 화면이 바뀌었고…",
|
|
|
"body": _P(
|
|
|
"""지우님, 안녕하세요. 현우입니다.
|
|
|
지난 디자인 리뷰에서 주신 코멘트 반영해서 온보딩 시안 v3 정리했습니다. 이번에 바뀐 건 크게 세 화면이에요.
|
|
|
1) 환영 화면 — 카피 톤을 조금 더 친근하게 바꿨고, 일러스트는 교체 요청 넣어둔 상태입니다.
|
|
|
2) 권한 요청 화면 — 요청 순서를 재배치했어요. (알림 → 위치 → 연락처)
|
|
|
3) 음성 안내 화면 — 신규 추가했습니다. 한 번 봐주시면 좋겠어요.
|
|
|
금요일(6/13)까지 피드백 주시면 다음 스프린트에 바로 반영하겠습니다. 피그마 링크랑 변경사항 요약본 첨부했어요. 감사합니다!"""
|
|
|
),
|
|
|
"ai": {
|
|
|
"summary": "온보딩 시안 v3 도착 — 3개 화면(환영·권한요청·음성안내) 수정. 금요일 6/13까지 피드백 요청.",
|
|
|
"priority": "높음",
|
|
|
"category": "검토 요청",
|
|
|
"tasks": [
|
|
|
{
|
|
|
"text": "온보딩 시안 v3 피드백 정리",
|
|
|
"project": "온보딩 리디자인 · 와이어프레임",
|
|
|
"due": "6/13",
|
|
|
"prio": "높음",
|
|
|
},
|
|
|
{
|
|
|
"text": "음성 안내 화면 신규 검토",
|
|
|
"project": "온보딩 리디자인 · 음성 인터페이스",
|
|
|
"due": "6/12",
|
|
|
"prio": "보통",
|
|
|
},
|
|
|
],
|
|
|
"events": [],
|
|
|
"replies": [
|
|
|
{
|
|
|
"tone": "수락 · 일정 약속",
|
|
|
"preview": "금요일까지 피드백 드릴게요",
|
|
|
"body": "현우님, 잘 받았어요! 오늘 중으로 살펴보고 금요일 오전까지 화면별로 코멘트 정리해서 드릴게요. 음성 안내 화면은 특히 꼼꼼히 볼게요. 수고하셨어요 👏",
|
|
|
},
|
|
|
{
|
|
|
"tone": "질문 추가",
|
|
|
"preview": "권한 요청 순서 근거가 궁금해요",
|
|
|
"body": "현우님, 시안 잘 봤어요. 권한 요청 순서를 알림 → 위치 → 연락처로 두신 근거가 따로 있을까요? 리서치 결과랑 연결해서 보면 좋을 것 같아 여쭤봐요.",
|
|
|
},
|
|
|
{
|
|
|
"tone": "간단 확인",
|
|
|
"preview": "확인했고 회신 예정",
|
|
|
"body": "확인했습니다, 현우님! 금요일까지 피드백 드릴게요.",
|
|
|
},
|
|
|
],
|
|
|
"file": {"project": "온보딩 리디자인", "reason": "‘와이어프레임’ 작업과 직접 연결돼요"},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
"id": "m2",
|
|
|
"account": "work",
|
|
|
"from_key": "daepyo",
|
|
|
"to": "나, 재무팀",
|
|
|
"subject": "[중요] 오늘 14시 분기 전략 미팅 — 리포트 초안 공유 부탁",
|
|
|
"time": "42분 전",
|
|
|
"date": "오늘 08:38",
|
|
|
"read": False,
|
|
|
"starred": True,
|
|
|
"has_attach": False,
|
|
|
"labels": ["경영진"],
|
|
|
"preview": "지우님, 오늘 오후 미팅 전에 분기 리포트 초안 미리 돌려볼 수 있을까요? 특히 매출·예산 섹션 위주로…",
|
|
|
"body": _P("""지우님,
|
|
|
오늘 오후 2시 분기 전략 미팅 잘 부탁드려요. 미팅 전에 분기 리포트 초안을 미리 공유해 주시면 다같이 보고 들어갈 수 있을 것 같아요.
|
|
|
특히 매출 섹션과 예산 재배분 안건은 의사결정이 필요한 부분이라, 숫자가 확정된 버전으로 부탁드립니다. 리텐션 지표는 지난번 버전으로도 충분해요.
|
|
|
미팅은 60분, 대회의실입니다. 늦지 않게 시작하면 좋겠어요. 고생 많으십니다.
|
|
|
서지원 드림"""),
|
|
|
"ai": {
|
|
|
"summary": "오늘 14시 분기 전략 미팅 전, 매출·예산 섹션 확정본 리포트 공유 요청. 의사결정 안건 포함.",
|
|
|
"priority": "높음",
|
|
|
"category": "마감 임박",
|
|
|
"tasks": [
|
|
|
{
|
|
|
"text": "분기 리포트 매출 섹션 숫자 확정",
|
|
|
"project": "경영 전략 · 분기 리포트",
|
|
|
"due": "6/10",
|
|
|
"prio": "높음",
|
|
|
},
|
|
|
{
|
|
|
"text": "예산 재배분 안건 1p 요약",
|
|
|
"project": "경영 전략 · 예산 관리",
|
|
|
"due": "6/10",
|
|
|
"prio": "높음",
|
|
|
},
|
|
|
{
|
|
|
"text": "미팅 시작 전 리포트 메일로 공유",
|
|
|
"project": "경영 전략 · 분기 리포트",
|
|
|
"due": "6/10",
|
|
|
"prio": "높음",
|
|
|
},
|
|
|
],
|
|
|
"events": [
|
|
|
{
|
|
|
"title": "분기 전략 미팅",
|
|
|
"date": "6/10",
|
|
|
"day": "오늘",
|
|
|
"time": "14:00",
|
|
|
"dur": "60분",
|
|
|
"place": "대회의실",
|
|
|
},
|
|
|
],
|
|
|
"replies": [
|
|
|
{
|
|
|
"tone": "확정 회신",
|
|
|
"preview": "13시까지 확정본 공유할게요",
|
|
|
"body": "대표님, 확인했습니다. 매출·예산 섹션 숫자 확정해서 오후 1시까지 미팅 참석자분들께 공유드리겠습니다. 예산 재배분 안건은 1페이지 요약 따로 붙여둘게요.",
|
|
|
},
|
|
|
{
|
|
|
"tone": "일부 지연 양해",
|
|
|
"preview": "예산 섹션만 미팅 중 공유",
|
|
|
"body": "대표님, 매출 섹션은 1시까지 확정해서 보내드리겠습니다. 예산 재배분 안건은 재무팀 최종 확인이 오전 중 마무리되는 대로, 늦어도 미팅 직전에 공유드릴게요.",
|
|
|
},
|
|
|
],
|
|
|
"file": {"project": "경영 전략", "reason": "‘분기 리포트’ 마감 작업과 연결돼요"},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
"id": "m3",
|
|
|
"account": "work",
|
|
|
"from_key": "minseo",
|
|
|
"to": "나",
|
|
|
"subject": "오늘 1:1 안건 미리 정리해뒀어요",
|
|
|
"time": "2시간 전",
|
|
|
"date": "오늘 07:50",
|
|
|
"read": False,
|
|
|
"starred": False,
|
|
|
"has_attach": False,
|
|
|
"labels": ["팀"],
|
|
|
"preview": "지우님, 오후 1:1 때 이야기 나누고 싶은 거 두 가지 정리했어요. 1) 하반기 성장 로드맵 2) 업무 분장…",
|
|
|
"body": _P("""지우님, 좋은 아침이에요!
|
|
|
오늘 오후 1:1 때 이야기 나누고 싶은 거 미리 정리해봤어요.
|
|
|
1) 하반기 성장 로드맵 — 제 쪽 OKR이랑 어떻게 맞물리면 좋을지 같이 보면 좋겠어요.
|
|
|
2) 업무 분장 — 리서치 보드 업데이트랑 회고 문서 배포, 둘 중 하나는 재호님께 넘기는 게 어떨까요?
|
|
|
편하게 오시면 됩니다. 이따 봬요 :)"""),
|
|
|
"ai": {
|
|
|
"summary": "오늘 1:1(16:30) 안건 2건: 하반기 성장 로드맵, 업무 분장(재호님께 일부 위임 제안).",
|
|
|
"priority": "보통",
|
|
|
"category": "준비 필요",
|
|
|
"tasks": [
|
|
|
{
|
|
|
"text": "1:1 전 하반기 로드맵 초안 훑어보기",
|
|
|
"project": "팀 운영",
|
|
|
"due": "6/10",
|
|
|
"prio": "보통",
|
|
|
},
|
|
|
],
|
|
|
"events": [
|
|
|
{
|
|
|
"title": "1:1 — 민서님",
|
|
|
"date": "6/10",
|
|
|
"day": "오늘",
|
|
|
"time": "16:30",
|
|
|
"dur": "30분",
|
|
|
"place": "포커스룸 B",
|
|
|
},
|
|
|
],
|
|
|
"replies": [
|
|
|
{
|
|
|
"tone": "준비해서 갈게요",
|
|
|
"preview": "로드맵 보고 갈게요",
|
|
|
"body": "민서님, 정리 고마워요! 1:1 전에 하반기 로드맵 초안 한 번 보고 갈게요. 업무 분장은 재호님 일정도 같이 보면서 정리하면 좋겠어요. 이따 봬요 :)",
|
|
|
},
|
|
|
],
|
|
|
"file": {"project": "팀 운영", "reason": "1:1·업무 분장 관련 항목이에요"},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
"id": "m4",
|
|
|
"account": "personal",
|
|
|
"from_key": "bank",
|
|
|
"to": "나",
|
|
|
"subject": "[우리카드] 6월 결제 예정 명세서 안내",
|
|
|
"time": "5시간 전",
|
|
|
"date": "오늘 04:30",
|
|
|
"read": False,
|
|
|
"starred": False,
|
|
|
"has_attach": False,
|
|
|
"labels": ["금융"],
|
|
|
"preview": "고객님의 6월 결제 예정 금액은 1,284,500원입니다. 결제일은 6월 25일이며, 등록된 카드…",
|
|
|
"body": _P("""안녕하세요, 우리카드입니다.
|
|
|
고객님의 6월 결제 예정 금액을 안내드립니다.
|
|
|
· 결제 예정 금액: 1,284,500원
|
|
|
· 결제 예정일: 2026년 6월 25일
|
|
|
· 결제 계좌: 우리은행 (***-12)
|
|
|
※ 등록하신 결제 카드의 유효기간이 6월 말 만료될 예정입니다. 자동 결제 중단을 막으려면 카드 정보를 갱신해 주세요.
|
|
|
본 메일은 발신 전용입니다."""),
|
|
|
"ai": {
|
|
|
"summary": "6월 결제 예정 1,284,500원(6/25). 결제 카드 유효기간 6월 말 만료 → 갱신 필요.",
|
|
|
"priority": "보통",
|
|
|
"category": "금융 · 액션 필요",
|
|
|
"tasks": [
|
|
|
{
|
|
|
"text": "구독 결제 카드 정보 갱신 (말일 전)",
|
|
|
"project": "개인",
|
|
|
"due": "6/28",
|
|
|
"prio": "보통",
|
|
|
},
|
|
|
],
|
|
|
"events": [
|
|
|
{
|
|
|
"title": "카드 결제일 (1,284,500원)",
|
|
|
"date": "6/25",
|
|
|
"day": "수",
|
|
|
"time": "종일",
|
|
|
"dur": "",
|
|
|
"place": "",
|
|
|
},
|
|
|
],
|
|
|
"replies": [],
|
|
|
"file": {"project": "개인", "reason": "결제·구독 관리 항목이에요"},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
"id": "m5",
|
|
|
"account": "side",
|
|
|
"from_key": "book",
|
|
|
"to": "나",
|
|
|
"subject": "이번 주 수요 독서모임 — 6/12 저녁 7시 ‘몰입’ 2부",
|
|
|
"time": "어제",
|
|
|
"date": "6월 9일 18:20",
|
|
|
"read": False,
|
|
|
"starred": False,
|
|
|
"has_attach": False,
|
|
|
"labels": ["모임"],
|
|
|
"preview": "이번 주는 ‘몰입(Deep Work)’ 2부를 다룹니다. 장소는 합정 모임공간, 저녁 7시예요. 발제는…",
|
|
|
"body": _P(
|
|
|
"""안녕하세요, 수요 독서모임입니다.
|
|
|
이번 주 모임 안내드려요.
|
|
|
· 일시: 6월 12일(목) 저녁 7시
|
|
|
· 장소: 합정 모임공간 ‘책상’
|
|
|
· 범위: ‘몰입(Deep Work)’ 2부 (128~210쪽)
|
|
|
· 발제: 지우님 (2장 담당)
|
|
|
지우님이 이번 주 2장 발제 맡아주셨어요. 부담 갖지 마시고 인상 깊었던 부분 위주로 준비해오시면 됩니다. 곧 뵐게요!"""
|
|
|
),
|
|
|
"ai": {
|
|
|
"summary": "6/12(목) 19시 독서모임 ‘몰입’ 2부. 지우님이 2장 발제 담당.",
|
|
|
"priority": "보통",
|
|
|
"category": "개인 일정",
|
|
|
"tasks": [
|
|
|
{
|
|
|
"text": "‘몰입’ 2장 발제 준비 (128~210쪽)",
|
|
|
"project": "개인 · 성장",
|
|
|
"due": "6/12",
|
|
|
"prio": "보통",
|
|
|
},
|
|
|
],
|
|
|
"events": [
|
|
|
{
|
|
|
"title": "수요 독서모임 (2장 발제)",
|
|
|
"date": "6/12",
|
|
|
"day": "목",
|
|
|
"time": "19:00",
|
|
|
"dur": "120분",
|
|
|
"place": "합정 ‘책상’",
|
|
|
},
|
|
|
],
|
|
|
"replies": [
|
|
|
{
|
|
|
"tone": "참석 확정",
|
|
|
"preview": "발제 준비해서 갈게요",
|
|
|
"body": "안녕하세요! 6/12 참석합니다. 2장 발제 준비해서 갈게요. 인상 깊었던 부분 위주로 정리해볼게요. 곧 뵐게요 :)",
|
|
|
},
|
|
|
],
|
|
|
"file": {"project": "개인", "reason": "독서·성장 관련 일정이에요"},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
"id": "m6",
|
|
|
"account": "work",
|
|
|
"from_key": "recruit",
|
|
|
"to": "나",
|
|
|
"subject": "프로덕트 디자이너 지원합니다 — 박서연 포트폴리오",
|
|
|
"time": "어제",
|
|
|
"date": "6월 9일 14:05",
|
|
|
"read": True,
|
|
|
"starred": False,
|
|
|
"has_attach": True,
|
|
|
"attachments": [{"name": "박서연_포트폴리오.pdf", "size": "12MB"}],
|
|
|
"labels": ["채용"],
|
|
|
"preview": "안녕하세요, 프로덕트 디자이너 직무에 지원하는 박서연입니다. 5년 차 디자이너로 모바일 앱…",
|
|
|
"body": _P("""안녕하세요, 채용 담당자님.
|
|
|
프로덕트 디자이너 직무에 지원하는 박서연입니다. 5년 차 디자이너로, 핀테크와 헬스케어 분야 모바일 앱 디자인을 주로 해왔습니다.
|
|
|
특히 온보딩 플로우 개선으로 전환율을 23% 높인 경험이 있어, Lumi의 온보딩 리디자인 방향성과 잘 맞을 것 같아 지원하게 되었습니다.
|
|
|
포트폴리오 첨부드립니다. 검토 후 연락 주시면 감사하겠습니다."""),
|
|
|
"ai": {
|
|
|
"summary": "프로덕트 디자이너 지원(5년 차, 온보딩 전환율 +23% 경험). 포트폴리오 첨부.",
|
|
|
"priority": "보통",
|
|
|
"category": "채용",
|
|
|
"tasks": [
|
|
|
{
|
|
|
"text": "박서연 포트폴리오 검토 & 1차 의견",
|
|
|
"project": "팀 운영 · 채용 & 온보딩",
|
|
|
"due": "6/13",
|
|
|
"prio": "보통",
|
|
|
},
|
|
|
],
|
|
|
"events": [],
|
|
|
"replies": [
|
|
|
{
|
|
|
"tone": "검토 후 회신 약속",
|
|
|
"preview": "검토 후 다음 주 연락드릴게요",
|
|
|
"body": "박서연님, 지원해 주셔서 감사합니다. 포트폴리오 잘 받았습니다. 내부 검토 후 다음 주 초 연락드리겠습니다. 좋은 하루 보내세요!",
|
|
|
},
|
|
|
],
|
|
|
"file": {"project": "팀 운영", "reason": "‘채용 & 온보딩’ 작업과 연결돼요"},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
"id": "m7",
|
|
|
"account": "personal",
|
|
|
"from_key": "stripe",
|
|
|
"to": "나",
|
|
|
"subject": "Your receipt from ChatGPT Plus — $20.00",
|
|
|
"time": "2일 전",
|
|
|
"date": "6월 8일 09:00",
|
|
|
"read": True,
|
|
|
"starred": False,
|
|
|
"has_attach": False,
|
|
|
"labels": ["영수증"],
|
|
|
"preview": "Receipt #2451-0098 · ChatGPT Plus Subscription · $20.00 paid on Jun 8, 2026…",
|
|
|
"body": _P("""Receipt from OpenAI, LLC
|
|
|
Amount paid: $20.00
|
|
|
Date: June 8, 2026
|
|
|
Subscription: ChatGPT Plus (monthly)
|
|
|
Payment method: Visa ···· 4242
|
|
|
Thank you for your business."""),
|
|
|
"ai": {
|
|
|
"summary": "ChatGPT Plus 월 구독 $20 결제 영수증. 별도 조치 불필요.",
|
|
|
"priority": "낮음",
|
|
|
"category": "영수증",
|
|
|
"tasks": [],
|
|
|
"events": [],
|
|
|
"replies": [],
|
|
|
"file": {"project": "개인", "reason": "구독 영수증으로 보관하면 좋아요"},
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
"id": "m8",
|
|
|
"account": "work",
|
|
|
"from_key": "jaeho",
|
|
|
"to": "나, 수아",
|
|
|
"subject": "리텐션 코호트 데이터 v2 — 이탈 사유 태깅 완료",
|
|
|
"time": "2일 전",
|
|
|
"date": "6월 8일 17:42",
|
|
|
"read": True,
|
|
|
"starred": False,
|
|
|
"has_attach": True,
|
|
|
"attachments": [{"name": "retention_cohort_v2.xlsx", "size": "880KB"}],
|
|
|
"labels": ["데이터"],
|
|
|
"preview": "지우님, 수아님. 이탈 사유 태깅까지 끝내서 코호트 데이터 v2 올려요. 주차별 잔존율이랑…",
|
|
|
"body": _P(
|
|
|
"""지우님, 수아님.
|
|
|
이탈 사유 태깅까지 마무리해서 리텐션 코호트 데이터 v2 공유드려요. 주차별 잔존율, 코호트별 이탈 사유 분포까지 정리돼 있습니다.
|
|
|
분기 리포트 리텐션 섹션에 바로 쓰실 수 있게 시각화용 표도 시트 2번에 넣어뒀어요. 추가로 필요한 분석 있으면 말씀 주세요."""
|
|
|
),
|
|
|
"ai": {
|
|
|
"summary": "리텐션 코호트 v2 완료(이탈 사유 태깅 포함). 리포트용 시각화 표 포함.",
|
|
|
"priority": "보통",
|
|
|
"category": "데이터 수신",
|
|
|
"tasks": [
|
|
|
{
|
|
|
"text": "코호트 v2 표 → 분기 리포트 리텐션 섹션 반영",
|
|
|
"project": "경영 전략 · 분기 리포트",
|
|
|
"due": "6/10",
|
|
|
"prio": "보통",
|
|
|
},
|
|
|
],
|
|
|
"events": [],
|
|
|
"replies": [
|
|
|
{
|
|
|
"tone": "감사 + 확인",
|
|
|
"preview": "리포트에 반영할게요",
|
|
|
"body": "재호님, 수고하셨어요! 시각화 표까지 챙겨주셔서 감사해요. 리텐션 섹션에 바로 반영할게요. 추가 분석 필요하면 말씀드릴게요.",
|
|
|
},
|
|
|
],
|
|
|
"file": {"project": "경영 전략", "reason": "‘분기 리포트’ 데이터 소스예요"},
|
|
|
},
|
|
|
},
|
|
|
]
|
|
|
|
|
|
SENT = [
|
|
|
(
|
|
|
"s1",
|
|
|
"work",
|
|
|
"현우",
|
|
|
"hyunwoo",
|
|
|
"온보딩 리뷰 일정 공유",
|
|
|
"어제",
|
|
|
"6월 9일 11:00",
|
|
|
"현우님, 다음 리뷰는 목요일 오전으로 잡았어요…",
|
|
|
),
|
|
|
(
|
|
|
"s2",
|
|
|
"work",
|
|
|
"민서",
|
|
|
"minseo",
|
|
|
"회고 문서 잘 봤어요",
|
|
|
"3일 전",
|
|
|
"6월 7일 16:20",
|
|
|
"민서님, 회고 문서 정리 깔끔하네요. 액션 아이템만…",
|
|
|
),
|
|
|
]
|
|
|
DRAFTS = [
|
|
|
(
|
|
|
"d1",
|
|
|
"work",
|
|
|
"재무팀",
|
|
|
"예산 재배분 안건 정리 (작성 중)",
|
|
|
"1시간 전",
|
|
|
"예산 재배분 관련해서 세 가지 시나리오를…",
|
|
|
"",
|
|
|
),
|
|
|
]
|
|
|
|
|
|
|
|
|
def _seed_mail(s: Session) -> None:
|
|
|
# phase-16+: 메일 mock 데이터(계정/폴더/메일/보낸함/임시) 제거.
|
|
|
# 연락처(Person)만 유지 — 알림·결재 등 타 기능이 발신자를 참조한다.
|
|
|
# 실제 메일/계정은 Gmail·Outlook 을 '계정 추가'로 연결하면 유입된다.
|
|
|
for pid, name, ini, color, email, role in MAIL_PEOPLE:
|
|
|
if not s.get(Person, pid):
|
|
|
s.add(
|
|
|
Person(
|
|
|
id=pid, name=name, initial=ini, color=color, is_me=False, email=email, role=role
|
|
|
)
|
|
|
)
|
|
|
for pid, (email, role) in PEOPLE_MAIL_INFO.items():
|
|
|
p = s.get(Person, pid)
|
|
|
if p:
|
|
|
p.email = email
|
|
|
p.role = role
|
|
|
s.add(p)
|
|
|
s.commit()
|
|
|
|
|
|
|
|
|
# ---- 알림 (notify-data.js) ----
|
|
|
NOTIFY_STATS = dict(total=47, seen=6, filtered="87%", later_more=6, held_more=23)
|
|
|
|
|
|
NOTIF_NOW = [
|
|
|
(
|
|
|
"n1",
|
|
|
"mail",
|
|
|
"메일 · 회사",
|
|
|
"수아님 — 분기 리포트 피드백",
|
|
|
"수치 2곳 수정 요청, 목요일까지 회신을 원해요.",
|
|
|
"09:12",
|
|
|
"VIP 발신자",
|
|
|
"coral",
|
|
|
"답장 초안 보기",
|
|
|
),
|
|
|
(
|
|
|
"n2",
|
|
|
"cal",
|
|
|
"캘린더",
|
|
|
"디자인 리뷰 15분 전",
|
|
|
"14:00 · 회의실 B · 현우·민서 참석 — 브리핑 준비됨.",
|
|
|
"13:45",
|
|
|
"곧 시작",
|
|
|
"blue",
|
|
|
"브리핑 열기",
|
|
|
),
|
|
|
(
|
|
|
"n3",
|
|
|
"chat",
|
|
|
"팀 메신저",
|
|
|
"현우님이 나를 멘션",
|
|
|
"“온보딩 검수, 지우님 확인 필요해요” — #온보딩 채널.",
|
|
|
"11:20",
|
|
|
"직접 멘션",
|
|
|
"violet",
|
|
|
"스레드 열기",
|
|
|
),
|
|
|
(
|
|
|
"n4",
|
|
|
"fin",
|
|
|
"카드",
|
|
|
"평소와 다른 결제 감지",
|
|
|
"해외 온라인 결제 42,000원 — 본인 결제가 맞나요?",
|
|
|
"10:31",
|
|
|
"보안",
|
|
|
"coral",
|
|
|
"확인하기",
|
|
|
),
|
|
|
(
|
|
|
"n5",
|
|
|
"app",
|
|
|
"배포 시스템",
|
|
|
"온보딩 v2 배포 완료",
|
|
|
"QA 시작 가능 — 체크리스트가 작업 보드에 추가됐어요.",
|
|
|
"10:05",
|
|
|
"내 프로젝트",
|
|
|
"green",
|
|
|
"작업 보기",
|
|
|
),
|
|
|
(
|
|
|
"n6",
|
|
|
"mail",
|
|
|
"메일 · 회사",
|
|
|
"민서님 — 1:1 노트 공유",
|
|
|
"지난 1:1 액션 2건을 완료로 표시했어요.",
|
|
|
"08:40",
|
|
|
"팀",
|
|
|
"blue",
|
|
|
"노트 보기",
|
|
|
),
|
|
|
]
|
|
|
NOTIF_LATER = [
|
|
|
(
|
|
|
"l1",
|
|
|
"mail",
|
|
|
"메일 · 개인",
|
|
|
"뉴스레터 5통 묶음",
|
|
|
"프로덕트 위클리 외 4종 — 저녁 다이제스트에 들어가요.",
|
|
|
"오전",
|
|
|
"다이제스트",
|
|
|
"violet",
|
|
|
),
|
|
|
(
|
|
|
"l2",
|
|
|
"app",
|
|
|
"분석 도구",
|
|
|
"주간 지표 리포트 도착",
|
|
|
"온보딩 전환율 +2.1%p — 자세한 건 리서치에 정리해둘게요.",
|
|
|
"07:00",
|
|
|
"주간 보고",
|
|
|
"blue",
|
|
|
),
|
|
|
(
|
|
|
"l3",
|
|
|
"chat",
|
|
|
"팀 메신저",
|
|
|
"#일반 채널 새 글 12개",
|
|
|
"회식 장소 투표가 열렸어요 — 마감은 내일 정오.",
|
|
|
"오전",
|
|
|
"낮은 우선순위",
|
|
|
"muted",
|
|
|
),
|
|
|
(
|
|
|
"l4",
|
|
|
"fin",
|
|
|
"구독",
|
|
|
"음악 구독 결제 예정 D-3",
|
|
|
"월 10,900원 — 지난달 재생 시간이 절반으로 줄었어요.",
|
|
|
"어제",
|
|
|
"결제 예고",
|
|
|
"amber",
|
|
|
),
|
|
|
(
|
|
|
"l5",
|
|
|
"app",
|
|
|
"디자인 툴",
|
|
|
"코멘트 3건",
|
|
|
"온보딩 화면 시안에 민서님이 코멘트를 남겼어요.",
|
|
|
"어제",
|
|
|
"낮은 우선순위",
|
|
|
"muted",
|
|
|
),
|
|
|
(
|
|
|
"l6",
|
|
|
"mail",
|
|
|
"메일 · 회사",
|
|
|
"사내 워크숍 신청 안내",
|
|
|
"7월 워크숍 신청 마감 6/20 — 일정 비어 있어요.",
|
|
|
"어제",
|
|
|
"마감 여유",
|
|
|
"muted",
|
|
|
),
|
|
|
]
|
|
|
NOTIF_HELD = [
|
|
|
(
|
|
|
"h1",
|
|
|
"mail",
|
|
|
"메일 · 전체",
|
|
|
"프로모션·마케팅 18건 자동 보관",
|
|
|
"광고성 메일은 읽지 않고 보관함으로 옮겼어요.",
|
|
|
"오늘",
|
|
|
"규칙: 자동 보관",
|
|
|
"muted",
|
|
|
"sr5",
|
|
|
),
|
|
|
(
|
|
|
"h2",
|
|
|
"cal",
|
|
|
"캘린더",
|
|
|
"회의 초대 자동 수락",
|
|
|
"목 11:00 ‘QA 싱크’ — 빈 시간 확인 후 수락했어요.",
|
|
|
"10:40",
|
|
|
"빈 시간 일치",
|
|
|
"green",
|
|
|
"",
|
|
|
),
|
|
|
(
|
|
|
"h3",
|
|
|
"app",
|
|
|
"쇼핑",
|
|
|
"배송 출발 → 일정에 기록",
|
|
|
"내일 도착 예정 — 캘린더에 메모로 달아뒀어요.",
|
|
|
"09:30",
|
|
|
"정보성",
|
|
|
"blue",
|
|
|
"",
|
|
|
),
|
|
|
(
|
|
|
"h4",
|
|
|
"mail",
|
|
|
"메일 · 개인",
|
|
|
"인증·OTP 메일 4건 정리",
|
|
|
"사용이 끝난 인증 메일은 휴지통으로 보냈어요.",
|
|
|
"오늘",
|
|
|
"일회성",
|
|
|
"muted",
|
|
|
"",
|
|
|
),
|
|
|
(
|
|
|
"h5",
|
|
|
"app",
|
|
|
"앱 푸시",
|
|
|
"광고 푸시 3건 차단",
|
|
|
"같은 앱에서 반복된 프로모션 푸시를 묶어 차단했어요.",
|
|
|
"오늘",
|
|
|
"반복 광고",
|
|
|
"muted",
|
|
|
"",
|
|
|
),
|
|
|
(
|
|
|
"h6",
|
|
|
"chat",
|
|
|
"메일 + 메신저",
|
|
|
"중복 알림 합침",
|
|
|
"같은 문서 공유 알림이 두 채널로 와서 하나로 합쳤어요.",
|
|
|
"08:15",
|
|
|
"중복",
|
|
|
"blue",
|
|
|
"",
|
|
|
),
|
|
|
]
|
|
|
DIGESTS = [
|
|
|
("dg-am", "09:00", "아침 브리핑", "밤사이 메일·뉴스·일정 변화", 11, True),
|
|
|
("dg-noon", "13:00", "점심 묶음", "오전의 ‘나중에’ 알림", 7, True),
|
|
|
("dg-eve", "18:30", "저녁 다이제스트", "뉴스레터·소셜·구독 소식", 12, False),
|
|
|
]
|
|
|
SENDERS = [
|
|
|
("sr1", "수아님", "메일 · 메신저", "항상 즉시", "now", "coral"),
|
|
|
("sr2", "현우 · 민서 · 재호", "팀 메신저", "멘션만 즉시", "now", "blue"),
|
|
|
("sr3", "뉴스레터 12종", "메일", "저녁 다이제스트", "later", "violet"),
|
|
|
("sr4", "은행 · 카드", "푸시", "이상 거래만 즉시", "now", "green"),
|
|
|
("sr5", "마케팅 · 프로모션", "메일 · 푸시", "자동 보관", "held", "amber"),
|
|
|
]
|
|
|
|
|
|
|
|
|
def _seed_notify(s: Session) -> None:
|
|
|
s.add(NotifyStats(id=1, **NOTIFY_STATS))
|
|
|
s.add(NotificationGuard(id=1, on=True, until="16:00", held=4, quiet="22:30 – 07:00"))
|
|
|
order = 0
|
|
|
for tup in NOTIF_NOW:
|
|
|
nid, src, app, title, summ, time, why, tone, act = tup
|
|
|
s.add(
|
|
|
Notification(
|
|
|
id=nid,
|
|
|
bucket=NotifyBucket.now,
|
|
|
src=src,
|
|
|
app=app,
|
|
|
title=title,
|
|
|
sum=summ,
|
|
|
time=time,
|
|
|
why=why,
|
|
|
tone=tone,
|
|
|
act=act,
|
|
|
held_by_rule="",
|
|
|
sort_order=order,
|
|
|
)
|
|
|
)
|
|
|
order += 1
|
|
|
for tup in NOTIF_LATER:
|
|
|
nid, src, app, title, summ, time, why, tone = tup
|
|
|
s.add(
|
|
|
Notification(
|
|
|
id=nid,
|
|
|
bucket=NotifyBucket.later,
|
|
|
src=src,
|
|
|
app=app,
|
|
|
title=title,
|
|
|
sum=summ,
|
|
|
time=time,
|
|
|
why=why,
|
|
|
tone=tone,
|
|
|
act="",
|
|
|
held_by_rule="",
|
|
|
sort_order=order,
|
|
|
)
|
|
|
)
|
|
|
order += 1
|
|
|
for tup in NOTIF_HELD:
|
|
|
nid, src, app, title, summ, time, why, tone, rule = tup
|
|
|
s.add(
|
|
|
Notification(
|
|
|
id=nid,
|
|
|
bucket=NotifyBucket.held,
|
|
|
src=src,
|
|
|
app=app,
|
|
|
title=title,
|
|
|
sum=summ,
|
|
|
time=time,
|
|
|
why=why,
|
|
|
tone=tone,
|
|
|
act="",
|
|
|
held_by_rule=rule,
|
|
|
sort_order=order,
|
|
|
)
|
|
|
)
|
|
|
order += 1
|
|
|
for i, (did, time, name, desc, count, done) in enumerate(DIGESTS):
|
|
|
s.add(Digest(id=did, time=time, name=name, desc=desc, count=count, done=done, sort_order=i))
|
|
|
for i, (rid, who, frm, rule, bucket, tone) in enumerate(SENDERS):
|
|
|
s.add(
|
|
|
SenderRule(
|
|
|
id=rid,
|
|
|
who=who,
|
|
|
from_label=frm,
|
|
|
rule=rule,
|
|
|
bucket=NotifyBucket(bucket),
|
|
|
tone=tone,
|
|
|
sort_order=i,
|
|
|
)
|
|
|
)
|
|
|
s.commit()
|