U
    e                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	Z	d dl
mZ d dlZd dlmZ d dlmZ d dlT d dlZd dlmZ d d	lmZ G d
d dejZejdd  dS )    N)md5)	randrange)Random)post)commit_all_ds)*)BeautifulSoup)
cmf_personc                       sN  e Zd Zej dZedddd fdd
Zdd Zed	d
 Z	edddZ
edddZedd Zdd Zdd ZdddZdddZdddZedd Zdd Zd d! Zd"d# Zd$d% Zedd&d'Zed(d) Zeejddd*ddd+d,d-Zeejddd*dd.d/Zddddddd0d1d2Z fd3d4Z d5d6 Z!d7d8 Z"d9d: Z#eddd; fd<d=
Z$d>d? Z%d@dA Z&dBdC Z'dDdE Z( fdFdGZ)dHdI Z*dJdK Z+dLdM Z,ddOdPZ-dQdR Z.ddS fdTdU
Z/dVdW Z0dXdY Z1 fdZd[Z2dd]d^Z3 fd_d`Z4 fdadbZ5 fdcddZ6eddedfZ7dgdh Z8eejddie$djdkdlZ9eddmdndoZ:edddpdqdrZ;dsdt Z<edudv Z=ed fdwdx	Z>eddydzZ?d{d| Z@edd}d~ZAdd ZBdd ZCdddZDdd ZEeejddddd ZFedd ZGdddZHedd ZIedd ZJeeKdddd ZL  ZMS )	CmfPersonz/custom/static/avatar/ Nqueryfieldsfilterc             	      s>   | dpdddddddd	d
g	|d< t j||||d|S )NZfields_filternametextcodephoneemailphone_internalphone_mobilephone_2Zphone_assistantr   )getsupersearch)clsr   r   r   argskwargs	__class__ %./modules/person/models/cmf_person.pyr      s    $   zCmfPerson.searchc                 O   s   t dt| jS Nr   )strjoinreversedr   selfr   r   r    r    r!   reverse_name"   s    zCmfPerson.reverse_namec                 C   s   | j ddS )N.CmfPerson:00000000-0000-0000-0000-000000000001idr   r   r    r    r!   system_person%   s    zCmfPerson.system_personTc                 O   s    t jjtjjddddddgdS )Nr   online_statuson_vacationrg_member_ofis_admin
two_factor)r+   r   )modelsr
   r   gcurrent_personr+   )r   Zcreate_args_kwargsr    r    r!   get_current_user)   s     zCmfPerson.get_current_userc                 C   sD   g }t jjdddtjjggddtjjgg|dD ]}|| q0|S )NOR	executorsINcmf_owner_id==r   r   )r4   
CmfProjectlistr5   r6   r+   append)r   r   resultprojectr    r    r!   get_current_projects/   s    
zCmfPerson.get_current_projectsc                 O   s<   | j p| jpd}| jpd}| jp"d}| d| d|  S Nr    )	last_namelogin
first_namesecond_namestrip)r'   r   r   rH   rJ   rK   r    r    r!   	full_name7   s    

zCmfPerson.full_namec              	   O   sr   |  dg | jsltjd | dddd}|jdd || _t  |   W 5 Q R X tj|ddd	jdd | jS )
Nhome_folderi'  u   Мои документыhome)tree_parent	cmf_ownerordernor   Zsys_typeF)notifyu   Документ1)rP   rR   r   )load_fieldsrN   r4   Z	CmfFoldersavecmfutildisable_aclZCmfDocument)r'   r   r   Zfolderr    r    r!   get_home_folder>   s     
zCmfPerson.get_home_folderc                 C   s   | j p| jp| jS N)rM   rI   r   r'   r    r    r!   gen_nameM   s    zCmfPerson.gen_namec                 C   s   d}|rt |d}nF|r:tjj|ddgd}|r\|j}n"|r\tjj|ddgd}|r\|j}|std| d| d	| d
 dS | tjkrtj	}ntj
j| dd}||krdS dS )u   
        ! Публичное API для bzPython
        Метод проверки, что пользователь находится в группе
        NCmfPersonGroup--r+   r   r   r   r   uX   Ошибка вызова in_person_group: не найдена группа (group_code=z, group_name=z, group=)FT)Zid_only)rV   get_obj_id_by_anyr4   r\   sgetr+   	cmf_alertr5   current_usercurrent_person__member_ofCmfAccessListZsubject_full_group_list)r'   groupZ
group_codeZ
group_nameZgroup_idZ	member_ofr    r    r!   in_person_groupP   s(    
zCmfPerson.in_person_groupc                 C   s   | j |||dS )u   
        ! DEPRICATED
        ! Публичное API для bzPython
        Для обратной совместимости
        )rD   	role_coderole)in_project_role)r'   rD   ri   rj   r    r    r!   has_project_rolep   s    zCmfPerson.has_project_rolec                 C   s   d}|rt |d}nF|r:tjj|ddgd}|r\|j}n"|r\tjj|ddgd}|r\|j}|std| d| d	| d
 dS t |d}| jjtj	||kS )u   
        ! Публичное API для bzPython
        Метод проверки, что пользователь назначен на Проектную роль
        role и project могут быть: объект, tuuid, code, name
        NCmfProjectRoler]   r+   r^   r_   ug   Ошибка вызова in_project_role - не найдена Проектная роль (role_code=z, role_name=z, role=r`   Fr@   )
rV   ra   r4   rm   rb   r+   rc   valuer
   get_project_role_members)r'   rD   rj   ri   Z	role_namerole_id
project_idr    r    r!   rk   x   s     zCmfPerson.in_project_rolec                 C   s   t j|t  t j| }||d  || }|d k	r>t|S t }tjjdd|gdd|ggddgdD ]"}|j	 D ]}|
|jj qvqh|t j|< t|S )Nparent=Zproject_rolemembersZproject_role_idr?   )APPZcache_in_project_role
setdefaultdictrA   setr4   ZCmfProjectRoleAssignrt   Z
all_nestedaddr+   rn   )r   rq   rp   Zproject_cacheZrole_cache_setZrulememberr    r    r!   ro      s    


z"CmfPerson.get_project_role_membersc                 C   s`   |  dddg d}| jrL| jrL| jtj  krL| jtj  krLd}| j|kr\|| _d S )Nr0   vacation_startvacation_endFT)rT   r{   r|   datetimeZutcnowdater0   )r'   Zcur_on_vacationr    r    r!   _calc_vacation   s    
zCmfPerson._calc_vacationc                 C   s   | j jr| j js| j dkrd S | j j}|| jd}|| jd }|d}t	|dkrl| j
sl|d | _
t	|dkr| js|d | _t	|dkr| js|d | _d S )Nr   rG   r         )r   
is_changedis_nullrn   replaceVACATION_SUFFIXDOES_NOT_WORK_SUFFIXrL   splitlenrH   rJ   rK   )r'   ZtmpZname_arrr    r    r!   _calc_from_name   s    


zCmfPerson._calc_from_namec                 C   sx   | j js<| jjs<| jjs<| jjs<| jjs<| jjs<| jjs<d S d}| jrRd| j }| jrdd| j	 }| j
 | | _ d S rF   )r   r   rJ   rK   rH   rI   r0   does_not_workr   r   rM   )r'   Zadd_strr    r    r!   
_calc_name   s,    	zCmfPerson._calc_namec                 C   sn   t tjjjtjjjtjjjtjjjd}| jrT|D ] }| jj	|r2| j| ||< q2|d sj| j
rjd|d< |S )N)
allow_baseZ
allow_ldapZallow_oauthZ	allow_ssor   T)rw   r5   global_settingsZauth_options_allow_basern   Zauth_options_allow_ldapZauth_options_allow_oauthZauth_options_allow_ssoauth_optionsr   r2   )r'   reskeyr    r    r!   get_auth_options  s    
zCmfPerson.get_auth_optionsc              
   C   sH  dddddgdddggddd	gdd
ddgd
dd	ggg}|rN|sN| dd|g g }tjj|ddddddddgddD ]}g }t|jj|jj|jj|j	j||j
j| d}|j
s|jstjjrdd |jD |d< ndd |jD |d< n(|jrt|jj|d< d	|_|jdd nqt| | qt|s(d	S t |ddd}td| d	S ) u   
        Отправляем учетки в аккаунт
        https://bcrm.carbonsoft.ru/project/Document/DOC-003025#spec-0-ldap
        ZANDr:   
user_localr>   Tservicedesk_allowrI   !=NZ
is_supportZcmf_modified_at>zrg_member_of.ext_idcmf_deletedr   deleted_loginr   r   	ext_loginzrg_member_of.system)r   r   include_deleted)rI   r   r   r   r1   r   r   c                 S   s   g | ]}|j r|jjqS r    )systemr   rn   .0objr    r    r!   
<listcomp>J  s      z/CmfPerson.account_sync_push.<locals>.<listcomp>r1   c                 S   s   g | ]}|j jqS r    )r   rn   r   r    r    r!   r   L  s     Z	only_data)Zeva_app_tokenusersZrpc_account_sync_push)r   methodz/auth/sync_accounts)rB   r4   r
   rA   rw   rI   rn   r   r   r   r   r   r   r5   r   Zonly_system_grp_syncr1   r   rU   Zgen_eva_app_tokenZcall_eva_account)r   account_sync_lastforce_filterr   personr1   datar    r    r!   account_sync_push.  sN    

zCmfPerson.account_sync_pushc                 C   s   t td t| j d S )Ni  )timesleepr   cmf_deferred_taskaccount_sync_usersr-   r    r    r!   cron_account_sync_users]  s    z!CmfPerson.cron_account_sync_users)	only_onceZsystem_task)r   two_factor_optc           	      O   s  g }d}| s dddgddd gg} t jj| dddgdD ]}zF|jsVt j|j|jd	|_||j_|j  |  t	  |d
7 }W q6 t
k
r } z"t  |t| t| W 5 d }~X Y q6X q6d| }|r| dd| }t| tjd|d d S )Nr   r   r>   Tr3   r   r   r?   r   r   r   u   Обработано u-   </br> Не удалось настроить:z</br>u)   Закончили настройку 2FA)r   )r4   r
   rA   r3   CmfAuthTwoFactorr   r   r   rU   commit_with_event	ExceptionZrollback_purge_eventrB   r#   r5   debugr$   rV   Zadmin_alert)	r   r   r   r   Zfail_personZcntr   er   r    r    r!   init_2fa_settingsb  s0    


zCmfPerson.init_2fa_settingsc              
   O   s   t d t jjdkr<t jjjdkr.td nt d dS dt j_t jjj}t jj  t j	  t
  z&tjj|| d dt j_t j	  W nV tk
r } z8t| t| t| |t j_d	t j_t j	  W 5 d}~X Y nX dS )
uz   
        Синхронизируем уровень доступа с accounts сервером
        :return:
        u6   Запуск синхронизации с eva_accountZin_progressi  u   Синхронизация пользователей зависла, запускаем форсированно повторноu2   Синхронизация уже запущенаN)r   closederror)r5   r   Z
global_varZaccount_sync_statusr   Zagerc   rn   Zset_nowrU   r   r4   r
   r   r   logging	exceptionr   )r   r   r   r   r   r    r    r!   r     s,    





zCmfPerson.account_sync_users)slicer   order_bydo_count	do_unreadsearch_filterc             	   O   sN  t jjdddgddgd}	t }
|	D ]R}|jrRt|jjt jrR|jjrR|
| q$| j	jdd |
 D kr$|
| q$|rt jjd	d
dd| j	jggddddgddtjj	ggddttdd |
ggdS ddddgddtjj	ggddttdd |
gg}|r"dddgd	d
dd| j	jgg|g}|r2|| t jj||ddg|d}|S )NZ	list_typer>   Zpfeedrr   zparent.is_defaultr?   c                 S   s   g | ]}|j jqS r    )r+   rn   )r   r   r    r    r!   r     s     z-CmfPerson.pfeed_post_list.<locals>.<listcomp>Zperson_viewsz
NOT EXISTS	person_idrs   r:   cache_status_typer   ZOPENr=   listsr<   c                 S   s   | j S rY   r*   xr    r    r!   <lambda>      z+CmfPerson.pfeed_post_list.<locals>.<lambda>r   c                 S   s   | j S rY   r*   r   r    r    r!   r     r   z-status_in_progress_start-cmf_created_at)r   r   r   r   )r4   ZCmfListrA   rr   
isinstancern   r@   Z
is_defaultrB   r+   Zall_relation_personsCmfTaskcountr5   r6   map)r'   r   r   r   r   r   r   r   r   r   Zmy_listsZlstZfltZ	post_listr    r    r!   pfeed_post_list  sB    


 
zCmfPerson.pfeed_post_listc                    s   t  j|fd| ji|S )Nr   )r   mark_viewedr+   )r'   Zobj_idr7   r   r   r    r!   r     s    zCmfPerson.mark_viewedc                 O   s   d S rY   r    r&   r    r    r!   public_mark_viewed  s    zCmfPerson.public_mark_viewedc                 C   s   g }| j jrtj }|jdd | j D krtjjdd| jggdgd}|rZdd |D }|sdd|jggd	d
d| jggg}tjj|d	gdD ]h}t }|g|_	d|_
|  |j	|  |jdd |jD ]}|j	|  |jdd q|| q|S )Nc                 S   s   g | ]
}|j qS r    r*   r   r    r    r!   r     s     z.CmfPerson.create_p2p_chats.<locals>.<listcomp>r;   r<   p2pr?   c                 S   s   g | ]}|j r|qS r    )r   r   r    r    r!   r     s      r1   r+   zNOT INr)   Tr   )r1   r   r4   r\   
user_groupr+   ZCmfChatGrouprA   r
   r;   r   rU   rB   Ztopics)r'   r   Zusr_grpZ	cur_chatsr   r   rg   Ztopicr    r    r!   create_p2p_chats  s2    

zCmfPerson.create_p2p_chatsc                 C   s2   | j s
d S tjj| jkr$tddd tj  d S )Nu1   Нельзя удалить самого себяTabort)r   r5   r6   r+   rc   r4   rf   check_admin_moderZ   r    r    r!   
_check_del  s
    zCmfPerson._check_del)include_systemis_userc                   s.   |s| dd |dkr d|d< t j||S )Nr   FTr   )rv   r   rA   )r   r   r   r   r   r   r    r!   rA     s
    zCmfPerson.listc                 C   s,   | j rtjj| drd S tj| d  d S )Nr   )r   r4   CmfPersonVarrb   rU   rZ   r    r    r!   _check_person_var  s    zCmfPerson._check_person_varc                 C   sp   | j s| jrd S | jjrF| jjrF| jjsF| jjj dkrFtddd | jj	rlt
jd| jd}|  || _d S )Nr   u?   Контакт не может быть без компанииTr   )typer   )r   r   companyr   oldnewr   loadrc   r   r4   Z
CmfCompanyrM   rU   )r'   Znew_companyr    r    r!   _calc_company  s    "zCmfPerson._calc_companyc                 C   sL   | j r| jsdS tjdg | jD ]"}tjjD ]}|j|_|  q0q$dS )u   
        Вычисляем список избранного по умолчанию для новых пользователей
        Nzperson_var.favorites)is_newr   r5   r6   rT   
person_varZ	favoritesrU   )r'   r   Zcurrent_person_varr    r    r!   _calc_default_favorites  s    
z!CmfPerson._calc_default_favoritesc                 C   s   | j r| jsd S d S rY   )r   r   rZ   r    r    r!   _calc_avatar  s    zCmfPerson._calc_avatarc                    s8   t   ddddddddd	d
dddddddddddg S )NrI   notify_email
notify_smsr   r   rolesprimary_rolezcompany.typer   r   r   r0   r{   r|   rH   rJ   rK   r   r   ztwo_factor.two_factor_opt)r   save_preload_fieldsrZ   r   r    r!   r     s.                     zCmfPerson.save_preload_fieldsc                 C   s   | j r| j jsdS g }tjjdd| gdddggdD ] }|d|j d	|j d
 q4|rd|}d| j d	| j d| }tj| 	 d|d
  dS )zY
        https://bcrm.carbonsoft.ru/project/Document/DOC-003685#spec-eva-account
        Nresponsibler>   r   r   ZCLOSEDr   z	<a href="z">z</a>z<br>z</a> uM   Обработайте задачи уволенного сотрудника)r   r   r   )r   r   r4   r   rA   rB   Zhrefr   r$   get_supervisorrU   )r'   Zlinkstaskr   r    r    r!   _check_does_not_work!  s    

zCmfPerson._check_does_not_workc                    sh    fdd |  ddg d}| jrB| jjr6| jj}n | jj}|sdtj }|j  |jd }|S )u   
        Идем по структуре отделов роли и получаем первого руководителя
        c                    s6   | j rtjj| j dS | dg | jr2 | jS d S )N)r   ztree_parent.head)headr4   r
   r   rT   rP   )Zorg_unit	recursionr    r!   r   7  s    
z+CmfPerson.get_supervisor.<locals>.recursionzprimary_role.supervisorzprimary_role.tree_parent.headNr   )	rT   r   
supervisorrP   r4   r\   Zadmin_groupZ
rg_membersr   )r'   r   Z	admin_grpr    r   r!   r   3  s    



zCmfPerson.get_supervisorc              	   C   s   | j jsd S i }| dg | j D ]^}|js.q"t|jdD ]@}| }||krvtd||  d| d| dd q>|||< q>q"d S )Nz*rg_member_of.incompatible_combination_code,u\   Пользователь не может участвовать одновременно в u    и uS   , так как у них указан Код запрета совмещения: Tr   )r1   r   rT   Zincompatible_combination_coder#   r   rL   rc   )r'   ZcodesZgrZgr_coder    r    r!   %_check_roles_incompatible_combinationM  s    
z/CmfPerson._check_roles_incompatible_combinationFc                 C   sP   | j js|sd S | j sd | _n.| jjr4| j d | _n| j| j krL| j d | _d S )Nr   )r   r   r   r   )r'   r   r    r    r!   _calc_primary_roleb  s    zCmfPerson._calc_primary_rolec                 C   sB   | j rtjj| dsdS tjj| dD ]}d|_|jdd q&dS )uN   Надо пометить что данные не засинканы
        r   NTr   )r   r4   CmfAuthPluginDatar   rA   ZdirtyrU   )r'   	auth_datar    r    r!   _check_auth_datan  s
    zCmfPerson._check_auth_data)save_kwargsc                   s0   | drtddd t j|d|i| d S )Nr   u   Назначение или открепление должности пользователю необходимо производить в "Структуре" в карточке должностиTr   r   )r   rc   r   update)r'   r   r   r   r   r    r!   r   w  s    
zCmfPerson.updatec                 C   s8   | j r4tjjr4| js4| tjfkr4tj| j| j	d| _d S )Nr   )
r   r5   r   r   r3   r.   r4   r   r   r   rZ   r    r    r!   
_check_2fa  s     zCmfPerson._check_2fac                 C   sp   | j jsd S d }| j jD ]}|j r|jj} q4q|s<d S | jsVtj| j	| j
d| _|| j_| jjdd d S )Nr   Tr   )r1   r   r   r   r   rn   r3   r4   r   r   r   rU   )r'   r   grpr    r    r!   _check_2fa_group  s    
zCmfPerson._check_2fa_groupc                    s   |    t j|| d S rY   )r   r   _save_importr&   r   r    r!   r     s    zCmfPerson._save_importr   c                 K   sv   |dkrd S | j jsd S tjs@tjs@tjtjks@tjj	dddrDd S tj
jdddgd}|jjtjkrrtd	d
d d S )Nr   r   F)Zraise_errorr   r>   ZProjectAdminsr   u  Изменение членства в группах на карточке пользователя для Проектных администраторов временно недоступно. Откройте группу и добавьте пользователя там.Tr   )r1   r   r5   Zdisable_permissionsZacl_admin_moder6   r.   r4   rf   r   r\   r   r+   rn   re   rc   )r'   depthr   Zproject_admins_groupr    r    r!   _tmp_changing_member_of_alert  s    z'CmfPerson._tmp_changing_member_of_alertc                    s2  | j f | |   | jjr*| jr*|   | jrD| j| jkrD| j| _|   |   | 	  | 
  |   |   |   | jjr| jr| jjs| jjstddd |   |   |   |   |   tt| j||}|   | js| jrttjj  tj!| j"j# | j$r.tj%| d}|  |S )Nu   Для включения SMS уведомлений необходимо указать номер мобильного телефонаTr   )rr   )&r   r   r   r   r   rI   r   r   r   r   r   r   r   r   r   r   numberr   rc   r   _calc_servicedesk_allowr   r   r   r   r
   rU   r   r   r   r   r4   r   trigger_reloadr+   rn   r   ZCmfTimeTracker)r'   r   r   r   Zperson_timetrackerr   r    r!   rU     s<    zCmfPerson.savec                    s   |  dddg tjjdd| gdgd}|rDtd| d	d
d d S | jrrdtj d }| d| j | _| 	  |drtj
j| d
dD ]}|j|| qtjj| dD ]}|j|| qt j|| ttj tj| jj tj  d S )NrQ   r   employee_numberr   r>   Zauth_pluginr?   u;   Пользователь синхронизирован с u9   , сначала отключите интеграцию.Tr   ZDELz%Y%m%d%H%M%SrG   ZTEXKOM_db_delete)r   r   r   )rT   r4   r   r   rc   r  r}   Znowstrftimer   ZCmfPersonViewrA   deleter   r   r   r
   r   r  r+   rn   ZCmfProjectNotifyScheme)r'   r   r   r   prefixpvarr   r    r!   r    s$    

zCmfPerson.deletec                    s8   | j rt| jd| j j| _ t j|| ttj	 d S r"   )
r  resubZdelete_prefix_patternrn   r   restorer   r
   r   r&   r   r    r!   r    s    zCmfPerson.restorec                 C   sP   |rLt  }||d | }tj d| d}tj	|sLt
| |S )Nutf8/)hashlibr   r   encode	hexdigestr'   _AVATAR_DIRECTORYospathexistsmakedirs)r   rI   mZavatar_hashavatar_directoryr    r    r!   
avatar_dir  s    
zCmfPerson.avatar_dirc                 O   sf   t j| jj}tj|rNt|D ]&}| | }tj	|r&t
| q&ttj| jjgd d S )Nr   )r4   r
   r  rI   rn   r  r  isdirlistdirisfileremover   set_gravatarr+   )r'   r   r   r  filefilepathr    r    r!   remove_avatar  s    zCmfPerson.remove_avatar)r   )emailsc              
   O   s  ddl m} g }tjtjd s0td |S tj	j
rHtjjsXtjjsXtdtj | }tj }| D ]}|dkr|qlt|tjttt ttt d d|d	}td
|  tjjj|d< t|}	t|	}
tjjdgdjj}|d|
|d}|jtj  d|t!j"dd}td
| d|  |j#dksH|j$dkrh|% }td| d|  qldd|g}td|  tj&j|d}|std tj&|||gdd}n&td|j' d  |j()| d|_
t*+  |,  W 5 Q R X |)|j-j td! ql|S )"u   
        Регистрируем новых пользователей по email
        :param emails:
        :return:
        r   )sessionz/custom/org_namezCregister_persons: WARNING: org_name is not set, can't invite peopleu.   Операция не доступна для Ni:	 Zguid)rI   ZissZiatZexpZjtir
  zregister_persons:frominvite_must_change_passwordr   Zinvite_by_email)r   actioninvite_tokenr%  z/auth/signup   )r   cookiestimeout,    zSigned up successfullyuE   ERROR: Не удалось отправить приглашение z: r   r>   u"   Ищем пользователя r   u)   Создадим пользователяT)rI   r   r1   r   u(   Добавим пользователя u    в группуz!register_persons: person saved ok).requestsr#  r  r  r  configPROJECT_DIRr5   r   rd   r   r6   r2   r   Zallow_user_inviteZCmfPermissionErrorr4   r\   r   rw   ZAPP_FQDNr#   intr   r   rn   Z
create_jwtZrsa_sign_pack_jwtZCmfGlobalSettingsr   r%  r   ZAUTH_SERVER_URLrequestr*  status_coder   Zjsonr
   r   r1   rB   rV   rW   rU   r+   )r"  r   r   r#  rC   srg   r   ZpayloadZjwtr(  r%  r   r   r   r   r    r    r!   register_persons  sl    


 


zCmfPerson.register_personsr&  c                O   s   dg}| j |d|i|}|S )Navatar_filenamer   r,   )r   r   r   r   r   r    r    r!   
public_getG  s    zCmfPerson.public_get)r   r   c                O   s   d S rY   r    )r   r   r   r   r   r    r    r!   public_listO  s    zCmfPerson.public_listc                 O   sb   | j s
dS tjjdd| jgdgd}|r2|d }n,tj| jd}| j|_| g|_| |_|	  |S )uq   
        Возвращаем объект, с которым нужно начать переписку
        NZprimary_contact_idrs   r   )r   r   r   )r   )
r   r4   ZCmfDealrA   r+   r   r   ZcontactsZprimary_contactrU   )r'   r   r   ZdealsZdealr    r    r!   
start_chatS  s    
zCmfPerson.start_chatc                 C   s   | j jr| j jd k	r| j jS tjjdd| jgddgd}|rT|j dkrt|jtj	jkrtdtjj j
d d| j _| j jS |j r|j j
|j j pd}|j j|d| j _| j jS )	Nr   r>   r/   r?   Z	invisibleZoffline)Zjs_idr   r   )r/   Z
is_defined_valuer4   r   r   r+   r   r5   r6   choicesrn   )r'   r   r   r    r    r!   _online_statusf  s    
zCmfPerson._online_statusc                    s   |dkr|sg }|dd|gg}|dkrJ|rJ| drJ|s<g }|dddgg}|dkr||sZg }|d	d
ddgdddgdddggg}t j|f|||d|S )Nr   r   r>   r   r   Zis_internalTruer1   r:   r   Fr   rs   ZAdminsZUsers)object_fields	object_idr   )r   r   field_options_list)r   Zrelation_field_namer>  r?  r   r   r   r    r!   r@  s  s&    " zCmfPerson.field_options_listc           	   
   C   s   t d|  |s"dddddg}zt|d}t|tjjdd	  d
}ddd|gdd|gdd|gdd|gg}|r||g}tjj	||d}t d|  |W S  t
k
r } zt d|  W Y d	S d	}~X Y nX d	S )us   
        Ищем персону по номеру телефона
        :param phone:
        :return:
        u4   Ищем пользователя по номеру r   r   r   r   r   ZRUr   Nz;%r:   ZLIKEr>   r?   u.   Возвращаем пользователя %   Неправильный номер: )r5   r   phonenumbersparseZformat_numberZPhoneNumberFormatZE164r4   r
   r   r   )	r   r   r   r   Z	phone_objZformat_phoner   r   r   r    r    r!   get_by_phone  s&    
zCmfPerson.get_by_phonec                    sX   g }i }|  dg | jD ]$}|jrg }|||jj< || q fdd  | |S )Nzroles.tree_parent_idc                    s\   i }t jjdd| gddgdD ],}| |j d| |jr| |j ||j< q|rX | d S )Nr+   r<   tree_parent_idr   r?   r   )r4   Z
CmfOrgUnitZslistr+   insertrE  )Zou_idsZou_ids_nextZouquery_our    r!   rH    s    z.CmfPerson.get_org_units_list.<locals>.query_ou)rT   r   rE  rn   rB   )r'   r7   r8   rC   Zou_ids_firstrZou_listr    rG  r!   get_org_units_list  s    
	zCmfPerson.get_org_units_listc              
   C   s   | j |||d}|s~z*td|  tj||d}|  W n> tk
r| } z td| d|  W Y d S d }~X Y nX td|j  |S )Nr   u:   Создаем пользователя с номером )r   r   rA  r,  u@   Возвращаем пользователя с номером )rD  r5   r   r4   r
   rU   r   r   )r   r   r   r   r   r   r    r    r!   get_or_create_by_phone  s    z CmfPerson.get_or_create_by_phonec                 C   s2   t t|dd  j|d}|| jj| dS )u3   
        Позвонить клиенту
        :r   r*   N)varsr4   r   r   callbackr   Znumber_e164)r'   Z
channel_idrN  channelr    r    r!   
phone_call  s    zCmfPerson.phone_callc                 O   s0   t j| jst | j t| j d| S )Nr  )r  r  r  r  r  pathlibPath)r'   
image_hashr   r   r    r    r!   avatar_path  s    zCmfPerson.avatar_pathc              	   O   s   |sX| j  r*| | j }| r*|  d | _ | jdd |rTttj| j	j
gd d S |}t|trpt|}t| jj
d }| d| _ | | j }	|	d}
|
| W 5 Q R X | jdd d S )NTr   r  r  z.jpegwb)r6  r   rT  r  unlinkrU   r   r
   r  r+   rn   r   r#   base64Zurlsafe_b64decoder  r   rI   r  r  openwrite)r'   image
image_typer  r   r   rT  Z
image_datarS  Z
image_pathZ
image_filer    r    r!   
set_avatar  s&    


zCmfPerson.set_avatarc              
   C   s   | j std dS t }|| j j  	d d}d|
  d| d}zt j|tjdd	}W n: tk
r } ztd
|| W Y dS d}~X Y nX |jdkrtd
||j dS |jS )u>   
        Получаем аватарку с gavatar
        u/   Fetch gravatar skip: не задан логинNr  Zqwez https://www.gravatar.com/avatar/z/avatar.jpg?d=z&s=200r   )r+  u.   Ошибка запроса к gravatar {}: {}r-  )rI   r5   r   r  r   r   rn   lowerrL   r  r  rV   Zrequests_sessionr   r2  r   r   r   r   formatr3  r   Zcontent)r'   r  defaultZurlr   r   r    r    r!   fetch_gravatar  s     

zCmfPerson.fetch_gravatar<   )r   Zsoft_time_limitc                 K   s<   t jj| d}|t j| | }|j|ddd d S )Nr*   ZjpegF)r[  r  )r4   r
   r   rT   r   r`  r\  )r   r8   r   rZ  r    r    r!   r     s    zCmfPerson.set_gravatarc                 O   s   d S rY   r    )r   r   r   r    r    r!   public_get_org_units_list  s    z#CmfPerson.public_get_org_units_listc                 C   s*  |  dg | jjs$|s$| jjs$d S | jjr~tjjdd}|t| jjt| jj	 kr\d| _|t| jj	t| jj kr~d| _d}t
jjr| jsd}| jjr| js|rtddd n|r| j|kr|| _| jjr&tjjdd}|  dg | jr|| jkr&| j| n|| jkr&| j| d S )	Nr   ZServiceDeskClient)r   TFu   Нельзя снять опцию у пользователя, т.к. она активирована через Проектную роль или включена глобальная опция "Разрешить доступ всем"r   r1   )rT   r   r   r1   r4   r\   r   rx   r   r   r5   r   Zservicedesk_allow_auth_guestsr   rc   rB   r  )r'   r   Zsdesk_groupr   r    r    r!   r    s@    

z!CmfPerson._calc_servicedesk_allowc                 C   s   |t jkrt j| S tjj|ddddddddd	d
dddddddgd}|s^td| d dS |jsj|jrt	d| d dS |j
j|jj|jj|jj|jj|jj|jj|jj|jj|jj|jj|jj|jj|jjdt j|< t j| S )u_   
        Кешированное получение опций уведомления
        Temail_if_spectatoremail_if_authoremail_if_owneremail_if_responsibleemail_if_mentionsemail_if_self_changesr   r   	notify_osr   r   r   r   rI   r   r   )r+   r   r   u8   Пользователь не существует (ID: r`   NuV   Пользователь удален или не работает(уволен) (ID: )rc  rd  re  rf  rg  rh  r   r   ri  r   r   r   r   rI   )ru   cache_person_notify_optr4   r
   r   rc   r   r   r5   r   rc  rn   rd  re  rf  rg  rh  r   r   ri  r   r   r   r   r   rI   )r   r   r   r    r    r!   get_notify_opt_cachedE  sT    


zCmfPerson.get_notify_opt_cachedc                 C   s   t d d|i}td| d S )Nz!person_notify_opt::reload triggerr   CmfPerson:changed)printZcmf_emit_server_event)r   r   r   r    r    r!   r  {  s    zCmfPerson.trigger_reloadrl  )rO  c                     s0   |  d  fdd}td dat| d S )Nr   c                	      s   t d td tr|t d datj H tj	 
dd  tjjdtt ddd	rptd
 t  W 5 Q R X nt d d S )Nz0person_notify_opt_change::reload handler spawnedr   z2person_notify_opt_change::reload handler do reloadFr   z,person_notify_opt_change::clear_jscache:lockTi  )ZnxZpxzEperson_notify_opt_change::reload handler do CMF_CACHE.flush_jscache()z-person_notify_opt_change::reload handler skip)rm  r   r   _person_notify_opt_changeZcmfZappZcmf_contextru   rj  popr   ZREDIS_DBZredisrx   r#   r  getpidr5   r   Z	CMF_CACHEZflush_jscacher    r   r    r!   handler  s    

  
z6CmfPerson.on_person_notify_opt_change.<locals>.handlerz.person_notify_opt_change::reload spawn handlerT)r   rm  rn  ZgeventZspawn)r8   rr  r    rq  r!   on_person_notify_opt_change  s
    
z%CmfPerson.on_person_notify_opt_change)T)N)NNN)NN)NNN)N)N)F)r   )N)NNN)NN)NN)NNT)F)N__name__
__module____qualname__r/  r0  r  classmethodr   r(   r.   r9   rE   propertyrM   rX   r[   rh   rl   rk   ro   r   r   r   r   r   r   staticmethodZ
celery_appr   r   r   r   r   r   r   r   rA   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rU   r  r  r  r!  r5  r7  r8  r9  r<  r@  rD  rJ  rK  rP  rT  r\  r`  r  rb  r  rk  r  Zon_server_eventrs  __classcell__r    r    r   r!   r
      s   


 


W.
!	
		
)
	
B



8
5
r
   c                   C   s
   t j S rY   )r4   r
   r   r    r    r    r!   r     r   r   )rW  Zbinasciir  rQ  shutilr   r   Zrandomr   rB  ZCryptor   r.  Zrequests.apir   Zcmf.data_providers.baser   Zcmf.includer}   Zbs4r   Zmodules.person.fieldsr	   r
   ru   ZHOOK_CRON_HOURLYrB   r    r    r    r!   <module>   s6            