U
    hMT                     @   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	dd Z
edddZ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              
      st  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rt jj	dd	dgd
d| j| jggdd| j| jgggdrtddd | ddddg |  rtddd |  rtddd | j
jdkr| ddddddddg | jj| jks>| jj| jkrJtddd |  r`td dd ddd!d"d#d$ggd
d| j| jggdd| j| jggg}t jj	|drtd%dd |   t j||}t j| dd& | j
jdkr| jj  | j
jdkrP| js| jjrP|d'd(sP| jjjrP| jjjrPtt jj| jjd)d*d+ | j  | j  t j |  |S ),Nupdatebefore_saveuV   Внимание! Нельзя связывать задачу саму с собой!Tabortidz!=out_link==in_linkrelation_type_idfilteru2   Такая связь уже существует.)system.finish:startsystem.finish:finishsystem.start:startsystem.start:finishrelation_type.codesystem.additional_parentINu   Невозможно связать задачи связью ОО/ОН/НН/НО, так как они связаны связью Дополнительный родитель/Дополнительная дочерняя задача.+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   Невозможно связать суммарную задачу с одной из ее подзадач.u   Невозможно связать задачи, так как они уже связаны через другую последовательность задач.in_link.op_gantt_taskout_link.op_gantt_taskz out_link.cache_branch_gantt_pathzout_link.has_child_taskszin_link.cache_branch_gantt_pathin_link.has_child_tasksu  Невозможно связать задачи связью Дополнительный родитель/Дополнительная дочерняя задача, так как они являются родительской и дочерней задачами.u  Невозможно связать задачи связью Дополнительный родитель/Дополнительная дочерняя задача, так как они связаны через другую последовательность задач.r   r   r   r   u   Невозможно связать задачи связью Дополнительный родитель/Дополнительная дочерняя задача, так как они связаны связью ОО/ОН/НН/НО.
after_saveZfrom_task_copyFcreate)task_idaction)kwargs)!modelsCmfAutomationCrudTrigger	crud_hookr   r   	cmf_alertr   r   r   sgetrelation_typecodeload_fieldshas_parent_child_relationshas_start_finish_loopparent_taskhas_additional_parent_loop'_check_additional_parent_task_relationssupersaveop_gantt_task*additional_children_relations_changed_hookZis_newconstrain_lagZ
is_changedgetsched_start_datesched_finish_dateZschedule_deferred_jobsort_task_by_order_relationshas_related_tasks_hookCmfBackbonePeerZobj_after_save_hook)selfargsr"   Zduplicate_filter_filterres	__class__ ,./modules/task/models/cmf_relation_option.pyr1   
   s    



 
 



zCmfRelationOption.savec                    s   t j| dd | dg t j||}| j  | j  | j	j
dkrb| dg | jj  t j| dd t j|  |S )Ndeleter	   r(   r   r   r   )r#   r$   r%   r*   r0   rC   r   r9   r   r(   r)   r2   r3   r:   Zobj_after_delete_hook)r;   r<   r"   r>   r?   rA   rB   rC   \   s    

zCmfRelationOption.deleteTr       uc   Вычисление плановых дат у задач от выставленной связи)Z	only_onceZshow_bg_progressbarZonly_once_argsprioritydescriptionNr   c              
   C   sh  | d krd S |st  }| |kr"d S ||  tjjdd| gddddgd}|sRd S td|jj d	|j	j d
|j
j d|  |j
j}|j
j}|sd S |jj}tjjddddddggdd|ggddddgd}|D ]}	|	j}
|
j
}||  |jr|dkr|dksqt|	jjpd}|	jj	dkrN|j}|rtj|||}n|	jj	dkr|j| pjd}tj||j| }n`|	jj	dkr|j}|rtj|||}n4|	jj	dkr|j| pd}tj||j| }nq|j|dd}||jkrq||_|jjr||jjk r(| r(q|jdd |d dkrHt  tjj |
j!j||d d qd S )Nr   r   r2   zop_gantt_task.sched_finish_datezop_gantt_task.sched_start_datezproject.calendar.timezoner   Zfieldsz,sort_task_by_order_relations start task_id: z (z), sched_finish_date z	, depth: r   r   r   r   r   r   r   r   r   r4   r   r   T)Zreturn_correct_date)Zfrom_sort_order
   rD   )pathdepth)"setaddr#   CmfTaskr5   gdebugnamevaluer)   r2   r7   r6   projectcalendarr   listr   r*   save_preload_fieldsZ	is_manualintr4   r(   ZCmfCalendarZget_date_by_durationZsched_durationZcheck_correct_start_dateoldZ _get_task_blocking_back_movementr1   Z
cmf_commitr8   r   )r    r!   rI   rJ   taskZtask_finish_dateZtask_start_daterS   Zfollowing_linksZfollowing_linkZfollowing_taskZfollowing_gantt_taskr4   Znew_start_dateZdurationrA   rA   rB   r8   p   s    
 .



z.CmfRelationOption.sort_task_by_order_relationsc                 C   sp   | j }| j}t }|jr,|dd |jD B }|jr`|jjrP|dd |jjD B }||jjj |j|d d S )Nc                 S   s   h | ]}|d  qS r   rA   .0trA   rA   rB   	<setcomp>   s     zLCmfRelationOption._check_additional_parent_task_relations.<locals>.<setcomp>c                 S   s   h | ]}|d  qS rY   rA   rZ   rA   rA   rB   r]      s     )Z
gantt_path)	r   r   rK   cache_branch_gantt_pathr-   rL   r   rQ   Z_check_additional_relations)r;   Z
add_parentZ	add_childZadd_parent_gantt_pathrA   rA   rB   r/      s    z9CmfRelationOption._check_additional_parent_task_relationsc                    s@   | j dddd\}t t  fdd  | jjjS )NT)include_finish_finishinclude_start_startinclude_start_finishc                    sd   | krdS | krdS  |   |  | g D ]\}} |}|r8|  S q8|  dS NTF)rL   r5   remove)nodeneighbor_resultdfs	stack_settask_out_linksvisitedrA   rB   ri      s    



z4CmfRelationOption.has_start_finish_loop.<locals>.dfs)get_start_finish_graphsrK   r   op_gantt_task_idrQ   )r;   rf   rA   rh   rB   r,      s
    z'CmfRelationOption.has_start_finish_loop)returnc                    sN   t jjdddgdjd
 fdd	  fdd	}|| j| jpL|| j| jS )u   
        Проверяет, что связанные задачи не находятся друг у друга в родителях
        r)   r   r   r   r   c                    s   |dkrt ddd t }ddgdd| gg}dd	g}tjj||d
D ]N}|j}|jr|jjrz|jjD ]}||d  qf||jj	 ||j	 qFt }|D ]"}	 |	|d d}
|
r|
|
 q|
| |S )Nd   ui   DEV: Защита от рекурсии: cmf_realtion_option.has_parent_child_relations: if r_count > 100Tr
   r   r   Zout_link_idr   r   rG   r   rD   )r_count)r&   rK   r#   r   slistr   r-   r^   rL   r   r   )r    rq   additional_parent_idsr=   _fieldsrelZadd_parent_taskr\   Zsub_additional_parent_idsr   additional_ids_add_additional_parent_idsZadditonal_parent_type_idrA   rB   rx      s0    
zPCmfRelationOption.has_parent_child_relations.<locals>._add_additional_parent_idsc                    s   t |jjg}|jrH||jjj |jjrH|jjD ]}||d  q4t  }|D ]} |}|rR|| qR|| | jj|kS )Nr   )rK   r   rQ   r-   rL   r^   r   )childparentZparent_task_idsr\   Zadditional_parent_task_idsr   rv   )rx   rA   rB   _find_in_parents  s    
zFCmfRelationOption.has_parent_child_relations.<locals>._find_in_parents)r   )r#   ZCmfRelationTyper'   r   r   r   )r;   r{   rA   rw   rB   r+      s     z,CmfRelationOption.has_parent_child_relationsc                    s6   t  t  dd  fdd  | jjjjS )Nc                 S   sz   g }t jjdd| gdgd}|r4|jr4||jj dd| gdddgg}t jj|d	gd}|rvd
d |D }|| |S )Nrn   r   zparent_task.op_gantt_task_idrG   zout_link.op_gantt_task_id=r   r   zin_link.op_gantt_task_idc                 S   s   g | ]}|j jqS rA   )r   rn   )r[   ru   rA   rA   rB   
<listcomp><  s     zXCmfRelationOption.has_additional_parent_loop.<locals>.get_parent_ids.<locals>.<listcomp>)	r#   rM   r'   r-   appendrn   r   rr   extend)gantt_task_idZ
parent_idsrX   r=   Zadditional_parents_relationsrs   rA   rA   rB   get_parent_ids/  s    

zDCmfRelationOption.has_additional_parent_loop.<locals>.get_parent_idsc                    s\   | krdS | krdS  |   |  | D ]} |}|r4|  S q4|  dS rb   )rL   rc   )rd   re   rg   ri   r   rj   rl   rA   rB   ri   A  s    



z9CmfRelationOption.has_additional_parent_loop.<locals>.dfs)rK   r   r2   r   rQ   r;   rA   r   rB   r.   *  s
    z,CmfRelationOption.has_additional_parent_loopc                    s   t   dddg S )Nr(   zout_link.project_idzin_link.project_id)r0   rU   r   r?   rA   rB   rU   V  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   rR   Zcheck_project_role_accessr   r   rA   rA   rB   check_edit_permY  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 r   r   r   rA   rA   rB   check_delete_perma  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-r   )ZroomZevent_personsZ	out_tasks)r*   rN   Zsession_tab_idr   rz   rQ   
class_nameZcurrent_personr   Zcomponent_idZcmf_emit_eventr   )r;   Zinitiator_actionZeventrA   rA   rB   r   h  s4    

$$

z CmfRelationOption.project_notifyc                 O   s   t jj| df|| d S )Nupdatedr#   ZCmfEventZdo_eventr;   r<   r"   rA   rA   rB   _do_event_save  s    z CmfRelationOption._do_event_savec                 O   s   t jj| df|| d S )NZdeletedr   r   rA   rA   rB   _do_event_deleted  s    z#CmfRelationOption._do_event_deletedFc           	         s    fdd}t tt t dddg}dg}|r<|d |rJ|d |rX|d	 d
d|gg}tjj||dD ]<}|jj |jj|j	f  |jj |jj|j	f qt| r|| S  fS )Nc                    s~   t | }t }t }t }|rv| }| ||<  | ||< || || ||  D ]\}}||krX|| qXq||fS )N)r   rK   dictpopleftrL   r~   )r   qZdoneZfiltered_task_out_linksZfiltered_task_in_linksZcurelrf   Ztask_in_linksrk   rA   rB   _filter_by_gantt_task_id  s    
zKCmfRelationOption.get_start_finish_graphs.<locals>._filter_by_gantt_task_idr   r   r4   r   r   r   r   r   r   rG   )
r   rT   r~   r#   r   rr   r   rn   r   r4   )	r   r_   r`   ra   r   Z
rel_fieldsZ	rel_typesZ
rel_filterru   rA   r   rB   rm     s,    


z)CmfRelationOption.get_start_finish_graphs)NNNr   )r   )NFFF)__name__
__module____qualname____doc__r1   rC   staticmethodZcmf_deferred_jobr8   r/   r,   boolr+   r.   rU   r   r   r   r   r   rm   __classcell__rA   rA   r?   rB   r      s.   RR;,
!    r   N)Zcmf.includeZmodules.task.fieldsr   collectionsr   r   r   r   rA   rA   rA   rB   <module>   s   