U
    vmc                    @   sx   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m	Z	 d dl
Zd dlmZ G dd	 d	ejjjjZdS )
    N)	timedelta)FileStorage)relativedelta)*)CmfTUUID)CmfActiveEntityc                       sz  e Zd Zdd Zdd Z fddZ fddZ fd	d
Zdd Zdd Z	dd Z
dd Zdd Z fddZdd Zdd Zdd Zdd Zdd  Z fd!d"Zd#d$ Z fd%d&Z fd'd(Zd)d* Zd+d, Zd-d. Zd/d0 Zdd2d3Zdd5d6Zdd7d8Zd9d:d;d<d=d>d?d@dAdBdCdDdEZdFdG ZddHdIZ dJdK Z!ddLdMZ"dNdO Z#dPdQ Z$ fdRdSZ% fdTdUZ&e'd fdVdW	Z(e'ddXdYZ)e'd fdZd[	Z*e'd fd\d]	Z+e,e-j.d^d_dd`daZ/e,ddbdcZ0ddde Z1dfdg Z2dhdi Z3djdk Z4ddmdnZ5ddodpZ6dqdr Z7d fdtdu	Z8dvdw Z9ddxdyZ: fdzd{Z; fd|d}Z<dddZ=e,e-j.d^dd^ddd Z>  Z?S )CmfTaskc              	   C   s   | j dkrd S t| jjtjs"d S |  \}}|s:|s:d S | jsd| jjrZt	| jj
 d || _d S | js||r|tjj | _|r| j|kr| j| j kr|| _| jjrt	| jj
 d| j d| jj
 d| d d S )NcloseduK    не может быть пустой при плановом списке u'    не может быть дальше ())cache_status_type
isinstanceparentvaluemodels
CmfProject_calc_list_plan_interval
alarm_date
is_changed	cmf_alertcaptioncmffieldsCmfDateTimenowplan_end_dateselflist_plan_start_date_maxlist_plan_end_date_min r!   !./modules/task/models/cmf_task.py_calc_alarm_date_list   s,    

$zCmfTask._calc_alarm_date_listc                 C   s<   | j s8| jr8| jjr8| jjjdkr8| jj  r8| jj | _ d S Nr   )responsibler   r   r   
class_nameloadr   r!   r!   r"   _calc_responsible-   s    
zCmfTask._calc_responsiblec                    s   | j sB| jjsB| jjsB| jjsB| jjsB| jjsB| jjsB| jjsBd S t	 
  | jjr| jr| jjjdkr| jj r| jr| j| _| jr|   | jr| jjs| j r| j| j k r| j  d S r$   )is_newr   r   statusdeadlineactivitylistsplan_start_dater   super_calc_alarm_dater   r   r&   Zauto_alarm_dater'   r#   r   set_nowr(   	__class__r!   r"   r1   5   sN    


zCmfTask._calc_alarm_datec                    s   | j jr| j rdS | js<| jjs<| jjs<| j js<| j js<dS | jjrl| jrlt| jdrl| jj  rl| jj | _ | jjrd}| jjD ]}|| jj	kr|j  }q|s| jr| jd j  }|r|| _ | j st
   | j r| j jdgd dS )u   
        Вычисляем вид деятельности
        Метод вызывается из базового класса.
        :return:
        Nr-   r   r   r   )r-   r   r*   r   r.   is_nullhasattrr'   newoldr0   _calc_activityload_fields)r   Ztmp_activityobjr3   r!   r"   r:   Y   s:    


zCmfTask._calc_activityc                    s8   | j r| j j | _d S t   | js4tj|  d S N)parent_taskr   r'   r0   _calc_parentr   r   Z_calc_task_parentr(   r3   r!   r"   r?      s    
zCmfTask._calc_parentc                 C   s   | j js&| jjs&| jjr"| jdks&d S | jsB| jdkrBtddd | jdkrtjj| jddgd| _	| j	rr| j	j
rz| j| _	d| _n6| jd	kr| jr| j| _	n| j| _	d
| _nd | _	d | _d S )N	task.epictask.subprojectuK   task.epic и task.subproject не могут быть без ПроектаTabortrA   epictree_hidden)r   sys_typer   rB   
subproject)
logic_typer   r   r>   logic_prefixr   r   Z	CmfFoldergettree_parentrF   rG   rH   r(   r!   r!   r"   _calc_tree_parent   s.    


zCmfTask._calc_tree_parentc                 C   sR   | j s| jjsd S | j}|rN|jdkrN|ddg |jdkrF|| _qN|j}qd S )Nr   rJ   rL   r@   )r*   rL   r   r&   r;   rJ   r>   )r   Ztmp_tree_parentr!   r!   r"   _calc_parent_task   s    
zCmfTask._calc_parent_taskc                 C   s&   | j r
d S | jjsd S tj|  d S r=   )r*   r+   r   r   CmfTimeTrackerZtimetracker_task_change_statusr(   r!   r!   r"   _calc_timetracker   s
    zCmfTask._calc_timetrackerc                 C   s:   | j jsd S | j sd| _ | j | j | _| jdk r6d| _d S )Nr   )Ztime_estimater   
time_spentremaining_estimater(   r!   r!   r"   _calc_remaining_estimate   s    
z CmfTask._calc_remaining_estimatec                 C   s   | j s*| jjs*| jjs*| jjs*| jjs*d S |   d }| jrD| j}n8| jrbt| jjt	j
rb| j}n| jrp| j}n| jr|| j}|| _d S r=   )r*   rL   r   r   r>   	main_listZ_load_perm_fieldsr   r   r   ZCmfDocumentperm_parent)r   rU   r!   r!   r"   _calc_perm_parent   s,    	zCmfTask._calc_perm_parentc                    sT   t   }dd | jD |d< dd | jD |d< | j|d< | j|d< | j|d< |S )	Nc                 S   s   g | ]}| d ddgqS idnamecodeZto_json.0ir!   r!   r"   
<listcomp>   s     z1CmfTask.get_cache_fields_json.<locals>.<listcomp>r.   c                 S   s   g | ]}| d ddgqS rW   r[   r\   r!   r!   r"   r_      s     tags
is_checked	parent_idactivity_id)r0   get_cache_fields_jsonr.   r`   ra   rb   rc   )r   retr3   r!   r"   rd      s    



zCmfTask.get_cache_fields_jsonc                 C   sp   d }d }| j D ]D}|jjr2|d ks,|j|kr2|j}|jjr|d ksL|j|k r|j}q|sh|rhtjj }||fS r=   )r.   r/   is_not_nullr   r   r   r   r   )r   r   r    Zw_listr!   r!   r"   r      s    
z CmfTask._calc_list_plan_intervalc                 C   sz  | j jr<t| j r|s<|s<| js&| jr,d | _d | _d | _d S d }| jrX| jrX| j| j }| j jrx|rx|| _|| _| j| _| jjr|r|| _| jjr|r|| _| jjr|s|r|d | _|r|r| jr| j|ks| j|k r| jjrt| jj d || _|r| j| | _n|r|| _|rP| jr8| j|krPt| jj d || _| jrv| jrv| j| jk rv| j| _d S )N   uP    установлена в соответствии с планом списка)	r.   r   lenr/   r   r   r6   r   r   )r   r   r    Zself_plan_shiftr!   r!   r"   _calc_plan_list  sZ    

zCmfTask._calc_plan_listc                 C   s   | j jr| j r| jdkr| jr| j | jk sT| jr<| j | jksT| js| j | j jdkr| j | j }| j | _| jr~| j j|7  _td |   d S )Nopen
   uM   План сдвинут в соответствии с будильником)	r   r   r   r/   r   daysr   r   
_calc_name)r   Z	date_diffr!   r!   r"   _calc_plan_nolistG  s2    

		zCmfTask._calc_plan_nolistc                 C   sj   | j js*| js*| jjs*| jjs*| jjs*dS |  \}}t| j sH| j jrV| || n| 	  | 
  dS )u`   
        Ф-я вызывается из базового класса
        :return:
        N)r.   r   r*   r   r/   r   r   rh   ri   rn   rm   r   r!   r!   r"   
_calc_plan]  s"    zCmfTask._calc_planc                 C   s   | j s"| jjs"| jjs"| jjs"d S | jjr4| j s4d S | jrH| jjjdkrRd| _d S | jsv| jj	  | jjsvd| _d S t
| jdr| j s| jjr| jdg | jj| _| j| jj	 ks| jj| jjkrtj| jkrd| _| j r| jjr| jr| jsd| _d S )Nr   Tauto_approve)r*   approvedr   	cmf_ownerr   r   r&   workflowZdefault_task_need_approver'   r7   r;   rp   rX   gcurrent_personZ
cmf_importZ
is_definedr(   r!   r!   r"   _calc_approvedu  s8    
"
zCmfTask._calc_approvedc                    sN   t t  }| ddg | jD ]"}||j |jr"||j q"t|S )Nzlists.cmf_ownerzlists.cmf_owner_assistant)	setr0   
get_ownersr;   r.   addrr   Zcmf_owner_assistantlist)r   argskwargsZownersZlstr3   r!   r"   rx     s    
zCmfTask.get_ownersc                 C   s  | j js<| jjs<| jjs<| jjs<| jjs<| jjs<| jjs<dS tj	
drLdS | j}d}| jrz| jjjdkrzd}| jj }|r| jjr| js| jj| _d| _| jjr| jr| jdkrd| _d| _| jr`| jjr| jj| jks| jjs| j| _| jjr| jj| jkr| j| _| jjrH| jrH| jjrH| jjj| jkrH| jj| _| jjr`| js`d| _| jjrx| jpt|| _| jrdS d}| jjr| jjs| jjs| jjr| jjsd}| j jr| j jr| j jrd}|sdS | j jjdkr| j jjdkr| j jjdkr(| jp$|| _| jsl| j|krl|| _|| _d	| _tj| d
|j ddd  | jjs| jjr| j|kr| jr| j| _tj| d| j ddd  | jd	krd| _d| _dS | j jjdkr~|r,tj|  kr,| js,| jjddd}|r,|| _ t d q| j jjdkrZtj| _| jtj!krZt d | jdksn| jrzd| _d| _dS | j jjdkr2| jr| jd| _ t d q| js| j"  | j jjdkr| j| j# kr| j"  | j| _| j| _d| _tj| d| jj d| j j ddd  dS | j jdkr| j jjdkr`| js`t d | j jjdkr| jpz|| _tj| ddd  | js| j"  | j jjdkr| j| j# kr| j"  tj| d| j j dd  dS qqdS )uS   
            Ф-я вызывается из базового класса
        NimportFr   TZapprove2rj   )rj   in_progressZapprove3_notassigneduh   SimpleLogic: Задачу переключили на Постановщика/Руководителя(u   ), т.к. не указан Будильник. Установите будильник, чтобы задача отобразилась у Исполнителя   )r   textZ	log_leveluM   SimpleLogic: Задачу переключили на Исполнителя(u   ), т.к. указан Будильник.Установите будильник, чтобы задача отобразилась у Исполнителяr	   Z	in_review)Zraise_erroru   Спасибо! Статус установлен в "Подтверждение закрытия", для проверки постановщиком или руководителем проектаu,   Спасибо! Задача закрыта.u   Спасибо! Статус изменен на «Закрыто» т.к установлен флаг «Без подтверждения».Zapprove1_reviewuO   SimpleLogic: Задачу переключили на Постановщика(u   ), т.к. статус=''r~   um   Внимание! Вы взяли задачу без согласования с руководителем.u^   SimpleLogic: waiting_for  установлен т.к. статус снижен в in_progressu[   SimpleLogic: будильник установлен т.к. статус сменен на )$r+   r   rq   r%   rr   r   r   waiting_forosenvironrK   r   r&   r'   approve_forapprove_for_placer9   r6   r*   r8   Zstatus_typerZ   r   
CmfCommentrY   savert   ru   rx   Z
no_controlrs   get_default_statusr   Zcurrent_userr2   r   )r   Ztask_controllerZis_project_taskZ
need_transZin_review_statusr!   r!   r"   _calc_wf_simple_logic  s    
.

	

 


*



zCmfTask._calc_wf_simple_logicc                    s:  t    | jjrd S | jj  | jjr>| jjjr>d | _d S | jjrR| jjrRd S | jjjr`d S | jjj	}t
j|d}t
j
t
jj}| jjr| jjs| jjr| jj	| | _d S | jjr| jr| jjdk r| jtjkr| jr| jj	| jj	kr| jj	| | _d S | jjr|| | _d S | jjr6| js6|| | _d S d S )N)rl   i  )r0   _calc_deadliner,   r   rs   Zdefault_deadline_shiftr'   r6   r%   r   datetimer   r   timezoneutcZperiod_next_dater9   r8   r   cmf_created_atagerr   rt   ru   )r   Z
days_shiftshiftr   r3   r!   r"   r   p  sP    







zCmfTask._calc_deadlinec                    s    | d| jdk t jf |S )NZstrikethroughr	   )
setdefaultr   r0   _place_notify)r   r|   r3   r!   r"   r     s    zCmfTask._place_notifyc                 O   s$   t jj|ddgd}| j| | S NrX   z
members.idr5   )r   CmfListrK   r.   remove)r   Zsrc_list_idr{   r|   Zsrc_listr!   r!   r"   remove_from_list  s    zCmfTask.remove_from_listc                 O   s$   t jj|ddgd}| j| | S r   )r   r   rK   r.   append)r   Zdst_list_idr{   r|   Zdst_listr!   r!   r"   copy_to_list  s    zCmfTask.copy_to_listc                 C   s   t j|j| d | S )N)r<   )r   CmfActiveEntityFilterrK   Zadd_active_entity)r   	filter_idr!   r!   r"   apply_filter  s    zCmfTask.apply_filterc                 C   s8   t jj|ddgd}|jr4| j|j | jdd | S )Nr   
filter_tagr5   TZ	only_data)r   r   rK   r   r`   r   r   )r   r   Zactive_entity_filterr!   r!   r"   remove_from_filter  s
    zCmfTask.remove_from_filterNc                 O   s   |  dg |stddd |s,tddd t|}t|}|tjkrV| | n(|tjkrl| | ntd| dd |tjkr| 	| n(|tjkr| 
| ntd| dd | S )Nr.   u   Укажите from_idTrC   u   Укажите to_idu(   Не могу перместить из u&   Не могу перместить в )r;   r   r   Zget_cls_by_tuuid_strr   r   r   r   r   r   r   )r   Zfrom_idZto_idr{   r|   Zfrom_clsZto_clsr!   r!   r"   move  s$    





zCmfTask.moveFc                 K   s   |d }|sdS |d dkr dS | d}tjjddd|gddd	| d
gggdgd}|sl| jjshdS dS |s|| j| dS )Ntoken_sanitizedFr   u   #№ORrY   ILIKEaliasz%"z"%)filterr   T)lstripr   ZCmfTagrK   rY   r   r`   r   )r   	only_namectxr   tagr!   r!   r"   _process_tag_token  s*    
	zCmfTask._process_tag_tokenc                 K   s   |d }|sdS | dsdS |d}t|dk r8dS dddgdd	d
d| dgdd
d| dggg}tjj|d}|s| jjrdS dS |s|| _dS )Nr   F@   
user_local==Tr   rY   r   %Zloginr   )	
startswithr   rh   r   	CmfPersonrK   rY   r   r%   )r   r   r   r   Z_filterpersonr!   r!   r"   _process_responsible_token  s*    

z"CmfTask._process_responsible_tokenu   Январьu   Февральu   Мартu   Апрельu   Майu   Июньu   Июльu   Августu   Сентябрьu   Октябрьu   Ноябрьu   Декабрь)   r         r            	   rk         c                 C   s(   |  }|  }|d| d| fkS )N#   №)lower)r   stringZhashtagr!   r!   r"   hashtag_cmp;  s    zCmfTask.hashtag_cmpc           	      K   s   |d }| j  D ],\}}| }|d| d| fkr qDqdS |s| jsb|| jj krbdS tjjtjj	dj
dddddd	}||j }|dk r|d
7 }|t|
 d7 }|tddd }| jr|j| jjjkr| jjj|jkrdS || _|| _dS )Nr   r   r   FT)Ztzr   r   )ZdayZhourZminutesecondZmicrosecondr   )months)r   rl   )_monthsitemsr   r*   rY   r9   r   r   r   r   replacemonthr   r/   r   Zyearr   )	r   r   r   r   Z	month_idxr   r/   r   r   r!   r!   r"   _process_month_tokenA  s>    
zCmfTask._process_month_tokenc                 C   s   | j dd dS )uG    Ф-я вызывается из базового класса
        T)r   N)_calc_from_namer(   r!   r!   r"   rm   k  s    zCmfTask._calc_namec                 C   s  | j js$| jjs$| jjs$| jjs$d S | j jp.d}| }g }|sFg | _t|D ]`\}}| 	d}t
  }|d= | jf |rqN| jf |rqN| jf |rqN|| |sNqNqNg }d}	|r|| t|d }
||
 d||
< t| jdd d	D ]}d
}	|d|j   q| jr>d
}	| j| jjj }|d|  |	rZ|rZ||
  d7  < d|| _ | jdkr| j r| j jdsd| j pd | _ d S )N z.,;:?!r   Fr   .c                 S   s   | j jS r=   )rY   r   )r   r!   r!   r"   <lambda>      z)CmfTask._calc_from_name.<locals>.<lambda>)keyTr   r
   rA   ZEpiczEpic 1)rY   r   r/   r`   r%   r   split	enumerater   striplocalscopyr   r   r   r   extendrh   rstripsortedr   r   joinrJ   r   )r   r   rY   Zname_tokensZundefined_tokensidxtokenr   r   Zneed_dotZdot_token_posr   r   r!   r!   r"   r   p  s\    


zCmfTask._calc_from_namec                 C   sF   | j js| jsd S | jdkr$d| _n| jdkr6d| _n| j | _d S )Nr@   rz   z
pfeed.basepost)rI   r   r*   rJ   ui_view_formZui_namer   r(   r!   r!   r"   _calc_ui_view_form  s    

zCmfTask._calc_ui_view_formc                 C   s$   | j r| j jjdkrd S |   d S r$   )r   r   r&   Z_check_simple_permr(   r!   r!   r"   check_simple_perm  s    zCmfTask.check_simple_permc                    sJ   ddddddddd	d
ddddddddddddddddddg}t   | S )Nzparent.project_typezparent.auto_alarm_datezparent.logic_prefixzparent.activity.prefixr>   rL   ztags.tag_categoryzlists.plan_start_datezlists.plan_end_datezlists.ordernozlists.perm_has_aclzlists.sys_typezlists.logic_prefixzmain_list.plan_start_datezmain_list.plan_end_datezmain_list.ordernozmain_list.perm_has_aclzactivity.prefixzworkflow.default_deadline_shiftzcomments.log_levelr   r   cmf_modified_byrT   Ztimetracker_historyhas_child_tasksrH   rE   )r0   save_preload_fields)r   r   r3   r!   r"   r     s<    zCmfTask.save_preload_fieldsc           	         s  | j jr|   |   |   |   | jj }rHt|drH|	|  | j
jr| jrt| j
jt| j
j D ]}|| jkrnd | _qn| js| j
D ]}|jdkr|| _ qq| js| j
D ]}|jdkr|| _ qq| j
jr4| jr4| dg | jjdkr4t| j
jt| j
j D ]}|jdkr|| _ q4q| jjrb| jrb| j| j
krb| j
| j | j
jrt| j
jt| j
j D ]0}|jdkrtd|j  d| j  dd	d
 q|   |   |   |   | jjr| jdkrtd| j dd	d
 t j||}| j
jr&ttjj dD ]&}t| |jr*ttj j  qRq*| j!jr~| j!r~| j!jdkr~ttj"j | j#jr| jrt$| jjtj%r| j&| j# | jjr| jdkr| 't(j)j* | j+dd |S )Nhook_task_savelist.agile_sprint	list.basezmain_list.logic_prefixr	   uM   Нельзя добавить задачу в Закрытый список "z" - ""TrC   )taskrz   r   Zganttu   Вид отображения uk    временно не поддерживается, используйте "task", "list", "post", "gantt")r+   r   r`   r%   r/   rq   rA   r   )priority),rY   r   r   rP   rS   r?   r   r   r7   r   r.   rT   rw   r9   r8   rJ   r;   r   r   r   _calc_logic_type_change_guardrN   !_calc_parent_task_has_child_tasks_calc_gantt_pathr   r0   r   Zcmf_deferred_taskr   r   recalculate_cachegetattrr   r>   r   r`   r   r   Zhook_task_tags_changedZ_clear_notifyrt   ru   rX   Z_update_opened_notifies)	r   r{   r|   r   Zremoved_listlZappended_listZself_instance
field_namer3   r!   r"   r     sp    







"

 $zCmfTask.savec                    s   |sg }|sdg}|sg }|dddgddddgddd ggg}|oH| d	}|r\|d	d
|gg}|d |d t j|f||||d|S )NrY   r   !=r	   r   rG   Ztrashr   rb   =r   object_fieldsr   r   order_by)rK   r   r0   field_options_list)clsrelation_field_namer   r   r   r   r|   rb   r3   r!   r"   lists_options_list6  s2    

   zCmfTask.lists_options_listc                 K   sb   |sg }|r,| dd r,|dd| dgg}|ddddgdddggg}| j|f||||d|S )Nrb   r   r   rJ   r   r   r   )rK   r   r   r   r   r   r   r   r|   r!   r!   r"   main_list_options_listM  s    zCmfTask.main_list_options_listc                    sp   |sg }|r,| dd r,|dd| dgg}| dd sR|ddddgdddggg}t j|f||||d|S )	Nrb   r   searchr   rJ   rA   rB   r   )rK   r0   r   r   r3   r!   r"   parent_task_options_list[  s    z CmfTask.parent_task_options_listc                    s   |dkr$| j |f||||d|S |dkrH| j|f||||d|S |dkrl| j|f||||d|S t j|f||||d|S )Nr.   r   rT   r>   )r   r   r   r0   r   r   r3   r!   r"   r   j  s*        zCmfTask.field_options_listT)system_taskc              	   K   sd  t d|  d|  |  d| }t|d }	d|	 }
tjj|
ddgd}|r|jd	krt d
 |j	
 |_|j  tj|dd  nd}|rtjj|dgd}d}|rtj|}d}|rtjj|}n|r|jr|j}t d|j d|j d|  tj|
| | d|pd ||||d}|j  |  t d|j d|j d |jjS )u  
        Метод для автоматического создания задач.
        Переоткрывает задачу, если такая уже есть закрытая.
        Уникальность задачи определяется по topic + text.
        Дополнительную, переменную информацию, например параметры запроса, можно передать в extra_text
        z
Auto task z, info: /zutf-8zAuto-r   r+   )rZ   r   r	   zAuto task reopenu'   Переоткрываем задачу)r   r   Ndefault_projectr5   zNew auto task for r   z
) project 
r   )rZ   rY   r   r%   rr   r   r   r   )printhashlibZmd5encodeZ	hexdigestr   r   rK   r   rs   r   r+   r   r2   r   r   r   r   r   r   Zget_obj_by_tuuid_strr   rY   rZ   rX   r   )rY   r   Z
extra_textr   responsible_idZcmf_owner_idrb   _kwargsZtask_keyZ	task_hashZ	task_coder   r%   rr   r   r!   r!   r"   	auto_taskw  sH    



  
zCmfTask.auto_taskc                 O   s   t jjdddgd}dddg}dddg}|r:dd|jgg t }|D ]P}t jjdd|jgdddggd}	t jjdd|jgd}
||jj	|	|
d qD|S )	Nr   r   Tr   r   r~   r  )r~   count)
r   r   rz   rX   dictr   Zslistr  r   r   )r   r   r{   r|   personsZin_progress_filterZcount_filterr   resultZin_progress_countr  r!   r!   r"   get_responsibles_tasks_count  s    

z$CmfTask.get_responsibles_tasks_countc                O   sb   |  ddddg | jjr^| jjdkr^|| jjkr6dS || jjkrFdS |dd | jD kr^dS d	S )
Nr   r   r%   	executorsr~   Tc                 S   s   g | ]}|j jqS r!   )rX   r   )r]   r<   r!   r!   r"   r_     s     z%CmfTask.notify_os.<locals>.<listcomp>F)r;   r   r9   r   rX   r%   r  )r   	person_idr{   r|   r!   r!   r"   	notify_os  s    zCmfTask.notify_osc                 C   s`   | j js<| jjs<| jjs<| jjs<| jjs<| jjs<| jjs<d S | jjrN| jrNd S | j	
| | _d S r=   )r-   r   r   rJ   rs   r6   r.   rI   rT   Z	scheme_wfZcalc_workflowr(   r!   r!   r"   _calc_workflow  s$    	zCmfTask._calc_workflowc                 C   sN   | j jsd S | jdkrd S | jjdkr2tddd | jjdkrJtddd d S )NrB   uI   У Подпроекта больше нельзя изменять типTrC   rA   uP   Тип Епик можно поменять только на Подпроект)rI   r   rJ   r9   r   r(   r!   r!   r"   r     s    
z%CmfTask._calc_logic_type_change_guardc                 C   sB   | j js*| jjr&| jdks*| jjdks*d S |   | | j  d S )Nr@   )r>   r   rI   rJ   r9   _calc_cache_branch_gantt_path_recalc_gantt_pathr(   r!   r!   r"   r     s    
zCmfTask._calc_gantt_pathr   c                 C   s`  |dkrt ddd |rx|dddg | j|jkr<|j| _| j|jkrP|j| _|jdkrh|| _d | _n|jd	krx|| _tjj| d
dddddgdD ]}d}| jd	kr| |_| j|_d}nN| jdkr| |_d |_d}n2|j| jkr| j|_d}|j| jkr| j|_d}|jr0|	|  |j
j|j
jkr0d}|rB|jdd |jr|jd |d d qd S )Nd   uM   DEV: Защита от рекурсии: _recalc_gantt_path: if r_count > 100TrC   rE   rH   rJ   rB   rA   cache_branch_gantt_pathr>   r   )r>   r   Fr   r   )r>   r_count)r   r;   rE   rH   rJ   r   r   rz   r   r  r  r8   r9   r   r  )r   r>   r  ZchZ	need_saver!   r!   r"   r    sJ    

 


zCmfTask._recalc_gantt_pathc                 C   s|   | j sd | _d S |s(| ddg | j}|s6g | _d S |jj}|d krRtddd ||jj|jj|jj|j	jdf| _d S )Nz#parent_task.cache_branch_gantt_pathzparent_task.logic_prefixzODEV: WARNING: _calc_cache_branch_gantt_path: if cache_branch_gantt_path is NoneTrC   )rX   rZ   rY   rJ   )
r   r  r;   r>   r   r   rX   rZ   rY   rJ   )r   r>   r  r!   r!   r"   r    s$    z%CmfTask._calc_cache_branch_gantt_pathc                 C   s   | j jsdS | j jrH| dg | j jsHd| j _| j   | j jdd | j jrtj	j
dd| j jgdd| jggd	}|sd
| j j_| j j  | j jjdd dS )u   
            Рассчет has_child_tasks
            должен вызываться после _calc_parent_task
        Nzparent_task.has_child_tasksTr   r>   r   rX   r   r   F)r>   r   rf   r;   r   r  r   r9   r   r   rK   rX   )r   Zhave_childsr!   r!   r"   r   +  s    
$
z)CmfTask._calc_parent_task_has_child_tasks   Изменена задачаc              
      s   | j r
d}|r| dddddddd	g |dkrV| jjd
k rV| j| jjj||d d S | jdkr| j	g}| j
r| j
jdkr|| jj	 |D ]}| j|jj||d qd S t jf |||d| d S )Nu   Создана задачаr   zparent.cmf_owner_assistantzparent.cmf_ownerr   r   r   rr   r   <   )r  rY   msgr~   r   )r   notify_namer   )r*   r;   r   r   r   r   rX   r   r   rr   rb   	type_namer   r   r0   all_place_notify)r   r   r   r  r|   r
  r   r3   r!   r"   r  @  sD        
zCmfTask.all_place_notifyc                 C   s,   | j f || jdd}| j|d |jjS )u    Создание задачи из шаблона
        :param self: Шаблон документа
        :param params: Параметры для шаблона
        :return: Идентификатор новой задачи
        F)for_template)r   )Zcreate_from_templateget_additional_clone_attrsZcopy_attachmentsrX   r   )r   paramsZnew_taskr!   r!   r"   create_task_from_templatec  s    z!CmfTask.create_task_from_templatec                 C   sV   ddd}| j ddgd | jr@| jr@tj | j| j  |d< |sRtj |d< |S )uu   Дополнительные настройки создания шаблонов из задач и наоборотN)r   r,   r/   r,   r5   r   )r;   r/   r,   r   r   )r   r  Zattrsr!   r!   r"   r  n  s    
z"CmfTask.get_additional_clone_attrsc                    s&   | j dgd | jdkrdS t  S )uB    Шаблон уведомлений для разных workflow rJ   r5   ztask.ticketzhelpdesk_mail_notification.html)r;   rJ   r0   +get_default_mail_notification_template_namer(   r3   r!   r"   r   x  s    
z3CmfTask.get_default_mail_notification_template_namec                    s    |dkrdS t  j|f||S )N)r   r/   r   rq   r   )r0   _get_field_log_level)r   r   r{   r|   r3   r!   r"   r!    s    zCmfTask._get_field_log_level   Добавленоc                 C   s   t j| |||S r=   )r   rO   Ztimetracker_task_change_time)r   rQ   rR   r   r!   r!   r"   timetracker_change_time  s    zCmfTask.timetracker_change_timer  )Z	only_onceZsoft_time_limitr   c               	   K   s   t j}d}d}|jddgdD ]}|d7 }|jdd|gd}|j|kr|d7 }td	|j d
| d|j  ||_|jdd |jj	|jj	d}t
d|j | t
d| qtd| d| d |S )u   Актуализация кеша кол-ва задач в епике (нужно ли для подпроекта? Вроде как нет).r   rA   cache_child_tasks_count)rJ   r   r   r>   r   r   zUpdate cache_members_count z -> r
   Tr   )Znode_idZelements_countztree-node-count-changes-ztree-node-count-changeszRecalculate r   z lists caches)r   r   rz   r  r$  rt   debugrX   r   r   Zcmf_emit_event)r  r   Ztotal_countZ
calc_countZcmf_epicZ
real_countZ
event_datar!   r!   r"   r     s     
 zCmfTask.recalculate_cache)NN)F)F)F)F)NNNN)NNNN)NNNN)NNNN)NNNNNN)N)r   )N)Nr  )T)r"  )@__name__
__module____qualname__r#   r)   r1   r:   r?   rM   rN   rP   rS   rV   rd   r   ri   rn   ro   rv   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   rm   r   r   r   r   r   classmethodr   r   r   r   staticmethodZ
celery_appr   r  r  r  r  r   r   r  r  r   r  r  r  r   r!  r#  r   __classcell__r!   r!   r3   r"   r      s   $&!
	A'	 L<  
!
%

*
=!W                            
          -
(
#


r   )r   r   r  Zwerkzeug.datastructuresr   Zdateutil.relativedeltar   Zcmf.includeZcmf.fields.base_fieldsr   Zmodules.task.fields.cmf_taskmodulesZcommon.models.cmf_active_entityr   r   r   Zcmf_taskr   r!   r!   r!   r"   <module>   s   