
    0j                      F   d dl  d dlmZmZ d dlmZ d dlmZ d dlm	Z	m
Z
 d dlmZ dZej                  ej                  ej                   ej"                  ej$                  ej&                  ej(                  fZdZd	Zd
 Zd Zd Zd ZddZ G d dej:                        Zy)    )*)fields
base_error)cmf_roadmap)aliased)funcselect)defaultdict   u   Не назначеноop_gantt_task.c                 f    t        | t              xr  t        d | j                         D              S )uy   Проверяет, что значение является листом grouped Roadmap с уровнями задач.c              3   f   K   | ])  \  }}t        |t              xr t        |t               + y wN)
isinstanceintlist).0levelitemss      './modules/project/models/cmf_roadmap.py	<genexpr>z!_is_level_dict.<locals>.<genexpr>   s2      +E5 	5#::eT#::+s   /1)r   dictallr   )values    r   _is_level_dictr      s0    eT" s +!KKM+ (     c                   	
 t        t              	t        t              }g }t               }t        d | D              D ]  }| |   D ]v  }|d   }t	        |      dkD  r|d   nd}|r1|||   vs'||   j                  |       	|   j                  |       P||vsU|j                  |       |j                  |       x  g 
t               	
fd|D ]
  } |        
S )u   Сворачивает уровни Roadmap в XLSX-порядок: родитель всегда раньше потомков.c              3   B   K   | ]  }t        |t              s|  y wr   )r   r   )r   r   s     r   r   z4_ordered_task_ids_from_level_dict.<locals>.<genexpr>(   s     Q%*UC:PQs   r      Nc                     | v ryj                  |        j                  |        j                  | g       D ]
  } |        y)u|   Добавляет задачу один раз и затем рекурсивно добавляет её потомков.N)addappendget)tidchild_idchildren_mapordered_idsvisitedwalks     r   r)   z/_ordered_task_ids_from_level_dict.<locals>.walk7   sJ    '>C3$((b1 	HN	r   )r
   r   setsortedlenr!   r"   )levels_dictchildren_seenroots
roots_seenr   rowtask_id	parent_idroot_idr&   r'   r(   r)   s            @@@@r   !_ordered_task_ids_from_level_dictr5   !   s    t$L$MEJQ;QQ 
&u% 		&C!fG"%c(Q,ADI-	"::!),009 +227;
*w'W%		&
& KeG  W r   c                     | sd| fS | j                  t              }|rt        j                  nt        j                  }|r| j                  dd      d   n| }t        ||d      |fS )uh   Возвращает CMF-поле группировки, учитывая op_gantt_task-префикс.N.r   )
startswithGANTT_PREFIXmodelsCmfGanttTaskCmfTasksplitgetattr)
field_nameis_gantt_taskmodelplain_field_names       r   _group_field_objrC   F   se    Z)),7M#0FfnnE6Cz''Q/25*D13CCCr   c           	         |ddg fv rt         S t        |       \  }}|st        |      S t        |t        j
                        rH|j                  j                  ||j                  j                  t        |      t        |                  S t        |t        j                        r.|j                  j                  t        |      t        |            S t        j                  t        j                  t        j                  f}t        ||      rt        t        |dd      xs g       }t        |dd      }d}t        |t              r%d|v r!|j                  dd      d   }|r||v s|dv r|}|s|}|s|r|d   }t        |t              rt        t         |d      n|}	|	r-	 |	j                  |d	g
      }
|
r|
j(                  j*                  S t         S t        |      S # t"        j$                  t&        f$ r	 t         cY S w xY w)u*  Возвращает текст заголовка группы для XLSX-строки.

    Для пустых значений выводим «Не назначено», а relation/M2M ключи
    резолвим в имя связанного объекта. Если generic id уже содержит
    префикс модели (`CmfTask:...`), используем его раньше fallback-модели
    поля, чтобы не превращать назначенные значения в «Не назначено».
    N r:   rA   :r   r   )N	CmfEntitynamer   )UNASSIGNED_GROUP_LABELrC   str
issubclassr   CmfChoiceIntchoicesr#   	CmfChoiceCmfRelationCmfGenericRelation
CmfM2MBaser   r>   r   r=   r:   r   CmfErrorLookupErrorrH   r   )r?   key	field_obj_plain_field_namerelation_fieldsallowed_modelsdefault_model_name
model_nametyped_model_namerA   objs              r   _group_labelr^   P   s    tRn%%#3J#? I 3x)V001  $$S)*;*;*?*?C#c(*STT)V--.  $$SXs3x88))6+D+DfFWFWXO)_- gi4@FBG$Y>
c3C3J"yya03"#~5%)<<-
+Jn'*J5?
C5P
D1V`.iiVHi5 xx~~%%%s8O ''5 .--.s   G G>=G>c           	      J   t        |       r%t        |       D cg c]  }dt        |      d c}S g }|t        |      k  r||   nd}| j	                         D ]C  \  }}|j                  dt        ||      |d       |j                  t        |||dz                E |S c c}w )u  Строит плоский поток XLSX-строк с synthetic group headers.

    UI-группировка Roadmap возвращает вложенный dict, а Excel — плоскую
    таблицу. Поэтому каждая группа превращается в отдельную строку без id/code,
    где подпись группы записана в колонку «Наименование».
    task)typeidNgroup)ra   rH   depthr   )	r   r5   rK   r,   r   r"   r^   extend_build_grouped_export_rows)r   group_fieldsrd   r2   rowsgroup_field	group_keynested_values           r   rf   rf      s     e =UC
 3w<0
 	

 D).\1B)B,u%K#(;;= W	< i8
 	
 	.|\5ST9UVW K
s   B c                   \    e Zd ZdZej
                  j                  dgz   Zd Zd Z fdZ	 fdZ
dd fd	
Z fd
Ze edddd      d               Zed        Zed        Zed        Zed        Zed        Zed        Ze	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Zed fd	       Z xZS )
CmfRoadmapTncget_filtered_roadmap_by_levelc                 F    fd | j                   j                        S )Nc                     | sy | j                   dk(  r| S | j                  j                           | j                  j                        S )N
CmfProject)
class_nametree_parentloadr   )childroot_parents    r   rv   z,CmfRoadmap._calc_parent.<locals>.root_parent   sE    </!!&&("5#4#4#:#:;;r   )rs   r   )selfrv   s    @r   _calc_parentzCmfRoadmap._calc_parent   s!    	< 4++1122r   c                 X    | j                   j                  s| j                  sy d| _        y )Ngantt)
logic_type
is_changedis_newui_view_form)rw   s    r   _calc_ui_view_formzCmfRoadmap._calc_ui_view_form   s!    **;;#r   c                 *    t         |          ddgz   S )Nzmembers.responsibleztree_parent.activity)supersave_preload_fields)rw   	__class__s    r   r   zCmfRoadmap.save_preload_fields   s    w*,0EG]/^^^r   c                    | j                   s| j                         | _         | j                   r| j                   j                  g d       | j                  sK| j                  r?| j                  j                  j                         r| j                  j                  | _        | j                  sK| j                   r?| j                   j                  j                         r| j                   j                  | _        | j                  s&t        j                  j                  dd      | _        | j                  r| j                   r-| j                   j                  s| j                  xs d | _        n| j                  r%| j                  j                  j                  d      sV| j                   r2| j                   j                  dk(  rd	| j                  xs d | _        nd
| j                  xs d | _        | j                  r9| j                   j"                  s| j$                  j"                  rt'        dd       t)        | T  |i |}| j                  r>t        j,                  j/                  |        t        j0                  j/                  |        | j                   j"                  r#t3        t        j4                  j6                         | j                   j"                  rj| j                   r^| j                   D ]O  }|j                   j                         | j                   k7  s+| j                   |_          |j*                  |ddi| Q |S )N)	cmf_ownercmf_owner_assistantsactivitylogic_prefixadd_object_typerI   
productionT)codecache_inmemory1)Roadmapu   Дорожная картаzproject.baseu   Дорожная карта zRoadmap uL   Нельзя изменять memrers и tasks у корневого RoadmapabortnotifyF)parentrx   load_fieldsr   rs   rt   r:   CmfActivityr#   r}   r   rH   r   r8   r   systemmembersr|   tasks	cmf_alertr   saveCmfRoadmapQuickTransformscaffold_defaultsCmfRoadmapViewschedule_deferred_jobrm   recalculate_cache)rw   argskwargsresmemberr   s        r   r   zCmfRoadmap.save   s\   {{++-DK;;KK##k $ 
 }}!1!1d6F6F6O6O6T6T6V ,,55DM}}1E1E1J1J1L KK00DM}}"..22UY2ZDM;;{{4;;#>#>#yy/C0	YYdiioo&@&@Ak&l;;4;;#;#;~#M">tyy?OC>P QDI"*499+;*< =DI ;;||&&$***?*?hptuglD+F+;;++==dC!!33D9<<""!&"3"3"E"EF ;;!!dkk,, ?==%%'4;;6$(KKFMFKK>e>v>? 
r   F)skip_owner_checkc                
   t         j                  j                  |       D ]  } |j                  |ddi|  t         j                  j                  |       D ]  } |j                  |ddi|  t        |   |d|i|S )N)r   r   T)r:   r   r   deleter   r   )rw   r   r   r   qtviewr   s         r   r   zCmfRoadmap.delete   s    1166d6C 	>BBIIt=d=f=	>))..d.; 	@DDKK???	@w~tQ6FQ&QQr   c                    t        |   |i |}t        j                  j	                  | d      D ]  } |j                  |i |  t        j
                  j	                  | d      D ]  } |j                  |i |  |S )NT)r   include_deleted)r   restorer:   r   r   r   )rw   r   r   r   r   r   r   s         r   r   zCmfRoadmap.restore   s    got.v.1166dTX6Y 	(BBJJ''	())..dD.Q 	*DDLL$)&)	*
r   <      )	only_oncesoft_time_limit
system_jobpriorityc            	      V   t         j                  }d}d}|j                  ddg      D ]  }|dz  }t        |j                        }|j
                  |k7  r|dz  }t        j                  d|j
                   d| d|j                          ||_         |j                  d	
       |j                  j                  |j
                  j                  d}t        d|j                   |       t        d|       |dz  dk(  st                 t        j                  d| d| d       |S )u;   Актуализация кеша кол-ва членов.r   cache_members_countr   rI   r   zUpdate cache_members_count z ->  T)	only_data)node_idelements_countztree-node-count-changes-ztree-node-count-changes2   zRecalculate /z roadmaps caches)r:   rm   r   r,   r   r   gdebugrb   r   r   cmf_emit_event
cmf_commit)_kwargsclstotal_count
calc_countr   
real_count
event_datas          r   r   zCmfRoadmap.recalculate_cache   s-    
88,A9+M8N 	K1K[001J..*<a
5k6U6U5VVZ[eZffghshvhvgwxy2</   40)4)=)=Q\QpQpQvQvw
!9+..9IJJW!8:FB!#	  	
,zl!K=8HIJr   c                    g }g }| D ]  }|}|j                  |      }	|	r|n|}
|	rt        j                  nt        j                  }|}d }|	r|j	                  dd      d   }t        ||      }t        |t              st        d| dd       t        |
|d       rt        |
|      }|j                  |      }nt        |t        j                  t        j                  f      rt        |
|dz   d       }nt        |t        j                        r|j                         }|j                  |      }|j                   }|j"                  rd}d	}nd	}d}t%        j&                  t%        j(                  |j*                  |         d       }t-        |g      j/                  |j*                  |   |
j0                  k(        j3                         j                  |      }||j5                  |       |j5                  |        ||fS )
Nr7   r   u&   Группировка по полю "u#   " не поддерживаетсяTr   _idright_idleft_id)r8   r:   r;   r<   r=   r>   rL   ALLOWED_GROUP_TYPESr   labelr   rP   rQ   rR   m2m_model_clsdp_model	__table__rightr   array_remove	array_aggcr	   whererb   	as_scalarr"   )query_fieldsgantt_prefixsa_task_modelsa_gantt_modeldata_driverto_be_selected_colsfinal_fieldsfieldr?   r@   SaModelCmfModelaliascol	field_cls	m2m_modelsa_m2m_modeltblmy_id_field_namesub_id_field_nameaggs                        r   _select_group_fieldszCmfRoadmap._select_group_fields  s    ! +	0EJ!,,\:M(5n=G.;v**HECC+A.%0Ii)<=B:,Nqrz~ wt,gu-ii& i&*<*<f>W>W)XY!'55=$?C	6+<+<= ) 7 7 9I#.#7#7	#BL&00C +5(,5)+4(,6)++DNN355AR;S,TVZ[C!3%=..suu5E/F'**/TU%IKe  #**3/##J/W+	0Z #L00r   c                 r   |stt        t              }t        t              |d<   |d   d   j                  | D ch c]  }|d   	 c}       | D cg c]	  }|d   d f c}|d<   |j	                  |       |S |d   }t        t              }| D ]^  }||   }t        |t              r3|r|D ]  }||   j	                  |        6|d    j	                  |       K||   j	                  |       ` t               }	|j                         D ]"  \  }}
t        j                  |
|dd  |      |	|<   $ |	S c c}w c c}w )Nmapr   rb   r   )
r
   r   r*   updater"   r   r   r   rm   _nested_grouping)r   r   final_items_groupsitems_by_levelitemr   groupedrU   elr   	sub_itemss              r   r   zCmfRoadmap._nested_groupingK  sI   (.N$/$4N5!5!!$++E,JDT$Z,JK@E F$t*d!3 FN1%%n5!!q	d# 		*Du+C#t$! 1**401 DM((.##D)		* f%mmo 	^NC!229fQRjJ\]CH	^ 
/ -K Fs   D/D4c                    g }t        |      D ]  \  }}|t        |      k  r||   j                         nd}	|j                  |      rF|j	                  dd      \  }
}t        ||d       }|st        ||dz   d       }|j                  |      }nt        | |d       }|st        | |dz   d       }|	dk(  r|j                         n|j                         }|j                  |        |r |j                  | }|S )Nascr7   r   r   )	enumerater,   lowerr8   r=   r>   r   r   descr"   order_by)
task_modelgantt_task_modelquerysort_fieldssort_ordersr   order_by_clausesidxr   
sort_order_related_field_namer   clauses                 r   
_sort_rowszCmfRoadmap._sort_rowsi  s   #K0 	,JC583{;K5KS)//1QVJ-(-C(;%%.0BDI!"24F4NPTUCii&j%6!*eemTBC","5SWWY388:F##F+	, "ENN$45Er   c           	         i }d}t        dt        dz         D ]B  }g }t        ||   j                               }|s ng }|D ]"  }||   |   D ]  }|j	                  ||f        $ |dkD  r2||dz
     r|j	                  ||dz
            |r|j	                  |       |ry|dkD  rc|ra||dz
     D cg c]  \  }}|	 }}}g }||   j                         D ]#  \  }}|D ]  }||v s|j	                  |        # % d|dd|gdd|gg}|j	                  |       |r7|s|	r2| j                  |j                        j                  |      j                  |j                  j                  |            }|r)|j                  ||j                  |j                  k(        }|r7|j                  |t        j                  ||      \  }}|j                  |      }|	rt         j#                  ||||	|
|      }|j%                         }g }t'               } |D ]?  }!|!d   }||   |   D ]-  }||f}"|"| vs| j)                  |"       |j	                  |"       / A |||<   |}E |rt        |dd      D ]  }#||#   s
t'        ||#dz
           }$g }%||#   D ]@  \  }&}'||#dz
     |'   D ]-  }(|'|(f}"|"|$vs|$j)                  |"       |%j	                  |"       / B |%sh||#dz
     |%z   ||#dz
  <   |	s|t+        t              })||#dz
     D ]  \  }}*|)|   j	                  |*        | j                  |j                        j                  |      j                  |j                  j                  t        |)                  }+|r)|+j                  ||j                  |j                  k(        }+t         j#                  |||+|	|
|      }+|+j%                         D !*cg c]  }!|)|!d      D ]	  }*|!d   |*f  c}*}!||#dz
  <    ||fS c c}}w c c}*}!w )	Nr   r   ORparent_task_idINrb   	in_filterrA   sa_modelr   )range
MAX_LEVELSr   keysr"   r   r   rb   select_fromfilterin_joinop_gantt_task_idcollect_filter_expr:   r<   rm   r  r   r*   r!   r
   ),sessionTask	GanttTaskr   r-   additional_levels_dictfiltersglobal_bql_listchild_task_filterr   r   show_sub_itemsneed_gantt_joinr   final_levels_dict	max_levelr   conds	level_idslevel_ids_with_parentr2   parent_taskr$   r   previous_level_idsadditonal_tasks_of_prev_leveladd_task_idadd_task_parent_idsadd_task_parent_idquery_nquery_filterfiltered_ids
seen_pairsr1   pairllevel_pairsadded_pairsr   r3   grand_parent_idparents_by_idr  resort_querys,                                               r   _filter_levelszCmfRoadmap._filter_levels~  s   
 	1j1n- C	EE[/4467I %'!$ I#.u#5g#> IK)00';1GHII qy519%LL!34$LL!23 19<MeVWi<X)Y&#q#)Y&)Y461<RSX<Y<_<_<a &8%82E &.15GG = D D[ Q %&& ')41CDt%BC	'O _-e{!--0<<TBII$''++V_J`a"%ll9d6K6Ky||6[\G,7,J,J"'$nn!%%	 -K -)G\ &nn\:G(33D)Wk[fhtuG&{{}(*% U
' ?C!!fG'25'9''B ? '5z1&NN40188>	?? (=e$IGC	L 9a, "(+!"3AE":; &7&: 5NC+6q1u+=i+H 5 )?;{2'OOD1'..t4	55 #+<QU+Ck+Q!!a%( %0$5M3DQU3K F/%g.55nEF $+==#9#E#Ed#K#R#RSWSZSZS^S^_cdq_rSs#tL&'3'8'8DDYDY]f]i]iDi'j#-#8#8y,Xcepr~#L $0#3#3#50.;CF.C0 + Q0000%a!e,="H !)++g *ZZ0s   3O<Pc           	         t         j                  j                  }t        t              }t        t
              }t        dt        dz         D ]4  }	t        ||	dz
     j                               }
|
s&|D ]  }|	|j                  dt              kD  r|d   }|j                  dd      }|dk(  r| j                  |j                  |j                        j                  |j                  dk(  |j                   |k(  |j                  j#                  |
            j%                         }|D cg c]	  \  }}||f }}}n| j                  |j                  |j                        j                  |j                  dk(  |j                   |k(  |j                  j#                  |
            j%                         }|D cg c]	  \  }}||f }}}|D ]j  \  }}|||	   v r"|||	   |   vr!||	   |   j'                  |       n	|g||	   |<   |||	   v r#|||	   |   vsJ||	   |   j'                  |       b|g||	   |<   l  |st        |j                  |	dz
  i       j                               |j                  |	dz
  t                     z  }|sC|j(                  j#                  t        |            |j                  dk(  |j*                  dk(  g}|s|j'                  |j,                  dk(          | j                  |j.                  |j(                        j                  | j%                         }|D ]K  \  }}|||	   vr
|g||	   |<   n!|||	   |   vr||	   |   j'                  |       ||	   j1                  |       M 7 t2        j5                  d	d
j7                  d |j9                         D              z          |S c c}}w c c}}w )up   Насыщает levels_dict связанными задачами, возвращает additional_levels_dict.   r   level_torelation_type_id	directionoutinFz8ncget_filtered_roadmap_by_level additional_levels_dict= , c              3   D   K   | ]  \  }}d | dt        |         ywlvl=Nr,   r   r=  idss      r   r   z3CmfRoadmap._process_linked_items.<locals>.<genexpr>8  s8       X_s{svx{Z]^a]bbcdghkdlcmXn  X_    )r:   CmfRelationOptionr   r
   r   r*   r
  r  r   r  r#   r   
in_link_idout_link_idr  cmf_deletedr6  r  r   r"   r  is_dummycmf_archivedrb   r!   r   r   r  r   )r  r  r-   show_linked_itemsshow_child_tasksinclude_archivedRelationr  _linked_children_idsr   prev_level_idsrelation_typert_idr7  resultsin_idout_idpairsr  r2   ids_for_childrenchild_filterchild_resultsr%   r3   s                            r   _process_linked_itemsz CmfRoadmap._process_linked_items  s!    ++44!,T!2*3/1j1n- ;	BE!+eai"8"="="?@N!!2  R=,,ZDD%&89)--k5A	$%mmH,?,?AUAUV]] ,,5 11U: ++//? ce	 
 CJJeV_JEJ%mmH,@,@(BUBUV]] ,,5 11U: ,,00@ ce	 
 CJJfe_JEJ/4 R+NG+e"44)U1CG1LL'.w7>>~N7E6FE*73"8"??)1G1Nw1WW259'BII.YBPAQ.u5g>R+ RH  $'(>(B(B519b(Q(V(V(X$Y\p\t\tuz}~u~  AD  AF  ]G  %G #++//5E0FG((E1.$L
 ,$++D,=,=,FG$VGMM$''4;N;N$O$V$VXd$e$i$i$kM/< B+)#;u+==<E;K.x8&k%.@.JJ'.x8??	J,U377ABm;	Bz 	
Jdii  X_  @V  @\  @\  @^  X_  O_  _  	`%%[ K Ks   +O
:O
c	                    |r\|gt        dt        dz         D 	cg c]  }	t        |d|	        c}	z   }
 | j                  t	        |
d      D 	cg c]$  \  }	}|j
                  j                  d|	 d      & c}}	 j                  |      }t        dt        |
            D ]7  }	|j                  |
|	   |
|	   j                  |
|	dz
     j
                  k(        }9 |j                  |j
                  j                  |            }|r)|j                  ||j                  |j
                  k(        }|rt        j!                  ||||||      }|j#                         }n|D cg c]  }|fdt        dz
  z  z    }}t%        t&              }|D ]E  }t        dt        dz         D ]-  }||dz
     }|dk(  rd n||dz
     }||||   vs%|g||   |<   / G |S c c}	w c c}}	w c c}w )Nr4  r   T)rH   r=  r   r   )r
  r  r   r   r   rb   r   r  r,   	outerjoinr  r  r  r  r  rm   r  r   r
   r   )r  r  r  first_level_idsr  r   r   rJ  r   ialiasesar   rh   r2   r-   r1   level_indexr  s                      r   _build_levels_dictzCmfRoadmap._build_levels_dict;  s    fU1j[\nE]^Qqc7 ;^^G "GMM7@!7LMtq!!$$**s1#S\*Mk$  1c'l+ d
GAJ4M4MQXYZ]^Y^Q_QbQb4bcd LL_!=>E

9d.C.Cy||.ST"--dIukS^`lm99;D L[[WJJN!;;[D[ "$' 	JC$Q
Q7 JkAo.)4)9s;QR??S&7+k:R+R9G8IK,W5	J	J =  _ N \s   G)G
$G#c                    A | xs g } |xs g }|xs g }|xs g }|xs g }|xs g }t         j                  d| d| d| d| d| d| d|        |r;t               } |D ],  }!|!d   }"|"| v rt        d	|" d
       | j	                  |"       . ||||||||	|
|||||||||||g}#t        |#      D ]H  \  }$}%|%s	t        j                  j                  j                  t        j                  d|%i      d   |#|$<   J | r=t        j                  j                  j                  t        j                  d| i      d   } |r=t        j                  j                  j                  t        j                  d|i      d   }|r=t        j                  j                  j                  t        j                  d|i      d   }| j                  g d       | j                  g d       | j                  g d       |s| j                  g d       t        j                  j                  }&t        j                  j                  }'t        j                  j                  j                  }(|(j                         })|duxr |duxr
 ||k  xr | }*d}+d},dA|&j                  g}-|r:t         j#                  |A|&|'|(      \  }.}|-|.z   }-t         j                  d|        t%        Afd|D              xs t%        Afd|D              }/ |)j&                  |- j)                  |&      }0|/r)|0j+                  |'|&j,                  |'j                  k(        }0| |#d   g}1|r|r|1j                  |       |(j/                  |1t        j                  |&|0      \  }0}2|0j1                  |2      }0|rt         j3                  |&|'|0||A      }0|*r|0j5                  ||      }0|0j7                         }+|+D 3cg c]  }3|3d   	 },}3t         j                  dt9        |,              i }4|s|s|,D 5cg c]  }5|5df c}5|4d<   nt         j;                  |)|&|'|,|/|||A	      }6t         j                  ddj+                  d |6j=                         D              z          t?        t@              }7|rt         jC                  |)|&|6|||      }7t         jE                  |)|&|'|(|6|7|#||||||/A      \  }4}8t         j                  ddj+                  d |4j=                         D              z          |4sdg i}4|r g }9g }:|+D ]<  }3tA               };t        d g|z         D ]  \  }$}<|3|$   |;|<<    |9j                  |;       > t         jG                  |9||:      }=|rctI        d!8dz         D ]Q  }>|4|>   D ]G  \  }5}?|:D ]=  }@|?|@d"   |>dz
     v s@|>   j                  |5|?f       |@d"   |>   j	                  |5       ? I S |:D ]  }@|@jK                  d"        tA        |=      }4t         j                  d#dj+                  d$ |4j=                         D              z          t         j                  d%       |4S c c}3w c c}5w )&u  
        1) Делаем большой запрос с 20 JOIN (T1..T20) и узнаём, какие задачи есть на каждом уровне.
        Сохраняем в levels_dict = {1: {id: parent_id, ...}, 2: {id: parent_id, ...}, ...}.

        2) Для каждого уровня (1..20) делаем новый запрос, где:
        - Условие: CmfTask.id IN (levels_dict[level])
        - Плюс фильтр по уровню — если он задан
        - Плюс глобальный фильтр — если он задан

        3) Результат: словарь {1: [(id_1, parent_id_1), (id_1, parent_id_2), ...], 2: [...], ..., 20: [...]},
        где лежат уже отфильтрованные задачи на данном уровне.

        4) Реализуем вложеную группировку, если переданы group_by_fields
        z4ncget_filtered_roadmap_by_level method_start: start=z, end=z, group_by_fields=z, show_linked_items=z, show_sub_items=z, sort_fields=z, sort_orders=r6  u+   Дублирование relation_type_id: Tr   r  r   )r   z!=ztask.gantt_project)rF  ==F)rG  rc  F)rH  rc  FNr   )r   r   r   r   z2ncget_filtered_roadmap_by_level group_by_fields : c              3   @   K   | ]  }|j                          y wr   r8   r   fr   s     r   r   z=CmfRoadmap.ncget_filtered_roadmap_by_level.<locals>.<genexpr>  s     RQall<8R   c              3   @   K   | ]  }|j                          y wr   re  rf  s     r   r   z=CmfRoadmap.ncget_filtered_roadmap_by_level.<locals>.<genexpr>  s'       ZKyzZ[ZfZfgsZt  ZKrh  r  z7ncget_filtered_roadmap_by_level : len(first_level_ids)=r   z-ncget_filtered_roadmap_by_level levels_dict= r:  c              3   D   K   | ]  \  }}d | dt        |         ywr<  r?  r@  s      r   r   z=CmfRoadmap.ncget_filtered_roadmap_by_level.<locals>.<genexpr>  s8       PLksknpsRUVYUZZ[\_`c\d[ePf  PLrB  z3ncget_filtered_roadmap_by_level final_levels_dict= c              3   D   K   | ]  \  }}d | dt        |         ywr<  r?  r   r=  r   s      r   r   z=CmfRoadmap.ncget_filtered_roadmap_by_level.<locals>.<genexpr>  s8       RXoyortyTWX[W\\]^abg^h]iRj  RXrB  rb   r4  r   z*ncget_filtered_roadmap_by_level grouping: c              3   D   K   | ]  \  }}d | dt        |         yw)zgroup(z)=Nr?  rl  s      r   r   z=CmfRoadmap.ncget_filtered_roadmap_by_level.<locals>.<genexpr>%  s7       MWnxnqsxvVYUZZ\]`af]g\hMi  MWrB  z*ncget_filtered_roadmap_by_level method_end)&r   r   r*   r   r!   r   r:   r<   dp_get_filterr"   r   r;   r   Sessionrb   rm   r   anyr   r  r  r  r  r  r  slicer   r,   ra  r   r
   r   rX  r2  r   r
  pop)Binsert_bql_listr  lvl1_bql_listlvl2_bql_listlvl3_bql_listlvl4_bql_listlvl5_bql_listlvl6_bql_listlvl7_bql_listlvl8_bql_listlvl9_bql_listlvl10_bql_listlvl11_bql_listlvl12_bql_listlvl13_bql_listlvl14_bql_listlvl15_bql_listlvl16_bql_listlvl17_bql_listlvl18_bql_listlvl19_bql_listlvl20_bql_listrK  r  rJ  rI  r  startendr   r   group_by_fieldsseenr   rP  r  r]  fltrr  r  r   r  to_be_slicedfirst_level_rowsr\  to_be_selected_fieldsadditional_fieldsr  first_queryr  first_query_filterr1   r  r2   r-   r  r  
tasks_lvl1r   	task_datar   grouped_levels_dictr   r  final_items_groupr   sB                                                                    @r   rn   z*CmfRoadmap.ncget_filtered_roadmap_by_levela  ss   B */R)/R-3!'R!'R)/R	FugVTWSXXjkzj{ |%%6$77HHXXfgrfs  tB  CN  BOP 	Q 5D)  /0D= KE7S[_`	  =-=-NNNNNNNN	
 !) 	`GAt#^^..::6>>HVZK[\]^_
	` $nn//;;FNNXWfLghijkO$nn//;;FNNXWfLghijkO & 1 1 = =fnnxYjNk lmn o 	KL;<89""#@A ~~&&''00	nn''33%%'  $4$$ $#	 	  '!%	1;1P1Pl"9+ 2Q 2. %:<M$M!GGHHYZ[R/RR  KVY  ZK  J  ZK  WK#gmm%:;GGM%**9d6K6Ky||6[\K$gaj1	#4_-*5*H*H..	 +I +
'' "(();<$//ik[fhtuK%++E37K&??,-=>c3q6>>	I#oJ^I_`a $5CR#SWdO#Sa $77y/k ,K
 GGCdii  PL  xC  xI  xI  xK  PL  GL  L  M%0%6" )3)I)IT;0A$&6*& ,6+D+Dy+{&!;	,(y 	
E		  RX  ~O  ~U  ~U  ~W  RX  IX  X  	Y !"B J!#' - F	 )4&?*B C .HAu'*1vIe$.!!),	- #-"="=j/[m"n  "1i!m4 ME3DU3K M/1C M--1B51I%RS)1TT 1% 8 ? ?.@Y Z 1% 8 ? C CG LMMM &8 -!!%%e,- !%%8 9GG@499  MW  }N  }T  }T  }V  MW  DW  W  X	<=  I ? $Ts   YYc           	         |t        dd       |j                  dd      st        dd       |dk7  rt        dd        | j                  di |}|j                  d	      xs g }|rxt        ||      }g t	               }|D ]C  }	|	j                  d
      dk7  r|	d   }
|
|vs"|j                  |
       j                  |
       E t        | !  |ddg|||      S t        t              t        t              }g }t	               }t               |j                         D ]f  }|D ]_  \  }
}|r1|
||   vs||   j                  |
       |   j                  |
       9|
|vs>|j                  |
       |j                  |
       a h g t               fd|D ]  } |d        t        | !  |ddg||      S )u  Экспортирует Roadmap в XLSX с сохранением порядка задач и группировок.

        Обычный Roadmap передаёт в общий exporter только упорядоченные id задач.
        Сгруппированный Roadmap дополнительно передаёт плоский список `roadmap_group_rows`,
        чтобы exporter вставил group-header строки перед видимыми задачами группы.
        Nub   Невозможно экспортировать Roadmap без настроек фильтровTr   rt  zJExporting roadmaps without insert_bql_list is unavailable in this verison.xlsxz3Only xlsx file format is available in this verison.r  ra   r`   rb   r  )field_namesbqlformat_filerK  roadmap_ordered_idsroadmap_group_rowsc                     j                  |        t              }| vr|| <   || |f<   j                  | g       D ]  } ||dz           y )Nr   )r"   r,   r#   )	r$   r   sequence_numberr%   r&   level_ofr'   sequence_mapr)   s	       r   r)   z$CmfRoadmap.export2file.<locals>.walkh  sf    s#!+.O,&$3S!/4Hc?+,(,,S"5 *Xuqy)*r   r   )r  r  r  rK  r  roadmap_level_ofroadmap_sequence_map )r   r#   rn   rf   r*   r!   r"   r   export2filer
   r   r   values)r   r  r  rK  filter_settingsroadmapr  export_rowsseen_ids
export_rowr2   r.   r/   r0   tuplesr3   r4   r&   r  r'   r  r)   r   s                    @@@@@r   r  zCmfRoadmap.export2file+  s+    "z  CG  H""#4d;bjno& KSWX5#55HH)--.?@FB 5WoNKKuH) 0
>>&)V3$T*(*LL)&&w/0 7&;,0$+D3>8H;F:E ' G G #4(#C(U
6nn& 		.F&, ."mI&>>%i044W=$Y/66w?j0"w/W-.		. v	* 	*  	G!	 w"{(,dK'@/:4D7B4<8D # F 	Fr   ) NNNNNNNNNNNNNNNNNNNNNNFNFNFNNNNN)Nr  FN)__name__
__module____qualname__	api_allowr   rm   api_methodsrx   r   r   r   r   r   staticmethodcmf_deferred_jobr   r   r   r  r2  rX  ra  rn   classmethodr  __classcell__)r   s   @r   rm   rm      s`   I((448Y7ZZK
3$_0d .3 R bTTUV W 4 11 11f  :  ( r, r,h E& E&N # #J 8<8< GK HL LP LP9>:>9>:>7<.2,048488<G! G!R NF NFr   rm   N)r   )cmf.includecmfr   r   modules.project.fieldsr   sqlalchemy.ormr   
sqlalchemyr   r	   collectionsr
   r  rO   rM   CmfBoolCmfDaterP   rQ   rR   r   rJ   r9   r   r5   rC   r^   rf   rm   r  r   r   <module>r     s     " . " # #
 

NN
NN


  3 "JD2j4[F'' [Fr   