U
    de3                    @   s   d dl Z d dlZd dlmZ d dl mZ d dl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ZG dd	 d	ejjjjejjjjZejd
d  dS )    N)defaultdict)	timedelta)FileStorage)relativedelta)*)CmfTUUIDc                       s  e Zd Zedd fdd
Zedd f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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/d0Zd1d2 Z fd3d4Zd5d6 Zd7d8 Zd9d: Zd;d< Z dd=d>Z!dd@dAZ"ddBdCZ#ddDdEZ$dFdGdHdIdJdKdLdMdNdOdPdQdRZ%dSdT Z&ddUdVZ'dWdX Z(ddYdZZ)d[d\ Z*d]d^ Z+d_d` Z,dadb Z-dcdd Z.dedf Z/dgdh Z0 fdidjZ1dkdl Z2dmdn Z3dodp Z4dqdr Z5dsdt Z6e fdudvZ7 fdwdxZ8dydz Z9d?d{d|d}Z: fd~dZ; fddZ<dd?dddZ=dd Z>dd?dddZ?dddZ@dd?dddZAdddZBd fdd	ZCed fdd	ZDed fdd	ZEedddZFed fdd	ZGed fdd	ZHed fdd	ZIeJeKjLdddddZMeJd ddZNdd ZOdd ZPdd ZQdddZRdddZSdd ZTdd ZUdd ZVdd ZWdd ZX fddZYdddZZeJeKjLddddd Z[eJdd Z\eJdddÄZ]eJeKjLddddōddǄ Z^ddȜe_dɜ fdd˄Z`e fdd̈́Zad?d?d?d?dΜebececececdϜ fddфZdddӄ Zeef fddՄZgedddׄZhddل Zi fddۄZjd fdd݄	ZkedddޜddZl fddZmdd Zndd Zoedd ZpeJeKjLddddd Zq fddZredebdɜ fddZs  ZtS (  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   sD   d}| j dddgdd| jggdgdd	}|r@t|jd
d }|S )Ncodez
SIMILAR TOz
%-[0-9]+\Zroot_parent=z-cmf_created_atT)filterorder_byinclude_deleted-)sgetroot_parent_idintr   split)selfZ
max_numberZlastr   r   r    _get_current_code_number_from_db    s    z(CmfTask._get_current_code_number_from_dbc                 C   s   t j}d}| jr| jj}d| j d| }| j d| d}|jj|dd}|  z2||rl||}n|  d }||| W 5 z|  W nF tj	j
k
r } z$td| d|j d	|j  W 5 d
}~X Y nX X | S )uN    Высчитывает следующий номер для кода
        Z	NOPROJECTznext_code_number-r   z.lock   )timeoutzlock release error z, lock_name z
, timeout N   )APPZREDIS_DBr!   value
class_nameredislockacquirerelease
exceptionsZ	LockErrorgdebugnamer'   existsZincrr%   set)r$   Zredis_dbsuffixkeyZlock_keyr-   enext_code_numberr   r   r   r9   *   s$    
4zCmfTask.next_code_numberc              	   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parentr*   models
CmfProject_calc_list_plan_interval
alarm_date
is_changed	cmf_alertcaptioncmffieldsCmfDateTimenowplan_end_dater$   list_plan_start_date_maxlist_plan_end_date_minr   r   r   _calc_alarm_date_listH   s,    

$zCmfTask._calc_alarm_date_listc                 C   s   | j r| jjs| jjsd S | j jr&d S | jD ]0}|js<|jr,|jrJ|j| _ |jrX|j| _ q^q,| j s| jr| jjjdkr| jj 	 r| jj | _ d S NrB   )
responsibler@   rE   
componentsZdefault_responsibleZdefault_owner	cmf_ownerr*   r+   load)r$   compr   r   r   _calc_responsiblee   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 rQ   )is_newrD   rE   statusdeadlineactivitylistsplan_start_daterL   r   _calc_alarm_dater@   r*   r+   Zauto_alarm_daterU   rP   rK   set_nowr$   r   r   r   r^   ~   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 jdgd}q|s| jr| jd j jdgd}|r|| _ | j st
   dS )u   
        Вычисляем вид деятельности
        Метод вызывается из базового класса.
        :return:
        Nr[   r   rI   r   )r[   rE   rX   r@   r\   is_nullhasattrrU   newoldr   _calc_activity)r$   Ztmp_activityobjr   r   r   rf      s6    

zCmfTask._calc_activityc                 C   s   d S Nr   r`   r   r   r   _calc_parent   s    zCmfTask._calc_parentc                 C   s  | j jr| j jrd | _d S | j js,| j r,d S | j r| j jr| j | j jkr| j j  | j j| _| jr| jdg | jjdkr| j j| _| j	dd ddg}| | | j
sd S | j j| j
_| j
j	dd tjjdd| g|d	}|D ] }|j | j kr| j |_ |	  qd S )
Nlogic_prefixtask.gantt_projectTZ	only_datar@   op_gantt_taskparent_taskr   r   rI   )r@   rb   re   gantt_projectmain_gantt_projectrU   rn   load_fieldsrj   saverm   rA   r   r   r$   rI   Zchild_taskstaskr   r   r   _do_parent_is_changed   s0    "


zCmfTask._do_parent_is_changedc                 C   s  | j js$| jjs$| jjs$| jjs$d S | jr| jjr| j| jjkr| jddg | jjdkrd}| jj| _|   t	j
| |dd  t| d S | jjrd S | j jr| j r|  }|r|| jkr|ddd	d
g || _|   d S | jjr| jrd }d }| ddg | jjr8| jjjr8| jjj}| jjj}|r| jspd}|| _t	j
| |dd  |   d S |rd}|| _t	j
| |dd  |   d S d S )Nr@   rj   rk   u   SimpleLogic: в задаче установлен проект равный проекту родительской задачи   r@   text	log_levelrT   cmf_owner_assistantsr[   r!   8responsible.primary_role.structural_project.default_listz1responsible.primary_role.structural_project_forceu   SimpleLogic: Задача добавлена в Структурный проект Главной роли исполнителяu   SimpleLogic: Проект сменен, т.к. в Главной роли исполнителя указано менять проект)tree_parentrE   rR   rn   r@   	parent_idrr   rj   save_preload_fieldsrA   
CmfCommentrs   rF   Z_node_parentprimary_rolestructural_projectZstructural_project_force)r$   Z	sl_reasonr@   Zstruct_projectZstruct_project_forcer   r   r   _HACK24052023_calc_parent   s`    


z!CmfTask._HACK24052023_calc_parentc                 C   s   | j r| jjsd S | jdkrBtjj| jddgd| _ | j sB| j| _ | jjr| j r| jdkr| jjdkr| j	j
dd | j	rtd | j	D ]}| j |_ |  qd | _ | jdkrd | _ d S )	N	task.epictask.subprojectepicZtree_hidden)r@   sys_typerI   T)r   u   Скрываем задачу в дереве проекта, её дочерние элементы вставляем вместо неёrk   )r}   rj   rE   rA   Z	CmfFoldergetr@   
logic_typere   Z
tree_nodesrU   rF   rs   )r$   Zchildr   r   r   _calc_tree_parent7  s2    




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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 )NrB   rj   r}   r   r   ztask.subu2   У подзадач нельзя менять EpicTabortu@   У подзадач нельзя менять Подпроект)rX   r}   r*   r+   rr   rj   rn   rE   rU   r   rF   
subproject)r$   Ztmp_tree_parentr   r   r   _calc_parent_taskW  s,    



zCmfTask._calc_parent_taskc                 C   s&   | j r
d S | jjsd S tj|  d S rh   )rX   rY   rE   rA   CmfTimeTrackerZtimetracker_task_change_statusr`   r   r   r   _calc_timetrackers  s
    zCmfTask._calc_timetrackerc                 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 rh   )rX   r}   rE   r@   rn   	main_listZ_load_perm_fieldsr?   r*   rA   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 idr3   r   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 r   r   r   r   r   r   r     s     tags
is_checkedr~   activity_id)r   get_cache_fields_jsonr\   r   r   r~   r   )r$   retr   r   r   r     s    



zCmfTask.get_cache_fields_jsonc                 C   s|   d }d }| j D ]P}|jdkrq|jjr>|d ks8|j|kr>|j}|jjr|d ksX|j|k r|j}q|st|rttjj }||fS Nr:   )	r\   r>   r]   is_not_nullrL   rH   rI   rJ   rK   )r$   rN   rO   Zw_listr   r   r   rC     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 )Nr&   uP    установлена в соответствии с планом списка)	r\   rE   lenr]   rL   rD   rb   rF   rG   )r$   rN   rO   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   План сдвинут в соответствии с будильником)	rD   rE   r>   r]   rL   daysr*   rF   
_calc_name)r$   Z	date_diffr   r   r   _calc_plan_nolist  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\   rE   rX   rD   r]   rL   rC   r   r   r   _calc_op_gantt_task_countersr   rM   r   r   r   
_calc_plan  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 )
NrB   Tu~   SimpleLogic: Задача согласована автоматически, т.к. это Непроектная задачаrw   rx   u   SimpleLogic: Задача согласована автоматически, т.к. согласование отключено в Fu   SimpleLogic: Выполнен сброс согласования, т.к. сменился Постановщик или Проектu   SimpleLogic: Задача согласована автоматически, т.к. постановщик - руководитель.)rX   approvedrE   rT   r@   r*   r+   rA   r   rs   _get_sl_optionssl_task_need_approveZsl_controller_strrU   r   r1   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_assistantsrT   r{   )r5   r   
get_ownersrr   r\   addrT   r{   rE   re   rd   r   )r$   r   r   ZownersZlstownerr   r   r   r   W  s    


zCmfTask.get_ownersc                    s&   | j r
d S | jdkrd S t   d S r   )waiting_forr>   r   _calc_waiting_forr`   r   r   r   r   j  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| _| 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rD| jp*|| _| j jdkrD| j| _| jrPdS d}| jjr| jjsr| jjs| jjr| jjsd}| j jr| j jr| j jrd}| jjrd}| jjrd}|sdS | j jjdkrD| j jjdk}|s| jjddds| j j| jdk}|rD| j jjdkr@| jp<|| _| js| j|kr|sf|| _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| _| jr@| j|kr@| jr@| jr@| j| _tj | d| j dd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 q| j jjdkrd| _| jdks| jrd| _d| _dS | j jjdkr| j$r| jd| _ td q| js | j%  | j jjdkrL| j| j& krL| 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rB| j|krB| jp*|| _tj | d"dd"  | jsT| 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importFrB   T	IN_REVIEWZapprove2Zapprove1_reviewu[   Только Владелец проекта может согласовать задачуr   r   open)status_coderaise_error)r   IN_PROGRESSZapprove3_notassigneduh   SimpleLogic: Задачу переключили на Постановщика/Руководителя(u   ), т.к. не указан Будильник. Установите будильник, чтобы задача отобразилась у Исполнителяrw   rx   uM   SimpleLogic: Задачу переключили на Исполнителя(u   ), т.к. указан Будильник.Установите будильник, чтобы задача отобразилась у Исполнителяr=   r:   )r   u   Спасибо! Статус установлен в "Подтверждение закрытия", для проверки постановщиком или владельцем проектаu   Спасибо! Статус изменен на «Закрыто» т.к установлен флаг «Без подтверждения».uO   SimpleLogic: Задачу переключили на Постановщика(u   ), т.к. статус=''r   uT   Нельзя брать в работу несогласованную задачу.um   Внимание! Вы взяли задачу без согласования с руководителем.u^   SimpleLogic: waiting_for  установлен т.к. статус снижен в in_progressui   SimpleLogic: waiting_for установлен т.к. статус перешел из open в in_progressu[   SimpleLogic: будильник установлен т.к. статус сменен на )(rY   rE   r   rR   rT   r@   rD   r   osenvironr   r   r*   r+   rU   rd   status_typeapprove_forapprove_for_placeZsl_only_owner_approver   r1   r   r   rF   re   rb   rX   r   workflowget_default_statusrA   r   r3   rs   Zsl_task_only_owner_closeZ
no_controlr_   rK   Zsl_deny_no_approve)r$   r   Ztask_controllerZis_project_taskZ
need_transZsimple_logicZin_review_statusr   r   r   _calc_wf_simple_logicr  sL   
 $2


	



 
$


*




zCmfTask._calc_wf_simple_logicc                    s   t    | jjs,| jjs,| jjs,| js,d S | jjr8d S |  }|j	d krNd S |j	}t
j|d}t
j
t
jj}| 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s| jjr
| js|| | _n$| jr| j|| kr|| | _n d S | js|| | _d S )N)r   i  )r   _calc_deadliner   rE   r@   rD   rX   rZ   r   Zsl_deadline_shiftdatetimer   rK   timezoneutcZcmf_created_atagerT   r1   r   r*   )r$   r   Z
days_shiftshiftrK   r   r   r   r   u  sP    



zCmfTask._calc_deadlinec                 O   s$   t jj|ddgd}| j| | S Nr   z
members.idra   )rA   CmfListr   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   )rA   r   r   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rg   )rA   CmfActiveEntityFilterr   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_tagra   Trl   )rA   r   r   r   r   r   rs   )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\   rn   zparent_task.nameu   Укажите from_idTr   u   Укажите to_idu(   Не могу перместить из r3   r   rI   u5   Нельзя переместить задачу в "u/   ", так как она находится в ""u&   Не могу перместить в )rr   rF   r   Zget_cls_by_tuuid_strrA   r   r   r   r   r   rn   r   r*   r   r   r   r3   )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      #№@ORr3   ILIKEaliasz%"z"%ro   T)lstriprA   ZCmfTagr   r3   rE   r   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   rA   ZCmfLogicTyper   r3   rE   r   )r$   r   r   r   ltr   r   r   _process_logic_type_token%  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   F)#   №@r      
user_local==Tr   r3   r   %Zloginr   )	
startswithr   r   rA   	CmfPersonr   r3   rE   rR   )r$   r   r   r   _filterpersonr   r   r   _process_responsible_tokenJ  s*    

z"CmfTask._process_responsible_tokenu   Январьu   Февральu   Мартu   Апрельu   Майu   Июньu   Июльu   Августu   Сентябрьu   Октябрьu   Ноябрьu   Декабрь)r(   rw         r            	   r         c                 C   s0   |  }|  }|d| d| d| fkS )Nr   r   r   )lower)r$   stringZhashtagr   r   r   hashtag_cmpv  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   )monthsr   )r  r   )_monthsitemsr   rX   r3   re   r   rK   r   r   replacemonthr   r]   r*   ZyearrL   )	r$   r   r   r   Z	month_idxr  r]   r   rL   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_namer`   r   r   r   r     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r| jr| jjdgd | jr| jjs| jpd | _n,| jr| jjdsd| jpd | _n| jsd| _d S )N z.,;:?!r$   Fr(   .c                 S   s   | j jS rh   )r3   r*   )r   r   r   r   <lambda>      z)CmfTask._calc_from_name.<locals>.<lambda>r7   Tr   r;   r   add_object_typera   1ZEpiczEpic zEpic 1)r1   Zglobal_settingsZshow_task_title_tagsr*   r3   rE   r]   r   rR   r#   	enumerater   striplocalscopyr   r   r   r   extendr   rstripsortedjoinrj   rX   r@   rr   r  r   )r$   r   Zname_tags_boundr3   Zname_tokensZundefined_tokensidxtokenr   r   Zneed_dotZdot_token_posr   r   r   r   r    sj    



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)r   gantt)r   ztask.gantt_subprojectr   z
pfeed.basepost)r   rE   rX   rj   ui_view_formui_namer   r`   r   r   r   _calc_ui_view_form  s    


zCmfTask._calc_ui_view_formc              	   C   sp  | 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 t R | js2tj| d }|| _| j	jsF| jjrb|| j_| j	| j_	| j  W 5 Q R X d S )NrB   r   r   rk   u_   task.epic, task.subproject и task.gantt_project не могут быть без ПроектаTr   r   zparent.main_gantt_projectz&parent.main_gantt_project.logic_prefixrp   rj   rk   z.DEV: _calc_gantt_task if not cur_gantt_project)r@   r*   r+   rj   rF   rm   rA   CmfGanttTaskcreate_gantt_taskrn   rr   rq   rp   rU   cmfutildisable_aclrE   rs   )r$   Zcur_gantt_projectrm   r   r   r   _calc_gantt_task  s@    






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)	rY   rE   rm   Ztask_status_is_changed_hookre   rd   r]   rL   Ztask_plan_dates_is_changed_hookr`   r   r   r   r   >  s    z$CmfTask._calc_op_gantt_task_countersc                 C   s$   | j r| j jjdkrd S |   d S rQ   )r@   r*   r+   Z_check_simple_permr`   r   r   r   check_simple_permG  s    zCmfTask.check_simple_permc                 C   s  | j js,| jdkr,|  }|jr,tddd | jr@| jjjdkrDd S | j	sT| jsTd S | jjrl| jj
d| d | jjr| 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r6| jjr6| jj
d| d | jjsT| jjsT| jjrd| jj
d| d | j jr| j jr| jj
d| d | jj
d| d | jjr| jj
d| d d S )Nr:   ud   Редактирование запрещено, так как задача в статусе CLOSEDTr   rB   zPPP-TSK-CREATEr   zPPP-TSK-ASSIGNzPPP-TSK-ASSIGNABLE)userrg   zPPP-TSK-CLOSE)rE   zPPP-TSK-EDITzPPP-TSK-MODIFY-OWNERzPPP-TSK-MOVEzPPP-TSK-RESOLVEzPPP-TSK-TRANSITIONzPPP-VW-MANAGE)rY   rE   r>   r   Zsl_readonly_closed_taskrF   r@   r*   r+   rX   check_project_role_accessrR   re   keysZproject_perm_allow_fieldsr   rT   rn   r\   
spectators)r$   r   Zchanged_fieldsZallowed_fieldr   r   r   _check_project_permM  sF    

zCmfTask._check_project_permc                 C   sb   | j s^| jjr^| jjs^| jr^tjjdd| jgddddgdddgggdD ]}| j|_|	  qHdS )u  
        При создании задачи - у нее не указывается имя сразу, но уже создается нотифай с пустым именем.
        Но нотифай по str-полям когда пусто меняется на имя - не создается и не обновляет информацию в созданных нотифаях.
        Поэтому мы сделал этот ХАК с нарушением слоёв.
        Zobj_idr   r   ry   r	  Nr   )
rX   r3   rE   re   rA   Z	CmfNotifyr   r   ry   rs   )r$   Ztask_notifyr   r   r   _update_empty_task_notify  s    
z!CmfTask._update_empty_task_notifyc                 C   s   | j r| j jjdks| j jr d S d}| jjrZt| jjt| jj D ]}|j	dkrD|}qDqD|sbd S t| j}|D ]D}||kr~qp|j	dkrqp|j
dkrqp|j
dkrtd | j| qpd S )NrB   Flist.agile_sprintr:   r   u\   Внимание! Задача перемещена из Запущенного списка)r@   r*   r+   Ztask_allow_multiple_sprintsr\   rE   r5   rd   re   rj   r>   rF   r   )r$   Z
add_sprintappended_listZcurrent_sprintsZ
cur_sprintr   r   r   _calc_sprints  s*    




zCmfTask._calc_sprintsc              '      s`   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 d!d"d#d$d%d&d'g'}t   | S )(Nzparent.project_typezparent.auto_alarm_datezparent.logic_prefixzparent.activity.prefixz"parent.task_allow_multiple_sprintsrn   parent_task.logic_prefixr}   ztags.tag_categoryzlists.plan_start_datezlists.plan_end_date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   Zcmf_modified_byr   Ztimetracker_historyhas_child_tasksr   r   rp   rm   op_gantt_task.actual_start_daterj   zcomponents.default_responsiblezcomponents.default_ownerz!scheme_wf.default_task_logic_typez$scheme_wf.default_subtask_logic_typezlists.default_task_logic_typezstatus.need_approve)r   r   )r$   rI   r   r   r   r     sR    *zCmfTask.save_preload_fieldsc                 O   s:   t j| d d| _| jdd t jj| df|| d S )Nr   Zapprove4Trl   Zapprove_started)rA   
CmfApproveZstart_approve_processr   rs   CmfEventdo_eventr$   r   r   r   r   r   start_approve  s    zCmfTask.start_approvec                 C   sR   |  dddg | jjj| _| jD ]}| j| q"| jdd tj	| d d S )Nzstatus.trans_approvedzstatus.trans_approved.status_toapprovers_forTrl   Zapprove_success_full)
rr   rY   Ztrans_approved	status_tor8  r   rs   rA   r4  r5  r$   Zapprover_forr   r   r   _approve_approved  s    
zCmfTask._approve_approvedc                 C   sR   |  dddg | jjj| _| jD ]}| j| q"| jdd tj	| d d S )Nzstatus.trans_rejectedzstatus.trans_rejected.status_tor8  Trl   Zapprove_rejected)
rr   rY   Ztrans_rejectedr9  r8  r   rs   rA   r4  r5  r:  r   r   r   _approve_rejected  s    
zCmfTask._approve_rejectedc                 C   s8   |  dddg | jjj| _| jD ]}| j| q"d S )Nzstatus.trans_updatedzstatus.trans_updated.status_tor8  )rr   rY   Ztrans_updatedr9  r8  r   r:  r   r   r   _approve_updated  s    
zCmfTask._approve_updatedc                 K   sl   | d}| d}| d}tjj | |tjdd}|rL|jf d|i| | jtj tj	| d d S )Napprove_group
resolutionry   r   )rg   r>  ZapproverZapprove_typeZapprove_success_one)
r   rA   r3  r1   current_userZ_approve_oner8  r   r4  r5  )r$   r   r>  r?  ry   Zapprover   r   r   approve_one  s    



 zCmfTask.approve_onec                    s   dt _t j||S )NT)r1   TEXCOM_ENABLE_GROWCACHE_HACKr   create)r   r   r   r   r   r   rC    s    zCmfTask.createc           
   	      s^  | j r| jsdt_|   |   |   |   |   | 	  | 
  | jrx| jj rxt  |   W 5 Q R X tjj t_|   |   |   |   |   t j|ddi|S | jjr|   |   |    | !  | "  | j#jr8| j$r8t%| j#j&t%| j#j' D ]}|| j$krd | _$q| j$s| j#D ]}|j(dkrF|| _$ qfqF| j$s| j#D ]}|j(dkrt|| _$ qqt| j#jr| j$r| )dg | j$j(dkrt%| j#j't%| j#j& D ]}|j(dkr|| _$ qq| j$jr&| j$r&| j$| j#kr&| j#*| j$ | j+jr8| j+r8| j+j,j-dkr8| j+)dd	d
dddg | j+j.r| j+j.| j#kr| j#*| j+j. d| j+j.j d| j+j d}t/j0| |dd  | j+j&r8| j+j&j-dkr8| j+j&j.  | j+j&j.}|r8|| j#kr8| j#1| d|j d| j+j&j d}t/j0| |dd  | j#jrtj2st%| j#j't%| j#j& D ]0}|j3dkrbt4d|j d| j ddd qbt%| j#j&t%| j#j' D ]D}|j3dkrt4d|j d| j ddd |j3dkrt4d q| 5  | 6  | 7  | 8  |   |   | 9  | :  | j;jrj| j;dkrj| j(dkrjt4d| j; ddd | <  t j||}| jr| jjr| jj rt  |   W 5 Q R X | j+jr| =  | j>dkrt/j?@|  | j s| jrt/jAB|  | j#jrtCt/jDjE d D ]&}	tF| |	jrtCt/jGjE  qDq| jHrt| jHjrt| jHj( d!krttCt/jIjE | jHj&r| jHjr| jHj&j( d!krtCt/jIjE | j(jr| j(j&d!krd"| _J| jHjr| K  | jLjr
| j+r
tM| j+j,t/jNr
| j+O| jL | j3jr:| j3dkr:| PtjQjR | jSd"d# | jTrZ| j(d$krZt4d%dd |S )&NTemitFr,  	list.basezmain_list.logic_prefixrB   zdefault_list.plan_start_datezdefault_list.plan_end_datezdefault_list.ordernozdefault_list.perm_has_aclzdefault_list.sys_typezdefault_list.logic_prefixuU   SimpleLogic: Задача добавлена в Cписок по умолчанию "   " проекта "r   rw   rx   uS   SimpleLogic: Задача удалена из Cписка по умолчанию "r:   uS   Нельзя добавить задачу в Завершенный список "z" - "r   uU   Нельзя удалить задачу из Завершенного списка "r   uV   Внимание! Задача удалена из Запущенного списка)ru   r   r  r  r   u   Вид отображения uk    временно не поддерживается, используйте "task", "list", "post", "gantt"project.servicedesk)rY   r@   r   rR   r]   r   r   r   )priorityr  us   DEV: Недопустимое перемещение простой задачи в структуру дерева)UrX   r3   r1   rB  _calc_gantt_pathr$  rf   Z_calc_scheme_wfZ_calc_logic_type_calc_workflowZ_calc_statusrY   Zneed_approverU   r"  r#  r7  rH   rI   rJ   rK   Zhttp_client_date_hackr   r   r^   Z_calc_parent_logic_prefixr  r   rs   rE   r  r+  r   _calc_estimate_workr   r\   r   r5   re   rd   rj   rr   r   r@   r*   r+   default_listrA   r   r   Zimport_moder>   rF   r.  _calc_logic_type_change_guardr   !_calc_parent_task_has_child_tasksr   _calc_agile_story_pointsr  _calc_structural_listrv   parent_logic_prefixCmfSDeskSlaTriggertask_changed_hookZCmfSDeskSlaCycleZupdate_cycle_goalscmf_deferred_taskr   recalculate_cachegetattrr   rn   r   cache_child_tasks_count_update_actual_workr   r?   rB   Zhook_task_tags_changedZ_clear_notifyr   r   Z_update_opened_notifiesr}   )
r$   r   r   Zremoved_listlr-  	audit_msgZold_default_listZself_instanceZ
field_namer   r   r   rs     s    






"	
" 



$(
$zCmfTask.savec                 C   s   | j j  | j j| _| jr(| jj   | jr<| jj | j krF| j j| _ddg}| | | jsbd S | j j| j_tjj	dd| g|d}|D ] }|j | j kr| j |_ |
  qd S )Nr@   rm   rn   r   ro   )r@   rq   rU   rp   rn   rr   rm   rA   r   r   rs   rt   r   r   r    _change_parent_and_gantt_project  s     


z(CmfTask._change_parent_and_gantt_project)TEXKOM_db_deletec          
      O   s   |sd S d | _ | jdd ddd| gdd| gdd| gg}tjj|ddD ]}|j|d	|i| qHtjj| dd
D ]}|j|d	|i| qrtjj| dd
D ]}|j|d	|i| qtjj| ddD ]}d |_	|jdd qtj
jddd| gdd| ggddD ]}	|	j|d	|i| q d S )NTrl   r   ru   r   rp   rn   r   r   r\  )ru   r   )rp   r   out_linkin_link)rm   rs   rA   r   r   deleteZCmfShadowLinkCmfTaskCodeHistoryr   rp   CmfRelationOption)
r$   r\  r   r   r   Z
gantt_tasklinkr   ru   Zrelr   r   r   _delete_relations  s     &zCmfTask._delete_relationsc                    s   |  dddddg | js,| js,| jtjkr^| jr^| jjdr^t	
| j }r^|jd| d | jr|| jD ]}|j|| qj| j|| | jd	kr| j|| | j|| | j|| t j||}| jr| jj|| |S )
Nry   r!   rT   sdesk_sla_cyclesrj   CmfProject:zPPP-TSK-DELETEr   r   )rr   ry   r3   rT   r1   r@  r!   r*   r   r"  Zget_obj_by_idr'  re  r`  _delete_timetracker_historyrj   _delete_epics_subtasks_delete_subtasksrd  r   rm   )r$   r   r   projectZsdesk_sla_cycleresr   r   r   r`    s$    

zCmfTask.deletec                    sz   t  j||}| dg | jr.| | j ntjj| d d |   |	ddrv| j
dkrj| jf | n| jf | |S )Nrm   )ru   Zbaseline	recursiveFr   )r   restorerr   rm   Z_restore_child_objectrA   r   r!  _restore_timetracker_historyr   rj   _restore_epics_subtasks_restore_subtasks)r$   r   r   rk  r   r   r   rm    s    	
zCmfTask.restoreTrl  r\  c                O   s4   t jj| |d}|D ]}|j|||d| qd S )Nr~   r   rq  )rA   CmfTimeTrackerHistoryr   r`  )r$   rl  r\  r   r   tt_history_listtthr   r   r   rg    s    z#CmfTask._delete_timetracker_historyc                 C   s&   t jj| dd}|D ]}|  qd S )NTrr  )rA   rs  r   rm  )r$   rt  ru  r   r   r   rn    s    z$CmfTask._restore_timetracker_historyc                O   sF   t jj| |d}|D ],}t jj|j|dr|j|||d| qd S )Nr   r   )r   r   rq  )rA   r   r   r    r   r`  r$   rl  r\  r   r   
tasks_listru   r   r   r   rh  !  s    zCmfTask._delete_epics_subtasksc                 C   s*   t jj| dd}|D ]}|j|d qd S )NTrv  rl  rA   r   r   rm  r$   rl  rx  ru   r   r   r   ro  (  s    zCmfTask._restore_epics_subtasksc                O   s6   t jj| ||d}|D ]}|j|||d| qd S )N)rn   r   r	   rq  )rA   r   r   r`  rw  r   r   r   ri  -  s    zCmfTask._delete_subtasksc                 C   s*   t jj| dd}|D ]}|j|d qd S )NT)rn   r   ry  rz  r{  r   r   r   rp  2  s    zCmfTask._restore_subtasksc                    sL   |  ddg | jdkr6|r6|jdkr6tjj| |d t j|d|i|S )Nr@   rQ  rG  r   )commentr|  )rr   rQ  rz   rA   rR  rS  r   _comment_save_hook)r$   r|  r   r   r   r   r   r}  7  s    zCmfTask._comment_save_hookc           
         s   |sg }|sdg}|sg }|dddgddddggd	d
ddgd
dd ggg}|oT| d}| dd }	|r||sn|	s||dd|gg}|d
 |d t j|f||||d|S )Nr3   r>   !=r:   rj   INr,  rE  r   r   Ztrashr   r~   searchr   r@   object_fieldsr   rI   r   r   r   r   field_options_list
r   relation_field_namer  r   rI   r   Zfilter_by_projectr   r~   r  r   r   r   lists_options_list?  s6    

   zCmfTask.lists_options_listc           
         s   |sg }|sdg}|sg }|dddgg}|o4| d}| dd }	|r\|sN|	s\|dd|gg}|d |d	 t j|f||||d
|S )Nr3   rj   r   zlist.releaser~   r  r   r   r@   r  r  r  r   r   r   releases_options_listZ  s.    

   zCmfTask.releases_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   rj   r,  rE  r  )r   r  r   r  r  r   rI   r   r   r   r   r   main_list_options_listq  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   rj   r   r   r  r   r   r  r  r   r   r   parent_task_options_list  s    z CmfTask.parent_task_options_listc                    sX   |sg }|dddgg}|r:| dd r:|dd| dgg}t j|f||||d|S )NZ
cmf_hiddenr   Fr~   r  r  r  r   r   r   components_options_list  s    zCmfTask.components_options_listc                    s   |dkr$| j |f||||d|S |dkrH| j|f||||d|S |dkrl| j|f||||d|S |dkr| j|f||||d|S |dkr| j|f||||d|S t j|f||||d|S )Nr\   r  )Zfix_versionsZaffected_versionsr   rn   rS   )r  r  r  r  r  r   r  r  r   r   r   r    s<         zCmfTask.field_options_list)system_taskc              	   K   sR  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|}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>   rY   )r   rI   r:   zAuto task reopenu'   Переоткрываем задачу)r@   ry   NZdefault_projectra   zNew auto task for r<   z
) project 
r	  )r   r3   ry   rR   rT   rH  r@   r=   )printhashlibZmd5encodeZ	hexdigestrA   r   r   r>   r   r   rY   rD   r_   r   rs   r   rH   rI   r   Zget_obj_by_tuuid_strr3   r   r   r*   )r3   ry   Z
extra_textrH  responsible_idZcmf_owner_idr~   _kwargsZtask_keyZ	task_hashZ	task_coderu   rR   rT   r@   r   r   r   	auto_task  sD    


  
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)
rA   r   r   r   dictr   r   r  r   r*   )r   r   r   r   ZpersonsZin_progress_filterZcount_filterr   resultZin_progress_countr  r   r   r   get_responsibles_tasks_count  s    

z$CmfTask.get_responsibles_tasks_countc                 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 rh   )r[   rE   r@   rj   r   rb   r\   r   r   Z	scheme_wfZcalc_workflowr`   r   r   r   rJ    s$    	zCmfTask._calc_workflowc                 C   s\   | j jsd S | jdkr6| jjr6| jjdkr6tddd | jjdkrX| jdkrXtddd d S )Nrk   uL   Нельзя изменить тип задачи на Гант-проектTr   u?   Нельзя изменить тип у Гант-проекта)r   rE   rj   re   rF   r`   r   r   r   rM    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   )rn   rE   r   rj   re   _calc_cache_branch_gantt_path_recalc_gantt_pathr`   r   r   r   rI    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   r   r   rj   rp   r   r   cache_branch_gantt_pathrn   r1  )rn   rI   Frl   r(   )rn   r_count)rF   rr   r   r   rp   rj   rA   r   r   r1  r  r  rd   re   rs   r  )r$   rn   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| _| jjdd	 | jD krtd
| j
 d| jj
 ddd d S )Nr  z#parent_task.cache_branch_gantt_pathr/  zODEV: WARNING: _calc_cache_branch_gantt_path: if cache_branch_gantt_path is NoneTr   )r   r   r3   rj   c                 S   s   g | ]}|d  qS r   r   )r   tr   r   r   r   ^  s     z9CmfTask._calc_cache_branch_gantt_path.<locals>.<listcomp>ul   Произошло зацикливание! Попытка добавить дочернюю задачу "uK   ", которая уже является родительской для "r   )rj   rU   r1  r  rr   rn   r*   rF   r   r   r3   )r$   rn   r  r   r   r   r  F  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_tasksTrl   rn   r   r   r~  r   F)rn   rE   r   rr   r1  r  rs   re   rA   r   r   r   )r$   Zhave_childsr   r   r   rN  c  s    
$
z)CmfTask._calc_parent_task_has_child_tasksc                 C   s  | j jsd S d }| ddg | j r| j jr| j jjr| j jj}| j jj}|r|ddddddg | j| d	|j d
}t	j
| |dd  nt|jr| j|kr|j| jkr|jddddddg | j|j d|jj d|j d}t	j
| |dd  | j jr| j j}|ddg |jr|jjr|jj}|jj}|r||kr| j| d|j d}t	j
| |dd  n\|jr| j|kr|j| jkr| j|j d|jj d|j d}t	j
| |dd  d S )Nr|   z0responsible.primary_role.structural_project_listr]   rL   ZordernoZperm_has_aclr   rj   uU   SimpleLogic: Задача добавлена в структурный список "uG   " т.к. он указан в должности исполнителяrw   rx   u>   SimpleLogic: Задача добавлена в список "rF  u   " т.к. он является Структурным проектом Главной роли ответственного по задачеz,primary_role.structural_project.default_listz$primary_role.structural_project_listuS   SimpleLogic: Задача убрана из структурного списка "uX   " т.к. он указан в должности прошлого исполнителяu<   SimpleLogic: Задача удалена из списка "u   " т.к. он является Структурным проектом Главной роли прошлого ответственного по задаче)rR   rE   rr   r   r   Zstructural_project_listr\   r   r3   rA   r   rs   rL  r@   re   r   )r$   Zappend_structural_project_listr   rZ  Zold_responsibleZremove_structural_project_listr   r   r   rP  x  s^    


zCmfTask._calc_structural_listc                 C   sl   | j s| jjs| jjd ksd S | jrht| jjtjrh| dg | jjd krh| jj	jd k	rh| jj	| _d S d S )Nz!parent.default_agile_story_points)
rX   r@   rE   Zagile_story_pointsr*   r?   rA   rB   rr   Zdefault_agile_story_pointsr`   r   r   r   rO    s    
z CmfTask._calc_agile_story_pointsc                 C   s   | j jsd S | jr8| jj  | j | jjkr8tddd | jddg | jjr`| jj| j jkr|| jj	s|| j | j_| j
  d S )Nu   DEV: FATAL: нельзя изменять поле estimate_work, когда существует базовый Гант-планTr   
sched_work
const_work)Zestimate_workrE   Zbp_gantt_taskr  rU   rF   rm   rr   re   r  rs   r`   r   r   r   rK    s    
zCmfTask._calc_estimate_workc                 C   s   |  dg | jf |}tj }| jd |d |_| jjrV|jpHd| jjj	 |_|j
dd tj|d| j d| j dd	
  |jj	S )
u    Создание задачи из шаблона
        :param self: Шаблон документа
        :param params: Параметры для шаблона
        :return: Идентификатор новой задачи
        tmplt_document.textr;   z%d.%m.%Yr	  Trl   u0   Задача создана из шаблона rw   rx   )rr   create_from_templater   rK   r3   strftimetmplt_documentr   ry   r*   rs   rA   r   r   r   )r$   paramsnew_taskZnow_dater   r   r   create_task_from_template  s    
$z!CmfTask.create_task_from_templatec                    s&   | j dgd | jdkrdS t  S )uB    Шаблон уведомлений для разных workflow rj   ra   ztask.ticketzhelpdesk_mail_notification.html)rr   rj   r   +get_default_mail_notification_template_namer`   r   r   r   r    s    
z3CmfTask.get_default_mail_notification_template_name   Добавленоc                 C   s   t jj| |||||dS )N)Z
start_daterT   )rA   r   Ztimetracker_task_change_time)r$   Z
time_spentZremaining_estimatery   daterT   r   r   r   timetracker_change_time  s    
  zCmfTask.timetracker_change_time)	only_oncer  c                 K   s   t j|  d S rh   )rA   r   _recalculate_codes)r!   r  r   r   r   recalculate_codes_celery  s    z CmfTask.recalculate_codes_celeryc                 C   st   d}d}t jjdd| gddg||| gdd}||7 }|s>d S |D ]$}|jsNqB|jdd |jdd	 qBt  qd S )
Nr      r   r   r   T)r   rI   slicer   )from_recalculaterl   )rA   r   r   r   
_calc_coders   Zcommit_with_event)r!   r   limitZ
task_sliceru   r   r   r   r    s"    
zCmfTask._recalculate_codesc              	      sP  t  < tjj| d}|s4td W 5 Q R  dS td|  tjj|dgd}tdt|  dd	  t	| fd
dd}d}|D ]}|d7 }td|  |rtj
j|dD ]}|  q|jjdd  d| }tj
jdd|gddr.td| d |d7 }|jjdd  d| }q||_|jdd qW 5 Q R X dS )u  
            Метод для ручного запуска.
            Пересчитает номера в кодах задач начиная с единицы.
            ! Прошлые коды задач не сохраняются
            ! Пошлые коды задач удаляются
            Если код занят задачей из другого проекта - он пропусается
        r  u   Проект не найден!NuY   Удаляем историю выдачи кодов задачам из проекта r   )r   rI   u   Всего задач: c                 S   s   z
t | W S    Y dS X d S )Nr   )r"   )r   r   r   r   tryint$	  s    
z:CmfTask.reindex_project_tasks_code_numbers.<locals>.tryintc                    s    | j jdd S )Nr   rw   )r   r*   
rpartition)r  r  r   r   r  +	  r  z<CmfTask.reindex_project_tasks_code_numbers.<locals>.<lambda>r  r   r(   u'   Обрабатываем задачу: )ru   r   r   Tr]  u   Код u    занятrl   )r"  Zdisable_notifyrA   rB   r   r  r   r   r   r  ra  r`  r   r*   r  r    rs   )
project_idZwith_history_deleterj  	task_listr   ru   ZhistZnew_coder   r  r   "reindex_project_tasks_code_numbers	  s0    	
z*CmfTask.reindex_project_tasks_code_numbers<   )r  Z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   r   rW  )rj   rI   r(   rn   r   r   zUpdate cache_members_count z -> r;   Trl   )Znode_idZelements_countztree-node-count-changes-ztree-node-count-changeszRecalculate r  z lists caches)rA   r   r   r  rW  r1   r2   r   rs   r*   Zcmf_emit_event)r  r   Ztotal_countZ
calc_countZcmf_epicZ
real_countZ
event_datar   r   r   rU  ?	  s     
 zCmfTask.recalculate_cache	recursion)returnc             	      sX   t  }| dddddddg | jr<|| jj|d d	}t j|d
|i||S )Nzfollowers.personzfollowers.person.cmf_deletedzfollowers.person.does_not_workzfollowers.notify_volumezfollowers.follow_childrenr}   rn   r(   r  r  )r5   rr   rn   unionget_all_followersr   )r$   r  r   r   rk  r   r   r   r  X	  s    
   zCmfTask.get_all_followersc                   sN  d }|j r&|j jdkr&|j jdkr&| j|jddgd}	|	jr&|	jjr&|	jj}|r&|j j	}
|j
}|j}t|p|g }|d |
r|
dg }|D ]}||dg  q| |}| j||d	|d
|}|r"|jrd|j
 |_
|
|_||_||_|js"ttdr"tj|}|S |sJt j||||||d|S d S )NrB   rG  request_typezrequest_type.ui_form_view_innerr   cmf_deletedZui_group_fieldsrI   Zsimple)full_fields_loadZmapperr   zDELETED CmfAutomationUiForm)rI   tmp_objtmp_is_public_formtmp_ui_view_formtmp_include_deleted)r@   r+   rj   r   r   r  Zui_form_view_innerui_form_jsonrU   r*   r3   r   r5   r   updateZ_build_load_planZ_getr  ui_form_nameui_form_coderc   rA   r  Zui_get_hookr   _ui_form_get)r   rI   r  r  r  r  r   r   Zui_formrg   r  r  r  Z
fields_setgroupsZ
group_datar  r   r   r   r   r  `	  sF    


 zCmfTask._ui_form_get)copy_attachmentscopy_relationscopy_subtaskscopy_all)r3   r  r  r  r  c                   s  |rd}d}d}|  dddddddd	d
dg
 t j|||d|}|jjdd|_tjjdd}	|rdd|	gg}
tj	j
|
dd| gg dgdD ]}| }||_|  qtj	j
|
dd| gg dgdD ]}| }||_|  q| jstj	| ||	d  | | d|_|S )NTz**zattachments.urlr   r\   Z	executorsr)  zattachments.url_previewzattachments.url_preview_imgop_gantt_task.actual_workr   )r3   r  r   )r   zsystem.cloner   relation_typer~  r^  r   ro   r_  )r^  r_  r  )rr   r   r  r   r   rY   rA   ZCmfRelationTyper   rb  r   cloner^  rs   r_  Zis_template_clone_op_gantt_taskrX   )r$   r3   r  r  r  r  r   r   new_objZ
clone_typer   ZrelationZnew_relationr   r   r   r  	  s@       




zCmfTask.copyc                 C   s6   |j dg |j  |_ d|j _||j _|  d S )Nr   r   )rm   rr   r  actual_workru   rs   )r$   r  r   r   r   r  	  s
    zCmfTask._clone_op_gantt_taskc                    s2   |  dg | jdkr*d| j d| j S t jS )Nrj   r   z	/project/r  )rr   rj   r  r   r   hrefr`   r   r   r   r  	  s    
zCmfTask.hrefc           	      K   sz   t t}d}d}| j|dddg|| |d | gd}|D ]"}|jD ]}||j  d7  < qDq:t||k rlqv|d7 }q|S )Nr   i  z--r   zlists.idr(   )r   rI   r  )r   r"   r   r\   r   r   )	r   r   r  r  ZpageZ	page_sizer  ru   Zlist_r   r   r   count_tasks_by_lists	  s      

zCmfTask.count_tasks_by_listsc                 C   s   | j r| j jds| jS | dddg | jddg | jrL| jj  | j r| j jdr| jj	r| jr| jjr| jj
jd | jjj S | jj
jS )Nrf  zroot_parent.task_code_prefix+root_parent.task_code_use_logic_type_prefixzlogic_type.obj_code_prefixtask_code_use_logic_type_prefixtask_code_prefixr   )r!   r*   r   Zcode_prefixrr   r   r   Zobj_code_prefixrU   r  r  r`   r   r   r   get_code_prefix	  s    zCmfTask.get_code_prefixc              
      s   t   }dd l}| }d}d}tjjdd|gddr|d7 }t   }||k sjtd| d	| j d
| | }|dkr"td|dd| j d| j	 dd| j
ko| j d	 q"|S )Nr   i'  r   r   Tr]  r(   u8   Превышен лимит поиска кода limit=z model=uA   , возможно надо отключить def gen_code: passz$!!! --- gen_code::duration too long z.1fz sec, r<   z, r=   )r   gen_codetimerA   ra  r    AssertionErrorr+   r  r   rI   r   )r$   r   r  startr  r   Zdurationr   r   r   r  	  s    

 .zCmfTask.gen_codec                    sB  | j r| jjs| jjs|sd S | j s2t   d S | j rH| j drHd S d }d }| jrj| jjdrj| j}| jjr| jj	r| jj	j
jdr| jj	}|r|  }| j j| dr| j jd|dkr| j j}|rtjj|dstj|| |d}|  d| j_t   d S | jjr| j j|   ds| j j}| js~|r~tjj|ds~tj|| |d}|  d | _ t   d S | jjr>| dg | jr>| jj
jdr>| jjr>| j j|   ds>| j j}| js4|r4tjj|ds4tj|| |d}| jjr,||_|  t   d S )NzA-rf  r   r  )r   ru   rj  Tr  )r   r   rE   r   r   r  r   r!   r*   re   r   r  r  rA   ra  r    rs   rX   rr   r  r  )r$   r  rj  Zproject_oldZ
new_prefixZ	prev_codeZcode_historyr   r   r   r  	  sv    
.
$


zCmfTask._calc_coderI   r   c             	   O   sh   |sg }|sg }| j |||d|}g }|D ]4}z|  || W q. tk
r`   Y q.Y q.X q.|S )Nr  )r   Z_acl_check_readr   ZCmfPermissionError)r   rI   r   r   r   Zres_uncheckedrk  rr   r   r   public_list@
  s    zCmfTask.public_listc                    s   d|d< d|d< t  jf |S )NFZwith_parent_ownerZinherit_executors)r   all_relation_persons)r$   r   r   r   r   r  S
  s    zCmfTask.all_relation_personsc                 C   s<   | j j  | j jj}| | jj|  | | jj| d S rh   )rm   r  rU   r*   #_update_actual_work_for_all_parentsrn   re   rd   )r$   actual_work_timer   r   r   rX  [
  s    
zCmfTask._update_actual_workc                 C   sT   |sd S |j   |j j  |j  j|7  _|j jdk rBd|j _|j jdd d S )Nr   F)Z
user_input)rm   rU   r  rs   )r$   ru   r  r   r   r   r  a
  s    
z+CmfTask._update_actual_work_for_all_parentsc                 C   s   t | j d S rh   )rT  cron_celery_check_periodic)r   r   r   r   cron_check_periodicl
  s    zCmfTask.cron_check_periodicc                  O   s  t d ddddgdddggdd	d
ggddd gddtjjtjjdgg}tjj|dddddddddddddgdD ]^}|j	r|
 }t d|  |jjr|jj|_|jjdd|_|j  |j|_d |_d |_|  |  |jd
d qtt d|  |jdkr|jjdkrP|jj}|  |jr|j|jkr||_q|jjrd|jj|_|jr~|jjdd|_|jjdd|_|  qt|jjd krt|jjdd|_|jjdk r|j  |  qtd S )!Nz(Run CmfPerson.cron_celery_check_periodicr   zstatus.coder~  r   r>   r   period_create_newr   Tperiod_intervalperiod_next_datez<=r   r0  r[   r   period_clear_checkboxry   r  rZ   rD   ro   z6CmfPerson.cron_celery_check_periodic: create new task )r   rl   z2CmfPerson.cron_celery_check_periodic: reopen task )r:   r   r   ztox-checklist--checkedr	  pause)r1   r2   r   rK   r   r   rA   r   r   r  r  r  r   ry   r   r   rY   rD   r_   rZ   r  r  rs   Z_cacl_next_periodr>   r   r*   r  r  r   )_argsr  r   ru   r  Zold_deadliner   r   r   r  p
  sf    
      






z"CmfTask.cron_celery_check_periodicc                    sJ   |    |   |   |   |   |   |   t j|| d S rh   )	r   r   rN  rI  r$  r   rP  r   _save_importr6  r   r   r   r  
  s    zCmfTask._save_importcsvc              &      sd   |sTd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!d"d#d$d%d&g&}t  |||S )'Nr   r   r3   ry   Zresult_textzcmf_author.namezcmf_author.loginzcmf_owner.namezcmf_owner.loginzparent.namezworkflow.namezlogic_type.namezstatus.namer>   zcompany.namezresponsible.namezresponsible.loginzexecutors.namezexecutors.loginzspectators.namezspectators.loginz	tags.namezattachments.namezactivity.namez
lists.namezgit_repos.namezgit_branches.namezgit_merge_requests.namezgit_commits.namezrequest_type.namer2  z op_gantt_task.actual_finish_datezop_gantt_task.actual_durationzop_gantt_task.sched_start_datezop_gantt_task.sched_finish_datezop_gantt_task.sched_workzop_gantt_task.perform_workr  )r   export2file)r   rI   ZbqlZformat_filer   r   r   r  
  sF                        zCmfTask.export2file)NN)F)F)F)F)F)F)F)N)NNNNN)NNNNN)NNNN)NNNN)NNNN)NNNN)NNNNNN)N)r   )N)r  NN)F)N)F)NNr  )u__name__
__module____qualname__classmethodr   r   r%   r9   rP   rW   r^   rf   ri   rv   r   r   r   r   r   r   rC   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r  r   r  r  r$  r   r%  r*  r+  r.  r   r7  r;  r<  r=  rA  rC  rs   r[  rd  r`  rm  rg  rn  rh  ro  ri  rp  r}  r  r  r  r  r  r  staticmethodZ
celery_appru   r  r  rJ  rM  rI  r  r  rN  rP  rO  rK  r  r  r  r  r  r  rU  r5   r  r  strboolr  r  propertyr  r  r  r  r  r  r  rX  r  r  r  r  r  __classcell__r   r   r   r   r      sh  
$$-A 
	A2  G  
+
%
%

*
J7	7- 1

                                            
          +.9

,#&!M
K
r   c                   C   s
   t j S rh   )rA   r   r  r   r   r   r   r  
  r  r  )r   r  collectionsr   r   r  Zredis.exceptionsr,   Zwerkzeug.datastructuresr   Zdateutil.relativedeltar   Zcmf.includeZcmf.fields.base_fieldsr   Zmodules.task.fields.cmf_taskmodulesZ#modules.servicedesk.models.cmf_taskZservicedeskrA   Zcmf_taskZCmfTaskMixinru   rI   r   r)   ZHOOK_CRON_HOURLYr   r   r   r   r   <module>   sD   "                     ^