U
    f                     @   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jjddg ZeG d	d
 d
Zedd Zedd Zedd Zed;d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/d0 Z(ed1d2 Z)ed3d4 Z*ed5d6 Z+e%e&d d d7d8d9d: Z,  Z-S )?	CmfNotifyZNotifyZdeskZNTFzcommon/templateszcmf/templatesloaderclose_open_notifiesconfirm_unconfirmed_notifiesc                   @   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 r1   r1   ./cmf/models/cmf_notify.py	NotifyCtx   s2   
r3   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_bodyr1   r1   r2   send_email_notify_old?   s    zCmfNotify.send_email_notify_oldc                 C   s   t dd}|jp|j}t|dkr4|d d  d}| d|j d| |j }|jpZ|j}|svtd|j d d S t	| j
||gd d S )	NTZfull_url   z...
4   SMS уведомление пользователю _    не отправлено, не указан номер мобильного телефона.r8   )app_base_hrefr   msglenr   r   r    	cmf_alertr!   r>   process_sms)r@   rA   urlsubjr   phoner1   r1   r2   send_sms_notify_oldN   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< |rtdd}|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   rO   r   r   
first_name	last_namer   r   r   TrI   r   r   r   parentr   r   rU   r    phone_mobiler   r!   emailr"   loginr#   )r   nowr   utcpopgcurrent_personidvaluer   coder_   
isinstancer
   current_userload_fieldsrZ   r[   rN   hrefhasattrr\   models	CmfPersonget_notify_opt_cachedr3   )	r@   rB   r   kwargsrX   Znotify_ownerrS   notify_optsr7   r1   r1   r2   prepare_notify_ctx_old\   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 = FalseNrn   TFemail_if_self_changesr\   rg   openclosedobj_id==r   status	cron_done	confirmed
unread_cntr0   
cron_forcefilterfieldsrY   r   u
    + еще    r   r   )re   r   rg   r_   ZinitialsrW   z%H:%MzCmfComment:)Z	cmf_ownerZcmf_created_atZcmf_created_at_formattedmsg_type_textr   re   parent_name	log_level
notify_smsZnotify_emailr]   rU   r^   r_   Z	notify_os1z	notify-os)r   commentr   Zevent_persons2znotify-important-)?rc   disable_notifydebugcmfutilZget_obj_id_by_anyrm   rn   ro   rd   re   r\   
is_definedrg   rj   getr   r|   r   r}   ry   Zpriotityr   r   r   Zset_nowr   rw   r   ui_nameZobj_ui_namerl   rf   r   rk   r   loadrh   r	   Zobj_status_namer,   r0   rP   ri   rZ   r[   r_   r   r`   r   ra   Z	isoformatstrftimer   appendrz   person_notify_smsperson_notify_emailr    r"   saver   cmf_emit_eventr{   )r@   rO   personr   r   rB   force_notify_current_personforcer   r   rp   r   rq   Zdesk_notifynotifyZfilter_statusr   r   r   r1   r1   r2   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
        rs   NrO   .u   Укажите msgr   u   Укажите person_idr   rB   r\   rg   r   rk   r   zphone_mobile.numberzphone.numberre   r   u   В метод place_notify пришел отсутствующий или удаленный пользователь person_id=recipient_opt)rc   r   r   AssertionErrorrd   re   r   rb   rj   rm   rn   ZCmfPersonNotifyOptZcheck_permission_notify_eventZprepare_notify_ctxZcreate_desk_notifysend_email_notifysend_sms_notify)	r@   rp   rB   r   r   r   Znotify_allowedrA   r   r1   r1   r2   stol_place_notify;  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_userrt   ri   sdesk-client:default)rg   members)	parent_idZproject_role_idr   Znotify_custom_fieldCmfTaskzvar:zDEV: Var user in notify! )abortrg   r   z DEV: Var user person in notify! )#dictrl   
class_namer   
startswithZall_relation_personsre   rf   rm   ZCmfProjectNotifySchemeZget_notify_rule_data_cachedZextract_var_obj
setdefaultsetaddrn   ro   
user_localr   ZCmfProjectRoler   ZCmfProjectRoleAssignr\   rh   cmfr   ZCmfRelationBaserj   
issubclasstypeZ
CmfM2MBaserQ   configDEBUGrg   )r@   rB   r   Z
recipientsuZtmp_parent_idZ	rule_dataZnon_local_personsZuser_idZ	var_usersZvar_userrq   r^   Z	proj_roleZproj_role_assignuser
field_nameir1   r1   r2   get_notify_memberst  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 r1   )r,   r   ).0er1   r1   r2   
<listcomp>\  s     z5CmfNotify._prepare_notify_message.<locals>.<listcomp>u-   назначил соисполнителейZresolvedu   добавил решениеu1   В задаче добавлено решениеrv   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>удален: responsiblery   ZviewsZresult_textr\   updated)r   r   r   T)
is_changedr   u   изменилu   Пришло событие u    по объекту )r   	html_diffZperm_policy_anonymousZperm_policy_guestchoicesrf   Zcaptionnewr   r   r\   oldr   waiting_forry   r   	executorsr   joinr,   rg   Zcache_status_typeZ
spectatorsitemsr   Z_get_field_log_level)r@   rB   r   rO   r   Z	anonymousZguestresr   r   Znew_executorsr   Z	spectatorZskip_field_namesZtmp_listr   Z	field_objr   r   r1   r1   r2   _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-комментариев
        )re   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_idrf   r   cmf_owner_idre   r   rm   rn   r   ZCmfAccessListZcheck_accessZCmfACLNotInitializedErrorZCmfACLNotFoundErrorr9   Zprivater   Zcheck_visibility)r@   rB   	member_idobj_commentr   Zobj_parent_idr   Zself_idr   r   r   r1   r1   r2   _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 ]h\}}| j|||dsqtjj 6 tjj||||d |d d|krdnd|d W 5 Q R X qq<d S )NF)r   r   Tr   r   ZCmfAttachmentZCmfTimeTrackerHistoryrn   ZCmfGanttTask)r   ZCmfDocumentr   r   )r\   r   r   )r   )r   r   r   r   )r   ri   )rB   r   r   rO   r   r   r   )Zdisable_auditZsmart_notifyrc   r   r   r\   rf   r   r   Ztaskr   rm   r   r   r   rd   r   verbose_namer   r   r   utilr   Zdisable_aclr   r   )r@   rB   r   r   r   r9   rp   r   r   Zdependent_objZmsg_listZmsg_datar   r   r   Z	email_setr1   r1   r2   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   re   rf   )selfr9   rp   	__class__r1   r2   r   j  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   rx   ry   z!=rv   rw   r~   )rc   rd   re   rf   r   listry   r   )r@   r   rB   Z_filternotifiesr   r1   r1   r2   r   r  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   rx   r{   False)r   T)rc   rd   re   r   r{   r   )r@   r   r   r   r1   r1   r2   r     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CmfPersonGrouprn   z,DEV: handle_mention_event unknown obj type: Zemail_if_mentionsu   Вас упомянули в )rB   r   r   rO   )r   Z
rg_membersr   Z
all_nestedrQ   rm   rn   ro   re   rf   r   r   r   r   lower)r@   rB   Zevent_personZpersonsr   rq   r1   r1   r2   handle_mention_event  s     

zCmfNotify.handle_mention_event)	only_once
system_jobc                 O   s   t j }|j| ||d d S )NrD   )rm   CmfPluginMailBoxget_local_mailboxsend_message)Zrctp_torD   rG   r9   rp   mail_boxr1   r1   r2   r?     s    
zCmfNotify.process_emailc                 O   s   t j }|| | d S )N)rm   CmfPluginSMSGateget_local_smsgater   )rU   r   r9   rp   sms_gater1   r1   r2   rR     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=:)rm   rn   r   r   r   r   r   Zin_project_roler\   	ui_moduler   rg   r   )r@   r   rB   r   r1   r1   r2   _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}tdd | |_| j	
|}|j|d}tj }	|	j|||d d S )	Nr4   r5   r6   )r   rB   TrI   )r   r   )r"   rf   r   r   r   r:   r   rN   r   r;   r<   r=   rm   r   r   r   )
r@   r   rB   rC   rD   rE   rk   rF   rG   r   r1   r1   r2   r     s    
zCmfNotify.send_email_notifyc                 C   sf   |j std|j d d S tdd |j }|j}| d| }|j j}tj	 }|
|| d S )NrL   rM   TrI   rK   )r    rQ   r   rN   r   r   rf   rm   r   r   r   )r@   r   rB   rS   rT   r   rU   r   r1   r1   r2   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--rw   rz   rx   Fr}   T)r   r   c                 S   s   h | ]
}|j qS r1   )rw   )r   rB   r1   r1   r2   	<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: )rm   r   Zslistr   r   r`   r   printre   rw   r   Zget_obj_by_idr   r   Zsms_done	ExceptionZloggingZ	exceptionr   r   Z
email_donerz   r   ZdpZcommit)r9   rp   Zforce_objectsZforce_object_idsr   rB   r   r1   r1   r2   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   r   ZPROJECT_DIRZ_loaderZEnvironmentr;   r   r   Zapi_methodsr   r3   classmethodrH   rV   rr   r   r   r,   r   r   r   r   r   r   r   r   staticmethodZcmf_deferred_jobr?   rR   r   r   r   r   __classcell__r1   r1   r   r2   r   	   s   &


5          )
8k  )^





r   N)r   r   r   Zuuidr   Zdataclassesr   Zcmf.includeZ
cmf.fieldsr   r	   r
   r   r1   r1   r1   r2   <module>   s
   