U
    *8eU                    @   sP   d dl Zd dlT d dlmZmZ d dlZd dlT d dlm	Z	 G dd de	Z	dS )    N)*)ROUND_UP
ROUND_DOWN)CmfGanttTaskc                       s  e Zd Ze fddZedddZ fddZedd	 Zed
d Z	edd Z
edd ZdddZdddZdd Zdd Zdd ZdddZdd Zddd Zdd!d"Zdd#d$Zd%d& Zdd'd(Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Zdd5d6Zdd7d8Zd9d: Z d;d< Z!d=d> Z"dd?d@Z#dAdB Z$ddCdDZ%dEdF Z&dGdH Z'ddIdJZ(dKdL Z)ddMdNZ*dOdP Z+dQdR Z,dSdT Z-dUdV Z.dWdX Z/dYdZ Z0d[d\ Z1dd]d^Z2dd_d`Z3dadb Z4dcdd Z5dedf Z6ddgdhZ7ddidjZ8dkdl Z9dmdn Z:dodp Z;dqdr Z<dsdt Z=dudv Z>ddwdxZ?dydz Z@d{d| ZAd}d~ ZBddd fdd
ZCdd fdd
ZD fddZE fddZF  ZGS )r   c                    s   t  }ddddddddd	d
dddg}t jjd |j|d}|rT|D ]}|| ||< qB||_|  t  t j	|ddd W 5 Q R X |S )Nsched_start_datesched_finish_datesched_duration
sched_cost
sched_workconstrain_start_typeconstrain_start_dateconstrain_finish_typeconstrain_finish_dateprojectgantt_projecttaskparent_task)Z	parent_idtask_idfieldsFemitnotify)
modelsr   getidparentfix_null_variablescmfutildisable_notifysupersave)clsr   baseline
gantt_taskr   op_gantt_taskZfield	__class__ (./modules/gantt/models/cmf_gantt_task.py_create_gantt_task_for_baseline   s*          
z,CmfGanttTask._create_gantt_task_for_baselineNc              	   C   sz   t  }|r| ||S |jr4|jjjdkr4|j|_|j  |j|_||_	|j
|_
t  |jddd W 5 Q R X |S )NZ
CmfProjectFr   )r   r   r)   r   value
class_namer   r   loadr   r   r   r   r    )r!   r   r"   r#   r'   r'   r(   create_gantt_task   s    

zCmfGanttTask.create_gantt_taskc                    s    dddddddg}t   | S )Nr   r   task.logic_prefixztask.parent_task.logic_prefixztask.has_child_tasksztask.plan_start_dateztask.plan_end_date)r   save_preload_fields)selfr   r%   r'   r(   r/   1   s    	z CmfGanttTask.save_preload_fieldsc                 C   s2   | j jrd S | j | j d }t|jtdtdS )Nd   z1.11Zrounding)r	   is_null_perform_completeDecimalquantizer   r0   resr'   r'   r(   _perform_cost?   s    zCmfGanttTask._perform_costc                 C   s:   | j jrd S | j | j d }t|jtdtd}t|S Nr1   1r2   )r   r3   r4   r5   r6   r   intr7   r'   r'   r(   _perform_durationF   s
    zCmfGanttTask._perform_durationc                 C   s:   | j jrd S | j | j d }t|jtdtd}t|S r:   )r
   r3   r4   r5   r6   r   r<   r7   r'   r'   r(   _perform_workN   s
    zCmfGanttTask._perform_workc                 C   s   | j js| jjrdS ttj| j   }| j ttjkr@dS | j| j   }t|dkrj|| d }nd}|dkrzd}t	|j
t	dtd}t|S )Nr   r1   r;   r2   )r   r3   r   datetimeZnowtimezoneZutcZtotal_secondsr<   r5   r6   r   )r0   Zdelta_now_time_secZdelta_finish_time_secZperform_completer8   r'   r'   r(   r4   V   s    zCmfGanttTask._perform_completeFc                 C   s   |sd S d}|}| j dkr*| jr*d}d}n| jrd}| jj}| jdkrd||krdd}|}d|d}nN| jdkr||krd}|}d	|d}n&| jd
kr||k rd}|}d|d}d| d|d}|r|sd| jj d| jj d| d}t|dd |S )NF0-constTu   невозможно изменить дату начала, если зафиксированы дата окончания и длительность (   Фиксированное начало %d.%m.%Y3-after   Начало не раньше 4-before   Начало не позже    ограничение "uE   " конфликтует с плановой датой начала <   Конфликт планирования: В задаче "" () .abort)	r   const_durationr   r*   r   r   namecode	cmf_alertr0   estimated_datereturn_correct_dateZalertZcorrect_datetext
constraintZconstrain_dater'   r'   r(   check_correct_start_daten   s6     z%CmfGanttTask.check_correct_start_datec                 C   s   |sd S d}|}| j dkr*| jr*d}d}n| jrd}| jj}| jdkrd||krdd}|}d|d}nN| jdkr||krd}|}d	|d}n&| jd
kr||k rd}|}d|d}d| d|d}|r|sd| jj d| jj d| d}t|dd |S )NFrA   Tu   невозможно изменить дату окончания, если зафиксированы дата начала и длительностьrB   .   Фиксированное окончание rD   1-after%   Окончание не раньше 2-before#   Окончание не позже rI   uK   " конфликтует с плановой датой окончания rJ   rK   rL   rM   rN   )	r   rP   r   r*   r   r   rQ   rR   rS   rT   r'   r'   r(   check_correct_finish_date   s6     z&CmfGanttTask.check_correct_finish_datec                 C   s   d\}}}| j jrH| j jdkrH| j jj }||   | \}}}|}| jdkrx| j	}|rp|rpt
||}n|pv|}|}| jdkr| j}|r|rt||}n|p|}d}| jr| j}n|}|||fS )u  
        Получает из родительской задачи ограничения
        по дате начала, дате окончания и максимальной длительности.

        Returns:
            start_limit: Defaults to None
                левая граница, за которую нельзя уйти влево (_plan_start_limit_min)
            finish_limit: Defaults to None
                правая граница, за которую нельзя уйти вправо (_plan_finish_limit_max)
            duration_limit: Defaults to None
                лимит длительности, нельзя превысить (_plan_duration_limit_max)
        NNNtask.gantt_projectrA   rE   rA   r]   N)r   r   logic_prefixr$   r,   load_fieldsr/   get_parent_plan_limitr   r   maxr   r   minrP   r   )r0   Zparent_start_limitZparent_finish_limitZparent_duration_limitparent_gantt_taskstart_limitfinish_limitduration_limitr'   r'   r(   rf      s,    


z"CmfGanttTask.get_parent_plan_limitc           
      C   sH  d } }}| j jsdS tjjdd| j g|  dD ]}|jdkrf|sR|jj}n|jrft	||jj}|j
dkr|s|jj}|jrtj| |jjt|j }|}nD|jrt	||jj}|jrtj| |jjt|j }t	||}|j
dkr|s|jj}n|jrt||jj}|jd	kr|sd|jj}|jrtj| |jjt|j}|}nF|jrt||jj}|jrtj| |jjt|j}t||}|jr|s|j}n|jrt||j}|j jr4| \}}}	|s|}n|rt	||}|s|}n|r"t||}|s.|	}q4|	r4t||	}q4|||fS )
u~  
        !!! Очень тяжелый метод

        Получает из дочерних задач ограничения
        по дате начала, дате окончания и максимальной длительности.

        Returns:
            start_limit: Defaults to None
                левая граница, за которую нельзя уйти вправо (_plan_start_limit_max)
            finish_limit: Defaults to None
                правая граница, за которую нельзя уйти влево (_plan_finish_limit_min)
            duration_limit: Defaults to None
                самая большая фикс. длительность или фикс. трудозатраты (пока нет поддержки ресурсов),
                нельзя меньше (_plan_duration_limit_min)
        Nr`   task.parent_task=filterr   )rA   rG   rc   rA   r[   rb   )r   has_child_tasksr   r   listr/   r   r   r*   rh   r   r   r   CmfCalendarget_date_by_duration_get_calendarr<   rg   rP   rl   get_childrens_plan_limit)
r0   rj   rk   rl   r#   r   r   Zch_start_limitZch_finish_limitZch_duration_limitr'   r'   r(   rw      s    









z%CmfGanttTask.get_childrens_plan_limitc                 C   sB   t | ddrd S d| _|  \| _| _| _|  \| _| _| _	d S )N_calc_plan_limits_cache_doneFT)
getattrrx   rf   _plan_start_limit_min_plan_finish_limit_max_plan_duration_limit_maxrw   _plan_start_limit_max_plan_finish_limit_min_plan_duration_limit_minr0   r'   r'   r(   _calc_plan_limits_cacheF  s    z$CmfGanttTask._calc_plan_limits_cachec                 C   s\   | j r,| jr,tj|  | j j| jj| _n| j jrB| jjrBd| _| jj	rX| j
d|d d S )Nr   T)from_calc_sched_durationfrom_child_changes)r   r   r   rt   get_duration_minutesrv   r*   r   old
is_changed_do_sched_duration_is_changed)r0   r   r'   r'   r(   _calc_sched_durationP  s      z!CmfGanttTask._calc_sched_durationc                 C   sF   | j r,| jr,tj|  | j j| jj| _n| j jrB| jjrBd| _d S Nr   )	actual_start_dateactual_finish_dater   rt   r   rv   r*   actual_durationr   r   r'   r'   r(   _calc_actual_durationj  s      z"CmfGanttTask._calc_actual_durationc                 C   sR   t j|  | jjt| j }| j||d}| j	dkrN| j
rN| j
|krN| j
}|S )u  
        Расчитывает дату начала.
        При возникновении конфликтов ограничений, откатывает на дату ограничения при rollback=True

        Args:
            rollback (bool, optional): Defaults to False
                при конфликте откатить на дату ограничения

        Returns:
            sched_start_date:
                плановая дата начала
        rU   rV   r[   )r   rt   ru   rv   r   r*   r<   r   rY   r   rz   )r0   rollbackrU   r   r'   r'   r(   _calc_sched_start_dates  s      

z#CmfGanttTask._calc_sched_start_datec                 C   s0   t j|  | jjt| j}| j||d}|S )u  
        Расчитывает дату окончания.
        При возникновении конфликтов ограничений, откатывает на дату ограничения при rollback=True

        Args:
            rollback (bool, optional): Defaults to False
                при конфликте откатить на дату ограничения

        Returns:
            sched_finish_date:
                плановая дата окончания
        r   )	r   rt   ru   rv   r   r*   r<   r   r_   )r0   r   rU   r   r'   r'   r(   _calc_sched_finish_date  s      z$CmfGanttTask._calc_sched_finish_datec                 C   s   | j js| j dkrd | _d S | jjr0| jjr0d S | jrZ| jsZ| j|d| _|rVd | _nd S | jr| js|  | _| jdkr|  | _d S | jdkr| jdkr| jrt	d d S )Nr   r   r[   rA   u   Плановый период может не соответствовать плановой длительности, т.к. все переменные зафиксированы)
r   r3   r   r   r   r   r   r   rP   rS   )r0   r   r'   r'   r(   _calc_sched_period  s"    


zCmfGanttTask._calc_sched_periodc                 C   s   | j js| j dkrd | _d S | jjr0| jjr0d S | jrZtj|  | jjt	| j | _d S | jrtj|  | jjt	| j  | _d S d S r   )
r   r3   r   r   r   rt   ru   rv   r*   r<   r   r'   r'   r(   _calc_actual_period  s&        
z CmfGanttTask._calc_actual_periodc           
      C   s  | j jsdS | jdkrdS | jdkrtjjdd| j gdgd}|sFdS t|}d}|D ]6}|r||j|jkr|||jj	pvd7 }qV||jj	pd7 }qV|| }n | jd	krztj
jd
d| j gddgd}|sdS d}d}	|D ]}|r:|j|j jkr:|j ddg ||j jj	pd7 }|j jjdkrj|	|j jj	p4d7 }	q||jj	pHd7 }|jjdkr|	|jj	pfd7 }	q|	| d }n | jdkrdS | jdkrdS | j|k r|| _dS )uB   
        updated_ch_gantt_task - указан, когда
        N0-work
1-completerm   rn   actual_completero   r   2-story_pointsr   agile_story_pointszstatus.status_typeCLOSEDr1   3-costz4-fixed)r   rr   actual_complete_typer   r   rs   lenr   r   r*   CmfTaskre   r   statusstatus_type)
r0   updated_ch_gantt_taskZch_gantt_task_listZtotal_countZsum_actual_completecZres_actual_completeZch_task_listZtotal_story_pointsZfinished_story_pointsr'   r'   r(   _calc_summarry_actual_complete  sR    

z+CmfGanttTask._calc_summarry_actual_completec                 C   s  |    | jdkr(| js.| jr.| j| _nd | _| jdkrB| j| _n| jdkr| j}| jrl| jrlt| j| j}|r| jr| j|k r|| _nb| jdkr| j}| jr| jrt| j| j}|r| jr| j|kr|| _n| jr| j| _| jr| j| _| jr| jr| j| jkrtddd | jr>| jr>| j| jk r>tddd | j	j
r| jr`| j	j
| jk r| jrx| j	j
| jkr| js| j	j
| _n\| jdkrnN| jd	kr| j	j
| jk r| j	j
| _n&| jd
kr| j	j
| jkr| j	j
| _| jdk| _| jr| jjr|   | jdd d S )N)rA   rE   rG   rA   rE   rG   u~   Нельзя указать Дату начала больше зафиксированной у дочерней задачиTrN   u   Нельзя указать Дату начала меньше зафиксированной у родительской задачи)1-earlyrG   )z2-latterrE   	only_data)r   r   r   r   rz   rg   r}   rh   rS   r   Zplan_start_datelock_sched_start_dater   _do_sched_start_date_is_changedr    )r0   r   r'   r'   r(   #_do_constrain_start_date_is_changed  sd    







z0CmfGanttTask._do_constrain_start_date_is_changedc           	      C   s   g }| j  }| jjrT| jjdkrTdd|gdd| jgdddgg}tjj|| 	 d}dd| jgd	dd
gg}tj
j|dgd}ttdd |}dd|gdd|gg}tjj|| 	 d}|| S )Nra   r   rn   r   r.   !=ro   Zout_linkzrelation_type.codezsystem.additional_parentin_linkc                 S   s
   | j jjS N)r   r   r*   )Zrelr'   r'   r(   <lambda>e      z6CmfGanttTask._get_parent_gantt_tasks.<locals>.<lambda>IN)r   r,   r   r   rd   parent_task_idr   r   rs   r/   ZCmfRelationOptionmap)	r0   Znormal_parentsr"   rp   Zadditional_filterZadditional_parents_relationsZadditional_parents_tasks_idsZadditional_parents_filterZadditional_parentsr'   r'   r(   _get_parent_gantt_tasksR  s0    


z$CmfGanttTask._get_parent_gantt_tasksc                 C   s6   d }|  ddg | jr | jj}|p4tjjddgdS )Nzproject.calendarzproject.calendar.timezonezsystem:defaultr@   )rR   r   )re   r   calendarr   rt   r   )r0   r   r'   r'   r(   rv   o  s
    zCmfGanttTask._get_calendarc                 C   s   d }d }t jjdd| jg|  d}|D ]}|  |j| jjdd|_d |_	|jj
r`|  n|jdd |jdd |s|jj}nt||jj}|j	r|s|j	j}nt||j	j}| j|d | j|d q(|r|| _|r|| _	| jdd	 d S )
Nr   rn   ro   Tr   r   r   rU   r   )r   r   rs   r   r/   r   rY   r   newr   rr   "_calc_sched_period_for_child_tasksr   r    r*   rh   rg   r_   r   )r0   r   r   Zchild_tasks
child_taskr'   r'   r(   r   x  s>    



z/CmfGanttTask._calc_sched_period_for_child_tasksc                 C   s   | j | jjd |   | jjrt| jjrt| jrj| j| jk rj| j| _td| jj d| jj	 d| jdd | 
  n*| jr| jr| jsd | _|   n|   d S )Nr   u/   Предупреждение: В задаче "rK   u2   ) дата начала перемещена на rD   ub   , так как была позже даты ограничения дочерней задачи.)rY   r   r   r   r   rr   r}   rS   rQ   rR   r   r   lock_sched_finish_dater   r   r   r   r'   r'   r(   r     s    (

z,CmfGanttTask._do_sched_start_date_is_changedc                 C   s|   | j | jjd |   | jjrT| jjrTtj| 	 | jjt
| j | _|   n$| jrp| jrf| jrp|   n|   d S )Nr   )r_   r   r   r   r   rr   r   rt   ru   rv   r<   r   r   r   rP   r   r   r   r'   r'   r(    _do_sched_finish_date_is_changed  s      


z-CmfGanttTask._do_sched_finish_date_is_changedc              
   C   sF  |s|nd}|s|nd}t jjdd| jgddddgdddggg|  d}|D ]V}|rd|j|jkrdqN|r|jr|jr|j|jk r|}|r|jrN|jrN|j|jkrN|}qN|j}|j}|s|r|jr|js|j|k r|j}|s|r|jr|js|j|kr|j}d}	d}
| jr|rd	|jj	 d
|jj
 d}
| jj}| jdkrV||krVd|d}	nL| jdkrz||k rzd|d}	n(| jdkr||krd|d}	nd}
d}| jrF|rFd	|jj	 d
|jj
 d}| jj}| jdkr||krd|d}	nL| jdkr||k rd|d}	n(| jdkrB||krBd|d}	nd}|	r|
pT|}td| jj	 d
| jj
 d|	 d| d	dd || _|| _| jjs| jjr| jdd |s|r| j|jk r|j| _| jdd | jjrB| jjdkrBt > | jjj }||   |j||d  |jd!dd" W 5 Q R X dS )#u  
        Обновляет плановые даты родительской задачи.
        Плановая дата начала = самая ранняя плановая дата начала всех подзадач
        Плановая дата окончания = самая поздняя плановая дата окончания всех подзадач

        Args:
            child_task (optional): Defaults to None
                измененная дочерняя задача, которая еще не сохранена.
            ignore_child_task (bool, optional): Defaults to False
                игнорировать дочернюю задачу при обновлении дат родительской задачи.
        Nr   rn   ORr   r   r   ro   "rK   )rA   rC   rD   rE   rF   rG   rH   rZ   r[   r\   r]   r^   uU   Конфликт планирования: В родительской задаче "u   ) ограничение "u<   " конфликтует с дочерней задачей rM   TrN   r   ra   ignore_child_taskF
user_inputr   )r   r   rs   r   r/   r   r   r   r   rQ   rR   r*   r   r   r   rS   r   r   r   r   r   rd   r   disable_aclr$   r,   re   from_sched_dates_of_child_tasksr    )r0   r   r   Zchild_task_with_min_startZchild_task_with_max_finishZgantt_tasksr#   Zmin_start_dateZmax_finish_datesrX   Zconflict_child_task_min_startr   Zconflict_child_task_max_finishr   Zconflict_child_taskri   r'   r'   r(   r     s    



&
z,CmfGanttTask.from_sched_dates_of_child_tasksc              	   C   sp   |  dg | jjrl| jjdkrlt > | jjj }| |   |j	| |d |j
ddd W 5 Q R X dS )uC  
        Обновление дат начала и окончания родительской задачи.
        Передает дочернюю задачу (self), так как она еще не сохранена
        и родительская задача не может получить обновленные данные.

        Args:
            ignore_child_task (bool, optional): Defaults to False
                игнорировать дочернюю задачу при обновлении дат родительской задачи.
        z#task.parent_task, task.logic_prefixra   r   FTr   N)re   r   r   rd   r   r   r$   r,   r/   r   r    )r0   r   ri   r'   r'   r(   update_parent_task_sched_dates<  s    

z+CmfGanttTask.update_parent_task_sched_datesc                 C   s   |   }|D ]}|jdkr$td q| | r|| rD| | || k r|jdkrt|| rt| | || krttd  d S |jdkr|| r| | || k rtd  d S | | ||< |  |j|d qd S )NrA   ^   Дата родительской задачи является зафиксированнойrG   u   Предупреждение: Плановая дата начала дочерней задачи больше плановой даты начала родительской задачиrE   u   Предупреждение: Плановая дата начала дочерней задачи меньше плановой даты начала родительской задачи)
date_field)r   r   rS   r    _change_parent_start_date)r0   r   parentsri   r'   r'   r(   r   Q  s&    
 z&CmfGanttTask._change_parent_start_datec                 C   s   |   }|D ]}|jdkr$td q| | r|| rD| | || kr|jdkrt|| rt| | || k rttd  d S | | }|jdkr|| r| | || krtd |jr||jkr|j}|||< |  || q| jdk| _d S )NrA   r   r[   u   Предупреждение: Плановая дата окончания дочерней задачи меньше плановой даты окончания родительской задачиr]   u   Предупреждение: Плановая дата окончания дочерней задачи больше плановой даты окончания родительской задачи)r   r   rS   r   r    _change_parent_finish_dater   r   )r0   r   r   ri   Z
date_valuer'   r'   r(   r   g  s,    
 z'CmfGanttTask._change_parent_finish_datec                 C   s4  |    | jdkr(| js.| jr.| j| _nd | _| jdkrB| j| _n| jdkrx| j}| jrl| jrlt| j| j}|r|| _nb| jdkr| j}| jr| jrt| j| j}|r| jr| j|kr|| _n| jr| j| _| j	r| j	| _| jr&| j
r| j| j
krtddd | jr&| j| jk r&tddd | jjr| j
rH| jj| j
k r| jr`| jj| jkr| jst| jj| _n\| jdkrnN| jdkr| jj| jkr| jj| _n&| jdkr| jj| jk r| jj| _| jdk| _| jr| jjr| jrd | _|   | jr$| jjr$d | _|   | jdd	 d S )
N)rA   r[   r]   rA   r[   r]   u   Нельзя указать Дату окончания больше зафиксированной у родительской задачиTrN   u   Нельзя указать Дату окончания меньше зафиксированной у дочерней задачиr   )r   r   r   r   r~   rg   rh   rz   r   r}   r{   rS   r   Zplan_end_dater   r   r   r   r   r    )r0   r   r'   r'   r(   $_do_constrain_finish_date_is_changed  sp    







z1CmfGanttTask._do_constrain_finish_date_is_changedc                 C   s   | j dkr | jdkr tddd |   | jrF| j| jkrFtddd | jrd| j| jk rdtddd |s| jdkrd | _| j| _	nd | _	| 
  |s| jr| js| jr| j| _| jd|d | jr| jr| j| jk rtd	| jj d
| jj ddd d S )NrA   u   Конфликт планирования: невозможно изменить длительность, если зафиксирована дата начала и дата окончания.TrN   u   Конфликт планирования: невозможно установить длительность больше зафиксированной у родительской задачи.u   Конфликт планирования: невозможно установить длительность меньше зафиксированной у дочерней задачи.rq   )from_sched_duration_changedr      В задаче "rK   u   ) невозможно указать Длительность меньше чем Трудозатраты, когда установлена опция Фиксированные Ресурсы и Трудозатраты зафиксированы.)r   r   rS   r   r|   r   r   r   r   r   r   
const_workconst_resourcer
   _do_sched_work_is_changedr   rQ   rR   )r0   from_sched_work_changedr   r   r'   r'   r(   r     s:    


z*CmfGanttTask._do_sched_duration_is_changedc                 C   s   |    d S r   )r   r   r'   r'   r(   _do_actual_duration_is_changed  s    z+CmfGanttTask._do_actual_duration_is_changedc              	   C   s(  | j jrd S | j dk r"tddd | jjs2| j | _| jdkr| jjr| jdkrt	
| j | j d }t|d}| jjs|| jkr|| _|   | j jpd| j jpd }| jjr| jjdkrt 8 | jjj }||   || |jdd	 W 5 Q R X |s$| jjr$tj| j| d S )
Nr   uo   "Фактические трудозатраты" стал ниже нуля, выставляем в ноль.TrN   r   r1   ra   Fr   )actual_workr3   rS   r   rr   actual_myself_workr   r
   is_not_nullmathfloorrh   r   $notify_parent_update_actual_completer   r   r   rd   r   r   r$   r,   re   r/   from_child_add_workr    r   r   ZCmfTimeTrackerZ"_op_gantt_actual_work_changed_hook)r0   from_timetrackertmp_complete
work_deltari   r'   r'   r(   _do_actual_work_is_changed  s,    




z'CmfGanttTask._do_actual_work_is_changedc              	   C   s   | j jrd S | j dk r"tddd | jdkr~| jjr~| jdkr~t| j | j d }t|d}| j	jsp|| j	kr~|| _	| 
  | jjr| jjdkr| j jpd| j jpd }t 8 | jjj }||   || |jdd	 W 5 Q R X d S )
Nr   ue   "Фактические Затраты" стал ниже нуля, выставляем в ноль.TrN   r   r1   ra   Fr   )actual_costr3   rS   r   r	   r   r   r   rh   r   r   r   r   rd   r   r   r   r   r$   r,   re   r/   from_child_add_costr    )r0   r   
cost_deltari   r'   r'   r(   _do_actual_cost_is_changed  s$    




z'CmfGanttTask._do_actual_cost_is_changedc                 C   s,   | j jrd S | jdkrd S | jdkr(d S d S )Nr   r   )r   r3   r   r   r'   r'   r(   _do_actual_complete_is_changed#  s    

z+CmfGanttTask._do_actual_complete_is_changedc                 C   sH   | j jp
d| j jpd }| jjs*| j | _n|  j|7  _| j|d d S )Nr   r   )r   r   r   r   rr   r   r   )r0   r   r   r'   r'   r(   !_do_actual_myself_work_is_changed3  s
    
z.CmfGanttTask._do_actual_myself_work_is_changedc                 C   sD   | j jp
d| j jpd }| jjs*| j | _n|  j|7  _|   d S r   )actual_myself_costr   r   r   rr   r   r   r0   r   r'   r'   r(   !_do_actual_myself_cost_is_changed=  s
    
z.CmfGanttTask._do_actual_myself_cost_is_changedc              	   C   s|  | j jrd S | jjr| j | jk r| jd  d| jd  d}| j d  d| j d  d}| jrztd| d| ddd q| j| _ |std	| d
 nd|s| j r| js| jr| j | _	| j
dd | jr| jr| j	| j k rtd| jj d| jj ddd | jjrx| jjdkrx| j jp d| j jp,d }t : | jjj }||   || |jddd W 5 Q R X d S )N<      ч    мu   Нельзя запланировать меньше Трудозатрат, чем запланировано в подзадачах ( < ub   ). Увеличьте Трудозатраты или уменьшите их у подзадач.TrN   u   Указано Трудозатрат меньше, чем запланировано в подзадачах. Выставили uo   . Если нужно уменьшить Трудозатраты, уменьшите их у подзадач.)r   r   rK   u   ) нельзя указать Трудозатраты больше чем Длительность, когда установлена опция Фиксированные Ресурсы и Длительность зафиксирована.ra   r   Fr   )r
   r3   r   rr   agregat_workr   rS   rP   r   r   r   rQ   rR   r   rd   r   r   r   r   r$   r,   re   r/   from_child_agregate_workr    )r0   r   r   r   r
   r   ri   r'   r'   r(   r   G  s8    


z&CmfGanttTask._do_sched_work_is_changedc              	   C   s   | j jrd S | j | jk rX| jr>td| j  d| j ddd n| j| _ td| j d | jjr| jjdkr| j jpvd	| j j	pd	 }t
 : | jjj }||   || |jd
dd W 5 Q R X d S )Nu   Нельзя запланировать меньше Расходов, чем запланировано в подзадачах (r   uX   ). Увеличьте Расходы или уменьшите их у подзадач.TrN   u|   Указано Расходов меньше, чем запланировано в подзадачах. Выставили ue   . Если нужно уменьшить Расходы, уменьшите их у подзадач.ra   r   Fr   )r	   r3   agregat_cost
const_costrS   r   r   rd   r   r   r   r   r$   r,   re   r/   from_child_agregate_costr    r0   r   ri   r'   r'   r(   _do_sched_cost_is_changedv  s     

z&CmfGanttTask._do_sched_cost_is_changedc                 C   s"   | j r| jr|   n|   d S r   )r   r   r   r   r   r'   r'   r(    _do_actual_start_date_is_changed  s    
z-CmfGanttTask._do_actual_start_date_is_changedc                 C   s(   | j s| jr| jr|   n|   d S r   )r   r   r   r   r   r   r'   r'   r(   !_do_actual_finish_date_is_changed  s    
z.CmfGanttTask._do_actual_finish_date_is_changedc                 C   sF   | j dkr|   n.| j dkr0| jjr0|   n| j dkrB|   d S )Nr   r   r   r   )r   r   r   rr   r   r   r   r'   r'   r(   #_do_actual_complete_type_is_changed  s    



z0CmfGanttTask._do_actual_complete_type_is_changedc                 C   s   | j r|   d S r   )rP   r   r   r'   r'   r(   _do_const_duration_is_changed  s    z*CmfGanttTask._do_const_duration_is_changedc                 C   s*   | j rd| _| j| _n| jj| _d | _d S NrA   )r   r   r   r   defaultr   r'   r'   r(   $_do_lock_sched_start_date_is_changed  s
    

z1CmfGanttTask._do_lock_sched_start_date_is_changedc                 C   s*   | j rd| _| j| _n| jj| _d | _d S r   )r   r   r   r   r   r   r'   r'   r(   %_do_lock_sched_finish_date_is_changed  s
    

z2CmfGanttTask._do_lock_sched_finish_date_is_changedc                 C   s|   |sd S |  ddddg |j }| |   || j || j || j	 |
| j ||  |jdd d S )Nr	   r
   r   r   Fr   re   r$   r,   r/   r   r	   r   r
   r   r   r   r   r   r    r0   r   ri   r'   r'   r(   add_child_task_to_parent_task  s    

z*CmfGanttTask.add_child_task_to_parent_taskc                 C   s   |sd S |  ddddg |j }| |   || j  || j  || j	  |
| j  |j| dd |jdd d S )	Nr	   r
   r   r   Tr   Fr   r   r   r'   r'   r(   "remove_child_task_from_parent_task  s    
z/CmfGanttTask.remove_child_task_from_parent_taskc              	   C   sD   t  2 | jj}|r | | | jj}|r6| | W 5 Q R X d S r   )r   r   r   r   r   r   r   )r0   Z
old_parentZ
new_parentr'   r'   r(   _do_parent_task_is_changed  s    

z'CmfGanttTask._do_parent_task_is_changedc                 O   s   t jj| df|| d S )Nupdated)r   ZCmfEventZdo_event)r0   argskwargsr'   r'   r(   _do_event_save  s    zCmfGanttTask._do_event_savec                 O   s
   | | j S r   )Z	log_level)r0   Z
field_namer  r  r'   r'   r(   _get_field_log_level  s    z!CmfGanttTask._get_field_log_levelc                 C   sn  | j r`d| _d| _| jjr\| jjj r\| jjjj }|rNt|t	j
 | _d| _|   d S | jjrt|   d S | jjr|   d S | jjr|   d S | jjs| jjr|   |s|   d S | jjs| jjr|   |s|   d S | jjr|   |s|   d S | jjr&|   d S | jjr<|   d S | jjrR|    d S | j!jrh| "  d S | jjr| #  |s|   d S | j$jr| %  d S | j&jr| '  d S | j(jr| )  d S | j*jr| +  d S | j,jr| -  d S | jjr| .  |s|   d S | j/jrB| 0  |s>|   d S | j1jrX| 2  d S | j3jrj| 4  d S )Nr   r   )5is_newr   r
   r   r   r$   r,   r   rg   dtr?   Zutcnowr   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   r   r   rP   r   r   r   r   r   r   r   r   )r0   from_parent_changesZparent_sched_start_dater'   r'   r(   _save  s    














zCmfGanttTask._savec                 C   sl   |  |   |   |  j|7  _| jdd |d kr\| j| j |kr\| j| | _|   | jdd d S )NTr   r   )	re   r/   r   r   r   r
   r   r   r    )r0   r   Zremaining_estimater'   r'   r(   timetracker_add_work_hookA  s    z&CmfGanttTask.timetracker_add_work_hookc                 C   s(  |rL|j dkrL| jsL| |   |   | j  |   | jdd d S |r|j dkr|r|j dkr| |   |   | j  d| _	| 
  |   | jdd |   d S |r$|j dkr$|r$|j dkr$| |   |   d | _d| _	| 
  |   | jdd |   d S d S )NZIN_PROGRESSTr   r   r1   r   )r   r   re   r/   r   Zset_nowr   r    r   r   r   r   r   )r0   Z
old_statusZ
new_statusr'   r'   r(   task_status_is_changed_hookN  sF    

z(CmfGanttTask.task_status_is_changed_hookc                 C   s6   |  |   |   |   |   | jdd dS )u   
        В задаче изменились Agile-плановые даты, пересчитаем свои sched-даты, вдруг новые ограничения повлияют на них
        Tr   N)re   r/   r   r   r   r    r   r'   r'   r(   task_plan_dates_is_changed_hooku  s
    z,CmfGanttTask.task_plan_dates_is_changed_hookc                 C   s    | j jrd| _ |  j |7  _ d S r   )r   r3   )r0   r   r'   r'   r(   r     s    z CmfGanttTask.from_child_add_workc                 C   s    | j jrd| _ |  j |7  _ d S r   )r   r3   r   r'   r'   r(   r     s    z CmfGanttTask.from_child_add_costc              	   C   s&  | j jrd| _ |  j |7  _ | jsD| j | _| jjp4d| jjp>d }n~| j | jks| j d  d| j d  d}| jd  d| jd  d}td| d| d| j dd	d
 | j jpd| j jpd }| jjr"| jj	dkr"t
 : | jjj }||   || |jdd	d W 5 Q R X d S )Nr   r   r   r   u;   Превысили План на Трудозатраты ( <= +   ) в родительской задаче ub   . Увеличьте в ней план или введите меньше Трудозатрат.TrN   ra   Fr   )r   r3   r   r
   r   r   rS   r   r   rd   r   r   r$   r,   re   r/   r   r    )r0   r   r   r
   ri   r'   r'   r(   r     s&    

z%CmfGanttTask.from_child_agregate_workc              	   C   s   | j jrd| _ |  j |7  _ | js,| j | _n2| j | jks^td| j  d| j d| j ddd | jjr| jjdkr| j jp|d| j j	pd }t
 8 | jjj }||   || |jd	d
 W 5 Q R X d S )Nr   u1   Превысили План на Расходы (r  r  u[   . Увеличьте в ней план или введите меньше РасходовTrN   ra   Fr   )r   r3   r   r	   rS   r   r   rd   r   r   r   r   r$   r,   re   r/   r   r    r   r'   r'   r(   r     s     


z%CmfGanttTask.from_child_agregate_costc                 C   s   |  | dS )u   
        Оповестить родителя, что ему нужно пересчитать свой агрегат actual_complete
        N)r   )r0   r   r'   r'   r(   !from_child_update_actual_complete  s    z.CmfGanttTask.from_child_update_actual_completec              	   C   sV   | j jsdS t 8 | j jj }||   ||  |j	dd W 5 Q R X dS )uP  
        Оповещение родителя.
        Передаем себя, т.к. мы еще можем быть не сохранены и родитель не сможет получить наши данные
        Другой вариант: опочещать через отдельный таск в celery
        NFr   )
r   r   r   r   r$   r,   re   r/   r  r    )r0   ri   r'   r'   r(   r     s    

z1CmfGanttTask.notify_parent_update_actual_completec                 C   s  | j sp| jrpdd | jddD }|ddddh }|rp| jj  | jjrp| jjjjd	rp| jjj	d
| jd | j
jr| jjrtddd | jjr| jjrtddd | jjs| jjr| jr| jr| j| jk rtddd | jjr| jjs| jdkrtddd d S )Nc                 S   s   h | ]\}}|qS r'   r'   ).0k_r'   r'   r(   	<setcomp>  s     z0CmfGanttTask.check_user_input.<locals>.<setcomp>T)r   r   r   r   Zgantt_project_idzCmfProject:zPPP-TSK-SCHEDULE)obju   Нельзя менять поле "Фактические трудозатраты" у Summary-задач. Используйте поле "Фактические трудозатраты по собственным ресурсам задачи"rN   u   Нельзя менять поле "Фактические Затраты" у Summary-задач. Используйте поле "Фактические Затраты по собственным ресурсам задачи"u\   Нельзя выставить Дату начала позже Даты окончанияr   u   Этот вариант рассчета процента завершения можно использовать только у Summary-задач)r  r   itemsr   Zroot_parentr,   r   r*   
startswithZcheck_project_role_accessr   rr   rS   r   r   r   r   )r0   Zchanged_fieldsr'   r'   r(   check_user_input  s0    
zCmfGanttTask.check_user_inputc                 C   s   | j jrd| _ | jjrd| _| jjr*d| _| jjr8d| _| jjrFd| _| jjrTd| _| jjrbd| _| jjrpd| _| j	jr~d| _	| j
jrd| _
| jjrd| _| jjrd| _d S r   )r   r3   r   r	   r   r   r   r   r
   r   r   Zconstrain_slackZconstrain_slack_pctr   r'   r'   r(   r     s0    zCmfGanttTask.fix_null_variablesT)r   r  c                   sP   |r|    | j|| | j|d | jjr:| jjdd |   t j||S )N)r  Tr   )r  r  r	  r   r   r    r   r   )r0   r   r  r  r  r%   r'   r(   r      s    zCmfGanttTask.save)TEXKOM_db_deletec                   s   |  dddg |rVt| j tjj| jddD ] }t| d |_|jdd q2n&| j	r|| j	j| kr|| j	j
s|tddd | | j t j|d	|i|S )
Nztask.op_gantt_taskztask.cmf_deletedr   T)r$   Zinclude_deletedr   uY   Нельзя удалять Оперативную гант задачу у задачи!rN   r  )re   gdebugr   r   r   rs   r$   r    r   Zcmf_deletedrS   r   r   r   delete)r0   r  r  r  r   r%   r'   r(   r    s    
zCmfGanttTask.deletec                    sB   t  jf | | jrd S td tj| jdd td d S )N_CmfAutomationCrudTrigger startupdateZbefore_save_CmfAutomationCrudTrigger end)	r   before_save_hookr  r  r  r   CmfAutomationCrudTrigger	crud_hookr   r0   r  r%   r'   r(   r  -  s    
zCmfGanttTask.before_save_hookc                    sB   t  jf | | jrd S td tj| jdd td d S )Nr  r  Z
after_saver  )	r   before_save_data_hookr  r  r  r   r   r!  r   r"  r%   r'   r(   r#  7  s    
z"CmfGanttTask.before_save_data_hook)N)NF)NF)F)F)F)F)N)NF)F)FFF)F)F)FF)N)N)F)N)N)H__name__
__module____qualname__classmethodr)   r-   r/   propertyr9   r=   r>   r4   rY   r_   rf   rw   r   r   r   r   r   r   r   r   r   r   rv   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	  r
  r  r  r   r   r   r   r  r   r  r   r    r  r  r#  __classcell__r'   r'   r%   r(   r   
   s   




&
'+`

	


%
:>	.
s
E    
"
!



/


W
'

r   )
r?   r  Zcmf.includeZdecimalr   r   r   Z
cmf.fieldsZ#modules.gantt.fields.cmf_gantt_taskr   r'   r'   r'   r(   <module>   s   