U
    /Df                     @   s^   d dl m Z mZmZ d dlmZ d dlmZ d dlT d dlm	Z	m
Z
mZ G dd de	jZdS )	    )datetime	timedeltatimezone)uuid1)	dataclass)*)
cmf_notifyCmfRelationCmfTypec                       s  e Zd ZdZdZdZi Zee	j
ejde	j
ejdgZeed< ejf eZeG dd dZed	d
 Zedd Zedd Zed9ddZedd ZeedddZeedddZed:ddZedddedd d!Z fd"d#Zed;d$d%Zed<d&d'Z ed(d) Z!e"e#ddd*d+d, Z$e"e#ddd*d-d. Z%ed/d0 Z&ed1d2 Z'ed3d4 Z(e"e#ddd5d6d7d8 Z)  Z*S )=	CmfNotifyZNotifyZdeskZNTFzcommon/templateszcmf/templatesloaderc                   @   s*  e Zd ZU dZdZeed< dZeed< dZeed< dZ	e
ed< dZeed	< dZeed
< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZ dS )zCmfNotify.NotifyCtxu1  
        notify_type - тип сообщения
        возможные варианты:
        - просто сообщение (default) -- message
        - редактирование объекта -- obj_edit
        - создание объекта -- obj_create
        - удаление объекта -- obj_delete
        - добавление комментария -- comment_create
        - редактирование комментария -- comment_edit
        - удаление комментария -- comment_delete
        N	person_idnametextr   priorityFstrikethrough
alarm_datemessagenotify_typeobj_hrefobj_codeobj_parent_nameobj_link html_changed_fields
owner_nameowner_initialsperson_phone_mobileperson_phoneperson_nameperson_emailperson_loginmsg_from_idmsg_from_namemsg_from_codemsg_from_login)!__name__
__module____qualname____doc__r   str__annotations__r   r   r   intr   boolr   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   comments r/   r/   ./cmf/models/cmf_notify.py	NotifyCtx   s2   
r1   c                 C   sl   |j p
|j}d|j d|j d|j }|  }|r<| }| j|}|j|d}t	| j
|||gd d S )N[] () )ctxargs)r    r!   r   r   r   +get_default_mail_notification_template_name
_jinja_envget_templaterenderschedule_deferred_jobprocess_email)cls
notify_ctxobjrcpt_tosubjectmail_templatetemplate
email_bodyr/   r/   r0   send_email_notify_old:   s    zCmfNotify.send_email_notify_oldc                 C   s   dt j }|jp|j}t|dkr6|d d  d}| d|j d| |j }|jp\|j}|sxtd|j	 d d S t
| j||gd d S )Nhttps://   z...
4   SMS уведомление пользователю _    не отправлено, не указан номер мобильного телефона.r6   )configAPP_FQDNr   msglenr   r   r   	cmf_alertr   r<   process_sms)r>   r?   urlsubjr   phoner/   r/   r0   send_sms_notify_oldI   s    zCmfNotify.send_sms_notify_oldc           	      K   s  d|ks|d dkr&t jtjd|d< d|kr:|d}ntj}|jj|d< |j	j|d< |j
j|d< |jj|d< d	|d
< |rd|ks|d dkr|j	|d< d|ks|d dkrt jtjd|d< t|d tr|d j|d< |d |d< |ptj}|j	j|d< |ddg |jr |jjd nd|jr6|jjd nd |d< |rdtj }|j|d< |j
|d< | |d  |d< t|dr|jr|jj	j|d< nd |d< tj|}||d< |d |d< |d |d< |d
 |d< |d  |d!< |d" |d#< | jf |}|S )$Nr   .Ztzmsg_fromr"   r#   r$   r%      Уведомлениеr   r   rN   r   r   
first_name	last_namer   r   r   rG   r   r   r   parentr   r   rT   r   phone_mobiler   r   emailr    loginr!   )r   nowr   utcpopgcurrent_personidvaluer   coder^   
isinstancer
   current_userload_fieldsrY   rZ   rL   rM   hrefhasattrr[   models	CmfPersonget_notify_opt_cachedr1   )	r>   r@   r   kwargsrW   Znotify_ownerrR   notify_optsr5   r/   r/   r0   prepare_notify_ctx_oldW   sL    

4

z CmfNotify.prepare_notify_ctx_oldNr   Fr   c
              	   K   s  t jrt d dS t|d}tj|}|dkr8dS d}|t jj	krb|dkrb|d r^d}ndS |r|j
jrv|jjs|ddg d}|rd	}|sd
}| jdd|j	gdd|gdd|gdddgdddggdddgd}|st }|sd}|jr|jdkr| d|j }|jr$|jr$|r*||_d	|_| jd7  _||_||_d|_|	r^|	|_n
|j  |r|j|_|j	|_|j|_|j|_t|dr|j
r|j
jj|_ |j!|_"t|dr|j# rt$|jt%r|jj|_&nt'|j|_&nd|_|j(s
g |_(|j(rFt)|j(jdkrF|j(jdd d d |krF|S t j*j+r^t j*j+jd ndt j*j,rxt j*j,jd nd }|r|jjnd}t j*j	jt j*jjt j*jjt j*j-j|dt.j/t0j1d2 t./ 3d||dt4  |dd }|j(5| d|_6|jp||_|d! |_7|d" |_8|d# p.|d$ |_9|d% pB|d& |_:|sRd
|_|;  |d' sp|j<d(krt=d)|||j"jd*|gd+ |j<d,kr|j>st=d-| |gd+ |S ).u  
        obj: CmfEntity

        :param obj:
        :param msg_from:
        :param person: Идентификатор пользователя которому отправляется сообщение
        :param name: Наименование объекта уведомления
        :param msg: Текст сообщения
        force - форсированная отправка
        :param priority:
        :param strikethrough:
        :param alarm_date: Будильник для уведомлений
        :param force_notify_current_person: отправить сообщение себе
        :param notify_type: Тип сообщения. Описание см в структуре NotifyCtx
        B   Уведомления отключены g.disable_notify = FalseNrm   TFemail_if_self_changesr[   rf   openclosedobj_id==r   status	cron_done	confirmed
unread_cntr.   
cron_forcefilterfieldsrX   r   u
    + еще    r   r   )rd   r   rf   r^   ZinitialsrV   z%H:%MzCmfComment:)Z	cmf_ownerZcmf_created_atZcmf_created_at_formattedmsg_type_textr   rd   parent_name	log_level
notify_smsZnotify_emailr\   rT   r]   r^   Z	notify_os1z	notify-os)r   commentr   Zevent_persons2znotify-important-)?rb   disable_notifydebugcmfutilZget_obj_id_by_anyrl   rm   rn   rc   rd   r[   
is_definedrf   ri   getr   r{   r   r|   rx   Zpriotityr   r   r   Zset_nowr   rv   r   ui_nameZobj_ui_namerk   re   r   rj   r   loadrg   r	   Zobj_status_namer*   r.   rO   rh   rY   rZ   r^   r   r_   r   r`   Z	isoformatstrftimer   appendry   person_notify_smsperson_notify_emailr   r    saver   cmf_emit_eventrz   )r>   rN   personr   r   r@   force_notify_current_personforcer   r   ro   r   rp   Zdesk_notifynotifyZfilter_statusr   r   r   r/   r/   r0   place_notify   s    

	



zCmfNotify.place_notifyc           	      K   s0  t jrt d dS d|kr(|d dk	s0tdd|krD|d dk	sLtd|d t jjkrj|dsjdS d	|kr|d	}|d
dddg nd}|d}t	j
j|dddgd}|st d|  dS |dg }t	j||}| j||f|}|dkrdS | ||}|r,| || | | |S )u  
        obj: CmfEntity

        :param obj:
        :param msg_from:
        :param person_id: Идентификатор пользователя которому отправляется сообщение
        :param recipient_opt: Опции получателя для проверки разрешения получать уведомления пользователем
        :param name: Наименование объекта уведомления
        :param text: Тема сообщения
        :param msg: Текст сообщения
        :param priority:
        :param strikethrough:
        :param alarm_date: Будильник для уведомлений
        :param force_notify_current_person: отправить сообщение себе
        :param notify_type: Тип сообщения. Описание см в структуре NotifyCtx
        rr   NrN   .u   Укажите msgr   u   Укажите person_idr   r@   r[   rf   r   rj   r   zphone_mobile.numberzphone.numberrd   r   u   В метод place_notify пришел отсутствующий или удаленный пользователь person_id=recipient_opt)rb   r   r   AssertionErrorrc   rd   r   ra   ri   rl   rm   ZCmfPersonNotifyOptZcheck_permission_notify_eventZprepare_notify_ctxZcreate_desk_notifysend_email_notifysend_sms_notify)	r>   ro   r@   r   r   r   Znotify_allowedr?   r   r/   r/   r0   stol_place_notify6  s8    




zCmfNotify.stol_place_notify)event_type_codec                 C   s  t  }t|drL|jdkrL|jr,|jdsL| D ]}dh||jj< q4|S |j}|jdkrd|jj}t|dsrd}tj	
||j d| }|stj	
|d| }|sdS g }|d D ].}|j|d	d
}	|	dkr||t  || d q|	D ]}
tj|
jj}|dkrq|
js(||
 ||
jjt  d}|dkrX|d rXd	}nx|dkrr|d rrd	}n^|dkr|d rd	}nD|dkr|d rd	}n*|dkr|d rd	}||
jj d |r||
jj d qq|rbtjjdd}tjj|j|dgd}|D ]H}t|tjjr2|j}|jj|kr|r||d kr||jj= q|d r|jdkr||d  |d D ]}|| sqtt|| tjjr|| D ]*}||jjt  ||jj d qn,||| jjt  ||| jj d q|D ]n}|drDtd| dd t j!r"tjj|d gd!}|r"|j"r"|j"jdr"td"| dd q"|S )#uY   
        Рассчитываем набор юзеров и их галочек
        logic_prefixZ
CmfProjectzCmfProject:r]   N.z
AllModels.Znotify_membersT)Zall_nested_personsFz
var:authorZemail_if_authorz	var:ownerZemail_if_owner)zvar:responsiblezvar:executorsZemail_if_responsiblezvar:spectatorsZemail_if_spectatorzvar:current_userrs   rh   sdesk-client:default)rf   members)	parent_idZproject_role_idr   Znotify_custom_fieldCmfTaskzvar:zDEV: Var user in notify! )abortrf   r   z DEV: Var user person in notify! )#dictrk   
class_namer   
startswithZall_relation_personsrd   re   rl   ZCmfProjectNotifySchemeZget_notify_rule_data_cachedZextract_var_obj
setdefaultsetaddrm   rn   
user_localr   ZCmfProjectRoler   ZCmfProjectRoleAssignr[   rg   Zcmfr   ZCmfRelationBaseri   
issubclasstypeZ
CmfM2MBaserP   rL   DEBUGrf   )r>   r@   r   Z
recipientsuZtmp_parent_idZ	rule_dataZnon_local_personsZuser_idZ	var_usersZvar_userrp   r]   Z	proj_roleZproj_role_assignuser
field_nameir/   r/   r0   get_notify_memberso  s    



  

"
zCmfNotify.get_notify_membersc                 C   s*  |dkrd}d}d||dgS |dkr<d}d}d||dgS |d	krZd
}d}d||dgS |dkrd}|d|j   7 }d}d||dgS |dkr|jdkr|jdkrd}d}nDd}|jj|jj }|d| 7 }|jj|jj }|d| 7 }d}d||dgS |dkrPd}|d|j j d|j jr4|j jnd 7 }d}d||dgS |dkr|jrd}|d|j   7 }d}d||dgS |d krd!}|d|j j d|j jr|j jnd 7 }d"}d||dgS |d#kr|jrd$}|d%|j	 7 }d&}d||dgS |d'kr>d(}|d%|j	 7 }d)}d||dgS |d*kr^d+}d,}d||dgS |d-kr|jrd.}d/}d||dgS |d0krd1}d2}d||dgS |d3krd4}|j
jr|d5|j
jj	 7 }|j
r|d6|j
j	 7 }d7}d||dgS |d8krg }|jjrd9}|jr*|jj	}d9}	|jr>|jj	}	d:| }||	kr`|d;|	 7 }|d<7 }|jj r|d%|jj  7 }d=}|d>||d |jjrt|jt|jj }
|
rd?d@dA |
D }d:| d<}|jj r|d%|jj  7 }dB}|d>||d |S |dCkr2dD}d>dE|dgS |dFkrhdG}|jj rVt|jj }dH}d>||dgS |dIkrdJ}|jj rt|jj }dK}d>||dgS |dLkrdM}|jj rt|jj }dN}d>||dgS |dOkr
dP}|jj rt|jj }dQ}d>||dgS |dRkr|jjr>|jr>|jjj|jjkr>g S |jdSkr\dH}d>dT|dgS d9}	|jrp|jj	}	dU|jj	 dV|	 d<}|jj r|d%|jj  7 }|jjr|jrdW|jjj	 dX|jj	 dY}ndZ}d>||dgS |d[kr
d\| }d]}d>||dgS |d^kr*d_}d`}d>||dgS |dakrRdb| dc}dd}d>||dgS |dekrrdf}dg}d>||dgS |dhkrdi}dj}|jjD ]$}||jjkr|dk|j	 7 }q|jjD ]$}||jjkr|dl|j	 7 }qd>||dgS dmdndodpdqg}|drkrg g g ds}|jdtduD ]j\}}|js2q|j|jkrDq||krRq||}|dvk rjq| }|r|| | qg }dw}|dv r|dvd|dv |d |d> r|d>d|d> |d |d r|dd|d |d |S | }d>dx| dy|j	 |dgS )zu  
        Логика:
        - по спец. событиям типа assigned, придет и assigned и updated, поэтому поля спец.событий
            дополнительно нужно отфильтровывать в updated
        Zrestoredu   Восстановленоu   восстановил   )r   r   message_titleZdeletedu   Удаленоu   удалилZcreatedu   Созданоu   создалZ	publishedu9   Выпущены изменения в документеz<br>u!   выпустил документZshareddefaultu[   Отменен публичный доступ к документу в интернете.u9   отменил публикацию в интернетеui   Документ опубликован для публичного доступа в интернете.u   <br>Анонимные: u"   <br>Авторизованные: u,   опубликовал в интернетеZcomment_createdu$   Комментарий создан.: r   u%   написал комментарийZcomment_updatedu&   Комментарий изменен.u%   изменил комментарийZcomment_deletedu#   Комментарий удаленu#   удалил комментарийZattachment_createdu#   Добавлено вложение u   добавил вложениеZattachment_deletedu   Удалено вложениеu   удалил вложениеZworklog_createdu+   Сделана запись о работеu)   сделал запись о работеZworklog_updatedu&   Журнал работ измененu&   изменил журнал работZworklog_deletedu$   Журнал работ удаленu$   удалил журнал работZmovedu   Перемещеноu    из проекта u    в проект u1   переместил в другой проектassignedu   Не установленu%   Задача назначена на u   , ожидает r   u'   назначил исполнителяr   z, c                 S   s   g | ]}t |jqS r/   )r*   r   ).0er/   r/   r0   
<listcomp>W  s     z5CmfNotify._prepare_notify_message.<locals>.<listcomp>u-   назначил соисполнителейZresolvedu   добавил решениеu1   В задаче добавлено решениеru   u   Задача завершенаu   завершил задачуZwork_startedu   Работа начатаu   начал работуZwork_stoppedu#   Работа остановленаu%   приостановил работуZreopenedu#   Задача переоткрытаu!   переоткрыл задачуchanged_statusZCLOSEDu   Задача закрытаu!   Статус изменен на u   , ожидаем u   изменил статус c "u   " на ""u   изменил статусZapprove_startedu.   Ожидается подтверждение u+   запустил подтверждениеZapprove_rejectedu6   Пользователь отклонил запросu   отклонил запросZapprove_success_fullu   Утверждение u    завершеноu)   утверждение завершеноZapprove_success_oneu:   Пользователь подтвердил запросu!   подтвердил запросZspectators_changedu'   изменены наблюдателиu4   Изменен состав наблюдателейu   <br>добавлен: u   <br>удален: responsiblerx   ZviewsZresult_textr[   updated)r   r   r   T)
is_changedr   u   изменилu   Пришло событие u    по объекту )r   	html_diffZperm_policy_anonymousZperm_policy_guestchoicesre   Zcaptionnewr   r   r[   oldr   waiting_forrx   r   	executorsr   joinr*   rf   Zcache_status_typeZ
spectatorsitemsr   Z_get_field_log_level)r>   r@   r   rN   r   Z	anonymousZguestresr   r   Znew_executorsr   Z	spectatorZskip_field_namesZtmp_listr   Z	field_objr   r   r/   r/   r0   _prepare_notify_message  s   

*
*





















&













z!CmfNotify._prepare_notify_messagec              
   C   s  |j j}|jj}|jj}|jj}|j}tjj|d}	z&tj	j
|||||dd|	dsXW dS W nP tk
rp   Y dS  tk
r }
 z|
jd |krW Y 
dS  W 5 d}
~
X Y nX |jdkr|jrtjj|j|	dsdS |r|jdkr|jrtjj|j|	dsdS d	S )
u   
        Проверяет, что у получателя notify есть доступ к объекту
        Доп. проверяются права у private-комментариев
        )rd   readF)initial_acl_keyZobject_modelZobject_owner_idZ	object_idZobject_parent_idZaccess_levelZraise_errorchecking_personr   N
CmfComment)Zcheck_for_userT)Zperm_effective_acl_idre   r   cmf_owner_idrd   r   rl   rm   r   ZCmfAccessListZcheck_accessZCmfACLNotInitializedErrorZCmfACLNotFoundErrorr7   Zprivater   Zcheck_visibility)r>   r@   	member_idobj_commentr   Zobj_parent_idr   Zself_idr   r   r   r/   r/   r0   _check_perm_for_notify  s>       

z CmfNotify._check_perm_for_notifyT)r   auditc                O   s  |j r
d S |sd S |sd S |js$d S tjr.d S d}|dkr>d}d }d }	|jdkrj|}|jj}|jdkrjd S |jdkr|}|jj}|jdkr|}|jj}|jdkr|jsd S |jd	kr|}	|j	j}|r| 
||}
n|	r| 
|	|}
n| 
||}
|jd
kr.|s.|
D ]&}tj||d |d djdd q|s8d S |
D ]}|d dkrRq<| ||}tjj d|d  d|j }|r<| D ]P\}}| j|||dsqtjj||||d |d d|krdnd|d qq<d S )NF)r   r   Tr   r   ZCmfAttachmentZCmfTimeTrackerHistoryrm   ZCmfGanttTask)r   ZCmfDocumentr   r   )r[   r   r   )r   )r   r   r   r   )r   rh   )r@   r   r   rN   r   r   r   )Zdisable_auditZsmart_notifyrb   r   r   r[   re   r   r   Ztaskr   rl   r   r   r   rc   r   verbose_namer   r   r   r   )r>   r@   r   r   r   r7   ro   r   r   Zdependent_objZmsg_listZmsg_datar   r   r   Z	email_setr/   r/   r0   smart_all_place_notify  s    






z CmfNotify.smart_all_place_notifyc                    s<   t  j|| td| j  d| jji| j gd d S )Nznotify-person-Z	notify_idr   )superemitr   r   r   rd   re   )selfr7   ro   	__class__r/   r0   r   d  s     
zCmfNotify.emitc                 C   sd   |st jjj}dd|gdddgg}|r8|dd|jg | j|dgd}|D ]}d|_|  qLd S )Nr   rw   rx   z!=ru   rv   r}   )rb   rc   rd   re   r   listrx   r   )r>   r   r@   Z_filternotifiesr   r/   r/   r0   close_open_notifiesl  s    
zCmfNotify.close_open_notifiesc                 C   sD   |st jj}| jdd|gdddggd}|D ]}d|_|  q,d S )Nr   rw   rz   False)r~   T)rb   rc   rd   r   rz   r   )r>   r   r   r   r/   r/   r0   confirm_unconfirmed_notifies~  s    z&CmfNotify.confirm_unconfirmed_notifiesc                 C   s   |j dkr|j  }n&|j dkr,|g}ntd|j   d S |D ]H}tj|jj	}|d ksD|d sjqDtj
j|||jd|j  d qDd S )NZCmfPersonGrouprm   z,DEV: handle_mention_event unknown obj type: Zemail_if_mentionsu   Вас упомянули в )r@   r   r   rN   )r   Z
rg_membersr   Z
all_nestedrP   rl   rm   rn   rd   re   r   r   r   r   lower)r>   r@   Zevent_personZpersonsr   rp   r/   r/   r0   handle_mention_event  s     

zCmfNotify.handle_mention_event)	only_once
system_jobc                 O   s   t j }|j| ||d d S )NrB   )rl   CmfPluginMailBoxget_local_mailboxsend_message)Zrctp_torB   rE   r7   ro   mail_boxr/   r/   r0   r=     s    
zCmfNotify.process_emailc                 O   s   t j }|| | d S )N)rl   CmfPluginSMSGateget_local_smsgater   )rT   r   r7   ro   sms_gater/   r/   r0   rQ     s    
zCmfNotify.process_smsc                 C   s\   t jj|jdgd}|rV|jrV|jdrV|j|jddsVd|j	 d|j
 d|j S |jS )	Nr   r   ztask.sdr   )ZprojectZ	role_code/z/?obj=:)rl   rm   r   r   r   r   r   Zin_project_roler[   	ui_moduler   rf   r   )r>   r   r@   r   r/   r/   r0   _calc_notify_obj_link  s    zCmfNotify._calc_notify_obj_linkc           
      C   s   |j s
d S |j j}d|j d|j d|j }|  }|rB| }| j||d}dtj | |_	| j
|}|j|d}tj }	|	j|||d d S )Nr2   r3   r4   )r   r@   rG   )r   r   )r    re   r   r   r   r8   r   rL   rM   r   r9   r:   r;   rl   r   r   r   )
r>   r   r@   rA   rB   rC   rj   rD   rE   r   r/   r/   r0   r     s    
zCmfNotify.send_email_notifyc                 C   sd   |j std|j d d S dtj |j }|j}| d| }|j j}tj	
 }||| d S )NrJ   rK   rG   rI   )r   rP   r   rL   rM   r   r   re   rl   r   r   r   )r>   r   r@   rR   rS   r   rT   r   r/   r/   r0   r     s    
zCmfNotify.send_sms_notifyz	@minutely)r   r   Zschedulec               
   O   s  t jjddgdddgdddggd}d	d
 |D }t jjdddgdddt tdd gdddgdd|gggdgdgd}|sqtd|j d|  d }|j	rt
j|j	ddgd}|jrz td t j|| d|_W n4 tk
r } ztd|  W 5 d }~X Y nX |jrrz td t j|| d|_W n4 tk
rp } ztd|  W 5 d }~X Y nX d|_|  |j  q2d S )Nz--rv   ry   rw   Fr|   T)r   r~   c                 S   s   h | ]
}|j qS r/   )rv   )r   r@   r/   r/   r0   	<setcomp>  s     z1CmfNotify.celery_minutely_hook.<locals>.<setcomp>ORZcmf_modified_at<   )ZminutesINr   )r~   r   Zorder_byuB   Обработка отправки уведомлений для r   r   )Zinclude_deletedr   u   Отправляем СМСz"models.CmfNotify.send_sms_notify: u   Отправляем emailz$models.CmfNotify.send_email_notify: )rl   r   Zslistr   r   r_   r   printrd   rv   r   Zget_obj_by_idr   r   Zsms_done	ExceptionZloggingZ	exceptionr   r   Z
email_donery   r   ZdpZcommit)r7   ro   Zforce_objectsZforce_object_idsr   r@   r   r/   r/   r0   celery_minutely_hook  sL     
"
"zCmfNotify.celery_minutely_hook)Nr   NFFr   N)N)NN)N)+r&   r'   r(   r   r   Zcode_prefixZ_optionsZjinja2ZFileSystemLoaderospathr   rL   ZPROJECT_DIRZ_loaderZEnvironmentr9   r   r1   classmethodrF   rU   rq   r   r   r*   r   r   r   r   r   r   r   r   staticmethodZcmf_deferred_jobr=   rQ   r   r   r   r   __classcell__r/   r/   r   r0   r   	   sx   &


5          )
8k  )]





r   N)r   r   r   Zuuidr   Zdataclassesr   Zcmf.includeZ
cmf.fieldsr   r	   r
   r   r/   r/   r/   r0   <module>   s
   