
    @i{U                     T    d dl T d dlmZ d dlmZmZmZ  G d dej                  ZdS )    )*)cmf_relation_option)defaultdictdeque
namedtuplec                        e Zd ZdZ fdZ fdZe edddgdd          dd                        Zd Z	d Z
defdZd Z fdZd Zd ZddZd Zd Ze	 	 dd            Z xZS )CmfRelationOptionuN    Класс для соединения задач и типов связей c                 &   t           j                            | dd           | j        | j        k    rt          dd           dd| j        gdd	| j        gd
d	| j        gdd	| j        gg}t           j        	                    |          rt          dd           | j
        j        dv rt           j        	                    g dd
d| j        | j        ggdd| j        | j        ggg          rt          dd           |                     g d           |                                 rt          dd           |                                 rt          dd           | j
        j        dk    r|                     g d           | j        j        | j        k    s| j        j        | j        k    rt          dd           |                                 rt          dd           ddg dgd
d| j        | j        ggdd| j        | j        ggg}t           j        	                    |          rt          dd           |                                   t%                      j        |i |}t           j                            | dd           | j
        j        dk    r| j        j                                         | j
        j        dv rx| j        s| j        j        re|                    dd          sO| j        j        j        r>| j        j        j        r-t9          t           j        j        | j        j        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.coder   system.additional_parentINu   Невозможно связать задачи связью ОО/ОН/НН/НО, так как они связаны связью Дополнительный родитель/Дополнительная дочерняя задача.)+in_link.parent_task.cache_branch_gantt_path,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   Невозможно связать задачи, так как они уже связаны через другую последовательность задач.r   )in_link.op_gantt_taskout_link.op_gantt_taskr   z out_link.cache_branch_gantt_pathzout_link.has_child_tasksr   zin_link.cache_branch_gantt_pathin_link.has_child_tasksu  Невозможно связать задачи связью Дополнительный родитель/Дополнительная дочерняя задача, так как они являются родительской и дочерней задачами.u  Невозможно связать задачи связью Дополнительный родитель/Дополнительная дочерняя задача, так как они связаны через другую последовательность задач.r   u   Невозможно связать задачи связью Дополнительный родитель/Дополнительная дочерняя задача, так как они связаны связью ОО/ОН/НН/НО.
after_save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_hookis_newconstrain_lag
is_changedgetsched_start_datesched_finish_dateschedule_deferred_jobsort_task_by_order_relationshas_related_tasks_hookCmfBackbonePeerobj_after_save_hook)selfargsr(   duplicate_filter_filterres	__class__s         ,./modules/task/models/cmf_relation_option.pyr7   zCmfRelationOption.save
   s   '11$-PPPMT\))nvz{{{{ 4!t}-dl+t'<=	
 #((0@(AA 	XJRVWWWW"  'C  C  C',,5m5m5m6?W[WcGd5ehrtx{  |I  KO  KW  {X  hY5Z, [ [ S F NRS S S S        ..00 W  J  RV  W  W  W  W))++ O  B  JN  O  O  O  O"&@@@ 	 	 	 	 	 	 }(DL88DL<TX\Xe<e<e A IMN N N N ..00 V I QUV V V V &t  .J  .J  .J  KD4=$,"?@TDM4<#@AG
 ',,G,<< o bimo o o o 88:::egglD+F++'11$,OOO"&@@@L&QQSSS#  (D  D  D D $ 2 = DJJ/77 D }*; V@[@m V$V%=%Zoso|o  LT  dU  dU  V  V  V  V++---,,...224888
    c                    t           j                            | dd           |                     g d            t	                      j        |i |}| j                                         | j                                         | j	        j
        dk    r4|                     dg           | j        j                                         t           j                            | dd           t           j                            |            |S )Ndeleter   )r.   relation_type.out_type_namerelation_type.in_type_namer   r    r#   )r)   r*   r+   r0   r6   rN   r   rB   r   r.   r/   r8   r9   rC   obj_after_delete_hook)rE   rF   r(   rI   rJ   s       rK   rN   zCmfRelationOption.delete\   s   '11$-PPP 
 
 
 	 	 	 eggnd-f--++---,,..."&@@@'    L&QQSSS'11$,OOO44T:::
rL   Tr&      uc   Вычисление плановых дат у задач от выставленной связи)	only_onceshow_bg_progressbaronly_once_argsprioritydescriptionNr   c           
      J   | d S |st                      }| |v rd S |                    |            t          j                            dd| gg d          }|sd S t
                              d|j        j         d|j	        j         d|j
        j         d|            |j
        j        }|j
        j        }|sd S |j        j        }t          j                            d	d
g dgdd|ggg d          }|D ],}	|	j        }
|
j
        }|                    |                                           |j        r|dk    r|dk    sLt+          |	j        j        pd          }|	j        j	        dk    r+|j        }|r!t          j                            |||          }n|	j        j	        dk    r:|j        j        pd}||z
  }t          j                            ||j        |          }n|	j        j	        dk    r+|j        }|r!t          j                            |||          }nL|	j        j	        dk    r:|j        j        pd}||z
  }t          j                            ||j        |          }ns|                    |d          }||j        k    r||_        |j        j        r||j        j        k     r|                                r|                    d           |dz  dk    rt?                       t          j                             |
j!        j        ||dz              .d S )Nr   r   )r8   zop_gantt_task.sched_finish_datezop_gantt_task.sched_start_datezproject.calendar.timezoner   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   r%   r   r   r   r   T)return_correct_date)from_sort_order
   rR   )pathdepth)"setaddr)   CmfTaskr=   gdebugnamevaluer/   r8   r?   r>   projectcalendarr	   listr   r0   save_preload_fields	is_manualintr;   r.   CmfCalendarget_date_by_durationsched_durationcheck_correct_start_dateold _get_task_blocking_back_movementr7   
cmf_commitrA   r   )r&   r'   r^   r_   tasktask_finish_datetask_start_daterh   following_linksfollowing_linkfollowing_taskfollowing_gantt_taskr;   new_start_datedurationshifts                   rK   rA   z.CmfRelationOption.sort_task_by_order_relationst   s   
 ?F 	55Dd??F~!!$g)>*i *i *i " j j  	F	  oty  o  oRVR[Ra  o  ox|  yK  y]  o  o  hm  o  o  	p  	p  	p-?,= 	F<( 277AUW[  ^z  ^z  ^z  A{AKTSW@X@Z@V @V @V 8 W W
 . 3	w 3	wN+3N#1#?  ,,-A-U-U-W-WXXX
 %.!((:(: < B GaHHM+04III!1!7  v%+%7%L%LXWegt%u%uN-26LLL/>DI%0!'!3!H!HScSikp!q!q-26JJJ!0!6  v%+%7%L%LXWegt%u%uN-26KKK/>DI%0!'!3!H!HSbShjo!p!p1JJ>osJttN!5!FFF4B 1(9= !$8$I$MMM'HHJJ  %%d%;;;rzQ$AA.BSBY`dlqtuluAvvvvg3	w 3	wrL   c                 @   | j         }| j        }t                      }|j        r|d |j        D             z  }|j        rI|j        j        r|d |j        j        D             z  }|                    |j        j        j                   |                    |           d S )Nc                     h | ]
}|d          S r    .0ts     rK   	<setcomp>zLCmfRelationOption._check_additional_parent_task_relations.<locals>.<setcomp>   s    <q<q<qQtW<q<q<qrL   c                     h | ]
}|d          S r   r   r   s     rK   r   zLCmfRelationOption._check_additional_parent_task_relations.<locals>.<setcomp>   s4      AB  AB  ABQ4  AB  AB  ABrL   )
gantt_path)	r   r   r`   cache_branch_gantt_pathr3   ra   r   rf   _check_additional_relations)rE   
add_parent	add_childadd_parent_gantt_paths       rK   r5   z9CmfRelationOption._check_additional_parent_task_relations   s    ]
L	 #- 	r$9<q<qjNp<q<q<q$q!! 	G%= B(=  AB  ABR\Rh  SA  AB  AB  AB  )B%!%%j&<&?&EFFF--9N-OOOOOrL   c                     |                      ddd          \  }t                      t                      fd | j        j        j                  S )NT)include_finish_finishinclude_start_startinclude_start_finishc                     | v rdS | v rdS                      |                                 |                                | g           D ]\  }} |          }|r|c S                     |            dS NTF)ra   r=   remove)nodeneighbor_resultdfs	stack_settask_out_linksvisiteds       rK   r   z4CmfRelationOption.has_start_finish_loop.<locals>.dfs   s    y  twuKKMM$-11$;; " "!X "!MMM" T"""5rL   )get_start_finish_graphsr`   r   op_gantt_task_idrf   )rE   r   r   r   r   r   s     @@@@rK   r2   z'CmfRelationOption.has_start_finish_loop   s     88tim  EI8  J  J%%EE		 	 	 	 	 	 	 	& s4=17888rL   returnc                     t           j                            g d          j        dfd	fd} || j        | j                  p || j        | j                  S )u   
        Проверяет, что связанные задачи не находятся друг у друга в родителях
        )r/   r   r   r   r   c                 N   |dk    rt          dd           t                      }ddgdd| gg}dd	g}t          j                            ||
          D ]}|j        }|j        rU|j        j        r*|j        j        D ]}|                    |d                    |                    |j        j	                   |                    |j	                   t                      }|D ])}	 |	|dz             }
|
r|
                    |
           *|
                    |           |S )Nd   ui   DEV: Защита от рекурсии: cmf_realtion_option.has_parent_child_relations: if r_count > 100Tr   r   r   out_link_idr   r"   rY   r   rR   )r_count)r,   r`   r)   r	   slistr   r3   r   ra   r   r   )r&   r   additional_parent_idsrH   _fieldsreladd_parent_taskr   sub_additional_parent_idsr   additional_ids_add_additional_parent_idsadditonal_parent_type_ids              rK   r   zPCmfRelationOption.has_parent_child_relations.<locals>._add_additional_parent_ids   s   }}  F  NR  S  S  S  S$'EE! $T+CDg.G C.0G /55WW5UU > >"%+". N&2J ?!0!<!T ? ?A155ag>>>>)--o.I.LMMM%))/*<====(+%+ E E!;!;BRS!T!T!T! E-44^DDD!(()BCCC((rL   c                    t          |j        j        g          }|j        rZ|                    |j        j        j                   |j        j        r*|j        j        D ]}|                    |d                    t                      }|D ]$} |          }|r|                    |           %|                    |           | j        j        |v S )Nr   )r`   r   rf   r3   ra   r   r   )childparentparent_task_idsr   additional_parent_task_idsr   r   r   s          rK   _find_in_parentszFCmfRelationOption.has_parent_child_relations.<locals>._find_in_parents  s    !69?"344O! 5##F$6$9$?@@@%= 5#/G 5 5'++AdG4444),&% F F!;!;B!?!?! F.55nEEE""#=>>>8>_44rL   )r   )r)   CmfRelationTyper-   r   r   r   )rE   r   r   r   s     @@rK   r1   z,CmfRelationOption.has_parent_child_relations   s     $*#9#>#>FpFpFp#>#q#q#t 	) 	) 	) 	) 	) 	) 	)@	5 	5 	5 	5 	5&  dm<<m@P@PQUQ^`d`l@m@mmrL   c                     t                      t                      d fd | j        j        j        j                  S )Nc                 @   g }t           j                            dd| gdg          }|r&|j        r|                    |j        j                   dd| gg dg}t           j                            |dg          }|r!d	 |D             }|                    |           |S )
Nr   r   zparent_task.op_gantt_task_idrY   zout_link.op_gantt_task_id=)r   r   r   zin_link.op_gantt_task_idc                 &    g | ]}|j         j        S r   )r   r   )r   r   s     rK   
<listcomp>zXCmfRelationOption.has_additional_parent_loop.<locals>.get_parent_ids.<locals>.<listcomp>B  s    (n(n(n#)E(n(n(nrL   )	r)   rb   r-   r3   appendr   r	   r   extend)gantt_task_id
parent_idsrt   rH   additional_parents_relationsr   s         rK   get_parent_idszDCmfRelationOption.has_additional_parent_loop.<locals>.get_parent_ids5  s    J>&&/A4.Wa  aA&  B  BD E( E!!$"2"CDDD -c=AGGGG ,2+C+I+IQXb|a}+I+~+~(+ 9(n(nQm(n(n(n%!!"7888rL   c                     | v rdS | v rdS                      |                                 |             |           D ]} |          }|r|c S                     |            dS r   )ra   r   )r   r   r   r   r   r   r   s      rK   r   z9CmfRelationOption.has_additional_parent_loop.<locals>.dfsG  s    y  twuKKMM$*N400 " "X "!MMM" T"""5rL   )r`   r   r8   r   rf   )rE   r   r   r   r   s    @@@@rK   r4   z,CmfRelationOption.has_additional_parent_loop0  sl    %%EE		 	 	$	 	 	 	 	 	 	 	& s4=.17888rL   c                 N    t                                                      g dz   S )N)r.   zout_link.project_idzin_link.project_idrO   rP   )r6   rj   )rE   rJ   s    rK   rj   z%CmfRelationOption.save_preload_fields\  s/    ww**,, 0
 0
 0
 
 	
rL   c                     |                      ddg           | j        r2| j        j        r&| j        j                            d| j                   | j        r4| j        j        r*| j        j                            d| j                   d S d S d S Nzout_link.projectzin_link.projectzPPP-TSK-LINK)objr0   r   rg   check_project_role_accessr   rE   s    rK   check_edit_permz!CmfRelationOption.check_edit_perme  s    ,.?@AAA= 	_T]2 	_M!;;NPTP];^^^< 	]DL0 	]L ::>t|:\\\\\	] 	] 	] 	]rL   c                     |                      ddg           | j        r2| j        j        r&| j        j                            d| j                   | j        r4| j        j        r*| j        j                            d| j                   d S d S d S r   r   r   s    rK   check_delete_permz#CmfRelationOption.check_delete_permm  s    ,.?@AAA= 	_T]2 	_M!;;NPTP];^^^< 	]DL0 	]L ::>t|:\\\\\	] 	] 	] 	]rL   r   c           	         |                      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
           | 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 S d S d S d S )Nzout_link.parent.idzin_link.parent.id
CmfProjectproject_notifyr   in_tasks)initiatorSessionTabIdinitiatorCurrentPersonr'   initiatorActioninitiatorObjIdinitiatorObjChangedFieldsu   initiatorСomponentId	projectIdzproject_notify-r   )roomevent_persons	out_tasks)r0   rc   session_tab_idr   r   rf   
class_namecurrent_personr   component_idcmf_emit_eventr   )rE   initiator_actionevents      rK   r   z CmfRelationOption.project_notifyt  s    	.0CDEEE	 F= 	GT]1 	Gdm6J6P6[_k6k6k)*)9*+*:*=*C+,#+"&-"2"8.8\)*!]14:	 	E AU;-?AA5uU`Oarw  yD  sE  rF  G  G  G  G< 	GDL/ 	GDL4G4M4X\h4h4h)*)9*+*:*=*C+,#+"&,/"7.9])*!\039	 	E AU;-?AA5uU`Oarw  yD  sE  rF  G  G  G  G  G  G	G 	G 	G 	G4h4hrL   c                 <    t          j        j        | dg|R i | d S )Nupdatedr)   CmfEventdo_eventrE   rF   r(   s      rK   _do_event_savez CmfRelationOption._do_event_save  s/     	 yB4BBB6BBBBBrL   c                 <    t          j        j        | dg|R i | d S )Ndeletedr   r   s      rK   _do_event_deletedz#CmfRelationOption._do_event_deleted  s-     yB4BBB6BBBBBrL   Fc                 H  	
 	
fd}t          t                    
t          t                    	g d}dg}|r|                    d           |r|                    d           |r|                    d           dd|gg}t          j                            ||	          D ]n}
|j        j                                     |j        j        |j	        f           	|j        j                                     |j        j        |j	        f           o| r ||           S 
	fS )
Nc                 d   t          |           }t                      }t                      }t                      }|rq|                                }	|         ||<   |         ||<   |                    |           ||         ||         z   D ]\  }}||vr|                    |           |q||fS )N)r   r`   dictpopleftra   r   )
r   qdonefiltered_task_out_linksfiltered_task_in_linkscurelr   task_in_linksr   s
           rK   _filter_by_gantt_task_idzKCmfRelationOption.get_start_finish_graphs.<locals>._filter_by_gantt_task_id  s    }&&A55D&*ff#%)VV" %iikk/=c/B',.;C.@&s+4S9<RSV<WW % %EB~~  % +,BBBrL   )r    r!   r;   r   r   r   r   r   r   rY   )
r   ri   r   r)   r	   r   r   r   r   r;   )r   r   r   r   r   
rel_fields	rel_types
rel_filterr   r   r   s            @@rK   r   z)CmfRelationOption.get_start_finish_graphs  sq   	C 	C 	C 	C 	C 	C" %T**#D))
 
 

 ++	  	53444 	31222 	42333 "43

 +11J1WW 	s 	sC3<89@@#+B^`c`qArsss#+67>>@]_b_p?qrrrr 	;++M:::},,rL   )NNNr   )r   )NFFF)__name__
__module____qualname____doc__r7   rN   staticmethodcmf_deferred_jobrA   r5   r2   boolr1   r4   rj   r   r   r   r   r   r   __classcell__)rJ   s   @rK   r	   r	      s       XXP P P P Pd    0 $PY{ef #HI I IRw Rw RwI I \RwhP P P9 9 969nD 9n 9n 9n 9nv*9 *9 *9X
 
 
 
 
] ] ]] ] ]G G G GBC C C
C C C JOPU/- /- /- \/- /- /- /- /-rL   r	   N)cmf.includemodules.task.fieldsr   collectionsr   r   r   r	   r   rL   rK   <module>r     s        3 3 3 3 3 3 6 6 6 6 6 6 6 6 6 6F- F- F- F- F-+= F- F- F- F- F-rL   