import json, os from collections import Counter base = r'.scratch/opportunity-e2e/env-raw' out_path = r'.scratch/opportunity-e2e/env-analysis2.txt' _buf = [] def out(s=''): _buf.append(str(s)) def load(name): with open(os.path.join(base, name + '.json'), encoding='utf-8-sig') as f: return json.load(f) def fix(s): if not isinstance(s, str): return s try: return s.encode('latin-1').decode('utf-8') except (UnicodeEncodeError, UnicodeDecodeError): return s def deepfix(x): if isinstance(x, str): return fix(x) if isinstance(x, list): return [deepfix(i) for i in x] if isinstance(x, dict): return {k: deepfix(v) for k, v in x.items()} return x # 1. 各部门用户样例:挑普通用户(无管理员角色) out('=== USER CANDIDATES ===') for tag in ['yinxiao', 'tezhan', 'yunying', 'huannan-seed']: u = load('users-' + tag) ul = (u.get('data') or {}).get('content') or [] out('--- %s total=%s ---' % (tag, (u.get('data') or {}).get('total'))) for x in ul[:12]: roles = ','.join((r.get('name') or '') for r in (x.get('roles') or [])) out('id=%s name=%s dept=%s status=%s roles=[%s]' % ( x.get('id'), fix(x.get('username')), fix(x.get('primaryDeptName')) or fix(x.get('primaryDeptId')) or 'null', x.get('employmentStatus'), roles)) # 2. 商机全量明细 opp = load('opp-all') ol = (opp.get('data') or {}).get('content') or [] out('=== OPP ALL total=%s n=%s ===' % ((opp.get('data') or {}).get('total'), len(ol))) out('owner dist: %s' % Counter(fix(o.get('ownerNameSnapshot')) or o.get('ownerUserId') for o in ol).most_common()) out('ownerDept dist: %s' % Counter(fix(o.get('ownerDeptName')) or 'null' for o in ol).most_common()) out('source dist: %s' % Counter(fix(o.get('oppSourceName')) or o.get('oppSource') for o in ol).most_common()) out('--- all rows ---') for o in ol: out('id=%s name=%s status=%s owner=%s/%s poolReason=%s stage=%s created=%s' % ( o.get('id'), fix(o.get('oppName')), o.get('oppStatus'), fix(o.get('ownerNameSnapshot')), fix(o.get('ownerDeptName')) or '-', fix(o.get('poolReason')) or '-', fix(o.get('currentStageName')), o.get('createTime'))) # 3. dict industry 层级 di = load('dict-items') items = di.get('data') or {} out('=== DICT ITEMS industry / opp_stage / pool_reason ===') for grp in ['industry', 'opp_stage', 'pool_reason', 'pause_reason', 'close_reason']: lst = items.get(grp) or [] out('--- %s (%s items) ---' % (grp, len(lst))) for it in lst[:20]: out('code=%s name=%s parent=%s level=%s enabled=%s' % ( it.get('code'), fix(it.get('name')), it.get('parentId'), it.get('level'), it.get('status'))) with open(out_path, 'w', encoding='utf-8') as f: f.write('\n'.join(_buf)) print('written', out_path, len(_buf), 'lines')