# 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()