U
    z}c.                    @   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                       s  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 fd#d$Zd%d& Z fd'd(Z fd)d*Zd+d, Zd-d. Zd/d0 Zd1d2 Zdd4d5Zdd7d8Zdd9d:Zd;d<d=d>d?d@dAdBdCdDdEdFdGZdHdI Z ddJdKZ!dLdM Z"ddNdOZ#dPdQ Z$dRdS Z%dTdU Z& fdVdWZ' fdXdYZ( fdZd[Z)e*d fd\d]	Z+e*dd^d_Z,e*d fd`da	Z-e*d fdbdc	Z.e/e0j1dddeddfdgZ2e/ddhdiZ3djdk Z4dldm Z5dndo Z6dpdq Z7ddsdtZ8ddudvZ9dwdx Z:d fdzd{	Z;d|d} Z<dd~dZ= fddZ> fddZ?dddZ@e/e0j1dddddddd ZA  ZBS )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   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   r(   r!   r!   r"   _calc_tree_parent   s    

zCmfTask._calc_tree_parentc                 C   sJ   | j s
d S | j}|rF|jdkrF|ddg |jdkr>|| _qF|j}qd S )Nr   rG   rF   r@   )r*   rF   r&   r;   rG   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*   rF   r   r   r>   	main_listZ_load_perm_fieldsr   r   r   ZCmfDocumentperm_parent)r   rQ   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 rS   rW   rX   r!   r!   r"   r[      s     tags
is_checked	parent_idactivity_id)r0   get_cache_fields_jsonr.   r\   r]   r^   r_   )r   retr3   r!   r"   r`      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_nolist4  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   rd   re   rj   ri   r   r!   r!   r"   
_calc_planJ  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: Задача согласована автоматически, т.к. постановщик - руководитель.)r*   approvedr   	cmf_ownerr   r   r&   r   
CmfCommentsave_get_sl_optionssl_task_need_approveZsl_controller_strr'   rT   gcurrent_personZ
cmf_importZ
is_defined)r   
sl_optionsr!   r!   r"   _calc_approvedb  sV    



$

"zCmfTask._calc_approvedc                    s   t t  }| ddg | jD ]"}||j |jr"||j q"| jjrt | jj	t | jj
 D ]0}|ddg ||j |jrf||j qft|S )Nzlists.cmf_ownerzlists.cmf_owner_assistantrp   cmf_owner_assistant)setr0   
get_ownersr;   r.   addrp   ry   r   r9   r8   list)r   argskwargsZownersZlstr3   r!   r"   r{     s    
zCmfTask.get_ownersc                    s   | j r
d S t   d S r=   )waiting_forr0   _calc_waiting_forr(   r3   r!   r"   r     s    zCmfTask._calc_waiting_forc                 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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| _|r| jjr| jr|jr|jrtj| j krtddd	 | jr| jjrH| jj| jks@| jjsH| j| _| jjrj| jj| jkrj| j| _| jjr| jr| jjr| jjj| jkr| jj| _| jjr| jsd| _| jjr| jp|| _| jrdS d}| jjr| jjs | jjs| jjr| jjsd}| j jr:| j jr:| j jr:d}| jjrHd}|sRdS | j jjd
krJ| j jjd
krJ| j jjdkr| jp|| _| js| j|kr|s|| _d| _|| _tj| d|j ddd   | jjsF| jjrF| j|krF| jrF| j| _tj| d| j ddd   | jdkrF|sFd| _d| _dS | j jjdkr|r|j!rtj|  kr| j"s| j#j$ddd}|r|| _ td qR| j jjdkrtj| _| jtj%krtd | jdks| jrd| _d| _dS | j jjdkr| j"r,| j#$d| _ td qR| js>| j&  | j jjdkrj| j| j' krj| 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|j(rtddd	 td | j jjdkr"| jp
|| _tj| ddd   | j jjd
kr`| j|kr`| jpH|| _tj| d dd   | jsr| j&  | j jjdkr| j| j' kr| j&  tj| d!| j j dd   dS qȐqRdS )"uS   
            Ф-я вызывается из базового класса
        NimportFr   TZ	in_reviewZapprove2uL   Только Владелец может согласовать задачуabortrf   )rf   in_progressZapprove3_notassigneduh   SimpleLogic: Задачу переключили на Постановщика/Руководителя(u   ), т.к. не указан Будильник. Установите будильник, чтобы задача отобразилась у Исполнителяrl   rm   uM   SimpleLogic: Задачу переключили на Исполнителя(u   ), т.к. указан Будильник.Установите будильник, чтобы задача отобразилась у Исполнителяr	   )Zraise_erroru   Спасибо! Статус установлен в "Подтверждение закрытия", для проверки постановщиком или руководителем проектаu,   Спасибо! Задача закрыта.u   Спасибо! Статус изменен на «Закрыто» т.к установлен флаг «Без подтверждения».Zapprove1_reviewuO   SimpleLogic: Задачу переключили на Постановщика(u   ), т.к. статус=''r   uT   Нельзя брать в работу несогласованную задачу.um   Внимание! Вы взяли задачу без согласования с руководителем.u^   SimpleLogic: waiting_for  установлен т.к. статус снижен в in_progressui   SimpleLogic: waiting_for установлен т.к. статус перешел из open в in_progressu[   SimpleLogic: будильник установлен т.к. статус сменен на ))r+   r   ro   r%   rp   r   r   r   osenvironrH   rs   r   r&   r'   r8   Zstatus_typeapprove_forapprove_for_placeZsl_only_owner_approvert   ru   rv   r{   r   r9   r6   r*   rV   r   rq   rU   rr   Zsl_task_only_owner_closeZ
no_controlworkflowget_default_statusZcurrent_userr2   r   Zsl_deny_no_approve)r   rw   Ztask_controllerZis_project_taskZ
need_transZin_review_statusr!   r!   r"   _calc_wf_simple_logic  s*   
 $.

	


 


*




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)rh   i  )r0   _calc_deadliner,   r   rs   r   Zsl_deadline_shiftr%   r6   datetimer   r   timezoneutcZperiod_next_dater9   r8   r   r   cmf_created_atagerp   ru   rv   )r   rw   Z
days_shiftshiftr   r3   r!   r"   r     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 NrT   z
members.idr5   )r   CmfListrH   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   rH   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   CmfActiveEntityFilterrH   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   rH   r   r\   r   rr   )r   r   Zactive_entity_filterr!   r!   r"   remove_from_filter  s
    zCmfTask.remove_from_filterNc                 O   s   |  dddg |s tddd |s0tddd t|}t|}|tjkrZ| | n(|tjkrp| | ntd| dd |tjkr| 	| n(|tjkr| 
| ntd	| dd | S )
Nr.   r>   zparent_task.nameu   Укажите from_idTr   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   #№ORrU   ILIKEaliasz%"z"%)filterr   T)lstripr   ZCmfTagrH   rU   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   rU   r   %Zloginr   )	
startswithr   rd   r   	CmfPersonrH   rU   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   Декабрь)   rl         r            	   rg         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   rh   )_monthsitemsr   r*   rU   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"   ri     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=   )rU   r   )r   r!   r!   r"   <lambda>      z)CmfTask._calc_from_name.<locals>.<lambda>)keyTr   r
   rA   ZEpiczEpic 1)rU   r   r/   r\   r%   r   split	enumerater   striplocalscopyr   r   r   r   extendrd   rstripsortedr   r   joinrG   r   )r   r   rU   Zname_tokensZundefined_tokensidxtokenr   r   Zneed_dotZdot_token_posr   r   r!   r!   r"   r     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 )N)rA   rB   ztask.gantt_subprojectr}   z
pfeed.basepost)
logic_typer   r*   rG   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*| jdkr*tddd | j r>| j jjdkrBd S | jsj| jdkrj| 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| }|stddd | j
r$| jdkr$t }||_ d|_|  | jsTtjjd|dgd}tj| |}|| _| jjsh| jjr|| j_| j| j_| j  d S )Nr   rA   rB   rE   u_   task.epic, task.subproject и task.gantt_project не могут быть без ПроектаTr   r@   zparent.main_gantt_projectz&parent.main_gantt_project.logic_prefixgantt_projectrG   rE   z.DEV: _calc_gantt_task if not cur_gantt_projectr   )
is_operater   r   )r   r   r&   rG   r   r>   r;   Zmain_gantt_projectr   r'   r*   r   ZCmfGanttBaseliner   rr   op_gantt_taskrH   ZCmfGanttTaskZcreate_gantt_taskr   )r   Zcur_gantt_projectZop_gantt_baselineZop_baseliner   r!   r!   r"   _calc_gantt_task  sF    






zCmfTask._calc_gantt_taskc                 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                    sP   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.prefixr>   parent_task.logic_prefixrF   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_byrP   Ztimetracker_historyhas_child_tasks
subprojectrC   r   r   rG   )r0   save_preload_fields)r   r   r3   r!   r"   r     sB    !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r2ttj!j  qZq2| j"jr| j"r| j"jdkrt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 | j-r| jdkrtdd	d
 |S )Nhook_task_savelist.agile_sprint	list.basezmain_list.logic_prefixr	   uM   Нельзя добавить задачу в Закрытый список "z" - ""Tr   )taskr}   r   Zganttu   Вид отображения uk    временно не поддерживается, используйте "task", "list", "post", "gantt")r+   r   r\   r%   r/   ro   rA   r   )priorityr   us   DEV: Недопустимое перемещение простой задачи в структуру дерева).rU   r   r   rL   rO   r?   r   r   r7   r   r.   rP   rz   r9   r8   rG   r;   r   r   r   _calc_logic_type_change_guardrJ   !_calc_parent_task_has_child_tasks_calc_gantt_pathr   r   r0   rr   Zcmf_deferred_taskr   r   recalculate_cachegetattrr   r>   r   r\   r   r   Zhook_task_tags_changedZ_clear_notifyru   rv   rT   Z_update_opened_notifiesrF   )	r   r~   r   r   Zremoved_listlZappended_listZself_instance
field_namer3   r!   r"   rr   A  sv    







"

 $zCmfTask.savec                    s&   t  j||}| jr"| jj|| |S r=   )r0   deleter   )r   r~   r   resr3   r!   r"   r     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 )NrU   r   !=r	   r   rD   Ztrashr   r^   search=r   object_fieldsr   r   order_by)rH   r   r0   field_options_list)clsrelation_field_namer  r   r   r  r   r^   r3   r!   r"   lists_options_list  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 )Nr^   r   r   rG   r   r   r  )rH   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 )	Nr^   r   r   r   rG   rA   rB   r  )rH   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  rP   r>   )r  r	  r
  r0   r  r  r3   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   r+   )rV   r   r	   zAuto task reopenu'   Переоткрываем задачу)r   rn   Ndefault_projectr5   zNew auto task for r   z
) project 
r   )rV   rU   rn   r%   rp   r   r   r   )printhashlibZmd5encodeZ	hexdigestr   r   rH   r   r   r   r+   r   r2   rq   rr   r   r   r   r   Zget_obj_by_tuuid_strr  rU   rV   rT   r   )rU   rn   Z
extra_textr   responsible_idZcmf_owner_idr^   _kwargsZtask_keyZ	task_hashZ	task_coder   r%   rp   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  )r   count)
r   r   r}   rT   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!   )rT   r   )rY   r<   r!   r!   r"   r[   ,  s     z%CmfTask.notify_os.<locals>.<listcomp>F)r;   r   r9   r   rT   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   rG   r   r6   r.   r   rP   Z	scheme_wfZcalc_workflowr(   r!   r!   r"   _calc_workflow0  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 )
NrB   rE   uL   Нельзя изменить тип задачи на Гант-проектTr   u?   Нельзя изменить тип у Гант-проектаuI   У Подпроекта больше нельзя изменять типrA   uP   Тип Епик можно поменять только на Подпроект)r   r   rG   r9   r   r(   r!   r!   r"   r   C  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>   r   r   rG   r9   _calc_cache_branch_gantt_path_recalc_gantt_pathr(   r!   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 > 100Tr   rC   r   rG   r   rB   rA   cache_branch_gantt_pathr>   r   )r>   r   Fr   r   )r>   r_count)r   r;   rC   r   r   rG   r   r   r}   r   r  r!  r8   r9   rr   r  )r   r>   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 NoneTr   )rT   rV   rU   rG   )rG   r'   r   r!  r;   r>   r   r   rT   rV   rU   )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   rT   r   r   F)r>   r   rb   r;   r   r  rr   r9   r   r   rH   rT   )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   rp   r   <   )r  rU   msgr   r   )rn   notify_namer   )r*   r;   r   r   r   r   rT   r   r   rp   r^   	type_namer   r   r0   all_place_notify)r   rn   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_attachmentsrT   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   r,   r/   r,   r5   r   )r;   r/   r,   r   r   )r   r)  Zattrsr!   r!   r"   r*    s    
z"CmfTask.get_additional_clone_attrsc                    s&   | j dgd | jdkrdS t  S )uB    Шаблон уведомлений для разных workflow rG   r5   ztask.ticketzhelpdesk_mail_notification.html)r;   rG   r0   +get_default_mail_notification_template_namer(   r3   r!   r"   r-    s    
z3CmfTask.get_default_mail_notification_template_namec                    s    |dkrdS t  j|f||S )N)r   r/   r   ro   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   rK   Ztimetracker_task_change_time)r   rM   rN   rn   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)rG   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   r}   r  r1  ru   debugrT   rr   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/  )C__name__
__module____qualname__r#   r)   r1   r:   r?   rI   rJ   rL   rO   rR   r`   r   re   rj   rk   rx   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ri   r   r   r   r   r   rr   r   classmethodr  r	  r
  r  staticmethodZ
celery_appr   r  r  r  r  r   r   r  r  r   r(  r,  r*  r-  r.  r0  r   __classcell__r!   r!   r3   r"   r      s   $&
	A2 e<  
!
%

*
=:$\                            
          -
.
#

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