U
    Mdg                     @   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d5ddZedd ZeedddZeedddZed6ddZedddedd d!Z fd"d#Zed7d$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-d. Z&ed/d0 Z'e!e"j#ddd(d1d2 Z(ed3d4 Z)  Z*S )8	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}|t jj	krV|dkrV|d rRd}ndS |rx|j
jrj|jjsx|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|_|	rN|	|_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(sg |_(|j(r6t)|j(jdkr6|j(jdd d d |kr6|S t j*j+rNt j*j+jd ndt j*j,rht 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' sL|j<d(krft=d)|||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_notify3  s8    




zCmfNotify.stol_place_notify)event_type_codec                 C   s  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 ]}	||	jjt  d}
tj|	jj}|d	kr|d
 rd}
nx|dkr0|d r0d}
n^|dkrJ|d rJd}
nD|dkrd|d rdd}
n*|dkr|d rd}
||	jj d |
r||	jj d qq|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   )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   )r:   r<   r   Z
recipientsuZtmp_parent_idZ	rule_dataZuser_idZ	var_usersZvar_userrY   rm   r+   r+   r,   get_notify_membersl  sT    
  
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rd}|d|j j d|j jr|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r6d}|d|j j d|j jr|j jnd 7 }d}d||dgS |dkrVd}d}d||dgS |dkr~|jr~d}d}d||dgS |dkrd}d }d||dgS |d!krd"}|jjr|d#|jjj 7 }|jr|d$|jj 7 }d%}d||dgS |d&krd'}|jr|jj}d'}|j	r(|j	j}d(| }||krJ|d)| 7 }|d*7 }|j
j rn|d+|j
j  7 }d,}d-||dgS |d.krd/}d-d0|dgS |d1krd2}|j
j rt|j
j }d3}d-||dgS |d4krd5}|j
j rt|j
j }d6}d-||dgS |d7kr>d8}|j
j r,t|j
j }d9}d-||dgS |d:krtd;}|j
j rbt|j
j }d<}d-||dgS |d=krN|j
jr|j
r|j
jj|j
jkrg S |jd>krd3}d-d?|dgS d'}|j	r|j	j}d@|j
j dA| d*}|j
j r|d+|j
j  7 }|j
jr<|j
r<dB|j
jj dC|j
j dD}ndE}d-||dgS dFdGdHdIdJg}|dKkrhg g g dL}|jdMdND ]j\}	}
|
jsq~|
j|
jkrq~|	|krq~||	}|dOk rʐq~|
 }|r~|| | q~g }dP}|dO r|dOd|dO |d |d- r>|d-d|d- |d |d rd|dd|d |d |S | }d-dQ| dR|j |dgS )Su  
        Логика:
        - по спец. событиям типа assigned, придет и assigned и updated, поэтому поля спец.событий
            дополнительно нужно отфильтровывать в updated
        Zdeletedu   Удаленоu   удалил   )r   r   message_titleZcreatedu   Созданоu   создалZ	publishedu9   Выпущены изменения в документеz<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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   изменил статусresponsibleru   ZviewsZresult_textrW   updated)r   r}   r   T)
is_changedr   u   изменилu   Пришло событие u    по объекту )r
   	html_diffZcaptionnewr   rW   oldr	   r   waiting_forru   r%   rc   Zcache_status_typeitemsr   rb   Z_get_field_log_levelr   join)r:   r<   r   rJ   r   r   r   Zskip_field_namesZtmp_listZ
field_nameZ	field_objr   r   resr+   r+   r,   _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 n tk
rp   Y dS X |jdkr|jrtjj|j|	dsdS |r|jdkr|jrtjj|j|	dsd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_person
CmfComment)Zcheck_for_userT)Zperm_effective_acl_idrb   r   cmf_owner_idra   r   ri   rj   r   ZCmfAccessListZcheck_accessZCmfACLNotInitializedErrorZprivater   Zcheck_visibility)
r:   r<   	member_idobj_commentr   Zobj_parent_idr   Zself_idr   r   r+   r+   r,   _check_perm_for_notify^  s6       
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 }|jdkrf|}|jj}|jdkrfd S |jdkr||}|jj}|jdkr|jsd S |r| 	||}	n| 	||}	|jdkr|s|	D ]$}
t
j||
d	 |
d
 djdd q|sd S |	D ]}
|
d
 dkrq| ||}tjj d|
d  d|j }|r| D ]P\}}| j|||dsZq<t
jj||||
d	 |
d d|krdnd|d q<qd S )NF)r   r   Tr   r   ZCmfTimeTrackerHistoryrj   )ZCmfTaskZ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_localr   ri   r   r   r   r`   r	   verbose_namer   r   r   r   )r:   r<   r   r   r   r3   rl   r   r   Zmsg_listZmsg_datamembersr	   r   Z	email_setr+   r+   r,   smart_all_place_notify  sr    



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_filterZnotifiesr   r+   r+   r,   close_open_notifies  s    
zCmfNotify.close_open_notifiesc                 C   s   |j dkr|j  }n&|j dkr,|g}ntd|j   d S |D ]@}tj|jj	}|d sbqDt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_event  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     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   
  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     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   ).0r<   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<   er+   r+   r,   celery_minutely_hook3  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)+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   staticmethodZ
celery_appZtaskr9   rM   r   r   r   r   __classcell__r+   r+   r   r,   r   
   sr   &


5          %
8> 3$O


*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         _