#!/usr/bin/env python3 """Demo Seed — 直接生成可执行的SQL,避免转义问题""" import uuid import subprocess import sys import os import json def uid(): return str(uuid.uuid4()) # ── 用户定义 ────────────────────────────────────────────────────────── FEMALE = [ ('demo_openid_f01','f01','小芳','female','1995-06-15',162,'321181','丹阳','never_married','bachelor','clerical','never','sometimes','是','是','结婚',90), ('demo_openid_f02','f02','晓燕','female','1993-09-20',165,'321181','丹阳','divorced','college','teacher','never','never','是','是','结婚',95), ('demo_openid_f03','f03','婷婷','female','1998-02-10',158,'321100','镇江','never_married','master','designer','sometimes','often','是','否','恋爱',85), ('demo_openid_f04','f04','美玲','female','1990-11-05',160,'321181','丹阳','never_married','senior_high','factory','never','never','是','是','结婚',70), ('demo_openid_f05','f05','慧琴','female','1996-07-22',163,'321181','丹阳','never_married','bachelor','nurse','never','sometimes','是','是','结婚',92), ('demo_openid_f06','f06','秀英','female','1992-04-18',157,'321181','丹阳','widowed','junior_high','farmer','often','often','是','是','结婚',60), ] MALE = [ ('demo_openid_m01','m01','张伟','male','1992-01-10',175,'321181','丹阳','never_married','bachelor','engineer','never','sometimes','是','是','结婚',88), ('demo_openid_m02','m02','李强','male','1990-08-25',178,'321181','丹阳','divorced','master','manager','sometimes','often','是','是','结婚',95), ('demo_openid_m03','m03','王磊','male','1997-12-03',180,'321100','镇江','never_married','college','programmer','never','never','是','是','恋爱',82), ('demo_openid_m04','m04','赵明','male','1988-05-30',172,'321181','丹阳','never_married','senior_high','sales','often','often','否','是','结婚',75), ('demo_openid_m05','m05','孙浩','male','1994-03-14',182,'321181','丹阳','never_married','bachelor','doctor','never','sometimes','是','是','结婚',97), ('demo_openid_m06','m06','周洋','male','1999-08-08',176,'320500','苏州','never_married','master','researcher','never','never','是','否','恋爱',80), ] ALL = FEMALE + MALE uid_map = {u[1]: uid() for u in ALL} print(f"Users: {len(uid_map)}") # ── UUIDs ───────────────────────────────────────────────────────────── org_ids = {t: uid() for t in ['women','trade','charity']} admin_id, mh_id, rv_id, mgr_id = uid(), uid(), uid(), uid() match_ids = {k: uid() for k in ['f01m01','f03m03','f05m05']} conv_ids = {k: uid() for k in ['f01m01','f03m03','f05m05']} act_summer, act_qixi = uid(), uid() # ── 辅助函数 ────────────────────────────────────────────────────────── def q(s): """SQL字符串值(带单引号)""" if s is None: return 'NULL' return "'" + str(s).replace("\\","\\\\").replace("'","''") + "'" def json_arr(items): """PostgreSQL JSON数组文本(带单引号包裹)""" inner = ','.join(json.dumps(item) for item in items) return '[' + inner + ']' # ── 生成SQL到临时文件 ───────────────────────────────────────────────── sql = [] def emit(*lines): sql.extend(lines) sql.append('') emit("SET session_replication_role = 'replica';") # 1. Organizations emit("-- 1. 组织") emit(f"INSERT INTO organizations (id, name, type, contact_name, status) VALUES") emit(f"({q(org_ids['women'])}, '丹阳市妇女联合会', 'women_federation', '张丽华', 'active'),") emit(f"({q(org_ids['trade'])}, '丹阳市总工会', 'trade_union', '李明远', 'active'),") emit(f"({q(org_ids['charity'])}, '丹阳市慈善基金会', 'charity_center', '王秀英', 'active');") # 2. Operators emit("-- 2. 工作人员") emit(f"INSERT INTO operators (id, organization_id, name, username, password_hash, status) VALUES") emit(f"({q(admin_id)}, {q(org_ids['women'])}, '陈主任', 'admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHdBfKYuPIiCTB6MJJDEaK', 'active'),") emit(f"({q(mh_id)}, {q(org_ids['women'])}, '红娘小王', 'wanghongniang', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHdBfKYuPIiCTB6MJJDEaK', 'active'),") emit(f"({q(rv_id)}, {q(org_ids['charity'])}, '审核员小张', 'reviewer01', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHdBfKYuPIiCTB6MJJDEaK', 'active'),") emit(f"({q(mgr_id)}, {q(org_ids['trade'])}, '活动管理员赵', 'activitymgr', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHdBfKYuPIiCTB6MJJDEaK', 'active');") # 操作员角色 role_assign = [ ('admin',['00000000-0000-0000-0000-000000000001','00000000-0000-0000-0000-000000000002']), ('wanghongniang',['00000000-0000-0000-0000-000000000005','00000000-0000-0000-0000-000000000006']), ('reviewer01',['00000000-0000-0000-0000-000000000004','00000000-0000-0000-0000-000000000007']), ('activitymgr',['00000000-0000-0000-0000-000000000006','00000000-0000-0000-0000-000000000008']), ] op_uid = {'admin':admin_id,'wanghongniang':mh_id,'reviewer01':rv_id,'activitymgr':mgr_id} for uname, rids in role_assign: for rid in rids: emit(f"INSERT INTO operator_roles (operator_id, role_id) VALUES ({q(op_uid[uname])}, {q(rid)});") # 3. Users emit("-- 3. 用户 12人") status_map = { 'f01':'searching','f02':'searching','f03':'searching','f04':'paused', 'f05':'searching','f06':'searching','m01':'searching','m02':'getting_to_know', 'm03':'searching','m04':'searching','m05':'matched_successfully','m06':'searching', } created = { 'f01':'2026-03-15T10:00:00Z','f02':'2026-03-20T14:30:00Z','f03':'2026-04-01T09:15:00Z', 'f04':'2026-04-10T16:00:00Z','f05':'2026-05-01T11:20:00Z','f06':'2026-05-15T08:45:00Z', 'm01':'2026-03-10T09:00:00Z','m02':'2026-03-25T13:00:00Z','m03':'2026-04-05T15:30:00Z', 'm04':'2026-04-20T10:00:00Z','m05':'2026-05-01T14:00:00Z','m06':'2026-05-10T16:30:00Z', } emit("INSERT INTO users (id, wechat_openid, account_status, relationship_status, recommendation_enabled, created_at) VALUES") vals = [] for u in ALL: alias = u[1] vals.append(f"({q(uid_map[alias])}, {q(u[0])}, 'normal', {q(status_map[alias])}, true, {q(created[alias])})") emit(',\n'.join(vals) + ';') # 4. User Profiles emit("-- 4. 用户资料") emit("INSERT INTO user_profiles (user_id, display_name, gender, birth_date, height_cm, region_code, region_name, marital_status, children_status, education_code, occupation_code, smoking_status, drinking_status, long_term_danyang, future_danyang, relationship_goal, profile_completion, profile_status) VALUES") pvals = [] for u in ALL: alias = u[1] pvals.append( f"({q(uid_map[alias])}, {q(u[2])}, {q(u[3])}, {q(u[4])}, {u[5]}, {q(u[6])}, {q(u[7])}, " f"{q(u[8])}, 'none', {q(u[9])}, {q(u[10])}, {q(u[11])}, {q(u[12])}, " f"{q(u[13])}, {q(u[14])}, {q(u[15])}, {u[16]}, 'approved')" ) emit(',\n'.join(pvals) + ';') # 5. User Preferences — JSON数组用 json.dumps 正确转义 emit("-- 5. 用户择偶偏好") prefs = [ ('f01',[28,38,'required',170,185,'required'],['321181','321100'],'required',['never_married'],'required','bachelor','preferred'), ('f02',[28,40,'required',170,188,'required'],['321181'],'required',['never_married','divorced'],'preferred','college','preferred'), ('f03',[25,35,'preferred',172,185,'preferred'],['321181','321100','320500'],'preferred',['never_married'],'required',None,None), ('f04',[30,45,'required',168,185,'required'],['321181'],'required',['never_married','divorced'],'preferred','senior_high','preferred'), ('f05',[27,36,'required',172,186,'required'],['321181','321100'],'preferred',['never_married'],'required','bachelor','preferred'), ('f06',[30,50,'required',165,185,'required'],['321181'],'required',['never_married','divorced','widowed'],'preferred',None,None), ('m01',[22,32,'required',155,170,'preferred'],['321181','321100'],'required',['never_married'],'required','junior_high','preferred'), ('m02',[25,38,'preferred',158,172,'preferred'],['321181'],'preferred',['never_married','divorced'],'preferred','college','preferred'), ('m03',[22,30,'preferred',155,168,'preferred'],['321181','321100','320500'],'preferred',['never_married'],'required','college','preferred'), ('m04',[25,40,'preferred',155,170,'preferred'],['321181'],'required',['never_married','divorced'],'preferred',None,None), ('m05',[23,33,'required',158,170,'preferred'],['321181','321100'],'preferred',['never_married'],'required','bachelor','preferred'), ('m06',[22,32,'preferred',155,170,'preferred'],['321181','321100','320500'],'preferred',['never_married'],'required','master','preferred'), ] emit("INSERT INTO user_preferences (user_id, min_age, max_age, age_priority, min_height_cm, max_height_cm, height_priority, region_scope, region_priority, marital_statuses, marital_priority, min_education_code, education_priority) VALUES") pvals2 = [] for p in prefs: alias = p[0] ages = p[1] region_scope = json_arr(p[2]) # list -> JSON text p_region_pri = p[3] marital_list = p[4] p_marital_pri = p[5] min_edu = q(p[6]) if p[6] else 'NULL' edu_pri = q(p[7]) if p[7] else 'NULL' pvals2.append( f"({q(uid_map[alias])}, {ages[0]}, {ages[1]}, {q(ages[2])}, {ages[3]}, {ages[4]}, {q(ages[5])}, " f"{q(region_scope)}, {q(p_region_pri)}, {q(json_arr(marital_list))}, {q(p_marital_pri)}, {min_edu}, {edu_pri})" ) emit(',\n'.join(pvals2) + ';') # 6. Identities emit("-- 6. 实名认证(mock)") emit("INSERT INTO user_identities (id, user_id, real_name_enc, id_number_enc, id_number_hash, gender, birth_date, verification_status, provider, verified_at) VALUES") id_vals = [] for i, u in enumerate(ALL): alias = u[1] id_vals.append( f"({q(uid())}, {q(uid_map[alias])}, E'\\\\xenc_{alias}', E'\\\\xenc_id_{alias}', " f"'demo_sha256_{alias}', {q(u[3])}, {q(u[4])}, 'verified', 'mock', '2026-03-16T10:00:00Z')" ) emit(',\n'.join(id_vals) + ';') # 7. Interests emit("-- 7. 兴趣标签") interests_def = [ ('f01',['reading','cooking','travel']), ('f02',['sports','music','outdoor']), ('f03',['photography','dance','movie']), ('f04',['pets','cooking']), ('f05',['reading','fitness','charity']), ('f06',['gardening','cooking']), ('m01',['sports','gaming','travel']), ('m02',['reading','investment','hiking']), ('m03',['gaming','music','coding']), ('m04',['cars','cooking']), ('m05',['running','reading','charity']), ('m06',['research','travel','photography']), ] emit("INSERT INTO user_interests (user_id, interest_code) VALUES") int_vals = [] for alias, codes in interests_def: for code in codes: int_vals.append(f"({q(uid_map[alias])}, {q(code)})") emit(',\n'.join(int_vals) + ';') # 8. Privacy emit("-- 8. 隐私设置") priv_data = { 'f01':(True,True,True,True,True,True), 'f02':(True,True,True,False,True,True), 'f03':(True,False,True,True,True,False),'f04':(True,True,False,True,True,True), 'f05':(True,True,True,True,False,True),'f06':(True,False,True,True,True,True), 'm01':(True,True,True,True,True,True), 'm02':(True,True,True,False,True,True), 'm03':(True,True,True,True,True,False),'m04':(True,False,True,True,True,True), 'm05':(True,True,True,True,True,True), 'm06':(True,True,True,True,True,True), } emit("INSERT INTO user_privacy_settings (user_id, visible_in_recommendations, visible_in_search, show_occupation, show_lifestyle_photos, receive_activity_recommendations, accept_matchmaker_recommendations) VALUES") priv_vals = [] for u in ALL: alias = u[1] p = priv_data[alias] priv_vals.append( f"({q(uid_map[alias])}, {str(p[0]).lower()}, {str(p[1]).lower()}, {str(p[2]).lower()}, " f"{str(p[3]).lower()}, {str(p[4]).lower()}, {str(p[5]).lower()})" ) emit(',\n'.join(priv_vals) + ';') # 9. Photos emit("-- 9. 照片") emit("INSERT INTO user_photos (id, user_id, file_key, photo_type, sort_order, review_status) VALUES") photo_vals = [] for u in ALL: alias = u[1] photo_vals.append(f"({q(uid())}, {q(uid_map[alias])}, 'photos/demo/{alias}/avatar.jpg', 'avatar', 0, 'approved')") photo_vals.append(f"({q(uid())}, {q(uid_map[alias])}, 'photos/demo/{alias}/lifestyle1.jpg', 'lifestyle', 1, 'approved')") emit(',\n'.join(photo_vals) + ';') # 10. Review Tasks emit("-- 10. 审核任务") review_aliases = ['f01','f02','f03','m01','m02','m03','m05'] review_dates = ['2026-03-15','2026-03-20','2026-04-01','2026-03-10','2026-03-25','2026-04-05','2026-05-01'] emit("INSERT INTO review_tasks (id, user_id, review_type, status, assigned_operator_id, submitted_at, started_at, completed_at, final_comment, version) VALUES") rt_vals = [] for i, alias in enumerate(review_aliases): rt_vals.append( f"({q(uid())}, {q(uid_map[alias])}, 'initial_profile', 'approved', {q(rv_id)}, " f"{q(review_dates[i]+'T11:00:00Z')}, {q(review_dates[i]+'T11:30:00Z')}, " f"{q(review_dates[i]+'T12:00:00Z')}, '资料完整', 1)" ) emit(',\n'.join(rt_vals) + ';') # 11. User Relations emit("-- 11. 用户关系") rel_data = [ ('f01','m01','liked','2026-06-01T10:00:00Z'), ('m01','f01','liked','2026-06-01T10:05:00Z'), ('f02','m02','liked','2026-06-02T14:00:00Z'), ('f03','m03','liked','2026-06-03T09:00:00Z'), ('m03','f03','liked','2026-06-03T09:30:00Z'), ('m04','f02','liked','2026-06-04T11:00:00Z'), ('f04','m04','passed','2026-06-04T12:00:00Z'), ('f05','m05','liked','2026-06-05T10:00:00Z'), ('m05','f05','liked','2026-06-05T10:05:00Z'), ('m06','f01','liked','2026-06-06T14:00:00Z'), ('f04','m06','passed','2026-06-06T15:00:00Z'), ('f06','m04','blocked','2026-06-07T09:00:00Z'), ('m02','f03','passed','2026-06-07T10:00:00Z'), ] emit("INSERT INTO user_relations (id, user_id, target_user_id, relation_type, created_at) VALUES") rel_vals = [f"({q(uid())}, {q(uid_map[a])}, {q(uid_map[b])}, {q(r)}, {q(t)})" for a,b,r,t in rel_data] emit(',\n'.join(rel_vals) + ';') # 12. Matches emit("-- 12. Match") emit("INSERT INTO matches (id, user_a_id, user_b_id, status, source, matched_at) VALUES") emit(f"({q(match_ids['f01m01'])}, {q(uid_map['f01'])}, {q(uid_map['m01'])}, 'active', 'user_like', '2026-06-01T10:05:00Z'),") emit(f"({q(match_ids['f03m03'])}, {q(uid_map['f03'])}, {q(uid_map['m03'])}, 'active', 'user_like', '2026-06-03T09:30:00Z'),") emit(f"({q(match_ids['f05m05'])}, {q(uid_map['f05'])}, {q(uid_map['m05'])}, 'successful', 'user_like', '2026-06-05T10:05:00Z');") # 13. Success Requests emit("-- 13. 成功牵手请求") emit("INSERT INTO relationship_success_requests (id, match_id, initiated_by, status, confirmed_by, created_at, resolved_at) VALUES") emit(f"({q(uid())}, {q(match_ids['f05m05'])}, {q(uid_map['f05'])}, 'confirmed', {q(uid_map['m05'])}, '2026-07-01T10:00:00Z', '2026-07-01T10:30:00Z'),") emit(f"({q(uid())}, {q(match_ids['f01m01'])}, {q(uid_map['f01'])}, 'pending', NULL, '2026-07-15T14:00:00Z', NULL);") # 14. Conversations emit("-- 14. Conversations & Members") emit("INSERT INTO conversations (id, match_id, status, last_message_at) VALUES") emit(f"({q(conv_ids['f01m01'])}, {q(match_ids['f01m01'])}, 'active', '2026-07-10T16:00:00Z'),") emit(f"({q(conv_ids['f03m03'])}, {q(match_ids['f03m03'])}, 'active', '2026-07-08T20:00:00Z'),") emit(f"({q(conv_ids['f05m05'])}, {q(match_ids['f05m05'])}, 'active', '2026-07-01T18:00:00Z');") emit("INSERT INTO conversation_members (conversation_id, user_id, unread_count, can_send, joined_at) VALUES") emit(f"({q(conv_ids['f01m01'])}, {q(uid_map['f01'])}, 0, true, '2026-06-01T10:05:00Z'),") emit(f"({q(conv_ids['f01m01'])}, {q(uid_map['m01'])}, 0, true, '2026-06-01T10:05:00Z'),") emit(f"({q(conv_ids['f03m03'])}, {q(uid_map['f03'])}, 1, true, '2026-06-03T09:30:00Z'),") emit(f"({q(conv_ids['f03m03'])}, {q(uid_map['m03'])}, 0, true, '2026-06-03T09:30:00Z'),") emit(f"({q(conv_ids['f05m05'])}, {q(uid_map['f05'])}, 0, true, '2026-06-05T10:05:00Z'),") emit(f"({q(conv_ids['f05m05'])}, {q(uid_map['m05'])}, 0, true, '2026-06-05T10:05:00Z');") # Messages msg_data = [ (conv_ids['f01m01'], 'f01', '你好!看到你的资料觉得挺合适的~', '2026-06-15T14:00:00Z'), (conv_ids['f01m01'], 'm01', '你好!谢谢你的喜欢,我也觉得挺有缘的', '2026-06-15T14:05:00Z'), (conv_ids['f01m01'], 'f01', '你也在丹阳工作吗?平时喜欢做些什么?', '2026-06-15T14:10:00Z'), (conv_ids['f03m03'], 'm03', '嗨,你好!很高兴认识你', '2026-07-05T19:30:00Z'), (conv_ids['f03m03'], 'f03', '你好呀!我平时喜欢拍照和跳舞,你呢?', '2026-07-05T19:35:00Z'), (conv_ids['f05m05'], 'm05', '你好,很高兴认识你!', '2026-06-10T10:00:00Z'), ] emit("INSERT INTO messages (id, conversation_id, sender_id, message_type, content, status, risk_level, created_at) VALUES") msg_vals = [f"({q(uid())}, {q(cid)}, {q(uid_map[sid])}, 'text', {q(c)}, 'sent', 'normal', {q(t)})" for cid,sid,c,t in msg_data] emit(',\n'.join(msg_vals) + ';') # update last_message_at emit("UPDATE conversations SET last_message_at = (SELECT MAX(created_at) FROM messages WHERE messages.conversation_id = conversations.id);") # 15. Recommendation Records emit("-- 15. 推荐记录") rec_data = [ ('f01','m01',82.5,'high','2026-05-28T10:00:00Z','liked','2026-06-01T10:00:00Z'), ('f01','m03',70.0,'medium','2026-05-28T10:00:00Z','passed','2026-05-28T10:01:00Z'), ('m01','f01',85.0,'high','2026-05-28T11:00:00Z','liked','2026-06-01T10:05:00Z'), ('f03','m03',78.0,'high','2026-06-01T09:00:00Z','liked','2026-06-03T09:30:00Z'), ('m03','f03',75.0,'high','2026-06-01T09:30:00Z','liked','2026-06-03T09:30:00Z'), ('f05','m05',88.0,'high','2026-06-01T10:00:00Z','liked','2026-06-05T10:00:00Z'), ('m05','f05',86.0,'high','2026-06-01T10:30:00Z','liked','2026-06-05T10:05:00Z'), ('m06','f01',62.0,'medium','2026-06-06T14:00:00Z','liked','2026-06-06T14:00:00Z'), ] emit("INSERT INTO recommendation_records (id, user_id, target_user_id, source, score, level, shown_at, action, action_at, rule_version) VALUES") rec_vals = [f"({q(uid())}, {q(uid_map[s])}, {q(uid_map[t])}, 'daily', {sc}, {q(lv)}, {q(sa)}, {q(act)}, {q(aa)}, 1)" for s,t,sc,lv,sa,act,aa in rec_data] emit(',\n'.join(rec_vals) + ';') # 16. Activities emit("-- 16. 相亲活动") emit(f"INSERT INTO activities (id, title, description, organizer_org_id, coorganizer_text, start_at, end_at, location_name, location_address, male_limit, female_limit, total_limit, min_age, max_age, registration_start_at, registration_end_at, need_review, status, created_by) VALUES") emit(f"({q(act_summer)}, '丹阳公益单身联谊会(夏季场)', '面向丹阳市区及周边乡镇的单身青年,由妇联、工会联合主办。', {q(org_ids['women'])}, '丹阳市总工会、丹阳市慈善基金会', '2026-08-15T14:00:00Z', '2026-08-15T17:30:00Z', '丹阳市文化馆多功能厅', '丹阳市丹北路168号', 15, 15, 30, 22, 40, '2026-07-01T00:00:00Z', '2026-08-10T23:59:59Z', true, 'registration_open', {q(mgr_id)}),") emit(f"({q(act_qixi)}, '七夕特别活动·丹阳缘来是你', '七夕节特别策划,浪漫主题相亲活动。', {q(org_ids['trade'])}, '丹阳市新时代文明实践中心', '2026-08-29T15:00:00Z', '2026-08-29T18:00:00Z', '丹阳大剧院报告厅', '丹阳市书院路28号', 20, 20, 40, 25, 45, '2026-08-01T00:00:00Z', '2026-08-25T23:59:59Z', true, 'draft', {q(mgr_id)});") # 17. Activity Registrations emit("-- 17. 活动报名") reg_defs = [ ('f01','approved','2026-07-05T10:00:00Z',mgr_id,'2026-07-05T10:30:00Z'), ('f02','pending','2026-07-12T10:00:00Z',None,None), ('f03','approved','2026-07-06T14:00:00Z',mgr_id,'2026-07-06T14:15:00Z'), ('f04','rejected','2026-07-13T09:00:00Z',mgr_id,'2026-07-13T09:15:00Z'), ('f05','approved','2026-07-07T09:00:00Z',mgr_id,'2026-07-07T09:20:00Z'), ('m01','approved','2026-07-08T11:00:00Z',mgr_id,'2026-07-08T11:10:00Z'), ('m02','approved','2026-07-11T16:00:00Z',mgr_id,'2026-07-11T16:30:00Z'), ('m03','approved','2026-07-09T15:00:00Z',mgr_id,'2026-07-09T15:20:00Z'), ('m05','approved','2026-07-10T08:30:00Z',mgr_id,'2026-07-10T08:45:00Z'), ] emit(f"INSERT INTO activity_registrations (id, activity_id, user_id, status, registered_at, reviewed_by, reviewed_at, checkin_status) VALUES") reg_vals = [] for alias, status, reg_at, rev_by, rev_at in reg_defs: rb = q(rev_by) if rev_by else 'NULL' rat = q(rev_at) if rev_at else 'NULL' reg_vals.append(f"({q(uid())}, {q(act_summer)}, {q(uid_map[alias])}, {q(status)}, {q(reg_at)}, {rb}, {rat}, 'not_checked_in')") emit(',\n'.join(reg_vals) + ';') # 18. Activity Interests emit("-- 18. 活动互选意向") emit(f"INSERT INTO activity_interests (id, source_user_id, target_user_id, activity_id, status, confirmed_at, created_at) VALUES") emit(f"({q(uid())}, {q(uid_map['f01'])}, {q(uid_map['m01'])}, {q(act_summer)}, 'mutual', '2026-08-15T17:00:00Z', '2026-08-15T17:00:00Z'),") emit(f"({q(uid())}, {q(uid_map['f03'])}, {q(uid_map['m03'])}, {q(act_summer)}, 'mutual', '2026-08-15T17:05:00Z', '2026-08-15T17:05:00Z'),") emit(f"({q(uid())}, {q(uid_map['f05'])}, {q(uid_map['m05'])}, {q(act_summer)}, 'expressed', '2026-08-15T17:10:00Z', '2026-08-15T17:10:00Z');") # 19. Matchmaker Services emit("-- 19. 红娘服务") mk_svc_ids = [uid(), uid(), uid()] emit(f"INSERT INTO matchmaker_services (id, user_id, service_type, description, status, organization_id, assigned_operator_id, assigned_at, completed_at) VALUES") emit(f"({q(mk_svc_ids[0])}, {q(uid_map['f02'])}, 'recommend_partner', '离异用户希望找到合适的伴侣', 'in_service', {q(org_ids['women'])}, {q(mh_id)}, '2026-06-20T10:00:00Z', NULL),") emit(f"({q(mk_svc_ids[1])}, {q(uid_map['f06'])}, 'no_match_help', '丧偶用户希望重新融入社交', 'waiting_user', {q(org_ids['charity'])}, {q(mh_id)}, '2026-06-25T14:00:00Z', NULL),") emit(f"({q(mk_svc_ids[2])}, {q(uid_map['f04'])}, 'review_preference', '用户希望调整择偶条件', 'completed', {q(org_ids['women'])}, {q(mh_id)}, '2026-06-15T09:00:00Z', '2026-06-20T11:00:00Z');") # Matchmaker Recommendations emit(f"INSERT INTO matchmaker_recommendations (id, service_id, user_id, target_user_id, operator_id, reason, status, created_at, viewed_at, responded_at) VALUES") emit(f"({q(uid())}, {q(mk_svc_ids[0])}, {q(uid_map['f02'])}, {q(uid_map['m02'])}, {q(mh_id)}, '两人同在丹阳工作,年龄相仿,都离过婚有共同语言', 'viewed', '2026-06-21T10:00:00Z', '2026-06-22T09:00:00Z', NULL);") # Matchmaker Followups emit(f"INSERT INTO matchmaker_followups (id, service_id, operator_id, followup_type, content, result_code, next_followup_at, created_at) VALUES") emit(f"({q(uid())}, {q(mk_svc_ids[0])}, {q(mh_id)}, 'phone_call', '电话沟通用户情况,了解离异原因及择偶期望', '正常', '2026-07-01T10:00:00Z', '2026-06-22T10:00:00Z'),") emit(f"({q(uid())}, {q(mk_svc_ids[2])}, {q(mh_id)}, 'face_to_face', '面对面交流,帮助用户调整身高要求从170改为168', '已调整', NULL, '2026-06-18T15:00:00Z');") # 20. Notifications emit("-- 20. 系统通知") notif_data = [ ('f01','match','你们互相喜欢!','张伟也喜欢了你,可以开始聊天啦~','match','read','2026-06-01T10:05:00Z'), ('m01','match','你们互相喜欢!','小芳也喜欢了你,可以开始聊天啦~','match','read','2026-06-01T10:05:00Z'), ('f03','match','你们互相喜欢!','王磊也喜欢了你,可以开始聊天啦~','match','read','2026-06-03T09:30:00Z'), ('m03','match','你们互相喜欢!','婷婷也喜欢了你,可以开始聊天啦~','match','unread','2026-06-03T09:30:00Z'), ('f05','match','你们互相喜欢!','孙浩也喜欢了你,可以开始聊天啦~','match','read','2026-06-05T10:05:00Z'), ('m05','match','你们互相喜欢!','慧琴也喜欢了你,可以开始聊天啦~','match','read','2026-06-05T10:05:00Z'), ('f05','system','恭喜牵手成功!','您与孙浩已成功牵手,祝你们幸福!','match','read','2026-07-01T10:30:00Z'), ('m05','system','恭喜牵手成功!','您与慧琴已成功牵手,祝你们幸福!','match','read','2026-07-01T10:30:00Z'), ('f01','activity','活动报名已确认','您已成功报名「丹阳公益单身联谊会」','activity','read','2026-07-05T10:30:00Z'), ('f05','activity','活动报名已确认','您已成功报名「丹阳公益单身联谊会」','activity','unread','2026-07-07T09:20:00Z'), ('f02','matchmaker','红娘已为您服务','您的红娘服务申请已被分配,红娘小王将在24小时内与您联系','matchmaker','read','2026-06-20T10:30:00Z'), ] emit("INSERT INTO notifications (id, user_id, type, title, content, business_type, read_status, created_at) VALUES") notif_vals = [] for alias, ntype, title, content, btype, rstat, ctime in notif_data: notif_vals.append(f"({q(uid())}, {q(uid_map[alias])}, {q(ntype)}, {q(title)}, {q(content)}, {q(btype)}, {q(rstat)}, {q(ctime)})") emit(',\n'.join(notif_vals) + ';') # 21. Consent Records emit("-- 21. 同意记录") emit("INSERT INTO consent_records (id, user_id, type, version, agreed_at, ip_address, user_agent) VALUES") emit(f"({q(uid())}, {q(uid_map['f01'])}, 'terms_of_service', '1.0', '2026-03-15T10:00:00Z', '127.0.0.1', 'WeChat/8.0'),") emit(f"({q(uid())}, {q(uid_map['f01'])}, 'privacy_policy', '1.0', '2026-03-15T10:00:00Z', '127.0.0.1', 'WeChat/8.0'),") emit(f"({q(uid())}, {q(uid_map['m01'])}, 'terms_of_service', '1.0', '2026-03-10T09:00:00Z', '127.0.0.1', 'WeChat/8.0'),") emit(f"({q(uid())}, {q(uid_map['m01'])}, 'privacy_policy', '1.0', '2026-03-10T09:00:00Z', '127.0.0.1', 'WeChat/8.0');") # 22. Review Reasons emit("-- 22. 审核原因字典") emit("INSERT INTO review_reasons (code, name, category, enabled, sort_order) VALUES") emit("('profile_incomplete', '资料不完整', 'quality', true, 1),") emit("('photo_unclear', '照片不清晰', 'quality', true, 2),") emit("('fake_info', '信息疑似虚假', 'trust', true, 3),") emit("('inappropriate_photo', '照片内容不当', 'safety', true, 4),") emit("('duplicate_identity', '重复注册', 'duplicate', true, 5),") emit("('suspicious_behavior', '行为异常', 'risk', true, 6),") emit("('manual_review_needed', '需人工复核', 'quality', true, 7);") emit("SET session_replication_role = 'origin';") # Verification emit("DO $$ DECLARE u_cnt INTEGER; op_cnt INTEGER; m_cnt INTEGER; a_cnt INTEGER; p_cnt INTEGER;") emit("BEGIN SELECT COUNT(*) INTO u_cnt FROM users WHERE deleted_at IS NULL;") emit(" SELECT COUNT(*) INTO op_cnt FROM operators; SELECT COUNT(*) INTO m_cnt FROM matches;") emit(" SELECT COUNT(*) INTO a_cnt FROM activities WHERE deleted_at IS NULL;") emit(" SELECT COUNT(*) INTO p_cnt FROM user_profiles;") emit(" RAISE NOTICE '========================================';") emit(" RAISE NOTICE 'Demo 数据填充完成!';") emit(" RAISE NOTICE ' 用户: %人 | 资料: %条 | 操作员: %人', u_cnt, p_cnt, op_cnt;") emit(" RAISE NOTICE ' Match: %对 | 活动: %个', m_cnt, a_cnt;") emit(" RAISE NOTICE '========================================';") emit("END $$;") # Write SQL to file sql_content = '\n'.join(sql) # Fix: the activities INSERT has a typo on line with coorganizer_text # Let me check and fix if "coorganizer_text', '2026-08-15" in sql_content or "coorganizer_text'" in sql_content: # Check if there's an issue with the QIXI activity insert pass # Write to file output_path = '/tmp/demo-seed-clean.sql' with open(output_path, 'w', encoding='utf-8') as f: f.write(sql_content) print(f"SQL written: {len(sql)} lines, {len(sql_content)} bytes") # Copy to container and execute result = subprocess.run( ['docker', 'cp', output_path, 'danyang-match-postgres:/tmp/demo-seed-final.sql'], capture_output=True, text=True ) if result.returncode != 0: print(f"cp failed: {result.stderr}") sys.exit(1) result = subprocess.run( ['docker', 'exec', 'danyang-match-postgres', 'psql', '-U', 'postgres', '-d', 'danyang_match', '-f', '/tmp/demo-seed-final.sql'], capture_output=True, text=True, encoding='utf-8', errors='replace' ) print(result.stdout) if result.stderr: print("STDERR:", result.stderr) sys.exit(result.returncode)