U
    ck                    @   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                       s4  e Zd Zedd fdd
Zedd fd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 fd)d*Zd+d, Z fd-d.Z fd/d0Zd1d2 Zd3d4 Zd5d6 Zd7d8 Zdd9d:Zdd<d=Z dd>d?Z!dd@dAZ"dBdCdDdEdFdGdHdIdJdKdLdMdNZ#dOdP Z$ddQdRZ%dSdT Z&ddUdVZ'dWdX Z(dYdZ Z)d[d\ Z*d]d^ Z+d_d` Z, fdadbZ- fdcddZ. fdedfZ/ed fdgdh	Z0eddidjZ1ed fdkdl	Z2ed fdmdn	Z3e4e5j6dodpddqdrZ7e4ddsdtZ8dudv Z9dwdx Z:dydz Z;d{d| Z<dd~dZ=dddZ>dd Z?dd Z@d fdd	ZAdd ZBdddZC fddZD fddZEdddZFe4e5j6doddoddd ZGd}deHd fddZIeJeKeKeKd fddZLeM fddZN fddZO  ZPS )CmfTaskN)include_systemc                   s   |s| dd t j||S NsystemF)
setdefaultsuperlistclsr	   argskwargs	__class__ !./modules/task/models/cmf_task.pyr      s    zCmfTask.listc                   s   |s| dd t j||S r
   )r   r   slistr   r   r   r   r      s    zCmfTask.slistc              	   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_minr   r   r   _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_responsible9   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 r1   )is_newr#   r$   statusdeadlineactivitylistsplan_start_dater+   r   _calc_alarm_dater   r   r3   Zauto_alarm_dater4   r0   r*   set_nowr5   r   r   r   r=   A   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$   r7   r   r;   is_nullhasattrr4   newoldr   _calc_activityload_fields)r-   Ztmp_activityobjr   r   r   rD   e   s:    


zCmfTask._calc_activityc                    sP   | j r0| j jr0| j| j jkrL| j jdg| _nt   | jsLtj|  d S )Nroot_parent)	parent_task	parent_idr   r4   r   _calc_parentr    r!   Z_calc_task_parentr5   r   r   r   rJ      s    
zCmfTask._calc_parentc                 C   sN   | j r
d S | jdkr:tjj| jddgd| _ | j s:| j| _ | jdkrJd | _ d S )N	task.epictask.subprojectepicZtree_hidden)r   sys_typer(   task.gantt_project)tree_parentlogic_prefixr    Z	CmfFoldergetr   r5   r   r   r   _calc_tree_parent   s    

zCmfTask._calc_tree_parentc                 C   s   | j rD| j}|rD|jjdkrD|ddg |jdkr<|| _qD|j}q| jjr| jj  | jr| jjjdkr| jjdkr| j| _| j	jr| jdkrt
ddd	 | j	| _| jjr| jdkrt
d
dd	 | j| _d S )Nr!   rR   rQ   rK   r   ztask.subu2   У подзадач нельзя менять EpicTabortu@   У подзадач нельзя менять Подпроект)r7   rQ   r   r3   rE   rR   rH   r$   r4   rN   r%   
subproject)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 N)r7   r8   r$   r    CmfTimeTrackerZtimetracker_task_change_statusr5   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_estimater5   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 rY   )r7   rQ   r$   r   rH   	main_listZ_load_perm_fieldsr   r   r    ZCmfDocumentperm_parent)r-   r`   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 rb   rf   rg   r   r   r   rj      s     tags
is_checkedrI   activity_id)r   get_cache_fields_jsonr;   rk   rl   rI   rm   )r-   retr   r   r   rn      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 rY   )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#   r@   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_nolistP  s2    

		zCmfTask._calc_plan_nolistc                 C   sr   | 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$   r7   r#   r<   r+   r"   rr   rs   rx   _calc_op_gantt_task_countersrw   r,   r   r   r   
_calc_planf  s$    zCmfTask._calc_planc                 C   sL  | 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rfd| _tj| ddd	  d S | 
 }| js|jsd| _tj| d|j dd	  d S | jr|jr| jr| jjrd| _tj| ddd	  | j| jj ks| jj| jjkr tj| jkr d| _tj| d	dd	  | j rH| jjrH| jrH| jsHd| _d S )
Nr!   Tu~   SimpleLogic: Задача согласована автоматически, т.к. это Непроектная задача   r   textZ	log_levelu   SimpleLogic: Задача согласована автоматически, т.к. согласование отключено в Fu   SimpleLogic: Выполнен сброс согласования, т.к. сменился Постановщик или Проектu   SimpleLogic: Задача согласована автоматически, т.к. постановщик - руководитель.)r7   approvedr$   	cmf_ownerr   r   r3   r    
CmfCommentsave_get_sl_optionssl_task_need_approveZsl_controller_strr4   rc   gcurrent_personZ
cmf_importZ
is_defined)r-   
sl_optionsr   r   r   _calc_approved  sV    



$

"zCmfTask._calc_approvedc                    s   t t  }| ddg | jD ]&}||j |jD ]}|| q8q"| jjrt | jj	t | jj
 D ]4}|ddg ||j |jD ]}|| qqjt|S )Nzlists.cmf_ownerzlists.cmf_owner_assistantsr   cmf_owner_assistants)setr   
get_ownersrE   r;   addr   r   r$   rC   rB   r   )r-   r   r   ZownersZlstownerr   r   r   r     s    


zCmfTask.get_ownersc                    s   | j r
d S t   d S rY   )waiting_forr   _calc_waiting_forr5   r   r   r   r     s    zCmfTask._calc_waiting_forc                 C   s6  | 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r| jjjdkrd}| jj }|r| js| j jjdkr| jj| _d| _| jjr| jr| jdkrd| _d| _| jdkr| j jjdkrd| _d| _|r8| jjr8| jr8|jr8|jr8tj| j kr8td	dd
 | jr| jjrl| jj| jksd| jjsl| j| _| jjr| jj| jkr| j| _| jjr| jr| jjr| jjj | jkr| j| jks| js| jj| _| jjr| jjs| jj| _| jjr| jsd| _| jjr.| jp*|| _| jr:dS d}| jjrt| jjs\| jjsp| jjrt| jjstd}| j jr| j jr| j jrd}| jjrd}| 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sD| j|krD|s || _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r|sd| _d| _dS | j jjdkrd|r|j!rtj|  kr| j"s| j#j$ddd}|r|| _ td q| j jjdkr@tj| _| jtj%kr@td | jdksT| jr`d| _d| _dS | j jjdkr| 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r2| j jjdkrZ| jsZ|j(rRtddd
 td | j jjdkr| jpt|| _tj| d dd   | j jjdkr| j|kr| jp|| _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 q2qdS )#uS   
            Ф-я вызывается из базового класса
        NimportFr!   TZ	IN_REVIEWZapprove2Zapprove1_reviewu[   Только Владелец проекта может согласовать задачуrU   rt   open)rt   IN_PROGRESSZapprove3_notassigneduh   SimpleLogic: Задачу переключили на Постановщика/Руководителя(u   ), т.к. не указан Будильник. Установите будильник, чтобы задача отобразилась у Исполнителяr{   r|   uM   SimpleLogic: Задачу переключили на Исполнителя(u   ), т.к. указан Будильник.Установите будильник, чтобы задача отобразилась у Исполнителяr   )Zraise_erroru   Спасибо! Статус установлен в "Подтверждение закрытия", для проверки постановщиком или руководителем проектаu,   Спасибо! Задача закрыта.u   Спасибо! Статус изменен на «Закрыто» т.к установлен флаг «Без подтверждения».uO   SimpleLogic: Задачу переключили на Постановщика(u   ), т.к. статус=''r   uT   Нельзя брать в работу несогласованную задачу.um   Внимание! Вы взяли задачу без согласования с руководителем.u^   SimpleLogic: waiting_for  установлен т.к. статус снижен в in_progressui   SimpleLogic: waiting_for установлен т.к. статус перешел из open в in_progressu[   SimpleLogic: будильник установлен т.к. статус сменен на ))r8   r$   r~   r2   r   r   r#   r   osenvironrS   r   r   r3   r4   rB   Zstatus_typeapprove_forapprove_for_placeZsl_only_owner_approver   r   r   r   r%   rC   r@   r7   re   r    r   rd   r   Zsl_task_only_owner_closeZ
no_controlworkflowget_default_statuscurrent_userr>   r*   Zsl_deny_no_approve)r-   r   Ztask_controllerZis_project_taskZ
need_transZin_review_statusr   r   r   _calc_wf_simple_logic  s:   
 $2


	



 


*




zCmfTask._calc_wf_simple_logicc                    s2  t    | jjrd S |  }| jjr:|jd kr:d | _d S | jjrN| jjrNd S |jd kr\d S |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r.| js.|| | _d S d S )N)rv   i  )r   _calc_deadliner9   r$   r   r   Zsl_deadline_shiftr2   r@   datetimer   r*   timezoneutcZperiod_next_daterC   rB   r   r#   cmf_created_atager   r   r   )r-   r   Z
days_shiftshiftr*   r   r   r   r     sP    






zCmfTask._calc_deadlinec                    s    | d| jdk t jf |S )NZstrikethroughr   )r   r   r   _place_notify)r-   r   r   r   r   r     s    zCmfTask._place_notifyc                 O   s$   t jj|ddgd}| j| | S Nrc   z
members.idr?   )r    CmfListrS   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   rS   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rF   )r    CmfActiveEntityFilterrS   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_tagr?   TZ	only_data)r    r   rS   r   rk   r   r   )r-   r   Zactive_entity_filterr   r   r   remove_from_filter  s
    zCmfTask.remove_from_filterc                 O   s>  |  dddg |s tddd |s0tddd t|}t|}|tjkrZ| | nH|tjkrp| | n2|tj	kr|| j
jjkrd | _
ntd| dd |tjkr| | n|tjkr| | nl|tj	kr(tj	j|d	gd
}| j
r | j
|kr td|j d| j
j ddd || _
ntd| dd | S )Nr;   rH   zparent_task.nameu   Укажите from_idTrU   u   Укажите to_idu(   Не могу перместить из rd   )rc   r(   u5   Нельзя переместить задачу в "u/   ", так как она находится в ""u&   Не могу перместить в )rE   r%   r   Zget_cls_by_tuuid_strr    r   r   r   r   r   rH   rc   r   r   r   rS   rd   )r-   Zfrom_idZto_idr   r   Zfrom_clsZto_clsZtarget_taskr   r   r   move  s4    






 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      #№@ORrd   ILIKEaliasz%"z"%filterr(   T)lstripr    ZCmfTagrS   rd   r$   rk   r   )r-   	only_namectxr   tagr   r   r   _process_tag_token@  s*    
	zCmfTask._process_tag_tokenc                 K   sz   |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 |sv|| _dS r   )r   r    ZCmfLogicTyperS   rd   r$   
logic_type)r-   r   r   r   ltr   r   r   _process_logic_type_tokene  s*    
	z!CmfTask._process_logic_type_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   Fr      
user_local==Tr   rd   r   %Zloginr   )	
startswithr   rr   r    	CmfPersonrS   rd   r$   r2   )r-   r   r   r   _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            	   ru         c                 C   s0   |  }|  }|d| d| d| fkS )N#   №@)lower)r-   stringZhashtagr   r   r   hashtag_cmp  s    zCmfTask.hashtag_cmpc           	      K   s   |d }| j  D ]4\}}| }|d| d| d| fkr qLqdS |s| jsj|| jj krjd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   r   FT)Ztzr   r   )ZdayZhourZminutesecondZmicrosecondr   )months)r   rv   )_monthsitemsr   r7   rd   rC   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_token  s>     
zCmfTask._process_month_tokenc                 C   s   | j dd dS )uG    Ф-я вызывается из базового класса
        T)r   N)_calc_from_namer5   r   r   r   rw     s    zCmfTask._calc_namec                 C   s  t jjj}| jjs2| jjs2| jjr&|s2| jjs2d S | jjp<d}|	 }g }|rX|sXg | _t
|D ]`\}}| d}t  }	|	d= | jf |	rq`| jf |	rq`| jf |	rq`|| |s`q`q`g }d}
|r|| t|d }|| d||< |r,t| jdd d	D ]}d
}
|d|j  q|
rH|rH||  d7  < d|| _| jdkr| jrx| jjdsd| jpd | _d S )N z.,;:?!r-   Fr   .c                 S   s   | j jS rY   )rd   r   )r   r   r   r   <lambda>      z)CmfTask._calc_from_name.<locals>.<lambda>)keyTr   r   rL   ZEpiczEpic 1)r   Zglobal_settingsZshow_task_title_tagsr   rd   r$   r<   rk   r2   split	enumerater   striplocalscopyr   r   r   r   extendrr   rstripsortedjoinrR   r   )r-   r   Zname_tags_boundrd   Zname_tokensZundefined_tokensidxtokenr   r   Zneed_dotZdot_token_posr   r   r   r   r     s\    



zCmfTask._calc_from_namec                 C   sX   | j js| jsd S | jdkr$d| _n0| jdkr6d| _n| jdkrHd| _n| j | _d S )N)rM   gantt)rL   ztask.gantt_subprojectr   z
pfeed.basepost)r   r$   r7   rR   ui_view_formui_namer   r5   r   r   r   _calc_ui_view_form.  s    


zCmfTask._calc_ui_view_formc                 C   s  | j r| j jjdkr*| jdkr*tddd | j r>| j jjdkrX| jsTtj| d | _d S | j	s| jdkr| 
ddg | j j| _	| js| j	r| j	
d	d
g | j	jdkr| j	| _n
| j	j| _| js| jdks| j j  | j j| _| j}|s| jdkr| }|stddd | jr<| jdkr<t }||_ d|_|  | jsltjjd|dgd}tj| |}|| _| j	js| jjr|| j_| j	| j_	| j  d S )Nr!   rL   rM   rP   u_   task.epic, task.subproject и task.gantt_project не могут быть без ПроектаTrU   rK   zparent.main_gantt_projectz&parent.main_gantt_project.logic_prefixgantt_projectrR   rP   z.DEV: _calc_gantt_task if not cur_gantt_projectr   )
is_operater   r(   )r   r   r3   rR   r%   op_gantt_taskr    ZCmfGanttTaskZcreate_gantt_taskrH   rE   Zmain_gantt_projectr   r4   r7   ZCmfGanttBaseliner   r   rS   r$   )r-   Zcur_gantt_projectZop_gantt_baselineZop_baseliner   r   r   r   _calc_gantt_task@  sJ    






zCmfTask._calc_gantt_taskc                 C   s<   | j jr| j| j j| j j | jjs.| jjr8| j  dS )u   
        Изменяем счетчики Оперативной Гант-задачи при изменении задачи
        N)	r8   r$   r   Ztask_status_is_changed_hookrC   rB   r<   r+   Ztask_plan_dates_is_changed_hookr5   r   r   r   ry   }  s    z$CmfTask._calc_op_gantt_task_countersc                 C   s$   | j r| j jjdkrd S |   d S r1   )r   r   r3   Z_check_simple_permr5   r   r   r   check_simple_perm  s    zCmfTask.check_simple_permc                 C   s  | j r| j jjdkrd S | js(| js(d S | j jr@| j jd| d | jjrn| j jd| d | j jd| jj| d | jjr| jdkr| jjdkr| j jd| d | jr| j	d	d
}| 
 D ]}||kr|| q|r| j jd| d | jjr| jjr| j jd| d | jjs$| jjs$| j jr4| j jd| d | jjrh| jjrh| j jd| d | j jd| d | jjr| j jd| d d S )Nr!   zPPP-TSK-CREATEr   zPPP-TSK-ASSIGNzPPP-TSK-ASSIGNABLE)userrF   r   zPPP-TSK-CLOSET)r$   zPPP-TSK-EDITzPPP-TSK-MODIFY-OWNERzPPP-TSK-MOVEzPPP-TSK-RESOLVEzPPP-TSK-TRANSITIONzPPP-VW-MANAGE)r   r   r3   r7   r$   check_project_role_accessr2   r   rC   keysZproject_perm_allow_fieldsr   r   rH   r;   r8   Z
spectators)r-   Zchanged_fieldsZallowed_fieldr   r   r   _check_project_perm  s>    

zCmfTask._check_project_permc                     sR   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dddd g }t   | S )!Nzparent.project_typezparent.auto_alarm_datezparent.logic_prefixzparent.activity.prefixrH   parent_task.logic_prefixrQ   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comments.log_levelr   r   cmf_modified_byr_   Ztimetracker_historyhas_child_tasksrW   rN   r   r   zop_gantt_task.actual_start_daterR   )r   save_preload_fields)r-   r(   r   r   r   r    sD    "zCmfTask.save_preload_fieldsc                    sf  | 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rh| jrh| jjjdkrh| jj  | jjr| jj| j
kr| j
| jj d| jjj  d| jj  d}tj| |d	d
  | jjrh| jjjdkrh| jjj  | jjj}|rh|| j
krh| j
| d|j  d| jjj  d}tj| |d	d
  | j
jrt| j
jt| j
j D ]8}|jdkrtjstd|j  d| j  ddd q|   |   |   |    | !  | "  | j#jr,| j#dkr,| jdkr,td| j# ddd | $  t% j||}	| j
jrXt&tj'j( dD ]&}
t)| |
jr\t&tj*j(  qq\| j+r| j+jr| j+jdkrt&tj,j( | j+jr| j+jr| j+jjdkrt&tj,j( | j-jr| jrt.| jjtj/r| j0| j- | jjrB| jdkrB| 1tj2j3 | j4dd | j5rb| jdkrbtddd |	S )Nhook_task_savelist.agile_sprint	list.basezmain_list.logic_prefixr!   uU   SimpleLogic: Задача добавлена в Cписок по умолчанию "   " проекта "r   r{   r|   uS   SimpleLogic: Задача удалена из Cписка по умолчанию "r   uM   Нельзя добавить задачу в Закрытый список "z" - "TrU   )taskr   r   r   rK   u   Вид отображения uk    временно не поддерживается, используйте "task", "list", "post", "gantt")r8   r   rk   r2   r<   r~   rL   r   )priorityr   us   DEV: Недопустимое перемещение простой задачи в структуру дерева)6rd   r$   r   r[   r^   rJ   r   r   rA   r  r;   r_   r   rC   rB   rR   rE   r   r3   default_listr4   r    r   r   r   r   r   Zimport_moder%   _calc_logic_type_change_guardrX   !_calc_parent_task_has_child_tasks_calc_gantt_pathr   ry   r   _calc_structural_projectr   Zcmf_deferred_taskr   recalculate_cachegetattrr   rH   r   rk   r   r!   Zhook_task_tags_changedZ_clear_notifyr   rc   Z_update_opened_notifiesrQ   )r-   r   r   r   Zremoved_listlZappended_list	audit_msgZold_default_listZself_instance
field_namer   r   r   r     s    






"

"

 $$zCmfTask.savec                    st   |  dddg | js(| js(| jtjkrN| jrNt| jjt	j
rN| jjd| d t j||}| jrp| jj|| |S )Nr}   rG   r   zPPP-TSK-DELETEr   )rE   r}   rd   r   r   r   rG   r   r   r    r!   r  r   deleter   )r-   r   r   resr   r   r   r  W  s    zCmfTask.deletec                    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	}|rdd
|krd|d	d|gg}|d |d t j|f||||d|S )Nrd   r   !=r   r   rO   Ztrashr   rI   search=r   object_fieldsr   r(   order_by)rS   r   r   field_options_list)r   relation_field_namer  r   r(   r  r   rI   r   r   r   lists_options_listd  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 )NrI   r  r   rR   r	  r
  r  )rS   r"  r   r!  r  r   r(   r  r   r   r   r   main_list_options_list|  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 )	NrI   r  r  r   rR   rL   rM   r  )rS   r   r   r#  r   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  r_   rH   )r"  r$  r%  r   r   r#  r   r   r   r     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   r8   )re   r(   r   zAuto task reopenu'   Переоткрываем задачу)r   r}   Ndefault_projectr?   zNew auto task for r   z
) project 
r   )re   rd   r}   r2   r   r  r   r   )printhashlibZmd5encodeZ	hexdigestr    r   rS   r   r   r   r8   r#   r>   r   r   r   r'   r(   r   Zget_obj_by_tuuid_strr(  rd   re   rc   r   )rd   r}   Z
extra_textr  responsible_idZcmf_owner_idrI   _kwargsZtask_keyZ	task_hashZ	task_coder  r2   r   r   r   r   r   	auto_task  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-  )Zin_progresscount)
r    r   r   rc   dictr   r   r0  r   r   )r   r   r   r   personsZin_progress_filterZcount_filterr   resultZin_progress_countr0  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   r2   	executorsr   Tc                 S   s   g | ]}|j jqS r   )rc   r   )rh   rF   r   r   r   rj     s     z%CmfTask.notify_os.<locals>.<listcomp>F)rE   r   rC   r   rc   r2   r5  )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 rY   )r:   r$   r   rR   r   r@   r;   r   r_   Z	scheme_wfZcalc_workflowr5   r   r   r   _calc_workflow  s$    	zCmfTask._calc_workflowc                 C   s   | j jsd S | jdkrd S | jdkrD| jjrD| jjdkrDtddd | jjdkrf| jdkrftddd | jjdkr~tddd | jjdkrtd	dd d S )
NrM   rP   uL   Нельзя изменить тип задачи на Гант-проектTrU   u?   Нельзя изменить тип у Гант-проектаuI   У Подпроекта больше нельзя изменять типrL   uP   Тип Епик можно поменять только на Подпроект)r   r$   rR   rC   r%   r5   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   rK   )rH   r$   r   rR   rC   _calc_cache_branch_gantt_path_recalc_gantt_pathr5   r   r   r   r    s    
zCmfTask._calc_gantt_pathr   c              	   C   s  |dkrt ddd |r|ddddg | j|jkr>|j| _| j|jkrR|j| _| j|jkrf|j| _|jd	kr~|| _d | _n|jd
kr|| _tjj| dddddddgdD ]}d}|j| jkr| j|_d}| jd
kr| |_| j|_d}nR| jd	kr| |_d |_d}n4|j| jkr"| j|_d}|j| jkr<| j|_d}|j	rd|
|  |jj|jjkrdd}|rv|jdd |j	r|jd |d d qd S )Nd   uM   DEV: Защита от рекурсии: _recalc_gantt_path: if r_count > 100TrU   rN   rW   rR   r   rM   rL   cache_branch_gantt_pathrH   r  )rH   r(   Fr   r   )rH   r_count)r%   rE   rN   rW   r   rR   r    r   r   r  r9  r<  rB   rC   r   r:  )r-   rH   r=  ZchZ	need_saver   r   r   r:    s\    

  

zCmfTask._recalc_gantt_pathc                 C   s   | j   | js$| j dkr$d | _d S |s<| ddg | j}|sJg | _d S |jj}|d krftddd ||jj|j	j|j
j|j jdf| _d S )Nr   z#parent_task.cache_branch_gantt_pathr  zODEV: WARNING: _calc_cache_branch_gantt_path: if cache_branch_gantt_path is NoneTrU   )rc   re   rd   rR   )rR   r4   r  r<  rE   rH   r   r%   rc   re   rd   )r-   rH   r<  r   r   r   r9  M  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   rH   r  rc   r  r   F)rH   r$   rp   rE   r  r9  r   rC   r    r   rS   rc   )r-   Zhave_childsr   r   r   r  f  s    
$
z)CmfTask._calc_parent_task_has_child_tasksc                 C   s(  | j jsd S | dg | j r| j jr| j jjr| j jj}|jr| j|kr|j| jkr| j|j d|jj	 d|j	 d}t
j| |dd  | j jr$| j j}|dg |jr$|jjr$|jj}|jr$| j|kr$|j| jkr$| j|j d|jj	 d|j	 d	}t
j| |dd  d S )
Nz8responsible.primary_role.structural_project.default_listu>   SimpleLogic: Задача добавлена в список "r  u   " т.к. он является Структурным проектом Главной роли ответственного по задачеr{   r|   z,primary_role.structural_project.default_listu<   SimpleLogic: Задача удалена из списка "u   " т.к. он является Структурным проектом Главной роли прошлого ответственного по задаче)r2   r$   rE   Zprimary_rolestructural_projectr  r   r;   r   rd   r    r   r   rC   r   )r-   r>  r  Zold_responsibler   r   r   r  {  s(    

z CmfTask._calc_structural_project   Изменена задача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_assistantszparent.cmf_ownerr   r   r   r   r  <   )r6  rd   msgr   r!   )r}   notify_namer  )r7   rE   r   r   r   r   rc   r   r   r   rI   	type_namer   r   r   all_place_notify)r-   r}   r  rB  r   r2  r   r   r   r   rD    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_attrscopy_attachmentsrc   r   )r-   paramsZnew_taskr   r   r   create_task_from_template  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#   r9   r<   r9   r?   r#   )rE   r<   r9   r   r*   )r-   rE  Zattrsr   r   r   rF    s    
z"CmfTask.get_additional_clone_attrsc                    s&   | j dgd | jdkrdS t  S )uB    Шаблон уведомлений для разных workflow rR   r?   ztask.ticketzhelpdesk_mail_notification.html)rE   rR   r   +get_default_mail_notification_template_namer5   r   r   r   rJ    s    
z3CmfTask.get_default_mail_notification_template_namec                    s    |dkrdS t  j|f||S )N)r#   r<   r+   r~   r   )r   _get_field_log_level)r-   r  r   r   r   r   r   rK    s    zCmfTask._get_field_log_level   Добавленоc                 C   s   t j| |||S rY   )r    rZ   Ztimetracker_task_change_time)r-   r\   r]   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   rL   cache_child_tasks_count)rR   r(   r   rH   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   r   r0  rN  r   debugrc   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	recursion)returnc                   sT   t  }| dddddg | jr8|| jj|d d t j|d|i||S )	Nzfollowers.personzfollowers.notify_volumezfollowers.follow_childrenrQ   rH   r   rP  rQ  )r   rE   rH   unionget_all_followersr   )r-   rQ  r   r   r  r   r   r   rT    s      zCmfTask.get_all_followers)rd   rG  copy_relationscopy_subtasksc                   s   |  dddddg t j|||d|}tjjdd}|rd	d
|gg}	tjj|	dd| gg dgdD ]}
|
 }||_	|
  qhtjj|	dd| gg dgdD ]}
|
 }||_|
  qtj| ||d
  |S )Nz**zattachments.urlrk   zattachments.url_previewzattachments.url_preview_img)rd   rG  zsystem.clone)re   relation_typer  out_linkr   r   in_link)rX  rY  rW  )rE   r   r   r    ZCmfRelationTyperS   ZCmfRelationOptionr   ZclonerX  r   rY  )r-   rd   rG  rU  rV  r   r   Znew_objZ
clone_typer   ZrelationZnew_relationr   r   r   r      s,    
 



zCmfTask.copyc                    s2   |  dg | jdkr*d| j d| j S t jS )NrR   rM   z	/project/r'  )rE   rR   r   re   r   hrefr5   r   r   r   rZ    s    
zCmfTask.hrefc                    sB   t t jf |}| j r:| j s:|| jjf | t|S rY   )r   r   all_relation_personsr   r4   r5  updater   )r-   r   r2  r   r   r   r[    s    zCmfTask.all_relation_persons)NN)F)F)F)F)F)NNNN)NNNN)NNNN)NNNN)NNNNNN)N)r   )N)Nr?  )T)rL  )Q__name__
__module____qualname__classmethodr   r   r0   r6   r=   rD   rJ   rT   rX   r[   r^   ra   rn   r"   rs   rx   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rw   r   r   r   ry   r   r  r  r   r  r"  r$  r%  r   staticmethodZ
celery_appr  r/  r4  r7  r8  r  r  r:  r9  r  r  rD  rI  rF  rJ  rK  rM  r  r   rT  strboolr   propertyrZ  r[  __classcell__r   r   r   r   r      s   $&
	A2 s<  
+
%
%

*
C=	3%s                            
          -
.
#


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   