
    0i{U                     X    d dl  d dlmZ d dlmZmZmZ  G d dej                        Zy)    )*)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                 0   t         j                  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                  j                  |      rt        dd       | j                  j                  dv rt         j                  j                  g dd
d| j                  | j                  ggdd| j                  | j                  ggg      rt        dd       | j                  g d       | j                         rt        dd       | j                         rt        dd       | j                  j                  dk(  r| j                  g d       | j                  j                  | j                  k(  s#| j                  j                  | j                  k(  rt        dd       | j!                         rt        dd       ddg dgd
d| j                  | j                  ggdd| j                  | j                  ggg}t         j                  j                  |      rt        dd       | j#                          t%        | L  |i |}t         j                  j                  | dd       | j                  j                  dk(  r$| j                  j(                  j+                          | j                  j                  dv r| j,                  s| j.                  j0                  r|j3                  dd      s|| j                  j(                  j4                  r\| j                  j(                  j6                  r<t9        t         j                  j:                  | j                  j                  dd        | j                  j=                          | j                  j=                          t         j>                  jA                  |        |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MMT\\)nvz{ 4!t}}-dll+t'<'<=	
 ##((0@(AJRVW""  'C  C'',,5m6?W[WcWcGd5ehrtx{  |I  |I  KO  KW  KW  {X  hY5Z, [ F NRS    ..0  J  RV  W))+  B  JN  O""&@@ 	 	 }}((DLL8DLL<T<TX\XeXe<e A IMN ..0 I QUV &t  .J  KD4==$,,"?@TDMM4<<#@AG
 '',,G,< bimo 88:glD+F+''11$,O""&@@LL&&QQS##  (D  D 2 2 = =JJ/7}}**;;@[@[@m@m$V%=%=%Z%Zoso|o|oo  LT  dU  V++-,,.2248
    c                    t         j                  j                  | dd       | j                  g d       t	        |   |i |}| j                  j                          | j                  j                          | j                  j                  dk(  r6| j                  dg       | j                  j                  j                          t         j                  j                  | dd       t         j                  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 
 	 gnd-f-++-,,.""&@@'  LL&&QQS''11$,O44T:
rL   Tr&      uc   Вычисление плановых дат у задач от выставленной связи)	only_onceshow_bg_progressbaronly_once_argsprioritydescriptionc           
         | y |s
t               }| |v ry |j                  |        t        j                  j	                  dd| gg d      }|sy t
        j                  d|j                  j                   d|j                  j                   d|j                  j                   d|        |j                  j                  }|j                  j                  }|sy |j                  j                  }t        j                  j!                  d	d
g dgdd|ggg d      }|D ]  }	|	j"                  }
|
j                  }|j%                  |j'                                |j(                  r|dk(  r|dk(  sRt+        |	j,                  j                  xs d      }|	j.                  j                  dk(  r2|j                  }|r6t        j0                  j3                  |||      }n|	j.                  j                  dk(  rK|j4                  j                  xs d}||z
  }t        j0                  j3                  ||j                  |      }n|	j.                  j                  dk(  r0|j                  }|rt        j0                  j3                  |||      }nf|	j.                  j                  dk(  rK|j4                  j                  xs d}||z
  }t        j0                  j3                  ||j                  |      }n|j7                  |d      }||j                  k(  r||_        |j                  j8                  r||j                  j8                  k  r|j;                         r?|j=                  d       |dz  dk(  r
t?                t        j                  jA                  |
jB                  j                  ||dz           y )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   
 ?5Dd?~~!!$g)>*i " j 	>tyy>OrRVR[R[RaRaQbbwx|  yK  yK  y]  y]  x^  ^g  hm  gn  o  	p--??,,==<<(( 2277AUW[  ^z  A{AKTSW@X@Z@V 8 W
 . 3	wN+33N#1#?#?  ,,-A-U-U-WX
 %..!((: < < B B GaHM++004II!1!7!7 %+%7%7%L%LXWegt%uN--226LL/>>DDI%0!'!3!3!H!HScSiSikp!q--226JJ!0!6!6 %+%7%7%L%LXWegt%uN--226KK/>>DDI%0!'!3!3!H!HSbShShjo!p1JJ>osJtN!5!F!FF4B 1(99==!$8$I$I$M$MM'HHJ %%d%;rzQ$$AA.BSBSBYBY`dlqtuluAvg3	wrL   c                    | j                   }| j                  }t               }|j                  r ||j                  D ch c]  }|d   	 c}z  }|j                  ro|j                  j                  r*||j                  j                  D ch c]  }|d   	 c}z  }|j                  |j                  j                  j                         |j                  |       y c c}w c c}w )Nr   )
gantt_path)	r   r   r`   cache_branch_gantt_pathr3   ra   r   rf   _check_additional_relations)rE   
add_parent	add_childadd_parent_gantt_pathts        rK   r5   z9CmfRelationOption._check_additional_parent_task_relations   s    ]]
LL	 #--$9jNpNp<qQtW<q$q!!!%%==(=R\RhRh  SA  SA  ABQ4  AB  )B%!%%j&<&<&?&?&E&EF--9N-O =r ABs   C
C"c                     | j                  ddd      \  }t               t               fd | j                  j                  j                        S )NT)include_finish_finishinclude_start_startinclude_start_finishc                     | v ry| v ryj                  |        j                  |        j                  | g       D ]  \  }} |      }|s|c S  j                  |        yNTF)ra   r=   remove)nodeneighbor_resultdfs	stack_settask_out_linksvisiteds       rK   r   z4CmfRelationOption.has_start_finish_loop.<locals>.dfs   st    y wKKMM$-11$; "!X!M"
 T"rL   )get_start_finish_graphsr`   r   op_gantt_task_idrf   )rE   r   r   r   r   r   s     @@@@rK   r2   z'CmfRelationOption.has_start_finish_loop   sX     88tim  EI8  J%E		& 4==117788rL   returnc                     t         j                  j                  g d      j                  dfd	fd} || j                  | j
                        xs  || j
                  | j                        S )u   
        Проверяет, что связанные задачи не находятся друг у друга в родителях
        )r/   r   r   r   c                 h   |dkD  rt        dd       t               }ddgdd| gg}dd	g}t        j                  j	                  ||
      D ]  }|j
                  }|j                  rj|j                  j                  r/|j                  j                  D ]  }|j                  |d           |j                  |j                  j                         |j                  |j                          t               }|D ]#  }	 |	|dz         }
|
s|j                  |
       % |j                  |       |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   sM   }  F  NR  S$'E! $T+CDg.G C.0G //55WW5U >"%++"..&22JJ!0!<!<!T!T ?A155ag>?)--o.I.I.L.LM%))/*<*<=> ),%+ E!;BRS!T!-44^DE
 "(()BC((rL   c                    t        |j                  j                  g      }|j                  rt|j	                  |j                  j                  j                         |j                  j
                  r/|j                  j
                  D ]  }|j	                  |d           t               }|D ]  } |      }|s|j                  |         |j                  |       | 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    !699??"34O!!##F$6$6$9$9$?$?@%%==#//GG 5'++AdG45 *-&% F!;B!?!.55nEF
 ""#=>88>>_44rL   )r   )r)   CmfRelationTyper-   r   r   r   )rE   r   r   r   s     @@rK   r1   z,CmfRelationOption.has_parent_child_relations   sc     $*#9#9#>#>Fp#>#q#t#t 	)@	5&  dmm<m@PQUQ^Q^`d`l`l@mmrL   c                     t               t               d fd | j                  j                  j                  j                        S )Nc                    g }t         j                  j                  dd| gdg      }|r1|j                  r%|j	                  |j                  j
                         dd| gg dg}t         j                  j                  |dg      }|r4|D cg c]  }|j                  j
                   }}|j                  |       |S c c}w )	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_id)
r)   rb   r-   r3   appendr   r	   r   r   extend)gantt_task_id
parent_idsrt   rH   additional_parents_relationsr   r   s          rK   get_parent_idszDCmfRelationOption.has_additional_parent_loop.<locals>.get_parent_ids5  s    J>>&&/A4.Wa  aA&  BD((!!$"2"2"C"CD -c=AGG ,2+C+C+I+IQXb|a}+I+~(+Qm(n#)E)E(n%(n!!"78 )os   B>c                     | v ry| v ryj                  |        j                  |         |       D ]  } |      }|s|c S  j                  |        yr   )ra   r   )r   r   r   r   r   r   r   s      rK   r   z9CmfRelationOption.has_additional_parent_loop.<locals>.dfsG  sh    y wKKMM$*40 "X!M"
 T"rL   )r`   r   r8   r   rf   )rE   r   r   r   r   s    @@@@rK   r4   z,CmfRelationOption.has_additional_parent_loop0  s>    %E		$	& 4==..117788rL   c                 *    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    w*, 0
 
 	
rL   c                 z   | j                  ddg       | j                  rG| j                  j                  r1| j                  j                  j                  d| j                         | j                  rI| j                  j                  r2| j                  j                  j                  d| j                         y y y 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==T]]22MM!!;;NPTP]P];^<<DLL00LL  ::>t||:\ 1<rL   c                 z   | j                  ddg       | j                  rG| j                  j                  r1| j                  j                  j                  d| j                         | j                  rI| j                  j                  r2| j                  j                  j                  d| j                         y y y r   r   r   s    rK   check_delete_permz#CmfRelationOption.check_delete_permm  s    ,.?@A==T]]22MM!!;;NPTP]P];^<<DLL00LL  ::>t||:\ 1<rL   c           	      B   | j                  ddg       t        j                  sy | 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
       y y y y )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==T]]11dmm6J6J6P6P6[6[_k6k)*)9)9*+*:*:*=*=*C*C+,#+"&--"2"2"8"8.8\)*!]]1144::	E _U;-?,@A5uU`Oarw  yD  sE  rF  G<<DLL//DLL4G4G4M4M4X4X\h4h)*)9)9*+*:*:*=*=*C*C+,#+"&,,//"7"7.9])*!\\003399	E _U;-?,@A5uU`Oarw  yD  sE  rF  G 5i/<rL   c                 L    t        j                  j                  | dg|i | y )Nupdatedr)   CmfEventdo_eventrE   rF   r(   s      rK   _do_event_savez CmfRelationOption._do_event_save  s"     	  yB4B6BrL   c                 L    t        j                  j                  | dg|i | y )Ndeletedr   r   s      rK   _do_event_deletedz#CmfRelationOption._do_event_deleted  s       yB4B6BrL   c                 b  	
 	
fd}t        t              
t        t              	g d}dg}|r|j                  d       |r|j                  d       |r|j                  d       dd|gg}t        j                  j                  ||	      D ]  }
|j                  j                     j                  |j                  j                  |j                  f       	|j                  j                     j                  |j                  j                  |j                  f        | r ||       S 
	fS )
Nc                    t        |       }t               }t               }t               }|r]|j                         }	|   ||<   |   ||<   |j	                  |       ||   ||   z   D ]  \  }}||vs|j                  |        |r]||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5D&*f#%)V"iik/=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  s#   	C" %T*#D)

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

 ++11J1W 	sC3<<889@@#++B^B^`c`q`qArs#++667>>@]@]_b_p_p?qr	s +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Pd0 $PY{ef #HIRwI RwhP969nD 9nv*9X
]]GBC
C JOPU/- /-rL   r	   N)cmf.includemodules.task.fieldsr   collectionsr   r   r   r	    rL   rK   <module>r      s&     3 6 6F-+== F-rL   