U
    .e                     @   s`   d dl Z d dlmZ d dlT d dlT d dlmZ d dlmZ G dd dejZe	j
ej dS )    N)	dataclass)*)
cmf_notify)	BaseModelc                       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d7ddZedd ZeedddZeedddZed8ddZedddedd d!Z fd"d#Zed9d$d%Zed:d&d'Z ed(d) Z!e"e#j$ddd*d+d, Z%e"e#j$ddd*d-d. Z&ed/d0 Z'ed1d2 Z(e"e#j$ddd*d3d4 Z)ed5d6 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   datetimer   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   
r-   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cmf_deferred_taskprocess_email)cls
notify_ctxobjrcpt_tosubjectmail_templatetemplate
email_bodyr+   r+   r,   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 уведомление пользователю _    не отправлено, не указан номер мобильного телефона.r2   )configAPP_FQDNr
   msglenr   r   r   	cmf_alertr   r8   process_sms)r:   r;   urlsubjr   phoner+   r+   r,   send_sms_notify_oldJ   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
   rJ   r   r   
first_name	last_namer   r   r   rC   r   r   r   parentr   r   rP   r   phone_mobiler   r   emailr   loginr   )r)   nowtimezoneutcpopgcurrent_personidvaluer	   coderZ   
isinstanceZCmfTypecurrent_userload_fieldsrU   rV   rH   rI   hrefhasattrrW   models	CmfPersonget_notify_opt_cachedr-   )	r:   r<   r   kwargsrS   Znotify_ownerrN   notify_optsr1   r+   r+   r,   prepare_notify_ctx_oldX   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 }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% p.|d& |_:|s>d
|_|;  |d' s\|j<d(krxt=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 = FalseNrj   TFemail_if_self_changesrW   rc   openclosedobj_id==r   status	cron_done	confirmed
unread_cntr*   
cron_forcefilterfieldsrT   r   u
    + еще    r   r
   )ra   r	   rc   rZ   ZinitialsrR   z%H:%MzCmfComment:)Z	cmf_ownerZcmf_created_atZcmf_created_at_formattedmsg_type_textr
   ra   	log_level
notify_smsZnotify_emailrX   rP   rY   rZ   Z	notify_os1z	notify-os)r   commentr   Zevent_persons2znotify-important-)?r_   disable_notifydebugcmfutilZget_obj_id_by_anyri   rj   rk   r`   ra   rW   
is_definedrc   rf   getr   rx   r	   ry   ru   Zpriotityr   r   r   Zset_nowr
   rs   r   ui_nameZobj_ui_namerh   rb   r   rg   r   loadrd   ZCmfRelationZobj_status_namer%   r*   rK   re   rU   rV   rZ   r)   r[   r\   r]   Z	isoformatstrftimeZuuid1appendrv   person_notify_smsperson_notify_emailr   r   saver   cmf_emit_eventrw   )r:   rJ   personr	   r   r<   force_notify_current_personforcer   r   rl   r   rm   Zdesk_notifynotifyZfilter_statusr   r   r+   r+   r,   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
        ro   NrJ   .u   Укажите msgr   u   Укажите person_idr   r<   rW   rc   r   rg   r   zphone_mobile.numberzphone.number)ra   r|   u   В метод place_notify пришел отсутствующий или удаленный пользователь person_id=recipient_opt)r_   r   r   AssertionErrorr`   ra   r   r^   rf   ri   rj   ZCmfPersonNotifyOptZcheck_permission_notify_eventZprepare_notify_ctxZcreate_desk_notifysend_email_notifysend_sms_notify)	r:   rl   r<   r   r   r   Znotify_allowedr;   r   r+   r+   r,   stol_place_notify5  s8    




zCmfNotify.stol_place_notify)event_type_codec                 C   sr  t  }t|drB|jr"|jdsB| D ]}dh||jj< q*|S |j}t|dsVd}tj	||j
 d| }|stj	|d| }|sdS |d D ]}||}|dkr||t  || d q|D ]}	tj|	jj}
|
dkrq||	jjt  d}|d	kr |
d
 r d}nx|dkr:|
d r:d}n^|dkrT|
d rTd}nD|dkrn|
d rnd}n*|dkr|
d rd}||	jj d |r||	jj d qq|d rn|j
dkrn||d  |d D ]}|| sqtt|| tjjr>|| D ]*}||jjt  ||jj d qn,||| jjt  ||| jj d q|S )uY   
        Рассчитываем набор юзеров и их галочек
        logic_prefixzCmfProject:rY   N.z
AllModels.Znotify_membersFz
var:authorZemail_if_authorTz	var:ownerZemail_if_owner)zvar:responsiblezvar:executorsZemail_if_responsiblezvar:spectatorsZemail_if_spectatorzvar:current_userrp   re   Znotify_custom_fieldCmfTask)dictrh   	parent_id
startswithZall_relation_personsra   rb   ri   ZCmfProjectNotifySchemeZget_notify_rule_data_cached
class_nameZextract_var_obj
setdefaultsetaddrj   rk   rf   
issubclasstypeZcmfr|   Z
CmfM2MBase)r:   r<   r   Z
recipientsuZtmp_parent_idZ	rule_dataZuser_idZ	var_usersZvar_userrm   rY   
field_nameuserr+   r+   r,   get_notify_membersn  sn    
  

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rnd
}|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r0d}|d|j j d|j jr|j jnd 7 }d}d||dgS |dkrl|jrld}|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rd!}d"}d||dgS |d#kr|jrd$}d%}d||dgS |d&krd'}d(}d||dgS |d)krvd*}|j	j
rJ|d+|j	j
j 7 }|j	rd|d,|j	j 7 }d-}d||dgS |d.krg }|jjrd/}|jr|jj}d/}	|jr|jj}	d0| }||	kr|d1|	 7 }|d27 }|jj r|d3|jj  7 }d4}|d5||d |jjrt|jt|jj
 }
|
rd6d7d8 |
D }d0| d2}|jj rt|d3|jj  7 }d9}|d5||d |S |d:krd;}d5d<|dgS |d=krd>}|jj rt|jj }d?}d5||dgS |d@krdA}|jj rt|jj }dB}d5||dgS |dCkrLdD}|jj r:t|jj }dE}d5||dgS |dFkrdG}|jj rpt|jj }dH}d5||dgS |dIkr\|jj
r|jr|jj
j|jjkrg S |jdJkrd?}d5dK|dgS d/}	|jr|jj}	dL|jj dM|	 d2}|jj r|d3|jj  7 }|jj
rJ|jrJdN|jj
j dO|jj dP}ndQ}d5||dgS |dRkrdS| }dT}d5||dgS |dUkrdV}dW}d5||dgS |dXkrdY| dZ}d[}d5||dgS |d\krd]}d^}d5||dgS d_d`dadbdcg}|ddkrg g g de}|jdfdgD ]j\}}|js.q|j|j
kr@q||krNq||}|dhk rfq| }|r|| | qg }di}|dh r|dhd|dh |d |d5 r|d5d|d5 |d |d r |dd|d |d |S | }d5dj| dk|j |dgS )lu  
        Логика:
        - по спец. событиям типа assigned, придет и assigned и updated, поэтому поля спец.событий
            дополнительно нужно отфильтровывать в updated
        Zdeletedu   Удаленоu   удалил   )r   r   message_titleZ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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+   r,   
<listcomp>)  s     z5CmfNotify._prepare_notify_message.<locals>.<listcomp>u-   назначил соисполнителейZresolvedu   добавил решениеu1   В задаче добавлено решениеrr   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!   подтвердил запросresponsibleru   ZviewsZresult_textrW   updated)r   r}   r   T)
is_changedr   u   изменилu   Пришло событие u    по объекту )r
   	html_diffZperm_policy_anonymousZperm_policy_guestchoicesrb   Zcaptionnewr   rW   oldr	   r   waiting_forru   r   	executorsr   joinr%   rc   Zcache_status_typeitemsr   Z_get_field_log_level)r:   r<   r   rJ   r   Z	anonymousZguestresr   r   Znew_executorsr   Zskip_field_namesZtmp_listr   Z	field_objr   r   r+   r+   r,   _prepare_notify_message  sX   
*
*




















&












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-комментариев
        )ra   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_idrb   r   cmf_owner_idra   r   ri   rj   r   ZCmfAccessListZcheck_accessZCmfACLNotInitializedErrorZCmfACLNotFoundErrorr3   Zprivater   Zcheck_visibility)r:   r<   	member_idobj_commentr   Zobj_parent_idr   Zself_idr   r   r   r+   r+   r,   _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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|s d S |
D ]}|d dkr:q$| ||}tjj d|d  d|j }|r$| D ]P\}}| j|||dsqrtjj||||d
 |d d|krdnd|d qrq$d S )NF)r   r   Tr   r   ZCmfTimeTrackerHistoryrj   ZCmfGanttTask)r   ZCmfDocumentr   r   )rW   r
   r   )r   )r}   r   r   r   )r   re   )r<   r	   r   rJ   r   r   r   )Zdisable_auditZsmart_notifyr_   r   r   rW   rb   r   Z
user_localtaskr   ri   r   r   r   r`   r	   verbose_namer   r   r   r   )r:   r<   r   r   r   r3   rl   r   r   Zdependent_objZmsg_listZmsg_datamembersr	   r   Z	email_setr+   r+   r,   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   ra   rb   )selfr3   rl   	__class__r+   r,   r   $  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   rt   ru   z!=rr   rs   rz   )r_   r`   ra   rb   r   listru   r   )r:   r   r<   Z_filternotifiesr   r+   r+   r,   close_open_notifies,  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   rt   rw   False)r{   T)r_   r`   ra   r   rw   r   )r:   r   r   r   r+   r+   r,   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CmfPersonGrouprj   z,DEV: handle_mention_event unknown obj type: Zemail_if_mentionsu   Вас упомянули в )r<   r   r	   rJ   )r   Z
rg_membersr   Z
all_nestedrL   ri   rj   rk   ra   rb   r   r   r	   r   lower)r:   r<   Zevent_personZpersonsr   rm   r+   r+   r,   handle_mention_eventL  s     

zCmfNotify.handle_mention_event)Z	only_onceZsystem_taskc                 O   s   t j }|j| ||d d S )Nr>   )ri   CmfPluginMailBoxget_local_mailboxsend_message)Zrctp_tor>   rA   r3   rl   mail_boxr+   r+   r,   r9   c  s    
zCmfNotify.process_emailc                 O   s   t j }|| | d S N)ri   CmfPluginSMSGateget_local_smsgater   )rP   r   r3   rl   sms_gater+   r+   r,   rM   i  s    
zCmfNotify.process_smsc           	      C   s   |j s
d S |j j}d|j d|j d|j }|  }|rB| }dtj |j |_	| j
|}|j|d}tj }|j|||d d S )Nr.   r/   r0   rC   )r   r   )r   rb   r   r   r	   r4   rH   rI   r   r   r5   r6   r7   ri   r   r   r   )	r:   r   r<   r=   r>   r?   r@   rA   r   r+   r+   r,   r   o  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 )NrF   rG   rC   rE   )r   rL   r   rH   rI   r   r	   rb   ri   r   r   r   )r:   r   r<   rN   rO   r   rP   r   r+   r+   r,   r     s    
zCmfNotify.send_sms_notifyc               
   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--rs   rv   rt   Fry   T)r|   r{   c                 S   s   h | ]
}|j qS r+   )rs   )r   r<   r+   r+   r,   	<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: )ri   r   Zslistr   r)   r[   Z	timedeltaprintra   rs   r   Zget_obj_by_idr   r   Zsms_done	ExceptionZloggingZ	exceptionr   r   Z
email_donerv   r   ZdpZcommit)r3   rl   Zforce_objectsZforce_object_idsr   r<   r   r+   r+   r,   celery_minutely_hook  sL     
"
"zCmfNotify.celery_minutely_hookc                 C   s   t | j d S r   )r8   r   )r:   r+   r+   r,   minutely_hook  s    zCmfNotify.minutely_hook)Nr   NFFr   N)N)NN)N),r!   r"   r#   r   Z	ui_moduleZcode_prefixZ_optionsZjinja2ZFileSystemLoaderospathr   rH   ZPROJECT_DIRZ_loaderZEnvironmentr5   r   r-   classmethodrB   rQ   rn   r   r   r%   r   r   r   r   r   r   r   r   staticmethodZ
celery_appr   r9   rM   r   r   r   r   __classcell__r+   r+   r   r,   r   
   sv   &


5          '
8O c)X


*r   )r)   Zdataclassesr   Zcmf.includeZ
cmf.fieldsr   Z
cmf.modelsr   r   ZAPPZHOOK_CRON_MINUTELYr   r   r+   r+   r+   r,   <module>   s          ?