
    }j4              
       B   d Z ddlZddlZddlZddlZddlmZ ej                            d          Z	ej        
                    e	d          Zej        
                    e	d          Zej                            d          Zej        
                    ed          Zej        
                    ed	          Zej        
                    e	d
          Zej        
                    e	d          Zdej        v ZddddddZddddddddZg dZd Zd Zd Zd Zd  Zd! Zd" Zd# Zd$ Zd% Z d& Z!e"d'k    r e            \  Z#Z$Z%Z& e'd( e(e#           d)            e e#          \  Z)Z* e'd* e(d+ e)D                        d)            e+e)          D ]#Z, e'd,e, d- e(e)e,                    d.           $ e'              e'd/ e(e*           d)           e*D ] Z- e'd0e-d1          d2e-d3          d4           !er e'd5           dS  e'd6e            dS dS )7uf  
文书归档员 —— 把工作台文档按销售员自动归类到 归档/<销售员>/<类型>/

归属识别：
  1. AI 生成文件（生成文件/index.json）→ owner 字段直接给
  2. 客户管理/ 历史文档 → 文件名提取客户名 → 客户→销售员映射反查
  3. 识别不到 → 归档/未归类/

归档方式：软链接（symbolic link），不移动原文件，不破坏 file_manifest.json / 前端引用。

用法：
  python3 脚本/文书归档员.py            # 全量归档（清空重建软链接）
  python3 脚本/文书归档员.py --check     # 只报告，不落盘
    N)defaultdictu    ~/Desktop/Hermes输出-工作类u   数据u   归档u:   ~/Library/Application Support/宝锐工作台/生成文件z
index.jsonfiles   客户管理   AI生成文件z--checkvisitmarketvisitorprepminutes)	   拜访卡   市场调研卡	   来访卡   访前背调   拜访纪要r   r   r   r   r      调研报告   其他)r   r   r	   r
   r   reportother))r   r   )r   r   )	   调研卡r   )r   r	   )r   r
   )r   r   )   客户调研r   )r   r   c                     	 t          j        t          t          j                            t          d          d                    } d |                     dg           D             S # t          $ r t                      cY S w xY w)u   在职人员名单zpricing/_personnel.jsonutf-8encodingc                 P    h | ]#}|                     d           dk    |d         $S )statusu   在职name)get).0xs     J   /Users/liuxinyuan/Desktop/Hermes输出-工作类/脚本/文书归档员.py	<setcomp>z!load_personnel.<locals>.<setcomp>5   s1    YYYaQUU8__PX=X=X&	=X=X=X    	personnel)
jsonloadopenospathjoinDATAr   	Exceptionset)ps    r!   load_personnelr/   1   s    Id27<<.GHHSZ[[[\\YY155b#9#9YYYY   uus   A%A( (BBc                     i } 	 t          j        t          t          j                            t          d          d                    }|D ]r}|                    d          pd                                }|                    d          p|                    d          pd                                }|r|r|| |<   sn# t          $ r Y nw xY wt          j                            t          d          }t          j        
                    |          r	 t          j        t          |d                                        d	i           }|                                D ]Y\  }}|                     t          |                                          t          |                                                     Zn# t          $ r Y nw xY w| S )
uD   客户名 → 销售员 映射（_key_customers + customer_sp_map）zpricing/_key_customers.jsonr   r   r    salespersonsaleszcustomer_sp_map.jsonmap)r%   r&   r'   r(   r)   r*   r+   r   stripr,   existsitems
setdefaultstr)	mkccr   spspmdkvs	            r!   load_cust_sprB   :   s   
AYtBGLL/LMMX_```aa 	 	AEE&MM'R..00D%%&&>!%%..>BEEGGB  $		
    
',,t3
4
4C	w~~c 		$sW55566::5"EEA		 = =1SVV\\^^SVV\\^^<<<<= 	 	 	D	Hs%   B;C   
CCB%F; ;
GGc                    t           j                            |           d         }g d}|D ]}|                    |d          }t	          j        dd|          }t	          j        dd|          }t	          j        dd|          }t	          j        dd|          }t	          j        dd|          }|                    d	          S )
uc   从文件名提取客户名/销售员名（去扩展名、类型后缀、日期、AI回答前缀）r   )u!   沟通策略与销售准备报告u'   产品开发方向与原料匹配分析u   访前背调报告u   拜访作战卡r   u   简介卡片u   客户档案u   来访接待r   r   r   r   r   r   u	   作战卡u   飞书活动归纳u   纪要u   报告u   沟通u   样本r1   z_\d{6,8}z-\d{8}z-\d{4}-\d{2}-\d{2}u   ^AI回答_?z^\d{8,14}[-_]?z_ -)r(   r)   splitextreplaceresubr5   )fnamebasesuffixessufs       r!   extract_customerrL   Q   s    7E""1%D8 8 8H
  % %||C$$6+r4((D6)R&&D6'T22D6."d++D6#R..D::er#   c                 `    dD ]}|                      |d          } |                                 S )uY   归一化公司名：去法律后缀，保留行业词（科技/生物/医疗）做区分)u   股份有限公司u   有限责任公司u   有限公司u   集团r1   )rE   r5   )r   rK   s     r!   norm_companyrN   f   s4    U % %||C$$::<<r#   c                     i } t           j                            t          d          }t           j                            |          r	 t          j        t          |d                    }t          |t                    r|
                    dg           n|}|D ]}|
                    d          pd                                }d}|
                    d          }t          |t                    r*|
                    d          pd                                }n)t          |t                    r|                                }|r|r|| |<   n# t          $ r Y nw xY w| S )	ux   客户名 → 部门 映射（从 mcp_customers.json 的 field_5ed7ab 提取，用于无销售员归属的 CRM 客户）zmcp_customers.jsonr   r   	customersr   r1   field_5ed7ablabel)r(   r)   r*   r+   r6   r%   r&   r'   
isinstancedictr   r5   r9   r,   )r:   r.   r?   r7   r<   r   deptfs           r!   load_cust_deptrW   m   sX   
A
T/00A	w~~a 		$q733344A.8D.A.AHAEE+r***qE 	# 	#f+2244EE.))a&& %EE'NN0b7799DD3'' %7799D #D #"AdG	#  	 	 	D	Hs   	DE 
EEc                 >   | sdS | |v r||          S | |v r| S t          |           }t          |          dk    rd|                                D ]O\  }}t          |          }|s||k    s.t          |          dk    r||v st          |          dk    r||v r|c S PdS )u]   客户名 → 销售员。精确 → 归一化核心名包含 → 销售员本人名 → NoneN   rN   lenr7   )custcust_spr$   	norm_custcnr=   norm_cns          r!   identify_ownerra      s     twt}yT""I
9~~mmoo 	 	FB"2&&G G##I!(;(;	W@T@TZ]^eZfZfjkZkZkpw  |E  qE  qE			4r#   c                 2   | sdS | |v r||          S t          |           }t          |          dk    rd|                                D ]O\  }}t          |          }|s||k    s.t          |          dk    r||v st          |          dk    r||v r|c S PdS )uZ   客户名 → 部门（CRM 客户无销售员时的 fallback），归一化核心名匹配NrY   rZ   )r\   	cust_deptr^   r_   rU   r`   s         r!   identify_deptrd      s     tyT""I
9~~!)) 	 	HB"2&&G G##I!(;(;	W@T@TZ]^eZfZfjkZkZkpw  |E  qE  qE4r#   c                 \    |t           v rt           |         S t          D ]\  }}|| v r|c S dS )u9   文档类型：优先子目录名，其次文件名后缀r   )DIR_TYPESUFFIX_TYPE)rH   dirnamerK   ts       r!   
guess_typerj      sG    (    Q%<<HHH 7r#   c                     g } t                      t                      t                      fd}t          j                            t                    r=	 t          j        t          t          d                    }|
                    dg           D ]}t          j                            t          |
                    dd          |
                    dd          z             }t          j                            |          r{|                     ||
                    d          pd                                pd	d	t          |
                    d
d          d          |
                    d
d          dd           n# t           $ r Y nw xY wt          j                            t$                    rt          j        t$                    D ]\  }}}d|v sd|v rt          j                            |          }|D ]}	|	dk    s|	                    d          rt          j                            ||	          }t-          |	          }
 ||
          \  }}|                     |||t          |	|          |	dd           t          j                            t.                    rt          j        t.                    D ]}	|	                    d          s|	                    d          r-t          j                            t.          |	          }t-          |	          }
 ||
          \  }}|                     |||t          |	d          |	dd           | fS )uA   收集所有文档，返回 (docs, personnel, cust_sp, cust_dept)c                 V    t          |           }|r|dfS dt          |           fS )u9   客户名 → (owner, dept)：优先销售员，次部门N)ra   rd   )r\   ownerrc   r]   r$   s     r!   _resolvezcollect_docs.<locals>._resolve   s;    tWi88 	$;]43333r#   r   r   r   fidr1   extrm   Nr   u   AI生成)srcrm   rU   typer   sourcez/.u   /归档z	.DS_Store~r   .r   )r/   rB   rW   r(   r)   r6   PRIVATE_INDEXr%   r&   r'   r   r*   PRIVATE_FILESappendr5   rj   r,   isdir	CUST_MGMTwalkbasename
startswithrL   AI_FILES_DIRlistdir)docsrn   idxrV   fprootdirsr   rh   fnr\   rm   rU   rc   r]   r$   s                @@@r!   collect_docsr      ss   D  InnG  I4 4 4 4 4 4 4 
w~~m$$ 	)DAAABBCWWWb))  W\\-ub1A1AAEE%QSDTDT1TUU7>>"%% KK!QUU7^^-Ar,H,H,J,J,Rd\` *155+<+<b A A !fb 1 1",	! !     	 	 	D	 
w}}Y !#!3!3 	 	D$t||yD00g&&t,,G 
 
$$c(:(:$W\\$++'++&htnntt&r733.     
 
w}}\"" *\** 
	 
	B}}S!! R]]3%7%7 lB//B#B''D"(4..KE4KKE4"2r**&6     
 GY..s   D+F	 	
FFc                    t           j                            t                    rt          j        t                    D ]v\  }}}|D ]m}t           j                            ||          }t           j                            |          s|dk    r&	 t          j        |           ]# t          $ r Y iw xY wnwt          j        t          d          D ]J\  }}}	 |t          k    r(t          j	        |          st          j
        |           ;# t          $ r Y Gw xY wt          j        t          d           t          t                    }g }| D ]+}|d         }	|                    d          }
|d         }t                              |d	          }|	s|
rd
|
z   }	n|                    |           d}	t           j                            t          |	|          }t          j        |d           t           j                            |d                   }t           j                            ||          }t           j                            |          st           j                            |          rot           j                            |          \  }}ddl}t           j                            || dt+          |                                          dz   |           }t,          s-	 t          j        |d         |           n# t          $ r Y nw xY w||	                             |d         ||                    t2          d          |d         |d                             t2          d          d           -t,          st5          t           j                            t          d          dd          5 }t7          j        t;          d          j                                                             d          tC          |           tE          |          d|dd           ddd           n# 1 swxY w Y   tE          |          |fS )uU   归档：软链接到 归档/<销售员>/<类型>/，返回 (索引, 未归类列表)u   索引.jsonF)topdownTexist_okrm   rU   rr   r   u   部门/	   未归类rq   r   N_i r   r1   rs   )r   rr   r)   rs   rq   wr   r   datetimez%Y-%m-%d %H:%M:%S)updatedtotalowners   )ensure_asciiindent)#r(   r)   ry   ARCHIVEr{   r*   islinkunlinkr,   r   rmdirmakedirsr   listr   
TYPE_LABELrx   r|   r6   rD   timeint
CHECK_ONLYsymlinkrE   BASEr'   r%   dump
__import__r   nowstrftimer[   rT   )r   r   r   r   r   r   indexunclassifiedr?   rm   rU   typrR   dst_dirrI   dststemrp   r   rV   s                       r!   archiver      sj    
w}}W !#!1!1 	 	D$  W\\$++7>>"%% })<)<	"$    *= "$%!@!@!@ 	 	D$7??2:d+;+;?HTNNN   K$''''EL  '
uuV}}isH-- 	$ $!D(##A&&&#',,wu55
Gd++++w%))gll7D))7>># 	R"'.."5"5 	R((..ID#KKK',,w4(P(P#diikk2B2B62I(P3(P(PQQC 	
1U8S))))   efIuckk$6K6Kk!E(*:*:4*D*D
 
 	 	 	 	
  d"',,w66gNNN 	dRSI*Z"8"8"A"E"E"G"G"P"PQd"e"e #D		T%[[B BCDSXabd d d d	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d ;;$$sI   B##
B0/B03D
DD(L
LL7A.P11P58P5c                 z   	 |pd}|dk    rd}t          |pdd          }t                              |d          }t          j                            t          ||          }t          j        |d           t          j                            |pt          j                            |                     }t          j                            ||          }t          j        	                    |          st          j        
                    |          rdS t          j        | |           dS # t          $ r Y dS w xY w)u;  归档单个文件到 归档/<owner>/<类型>/（软链接，用原文件名）。供 AI 生成文件后即时归档。
    src_path = 实际文件路径（fid.html），name = 展示用原文件名，owner = 归属销售员。
    返回 True 表示已归档，False 表示跳过（未归类/已存在/失败）。u   未知r   r1   r   Tr   F)rj   r   r   r(   r)   r*   r   r   r|   r6   r   r   r,   )	src_pathrm   r   targetftyperR   r   rI   r   s	            r!   archive_oner   1  s   "(X F4:2r**uh//',,w66
Gd++++w B(8(8(B(BCCgll7D))7>># 	"'.."5"5 	5

8S!!!t   uus   DD, D, ,
D:9D:__main__u   扫描到文档: u    个u   归档目录数: c                     g | ]
}|d k    |S )r    )r   r@   s     r!   
<listcomp>r   K  s"    "F"F"FQ+5E5E15E5E5Er#   z  z: u
    个文档u   未归类: u     [未归类] r   z (rs   )u   
(--check 模式，未落盘)u   
✅ 已归档到 ).__doc__r%   r(   rF   syscollectionsr   r)   
expanduserr   r*   r+   r   PRIVATE_DIRrv   rw   rz   r~   argvr   rf   r   rg   r/   rB   rL   rN   rW   ra   rd   rj   r   r   r   __name__r   r$   r]   rc   printr[   r   r   sortedrm   r?   r   r#   r!   <module>r      s                    # # # # # #	w<==	w||D(##
',,tX
&
&g  !]^^[,77['22GLL~..	w||D"233#("
 XII 
 $5+~ 
      .  *    .  (  "  =/ =/ =/@;% ;% ;%|  , z*6,..'D)Wi	E
-cc$ii
-
-
-...C	E
Mcc"F"Fc"F"F"FGG
M
M
MNNN 9 97577CCE
OO7778888	EGGG	E
/L))
/
/
/000 < <:qy::AhK:::;;;; /./////-G--..... r#   