U
    gU/                     @   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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                    s4  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r0| js| jjr0| jjjr0| jjjr0tt jj| jjgddi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actioncreate)args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)selfr   r   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.deleteT   uc   Вычисление плановых дат у задач от выставленной связи)Z	only_onceZshow_bg_progressbarprioritydescriptionNr   c              	   C   s6  |s
t  }| |krd S ||  tjjdd| gdddgd}|jj}|sLd 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sq~t|jjpd}	||jjkr~|j}
|	r|jj}tj||
|	}
|jj|
dd}
|
|j_|jjdd |d rt  tjj|jj||d d q~d S )Nr   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)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   )Ztask_idr   r4   r5   ZtaskZtask_finish_dateZfollowing_linksZfollowing_linkZfollowing_taskr"   Znew_start_dater=   r+   r+   r,   r&   3   sX    


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)r7   r8   remove)ZnodeZneighbor_resultdfsZ	stack_settask_out_linksZvisitedr+   r,   rB   k   s    



z4CmfRelationOption.has_start_finish_loop.<locals>.dfs)r   r   get_start_finish_graphsr6   r   op_gantt_task_idr;   )r'   r?   r+   rA   r,   r   e   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,   rH      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   rI   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 rJ   rL   rI   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-rP   )ZroomZevent_personsZ	out_tasks)r   gZsession_tab_idr   parentr;   
class_nameZcurrent_personr   Zcomponent_idZcmf_emit_eventr   )r'   Zinitiator_actionZeventr+   r+   r,   rO      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deletedrU   rV   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   r6   dictpopleftr7   append)gantt_task_idqZdoneZfiltered_task_out_linksZfiltered_task_in_linksZcurelr?   Ztask_in_linksrC   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"   r2   INr   r1   )
r   r9   r   r   Zslistr   rE   r[   r   r"   )r\   r`   Z
rel_fieldsZ
rel_filterrelr+   r_   r,   rD      s    
z)CmfRelationOption.get_start_finish_graphs)NNr   )r   )N)__name__
__module____qualname____doc__r!   r-   staticmethodZcmf_deferred_jobr&   r   boolr   rH   rM   rN   rO   rW   rX   rD   __classcell__r+   r+   r)   r,   r      s$   #/
!r   N)Zcmf.includeZmodules.task.fieldsr   collectionsr   r   r   r   r+   r+   r+   r,   <module>   s   