U
    yb$h/0                     @   s>   d dl T d dlmZ d dlmZmZmZ G dd dejZdS )    )*)cmf_relation_option)defaultdictdeque
namedtuplec                       s   e Zd ZdZ fddZ fddZeedddgdd	d
d#ddZdd Z	e
dddZ fddZdd Zdd Zd$ddZdd Zdd  Zed%d!d"Z  ZS )&CmfRelationOptionuN    Класс для соединения задач и типов связей c                    s2  t j| dd | j| jkr(tddd dd| jgdd	| jgd
d	| jgdd	| jgg}t jj	|drntddd | j
jdkr| ddddg |  rtddd | j
jdkr|  rtddd t j||}t j| dd | j
jdkr.| js| jjr.| jjjr.| jjjr.tt jj| jjddd |S )Nupdatebefore_saveuV   Внимание! Нельзя связывать задачу саму с собой!T)abortidz!=out_link==in_linkrelation_type_id)filteru2   Такая связь уже существует.)system.finish:startzsystem.finish:finishz+in_link.parent_task.cache_branch_gantt_pathz,out_link.parent_task.cache_branch_gantt_pathz'out_link.op_gantt_task.sched_start_datez(out_link.op_gantt_task.sched_finish_dateum   Невозможно связать суммарную задачу с одной из ее подзадач.r   u   Невозможно связать задачи, так как они уже связаны через другую последовательность задач.
after_savecreate)task_idaction)kwargs)modelsCmfAutomationCrudTrigger	crud_hookr   r   Z	cmf_alertr   r   r   sgetrelation_typecodeload_fieldshas_parent_child_relationshas_start_finish_loopsupersaveZis_newconstrain_lagZ
is_changedop_gantt_tasksched_start_datesched_finish_dateZschedule_deferred_jobsort_task_by_order_relations)selfargsr   Zduplicate_filterres	__class__ ,./modules/task/models/cmf_relation_option.pyr!   
   s6    



zCmfRelationOption.savec                    s2   t j| dd t j||}t j| dd |S )Ndeleter	   r   )r   r   r   r    r.   )r'   r(   r   r)   r*   r,   r-   r.   -   s    zCmfRelationOption.deleteTr      uc   Вычисление плановых дат у задач от выставленной связи)Z	only_onceZshow_bg_progressbarZonly_once_argsprioritydescriptionNr   c              	   C   sb  t d|  d|  | d kr"d S |s,t }| |kr8d S ||  tjjdd| gdddgd}|sfd S |jj}|svd S tj	j
d	dd
gdd|ggdddddddgd}|D ]}|j}|jjr|dkr|dksqt|jjpd}	||jjkr|j}
|	r|jj}tj||
|	}
|jj|
dd}
|
|j_|jjdd |d rBt  tj	j|jj||d d qd S )Nz,sort_task_by_order_relations start task_id: z	, depth: r   r   r#   zop_gantt_task.sched_finish_datezproject.calendar.timezoner   Zfieldsrelation_type.coder   r   z&in_link.op_gantt_task.sched_start_datezin_link.op_gantt_task.is_manualz+in_link.op_gantt_task.constrain_finish_typez$in_link.op_gantt_task.const_durationz*in_link.op_gantt_task.constrain_start_datez*in_link.op_gantt_task.constrain_start_typer"   r   r   T)Zreturn_correct_date)Zfrom_sort_order
   r/   )pathdepth)gdebugsetaddr   ZCmfTaskgetr#   r%   r   listr   Z	is_manualintr"   valuer$   projectcalendarZCmfCalendarZget_date_by_durationZcheck_correct_start_dater!   Z
cmf_commitr&   r   )r   r   r5   r6   ZtaskZtask_finish_dateZfollowing_linksZfollowing_linkZfollowing_taskr"   Znew_start_dater@   r,   r,   r-   r&   3   sb    


z.CmfRelationOption.sort_task_by_order_relationsc                    s:   t j \}t t  fdd  | jjjS )Nc                    sd   | krdS | krdS  |   |  | g D ]\}} |}|r8|  S q8|  dS )NTF)r:   r;   remove)ZnodeZneighbor_resultdfsZ	stack_settask_out_linksZvisitedr,   r-   rE   t   s    



z4CmfRelationOption.has_start_finish_loop.<locals>.dfs)r   r   get_start_finish_graphsr9   r   op_gantt_task_idr>   )r'   rB   r,   rD   r-   r   n   s
    z'CmfRelationOption.has_start_finish_loop)returnc                 C   s   d}| j jr| j j| jks0| jjr4| jj| j kr4d}|sf| j jrf| j jjD ]}|d | jjjkrJd}qJ|s| jjr| jjjD ]}|d | j jjkr|d}q||S )u   
        Проверяет, что связанные задачи не находятся друг у друга в родителях
        FTr   )r   Zparent_taskr   Zcache_branch_gantt_pathr   r>   )r'   Zrelatedtr,   r,   r-   r      s&    z,CmfRelationOption.has_parent_child_relationsc                    s   t   dg S )Nr   )r    save_preload_fieldsr'   r*   r,   r-   rK      s    z%CmfRelationOption.save_preload_fieldsc                 C   sV   |  ddg | jr0| jjr0| jjjd| jd | jrR| jjrR| jjjd| jd d S Nzout_link.projectzin_link.projectzPPP-TSK-LINK)objr   r   r?   Zcheck_project_role_accessr   rL   r,   r,   r-   check_edit_perm   s
    z!CmfRelationOption.check_edit_permc                 C   sV   |  ddg | jr0| jjr0| jjjd| jd | jrR| jjrR| jjjd| jd d S rM   rO   rL   r,   r,   r-   check_delete_perm   s
    z#CmfRelationOption.check_delete_permr   c              	   C   s
  |  ddg tjsd S | jr| jjr| jjjjdkrtjtjjjdgd| jjjdgtj	| jjjjd}t
d|d	  ||d	 |d	 gd
 | jr| jjr| jjjjdkrtjtjjjdgd| jjjdgtj	| jjjjd}t
d|d	  ||d	 |d	 gd
 d S )Nzout_link.parent.idzin_link.parent.idZ
CmfProjectproject_notifyr   Zin_tasks)ZinitiatorSessionTabIdZinitiatorCurrentPersonr   ZinitiatorActionZinitiatorObjIdZinitiatorObjChangedFieldsu   initiatorСomponentId	projectIdzproject_notify-rS   )ZroomZevent_personsZ	out_tasks)r   r7   Zsession_tab_idr   parentr>   
class_nameZcurrent_personr   Zcomponent_idZcmf_emit_eventr   )r'   Zinitiator_actionZeventr,   r,   r-   rR      s4    

$$

z CmfRelationOption.project_notifyc                 O   s   t jj| df|| d S )Nupdatedr   ZCmfEventZdo_eventr'   r(   r   r,   r,   r-   _do_event_save   s    z CmfRelationOption._do_event_savec                 O   s   t jj| df|| d S )NZdeletedrW   rX   r,   r,   r-   _do_event_deleted   s    z#CmfRelationOption._do_event_deletedc                    s    fdd}t tt t dddg}dddggg}tjj||d	D ]<}|jj |jj|j	f  |jj |jj|j	f qF| r|| S  fS )
Nc                    s~   t | }t }t }t }|rv| }| ||<  | ||< || || ||  D ]\}}||krX|| qXq||fS )N)r   r9   dictpopleftr:   append)gantt_task_idqZdoneZfiltered_task_out_linksZfiltered_task_in_linksZcurelrB   Ztask_in_linksrF   r,   r-   _filter_by_gantt_task_id   s    
zKCmfRelationOption.get_start_finish_graphs.<locals>._filter_by_gantt_task_idzin_link.op_gantt_taskzout_link.op_gantt_taskr"   r3   INr   r2   )
r   r<   r   r   Zslistr   rH   r]   r   r"   )r^   rb   Z
rel_fieldsZ
rel_filterrelr,   ra   r-   rG      s    
z)CmfRelationOption.get_start_finish_graphs)NNNr   )r   )N)__name__
__module____qualname____doc__r!   r.   staticmethodZcmf_deferred_jobr&   r   boolr   rK   rP   rQ   rR   rY   rZ   rG   __classcell__r,   r,   r*   r-   r      s$   #8
!r   N)Zcmf.includeZmodules.task.fieldsr   collectionsr   r   r   r   r,   r,   r,   r-   <module>   s   