U
    {yd                    @   s   d dl Z 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mZ G d	d
 d
ejjjjZejdd  dS )    N)defaultdict)	timedelta)FileStorage)relativedelta)*)CmfTUUID)CmfActiveEntityc                       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 fd5d6Zd7d8 Zd9d: Zd;d< Z d=d> Z!dd?d@Z"ddBdCZ#ddDdEZ$ddFdGZ%dHdIdJdKdLdMdNdOdPdQdRdSdTZ&dUdV Z'ddWdXZ(dYdZ Z)dd[d\Z*d]d^ Z+d_d` Z,dadb Z-dcdd Z.dedf Z/ fdgdhZ0 fdidjZ1dkdl Z2 fdmdnZ3 fdodpZ4dqdr Z5dsdt Z6dudv Z7d fdwdx	Z8ed fdydz	Z9edd{d|Z:ed fd}d~	Z;ed fdd	Z<e=e>j?dddddZ@e=dddZAdd ZBdd ZCdd ZDdd ZEdddZFdddZGdd ZHdd ZIdd ZJdd ZKd fdd	ZLdd ZM fddZN fddZOdddZPe=e>j?ddddd ZQe=dd ZRe=dddZSe=e>j?dddddd ZTddeUd fddZVdd ZWdd ZXeddddddZYedd ZZeddddZ[eddddĄZ\dAdAdAdAdŜe]e^e^e^e^dƜ fddȄZ_ddʄ Z`ea fdd̄Zbeddd΄ZcddЄ Zd fdd҄Zed fddԄ	Zfeddd՜ddׄZgddل Zhddۄ Ziedd݄ Zje=e>j?ddddd߄ Zk fddZlede]d fddZm  ZnS )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-)sgetr   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j}d| j d| }| j d| d}|jj|dd}|  z2||rn||}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   id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   r:   +   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_listI   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 NrC   )responsiblerA   rF   r+   r,   loadr$   r   r   r   _calc_responsiblef   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 rR   )is_newrE   rF   statusdeadlineactivitylistsplan_start_daterM   r   _calc_alarm_daterA   r+   r,   Zauto_alarm_daterT   rQ   rL   set_nowrU   r   r   r   r]   n   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:
        NrZ   r   r   rJ   )rZ   rF   rW   rA   r[   is_nullhasattrrT   newoldr   _calc_activityload_fields)r$   Ztmp_activityobjr   r   r   rd      s:    


zCmfTask._calc_activityc                 C   s   d S Nr   rU   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
_tjj| j jdd| j
_ | j
j	dd tjjdd	| g|d
}|D ]$}|j | j kr| j |_ |	  qd S )Nlogic_prefixtask.gantt_projectTZ	only_datarA   op_gantt_taskrA   
is_operateparent_taskr   r   rJ   )rA   r`   rc   gantt_projectmain_gantt_projectrT   ro   re   ri   saverl   rB   CmfGanttBaselinegetr	   r   r$   rJ   Zchild_taskstaskr   r   r   _do_parent_is_changed   s2    "


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 )NrA   ri   rj   u   SimpleLogic: в задаче установлен проект равный проекту родительской задачи   rA   textZ	log_level	cmf_ownercmf_owner_assistantsrZ   root_parent_id8responsible.primary_role.structural_project.default_listz1responsible.primary_role.structural_project_forceu   SimpleLogic: Задача добавлена в Структурный проект Главной роли исполнителяu   SimpleLogic: Проект сменен, т.к. в Главной роли исполнителя указано менять проект)tree_parentrF   rS   ro   rA   	parent_idre   ri   save_preload_fieldsrB   
CmfCommentrs   rG   Z_node_parentprimary_rolestructural_projectZstructural_project_force)r$   Z	sl_reasonrA   Zstruct_projectZstruct_project_forcer   r   r   _HACK24052023_calc_parent   s`    


z!CmfTask._HACK24052023_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)rA   sys_typerJ   rj   )r   ri   rB   Z	CmfFolderru   rA   rU   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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 )NrC   ri   r   r   r	   ztask.subu2   У подзадач нельзя менять EpicTabortu@   У подзадач нельзя менять Подпроект)rW   r   r+   r,   re   ri   ro   rF   rT   r   rG   
subproject)r$   Ztmp_tree_parentr   r   r   _calc_parent_task9  s,    



zCmfTask._calc_parent_taskc                 C   s&   | j r
d S | jjsd S tj|  d S rg   )rW   rX   rF   rB   CmfTimeTrackerZtimetracker_task_change_statusrU   r   r   r   _calc_timetrackerU  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 rg   )rW   r   rF   rA   ro   	main_listZ_load_perm_fieldsr@   r+   rB   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 r*   r4   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   y  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 rg   )r[   r\   is_not_nullrM   rI   rJ   rK   rL   )r$   rO   rP   Zw_listr   r   r   rD     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[   rF   lenr\   rM   rE   r`   rG   rH   )r$   rO   rP   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   План сдвинут в соответствии с будильником)	rE   rF   r?   r\   rM   daysr+   rG   
_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[   rF   rW   rE   r\   rM   rD   r   r   r   _calc_op_gantt_task_countersr   rN   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 )
NrC   Tu~   SimpleLogic: Задача согласована автоматически, т.к. это Непроектная задачаry   rz   u   SimpleLogic: Задача согласована автоматически, т.к. согласование отключено в Fu   SimpleLogic: Выполнен сброс согласования, т.к. сменился Постановщик или Проектu   SimpleLogic: Задача согласована автоматически, т.к. постановщик - руководитель.)rW   approvedrF   r|   rA   r+   r,   rB   r   rs   _get_sl_optionssl_task_need_approveZsl_controller_strrT   r*   r2   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|   r}   )r6   r   
get_ownersre   r[   addr|   r}   rF   rc   rb   r   )r$   r   r   ZownersZlstownerr   r   r   r   6  s    


zCmfTask.get_ownersc                    s&   | j r
d S | jdkrd S t   d S )Nr;   )waiting_forr?   r   _calc_waiting_forrU   r   r   r   r   I  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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}|s| jjddds| j j| jdk}|r.| j jjdkr*| jp&|| _| jst| j|krt|sP|| _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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 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importFrC   T	IN_REVIEWZapprove2Zapprove1_reviewu[   Только Владелец проекта может согласовать задачуr   r   open)status_coderaise_error)r   IN_PROGRESSZapprove3_notassigneduh   SimpleLogic: Задачу переключили на Постановщика/Руководителя(u   ), т.к. не указан Будильник. Установите будильник, чтобы задача отобразилась у Исполнителяry   rz   uM   SimpleLogic: Задачу переключили на Исполнителя(u   ), т.к. указан Будильник.Установите будильник, чтобы задача отобразилась у Исполнителяr>   r;   )r   u   Спасибо! Статус установлен в "Подтверждение закрытия", для проверки постановщиком или руководителем проектаu,   Спасибо! Задача закрыта.u   Спасибо! Статус изменен на «Закрыто» т.к установлен флаг «Без подтверждения».uO   SimpleLogic: Задачу переключили на Постановщика(u   ), т.к. статус=''r   uT   Нельзя брать в работу несогласованную задачу.um   Внимание! Вы взяли задачу без согласования с руководителем.u^   SimpleLogic: waiting_for  установлен т.к. статус снижен в in_progressui   SimpleLogic: waiting_for установлен т.к. статус перешел из open в in_progressu[   SimpleLogic: будильник установлен т.к. статус сменен на ))rX   rF   r   rS   r|   rA   rE   r   osenvironru   r   r+   r,   rT   rb   Zstatus_typeapprove_forapprove_for_placeZsl_only_owner_approver   r2   r   r   rG   rc   r`   rW   r   workflowget_default_statusrB   r   r4   rs   Zsl_task_only_owner_closeZ
no_controlcurrent_userr^   rL   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_logicQ  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   rF   rA   rE   rW   rY   r   Zsl_deadline_shiftdatetimer   rL   timezoneutccmf_created_atager|   r2   r   r+   )r$   r   Z
days_shiftshiftrL   r   r   r   r   Q  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 Nr*   z
members.idr_   )rB   CmfListru   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   )rB   r   ru   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   )rB   CmfActiveEntityFilterru   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_   Trk   )rB   r   ru   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[   ro   zparent_task.nameu   Укажите from_idTr   u   Укажите to_idu(   Не могу перместить из r4   )r*   rJ   u5   Нельзя переместить задачу в "u/   ", так как она находится в ""u&   Не могу перместить в )re   rG   r   Zget_cls_by_tuuid_strrB   r   r   r   r   r	   ro   r*   r+   r   r   ru   r4   )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      #№@ORr4   ILIKEaliasz%"z"%rp   T)lstriprB   ZCmfTagru   r4   rF   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   rB   ZCmfLogicTyperu   r4   rF   
logic_type)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   r4   r   %Zloginr   )	
startswithr   r   rB   	CmfPersonru   r4   rF   rS   )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(   ry         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   rW   r4   rc   r   rL   r   r   replacemonthr   r\   r+   ZyearrM   )	r$   r   r   r   Z	month_idxr  r\   r   rM   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_namerU   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sd| jpd | _n| jsd| _d S )N z.,;:?!r$   Fr(   .c                 S   s   | j jS rg   )r4   r+   )r   r   r   r   <lambda>      z)CmfTask._calc_from_name.<locals>.<lambda>r8   Tr   r<   r   ZEpiczEpic 1zEpic 1)r2   Zglobal_settingsZshow_task_title_tagsr+   r4   rF   r\   r   rS   r#   	enumerater   striplocalscopyr   r   r   r   extendr   rstripsortedjoinri   rW   r   )r$   r   Zname_tags_boundr4   Zname_tokensZundefined_tokensidxtokenr   r   Zneed_dotZdot_token_posr   r   r   r   r	    sb    



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   rF   rW   ri   ui_view_formui_namer   rU   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 )NrC   r   r   rj   u_   task.epic, task.subproject и task.gantt_project не могут быть без ПроектаTr   r   zparent.main_gantt_projectz&parent.main_gantt_project.logic_prefixrq   ri   rj   z.DEV: _calc_gantt_task if not cur_gantt_projectrA   )rn   rA   rJ   )rA   r+   r,   ri   rG   rl   rB   CmfGanttTaskZcreate_gantt_taskro   re   rr   rq   rT   rW   rt   rn   rs   ru   rF   )r$   Zcur_gantt_projectZop_gantt_baselineop_baselinerl   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)	rX   rF   rl   Ztask_status_is_changed_hookrc   rb   r\   rM   Ztask_plan_dates_is_changed_hookrU   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 rR   )rA   r+   r,   Z_check_simple_permrU   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 )NrC   zPPP-TSK-CREATEr   zPPP-TSK-ASSIGNzPPP-TSK-ASSIGNABLE)userrf   r;   zPPP-TSK-CLOSET)rF   zPPP-TSK-EDITzPPP-TSK-MODIFY-OWNERzPPP-TSK-MOVEzPPP-TSK-RESOLVEzPPP-TSK-TRANSITIONzPPP-VW-MANAGE)rA   r+   r,   rW   rF   check_project_role_accessrS   r?   rc   keysZproject_perm_allow_fieldsr   r|   ro   r[   rX   
spectators)r$   Zchanged_fieldsZallowed_fieldr   r   r   _check_project_perm0  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.prefixro   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   cmf_modified_byr   Ztimetracker_historyhas_child_tasksr   r   rq   rl   op_gantt_task.actual_start_dateri   )r   r   )r$   rJ   r   r   r   r   c  sD    "zCmfTask.save_preload_fieldsc           
         s  | j jr|   |   |   |   | jjrd| jrdt| jj	t| jj
 D ]}|| jkrNd | _qN| js| jD ]}|jdkrp|| _ qqp| js| jD ]}|jdkr|| _ qq| jjr| jr| dg | jjdkrt| 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rP| jrP| jjjdkrP| 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j| |dd  | jj	rP| jj	jdkrP| jj	j  | jj	j}|rP|| jkrP| 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rrtjsrtd|j  d| j  ddd qr|   |   |   |   |   |    | !  | j"jr| j"dkr| jdkrtd| j" ddd | #  t$ j||}| jjrD| %  | j&dkr\tj'(|  | jjrrt)tj*j+ dD ]&}	t,| |	jrvt)tj-j+  qqv| j.r| j.jr| j.j dkrt)tj/j+ | j.j	r| j.jr| j.j	j dkrt)tj/j+ | j.jr| 0  | j1jrF| jrFt2| jjtj3rF| j4| j1 | jjrv| jdkrv| 5tj6j7 | j8dd | j9r| jdkrtd dd |S )!Nlist.agile_sprint	list.basezmain_list.logic_prefixrC   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   ry   rz   uS   SimpleLogic: Задача удалена из Cписка по умолчанию "r;   uM   Нельзя добавить задачу в Закрытый список "z" - "Tr   )rw   r   r  r  r   u   Вид отображения uk    временно не поддерживается, используйте "task", "list", "post", "gantt"project.servicedesk)rX   rA   r   rS   r\   r   r   r   )priorityr  us   DEV: Недопустимое перемещение простой задачи в структуру дерева):r4   rF   r	  r   _calc_estimate_workr   r[   r   r6   rc   rb   ri   re   r   rA   r+   r,   default_listrB   r   rs   rT   r   r?   r2   Zimport_moderG   _calc_logic_type_change_guardr   !_calc_parent_task_has_child_tasks_calc_gantt_pathr"  r   _calc_agile_story_pointsr  _calc_structural_listr   rx   parent_logic_prefixCmfSDeskSlaTriggertask_changed_hookcmf_deferred_taskr   recalculate_cachegetattrr   ro   r	   _update_actual_workr   r@   rC   Zhook_task_tags_changedZ_clear_notifyr   r*   Z_update_opened_notifiesr   )
r$   r   r   Zremoved_listlZappended_list	audit_msgZold_default_listZself_instance
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	| j jdd| j_ tj
jdd| g|d}|D ] }|j | j kr| j |_ |  qd S )NrA   rl   Trm   ro   r   rp   )rA   rr   rT   rq   ro   re   rl   rB   rt   ru   r	   r   rs   rv   r   r   r    _change_parent_and_gantt_project
  s"    


z(CmfTask._change_parent_and_gantt_projectc                    s   |  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rv| jD ]}|  qh|   t j||}| jr| jj|| | jdkr|   |   |S )	Nr{   r~   r|   sdesk_sla_cyclesCmfProject:zPPP-TSK-DELETEr   r   )re   r{   r4   r|   r2   r   r~   r+   r   cmfutilZget_obj_by_idr%  rE  delete_delete_timetracker_historyr   rl   ri   _delete_epics_subtasks_delete_subtasks)r$   r   r   projectZsdesk_sla_cycleresr   r   r   rH  "  s"    


zCmfTask.deletec                    sr   t  j||}| dg tjj| dd}tjj| jddd tt	 fdd|}t
|dkrn| |d  |S )	Nrq   T)rw   r   )rA   rn   r   c                    s   | j j jjkS rg   )r   r+   r*   )Zg_taskr!  r   r   r  @  r  z!CmfTask.restore.<locals>.<lambda>r(   r   )r   restorere   rB   r   r   rt   ru   rq   r   r   Z_restore_child_object)r$   r   r   rM  Zrelated_gantt_tasksZop_gantt_tasksr   rN  r   rO  :  s    zCmfTask.restorec                 C   s$   t jj| d}|D ]}|  qd S )N)r   )rB   ZCmfTimeTrackerHistoryr   rH  )r$   Ztt_history_listZtthr   r   r   rI  G  s    z#CmfTask._delete_timetracker_historyc                 C   s(   t jj| d}|D ]}|jdd qd S )N)r   T	recursiverB   r	   r   rH  r$   Z
tasks_listrw   r   r   r   rJ  L  s    zCmfTask._delete_epics_subtasksc                 C   s(   t jj| d}|D ]}|jdd qd S )N)ro   TrP  rR  rS  r   r   r   rK  Q  s    zCmfTask._delete_subtasksc                    s>   |  ddg | jdkr(tjj| |d t j|d|i|S )NrA   r:  r1  )commentrT  )re   r:  rB   r;  r<  r   _comment_save_hook)r$   rT  r   r   r   r   r   rU  V  s    
zCmfTask._comment_save_hookc                    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 )Nr4   r?   !=r;   r   r   Ztrashr   r   searchr   rA   object_fieldsr   rJ   r   )ru   r   r   field_options_list)r   relation_field_namerY  r   rJ   r   r   r   r   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   ri   r.  r/  rX  )ru   r\  r   r[  rY  r   rJ   r   r   r   r   r   main_list_options_listt  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   rW  r   ri   r   r   rX  )ru   r   rZ  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[   rX  r   ro   )r\  r^  r_  r   rZ  r]  r   r   r   rZ    s*        zCmfTask.field_options_listT)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?   rX   )r   rJ   r;   zAuto task reopenu'   Переоткрываем задачу)rA   r{   NZdefault_projectr_   zNew auto task for r=   z
) project 
r
  )r   r4   r{   rS   r|   r2  rA   r>   )printhashlibZmd5encodeZ	hexdigestrB   r	   ru   r?   r   r   rX   rE   r^   r   rs   r   rI   rJ   r   Zget_obj_by_tuuid_strr4   r   r*   r+   )r4   r{   Z
extra_textr2  responsible_idZcmf_owner_idr   _kwargsZtask_keyZ	task_hashZ	task_coderw   rS   r|   rA   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   rf  )Zin_progresscount)
rB   r   r   r*   dictr	   r   ri  r   r+   )r   r   r   r   personsZin_progress_filterZcount_filterr   resultZin_progress_countri  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   rS   	executorsr   Tc                 S   s   g | ]}|j jqS r   )r*   r+   )r   rf   r   r   r   r     s     z%CmfTask.notify_os.<locals>.<listcomp>F)re   r?   rc   r   r*   rS   rn  )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 rg   )rZ   rF   rA   ri   r   r`   r[   r   r   Z	scheme_wfZcalc_workflowrU   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 )
Nr   rj   uL   Нельзя изменить тип задачи на Гант-проектTr   u?   Нельзя изменить тип у Гант-проектаuI   У Подпроекта больше нельзя изменять типr   uP   Тип Епик можно поменять только на Подпроект)r   rF   ri   rc   rG   rU   r   r   r   r5    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   )ro   rF   r   ri   rc   _calc_cache_branch_gantt_path_recalc_gantt_pathrU   r   r   r   r7    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   ri   rq   r   r   cache_branch_gantt_pathro   r,  )ro   rJ   Frk   r(   )ro   r_count)rG   re   r   r   rq   ri   rB   r	   r   r,  rr  ru  rb   rc   rs   rs  )r$   ro   rv  ZchZ	need_saver   r   r   rs    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   r4   ri   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   )ri   rT   r,  ru  re   ro   r+   rG   r*   r   r4   )r$   ro   ru  r   r   r   rr  C  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_tasksTrk   ro   r   r*   rV  r   F)ro   rF   r   re   r,  rr  rs   rc   rB   r	   ru   r*   )r$   Zhave_childsr   r   r   r6  `  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  nV|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dg |jr|jjr|jj}|jj}|rl||krl| 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\   rM   ZordernoZperm_has_aclr   ri   uU   SimpleLogic: Задача добавлена в структурный список "uG   " т.к. он указан в должности исполнителяry   rz   u>   SimpleLogic: Задача добавлена в список "r0  u   " т.к. он является Структурным проектом Главной роли ответственного по задачеz,primary_role.structural_project.default_listz$primary_role.structural_project_listuS   SimpleLogic: Задача убрана из структурного списка "uX   " т.к. он указан в должности прошлого исполнителяu<   SimpleLogic: Задача удалена из списка "u   " т.к. он является Структурным проектом Главной роли прошлого ответственного по задаче)rS   rF   re   r   r   Zstructural_project_listr[   r   r4   rB   r   rs   r4  rA   rc   r   )r$   Zappend_structural_project_listr   rB  Zold_responsibleZremove_structural_project_listr   r   r   r9  u  sN    


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)
rW   rA   rF   Zagile_story_pointsr+   r@   rB   rC   re   Zdefault_agile_story_pointsrU   r   r   r   r8    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_workrF   Zbp_gantt_taskry  rT   rG   rl   re   rc   rz  rs   rU   r   r   r   r3    s    
zCmfTask._calc_estimate_work   Изменена задачаc              
      s   | j rd}d|kr,d|d< nd|kr,d|d< |r| ddddd	d
ddg |d	krz| jjdk rz| j| jjj||dd d S | jdkr| j	g}| j
r| j
jdkr|| jj	 |D ]}| j|jj||dd qd S t jf |||d| d S )Nu   Создана задачаnotify_typeZ
obj_createZobj_editrA   zparent.cmf_owner_assistantszparent.cmf_ownerr   r   r?   r|   r+  <   )ro  r4   msgr|  r   rC   )r{   notify_namerC  )rW   re   r   r   r   r   r*   r+   r?   r|   r   	type_namer   rA   r   all_place_notify)r$   r{   rC  r  r   rk  r   r   r   r   r    sP    
    
zCmfTask.all_place_notifyc                 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
  Trk   u0   Задача создана из шаблона ry   rz   )re   create_from_templater   rL   r4   strftimetmplt_documentr   r{   r+   rs   rB   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 ri   r_   ztask.ticketzhelpdesk_mail_notification.html)re   ri   r   +get_default_mail_notification_template_namerU   r   r   r   r    s    
z3CmfTask.get_default_mail_notification_template_namec                    s    |dkrdS t  j|f||S )N)rE   r\   rM   r   r   )r   _get_field_log_level)r$   rC  r   r   r   r   r   r    s    zCmfTask._get_field_log_level   Добавленоc                 C   s   t jj| ||||dS )N)Z
start_date)rB   r   Ztimetracker_task_change_time)r$   Z
time_spentZremaining_estimater{   dater   r   r   timetracker_change_time  s
    
  zCmfTask.timetracker_change_time)	only_oncer`  c                 K   s   t j|  d S rg   )rB   r	   _recalculate_codes)r~   rg  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   rJ   slicer   )from_recalculaterk   )rB   r	   r   r   
_calc_coders   Zcommit_with_event)r~   r   limitZ
task_slicerw   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  
            Метод для ручного запуска.
            Пересчитает номера в кодах задач начиная с единицы.
            ! Прошлые коды задач не сохраняются
            ! Пошлые коды задач удаляются
            Если код занят задачей из другого проекта - он пропусается
        rw  u   Проект не найден!NuY   Удаляем историю выдачи кодов задачам из проекта r   )r   rJ   u   Всего задач: c                 S   s   z
t | W S    Y dS X d S )Nr   )r"   )r   r   r   r   tryintF  s    
z:CmfTask.reindex_project_tasks_code_numbers.<locals>.tryintc                    s    | j jdd S )Nr    ry   )r   r+   
rpartitionrx  r  r   r   r  M  r  z<CmfTask.reindex_project_tasks_code_numbers.<locals>.<lambda>r  r   r(   u'   Обрабатываем задачу: )rw   r    r   Tr   r   u   Код u    занятrk   )rG  Zdisable_notifyrB   rC   ru   rc  r	   r   r   r  CmfTaskCodeHistoryrH  r   r+   r  r!   rs   )
project_idZwith_history_deleterL  	task_listr   rw   ZhistZnew_coder   r  r   "reindex_project_tasks_code_numbers4  s0    	
z*CmfTask.reindex_project_tasks_code_numbersr}  )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   cache_child_tasks_count)ri   rJ   r(   ro   r   r   zUpdate cache_members_count z -> r<   Trk   )Znode_idZelements_countztree-node-count-changes-ztree-node-count-changeszRecalculate ra  z lists caches)rB   r	   r   ri  r  r2   r3   r*   rs   r+   Zcmf_emit_event)rg  r   Ztotal_countZ
calc_countZcmf_epicZ
real_countZ
event_datar   r   r   r>  a  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_childrenr   ro   r(   r  r  )r6   re   ro   unionget_all_followersr   )r$   r  r   r   rM  r   r   r   r  z  s      zCmfTask.get_all_followersc                 C   s   |  ddg | jjd| jdds&dS | jtjkr6dS tjjdgdd	dgd
dtjgggd}t	 }|D ]}|j
D ]}||j qpqf| jj|krdS dS )Nr   r|   zPPP-PR-BROWSEF)rf   r   T
persons.idservicedesk_allowr   rk  INrJ   r   )re   r   r%  r|   r2   r   rB   
CmfCompanyr   r6   rk  r   r*   )r$   company_personsall_memberscompanyr   r   r   r   _sdesk_check_access  s     

zCmfTask._sdesk_check_accessc                 O   s    |   stddd | j||S )Nu   Нет доступа!Tr   )r  rG   updater$   r   r   r   r   r   sdesk_update  s    zCmfTask.sdesk_update)reporterrJ   r   c                O   s   |sg }| dddg |dkrtjjdgdddgdd	tjgggd
}t }|D ]}|jD ]}	||	j	j
 qZqP|r| dd	|g |dkr| ddtjg n,|r|dkr| ddtjg ntddd tjj||dd}
|
s|
S tdd |
}t|S )Nr:  r   r1  )allrelater  r  Trk  r  r  r|   r  rV  ZmyzUnknown reporter optionr   F)rJ   r   r   c                 S   s   |   S rg   )r  r  r   r   r   r    r  z$CmfTask.sdesk_list.<locals>.<lambda>)r   rB   r  r   r2   r   r6   rk  r   r*   r+   rG   r	   builtinsr   )r   r  rJ   r   r   r   r  r  r  r   rM  Zres_filteredr   r   r   
sdesk_list  s6    

zCmfTask.sdesk_listc                 O   s    | j ||}|r| sd S |S rg   )ru   r  )r   r   r   rM  r   r   r   	sdesk_get  s    zCmfTask.sdesk_getr_   c                O   s$   dg}t jj|d|i|}t|S )Nr*   rJ   )rB   r	   r  r   )r   rJ   r   r   r  r   r   r   sdesk_count  s    zCmfTask.sdesk_countc                O   s   | j }d}|dd}|rb| j|dgd}| s6dS |jrb|jjrb|jj}|rb|j j}|j}t	|pjg }	|r|dg }
|
D ]}|	
|dg  q| |	}| j||dd	|}|r||_||_|S )
ux   
        fields - список мета-правил для указания какие поля грузить
        defaultr   Nzrequest_type.ui_form_viewrp   Zui_group_fieldsrJ   Zsimple)full_fields_loadZmapper)ui_formru   r  Zrequest_typeZui_form_viewui_form_jsonrT   r+   r4   r6   r  Z_build_load_planZ_getui_form_name)r   rJ   r   r   r  r  r   rw   r  Z
fields_setgroupsZ
group_datar  r   r   r   r   sdesk_ui_get  s.    	
zCmfTask.sdesk_ui_get)copy_attachmentscopy_relationscopy_subtaskscopy_all)r4   r  r  r  r  c                   s  |rd}d}d}|  dddd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 ]}| }||_	|
  qtjj|
dd| gg dgdD ]}| }||_|
  q| jstj| ||	d
  | | d|_|S )NTz**zattachments.urlr   r[   rn  r'  zattachments.url_previewzattachments.url_preview_imgop_gantt_task.actual_work)r4   r  zsystem.cloner   relation_typerV  out_linkr   rp   in_link)r  r  r  )re   r   r  rB   ZCmfRelationTyperu   ZCmfRelationOptionr   cloner  rs   r  Zis_template_clone_op_gantt_taskrW   )r$   r4   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   )rl   re   r  actual_workrw   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 )Nri   r   z	/project/ra  )re   ri   r  r   r   hrefrU   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   rJ   r  )r   r"   r   r[   r*   r   )	r   r   rg  rl  ZpageZ	page_sizer  rw   Zlist_r   r   r   count_tasks_by_lists2	  s      

zCmfTask.count_tasks_by_listsc                 C   s   | j r| j jjds| jS | dddg | j ddg | j r| j 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+   r   Zcode_prefixre   r  r   Zobj_code_prefixr  rU   r   r   r   get_code_prefixB	  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timerB   r  r!   AssertionErrorr,   rc  r*   rJ   r   )r$   r   r  startr  r   Zdurationr   r   r   r  [	  s    

 .zCmfTask.gen_codec                    s:  | j r| jjs| jjs|sd S | j s2t   d S | j rH| j drHd S d }d }| jjjdrf| 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}|rtjj|dstj|| |d}|  d| j_t   d S | jjr| j j| 
  ds| j j}| jsv|rvtjj|dsvtj|| |d}|  d | _ t   d S | jjr6| dg | jr6| jjjdr6| jjr6| j j| 
  ds6| j j}| js,|r,tjj|ds,tj|| |d}| jjr$||_|  t   d S )NzA-rF  r    r  )r   rw   rL  Tr  )r   r   rF   r   r   r  r   r*   r+   rc   r  ri  rB   r  r!   rs   rW   re   r  r  )r$   r  rL  Zproject_oldZ
new_prefixZ	prev_codeZcode_historyr   r   r   r  m	  sv    
.
$


zCmfTask._calc_coder  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   rJ   r   r   r   Zres_uncheckedrM  rr   r   r   public_list	  s    zCmfTask.public_listc                 C   s<   | j j  | j jj}| | jj|  | | jj| d S rg   )rl   r  rT   r+   #_update_actual_work_for_all_parentsro   rc   rb   )r$   actual_work_timer   r   r   r@  	  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)rl   rT   r  rs   )r$   rw   r  r   r   r   r  	  s    
z+CmfTask._update_actual_work_for_all_parentsc                 C   s   t | j d S rg   )r=  cron_celery_check_periodic)r   r   r   r   cron_check_periodic	  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.coderV  r   r?   r   period_create_newr   Tperiod_intervalperiod_next_datez<=r  r*  rZ   r   period_clear_checkboxr{   r  rY   rE   rp   z6CmfPerson.cron_celery_check_periodic: create new task )r   rk   z2CmfPerson.cron_celery_check_periodic: reopen task )r;   r   r   ztox-checklist--checkedr
  pause)r2   r3   r   rL   r   r   rB   r	   r   r  r  r  r   r{   r   r   rX   rE   r^   rY   r  r  rs   Z_cacl_next_periodr?   r   r+   r  r  r   )_argsrg  r   rw   r  Zold_deadliner   r   r   r  	  sf    
      






z"CmfTask.cron_celery_check_periodicc                    sJ   |    |   |   |   |   |   |   t j|| d S rg   )	r   r   r6  r7  r"  r   r9  r   _save_importr  r   r   r   r  .
  s    zCmfTask._save_importcsvc                    s   |sdd | j  D }|d |d |d |d |d |d |d	 |d
 |d |d t |||S )Nc                 S   s   g | ]}|j r|jqS r   )Zvisibler,   )r   Zfieldr   r   r   r   <
  s      z'CmfTask.export2file.<locals>.<listcomp>r   r  r-  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  )rJ   valuesr   r   export2file)r   rJ   ZbqlZformat_filer   r   r   r  8
  s    









zCmfTask.export2file)NN)F)F)F)F)F)N)NNNN)NNNN)NNNN)NNNN)NNNNNN)N)r   )N)Nr{  )r  N)F)N)F)NNr  )o__name__
__module____qualname__classmethodr   r   r%   r:   rQ   rV   r]   rd   rh   rx   r   r   r   r   r   r   rD   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   rs   rD  rH  rO  rI  rJ  rK  rU  r\  r^  r_  rZ  staticmethodZ
celery_apprw   rh  rm  rp  rq  r5  r7  rs  rr  r6  r9  r8  r3  r  r  r  r  r  r  r  r  r>  r6   r  r  r  r  r  r  r  strboolr  r  propertyr  r  r  r  r  r  r@  r  r  r  r  r  __classcell__r   r   r   r   r	      sH  
$&.A
	A2  G  
+
%
%

*
F>	3%                             
          +
.
1
*

,1
%&M
J
r	   c                   C   s
   t j S rg   )rB   r	   r  r   r   r   r   r  K
  r  r  )r   r  r  collectionsr   r   rd  Zredis.exceptionsr-   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   rw   rJ   Zcmf_taskr	   r)   ZHOOK_CRON_HOURLYr   r   r   r   r   <module>   sD                       M