# -*- coding: utf-8 -*- """票 10-N3g 扩展:①重采文档现行示例客户 detail-head(projectCount 真值口径) ②图谱轻夹具(create+quickAdd+DB 改值)采 graph/detail isInternal/giftRemark 真值。 产物:并回 specimens-proj-truth.json。""" from __future__ import annotations import io import json import sys import time from pathlib import Path import pymysql import requests sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') BASE = 'http://localhost:8080' ADMIN = '739564171091247104' OUT = Path('.scratch/customer-integration-ready') DOC_CUST = '750844477165273088' # 详情公共头部.bru 现行示例客户(e2c-全字段-科技) PFX = 'e2c-r3d-n3' TS = str(int(time.time()))[-6:] specimens = json.loads((OUT / 'specimens-proj-truth.json').read_text(encoding='utf-8')) def get_token(uid): r = requests.get(f'{BASE}/api/auth/debug/token', params={'userId': uid}, timeout=10) r.raise_for_status() return r.json()['data'] def api(method, path, params=None, form=None, step=''): headers = {'Authorization': f'Bearer {get_token(ADMIN)}'} kw = {'headers': headers, 'timeout': 60} if method == 'POST': kw['data'] = form or {} else: kw['params'] = params or {} r = requests.request(method, BASE + path, **kw) try: body = r.json() except Exception: body = {'_raw': r.text[:300], '_status': r.status_code} print(f" [{step or path}] http={r.status_code} code={body.get('code') if isinstance(body, dict) else '?'}") return r, body def db(): return pymysql.connect(host='8.129.84.155', port=3306, user='root', password='Itc@123456', database='crm', charset='utf8mb4', autocommit=True, connect_timeout=10, cursorclass=pymysql.cursors.DictCursor) def dbq(sql, args=None): with db() as conn, conn.cursor() as cur: cur.execute(sql, args) return cur.fetchall() def dbx(sql, args=None): with db() as conn, conn.cursor() as cur: cur.execute(sql, args) return cur.rowcount def sweep(): rows = dbq("SELECT id FROM customer WHERE customer_name LIKE %s", (PFX + '%',)) for row in rows: cid = row['id'] for t in ['customer_contact_edge', 'customer_contact_graph', 'customer_contact_reveal_log', 'customer_contact', 'customer_oplog', 'team_member', 'customer_focus']: try: dbx(f'DELETE FROM {t} WHERE customer_id=%s', (cid,)) except Exception: pass dbx('DELETE FROM customer WHERE id=%s', (cid,)) print(f' sweep: 清扫 {len(rows)} 组') def main(): # 1) 重采文档示例客户 detail-head(对比旧快照只回填漂移字段) _, b = api('GET', '/api/customer/detail-head', params={'id': DOC_CUST}, step='detail-head doc 客户') specimens['GET /api/customer/detail-head(doc-cust)'] = { 'request': {'id': DOC_CUST}, 'response': b} # 2) 图谱轻夹具 sweep() name = f'{PFX}-图客-{TS}' r, cust = api('POST', '/api/customer/create', form={ 'customerName': name, 'customerType': 'customer_type_01', 'provinceCode': '440000', 'cityCode': '440100', 'districtCode': '440103', 'industryCode': 'other', 'customerStarLevel': 3, 'relationStarLevel': 3, 'isBizNegotiated': 0, 'isChild': 0, 'ownerUserId': ADMIN, }, step='create 图客') cid = (cust.get('data') or {}).get('id') assert cid, f'图客创建失败: {str(cust)[:200]}' print(f' 图客 id={cid}') try: r, qa = api('POST', '/api/customer/contact/quickAdd', form={ 'customerId': str(cid), 'rows[0].name': f'n3{TS}张内线', 'rows[0].jobTitleCode': 'chairman', 'rows[0].phone': '13800099901', 'rows[0].source': 'group_meeting', 'rows[0].isKeyContact': '0', }, step='quickAdd x1') d = qa.get('data') or {} assert d.get('successCount') == 1 and not d.get('failedRows'), f'quickAdd 失败: {str(qa)[:300]}' rows = dbq('SELECT id, is_internal, gift_remark FROM customer_contact ' 'WHERE customer_id=%s ORDER BY id LIMIT 1', (cid,)) assert rows, '联系人未落库' c0 = rows[0] orig = (c0['is_internal'], c0['gift_remark']) print(f" 联系人 {c0['id']} 原值 is_internal={orig[0]} gift={orig[1]!r}") dbx('UPDATE customer_contact SET is_internal=1, gift_remark=%s WHERE id=%s', ('e2c-r3d-n3-礼品-龙井茶两盒', c0['id'])) try: _, b3 = api('GET', '/api/customer/contact/graph/detail', params={'customerId': cid}, step='graph/detail') specimens['GET /api/customer/contact/graph/detail'] = { 'request': {'customerId': str(cid)}, 'response': b3} node = ((b3.get('data') or {}).get('nodes') or [{}])[0] print(' nodes[0].isInternal =', node.get('isInternal'), ' giftRemark =', node.get('giftRemark')) finally: dbx('UPDATE customer_contact SET is_internal=%s, gift_remark=%s WHERE id=%s', (orig[0], orig[1], c0['id'])) print(' 联系人已还原') finally: sweep() (OUT / 'specimens-proj-truth.json').write_text( json.dumps(specimens, ensure_ascii=False, indent=2), encoding='utf-8') print('== specimens-proj-truth.json 更新,', len(specimens), '条') if __name__ == '__main__': main()