
    (joK                     8    d dl  d dlmZ d dlZ G d de      Zy)    )*)CmfDatasourceFieldQueryNc                   .    e Zd Zej                  ddgz   Z ej                         Zd e_        e	d        Z
d Zd Zd Zi ddfd	Zed
        Zd Zed        Zedd       ZddZddZd Zed        Ze	dd       Z fdZ fdZe	dd       Z xZS )r   sql_query_previewrecalc_ext_fieldsc                      y)NT )names    9./modules/datasource/models/cmf_datasource_field_query.py<lambda>z CmfDatasourceFieldQuery.<lambda>   s        c                 p   d}i }t               }d}t        j                  ||       D ]  }|j                  d      }|j                  d      }|j	                  d      }i }	t        |      dkD  r(|d   dk(  r |d   }
|dd }||	|
<   |j                  |
       d| }|||	d	||<   |dz  } |t        |      d
S )u   
        Парсит SQL и возвращает список переменных с их компонентами.
        Примеры:
        ${ self.components.name }
        ${ self.name }
        zA\$\{\s*([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)\s*\}   r   .self   Nparam)
full_matchpathfieldsparams	depend_on)setrefinditergroupsplitlenaddlist)sql_textPATTERNr   r   cntmatchr   r   partsr   first_after_selfrest
param_names                r   	sql_parsez!CmfDatasourceFieldQuery.sql_parse   s     WE	[[(3 	EQJ;;q>DJJsOE F5zA~%(f"4#(8 QRy+/'(./ !J( "F: 1HC-	2 i
 	
r   c                 .    dd l }|j                  d|      S )Nr   zrow\.([a-zA-Z0-9_]+)r   findall)r   templater   s      r   _extract_search_fieldsz.CmfDatasourceFieldQuery._extract_search_fields<   s    zz18<<r   c                     |rt        |j                               dk  rd g fS |j                         }g }|r| j                  |      }|sd g fS ||fS )N   )r   stripr/   )r   search_valuer.   searchsearch_columnss        r   _prepare_sql_searchz+CmfDatasourceFieldQuery._prepare_sql_search@   s`    s<#5#5#781<8O##%!88BN!Rx~%%r   c                 l    |d   j                         D ]  \  }}|j                  |d   d|       } |S )uH   
        Заменяет placeholders ${ ... } на :param1..N
        r   r   :)itemsreplace)r   queryr   r)   
param_infos        r   replace_placeholdersz,CmfDatasourceFieldQuery.replace_placeholdersN   sI    
 '-X&6&<&<&> 	N"J
MM*\":a
|<LME	Nr   Nc                 z    | j                  ddg       | j                  j                  ||| j                  ||      S )N
datasourcesql_rows_limit)load_fieldsr?   sql_executer@   )r   r;   query_paramsr4   r5   s        r   rB   z#CmfDatasourceFieldQuery.sql_executeW   s;    ,(89:**5,@S@SU[]kllr   c                 .    t         j                  d|      S )u   
        Извлекает из шаблона поле Шаблон ID, 
        пример: {{ row.ext_id }} = ['ext_id']
        z\{\{\s*row\.(\w+)\s*\}\}r,   )clscode_templates     r   extract_id_fieldz(CmfDatasourceFieldQuery.extract_id_field[   s     zz5}EEr   c           	         | j                  g d       g }| j                  j                  dv rS| j                  |      }|r>|D cg c]
  }||d       }}t        j
                  j                  ddd|gdd|gg      }|S | j                  j                  d	v rqt        j                  | j                  j                  d         }| j                  |      }|r0|D cg c]
  }||d       }}|j                  ddd|gd
d|gg      }|S | j                  j                  rT| j                  j                  d|       |D ]1  }|j                  d
| j                  j                  d||      i       3 |S | j                  j                  d|       | j                  j                  d|       |D ]M  }|j                  | j                  j                  d|      | j                  j                  d||      d       O |S c c}w c c}w )N)parent.field_readonlyparent.field_custom_typezparent.models)userusersr   ORemailINcodefilter)rolesgroupsassetassetscompanyr
   name_tpl)rowrowscode_tpl)rY   )rP   r
   )rA   parentfield_custom_typerG   models	CmfPersonr!   cmfutilget_model_by_namefield_readonly_minijinja_envadd_templateappendrender_template)	r   rZ   rF   name_templateresultid_fieldrY   	row_fieldmodels	            r   render_optionsz&CmfDatasourceFieldQuery.render_optionsc   s$    
 	 ;;((,== ,,];H9=>#S!->	>))..tgtY=WZ`bfhqYr6s.tM[[**.__ --dkk.@.@.CDE,,];H9=>#S!->	>D642KfVZ\eMf+ghM[['',,ZG D//??
PSZ^?_   ,,ZG,,ZG  //??
PS?T //??
PSZ^?_  = ? ?s   H Hc                 V   t        |j                               }|j                         D ]  }|j                  |        |D ci c]  }||j	                  |g        c}|D ci c]  }|d c}g dt
        ffd|D ]  }|   dk(  s |        S c c}w c c}w )u  
        Формирует очередь обновления полей
        
        dependencies:
            ключ = поле
            значение = список полей, от которых оно зависит

        Пример:
            {
                "A": ["B"],
                "B": ["C"],
                "C": []
            }

        Результат:
            ["C", "B", "A"]
        r   fieldc                     |    dk(  rt        d|        |    dk(  ry d| <   |    D ]
  } |        d| <   j                  |        y )Nr   u+   Обнаружен цикл на поле: r   )	cmf_alertre   )rn   depdfs
normalizedorderstates     r   rr   z7CmfDatasourceFieldQuery.build_update_order.<locals>.dfs   sl    U|q "MeW UVVU|q E%L!%( C E%LLLr   )r   keysvaluesupdategetstr)	rE   dependencies
all_fieldsdepsrn   rr   rs   rt   ru   s	        @@@@r   build_update_orderz*CmfDatasourceFieldQuery.build_update_order   s    * **,-
 '') 	$Dd#	$ GQQUe\--eR88Q
'12e2	 s 	  	    	EU|q E
	 / R2s   B!)
B&c                    |j                         D cg c]6  \  }}|j                  d      r |j                  d      st        |dd      r|8 }}}t        j
                  j                  g ddd|ggdd	g
      }i }|D ]7  }	|	j                  }
|
j                  dg       ||	j                  j                  <   9 i }|r:|j                         D ci c]  \  }}||D cg c]	  }||v s| c} }}}}|S i }|j                         D ])  \  }}|D ]  }||vrg ||<   ||   j                  |       ! + |j                         D ch c]  \  }}||v s| }}}t        |      }|D ]  }|j                  |g       D ])  }||vs|j                  |       |j                  |       + |j                  |g       D ]4  }||k7  s	||v s||vs|j                  |       |j                  |       6  |D ]4  }||v sg }||   D ]  }||k7  s	||v s|j                  |         |||<   6 |S c c}}w c c}w c c}}}w c c}}w )u   
        Собирает из option_list_sql_select_fields
        cf_ поля, которые зависят от updated_field_name
        cf__idis_ext_datasourceF)zparent.is_ext_datasource==Tparent.namerO   r\   option_list_sql_select_fieldsrR   r   r   )r9   
startswithendswithgetattrr^   r   slistr   ry   r\   r
   re   r!   r    )rE   objupdated_field_namemass_reload
field_namern   
ext_fieldsfield_queriesgraphfield_queryselect_fieldsr{   noder}   rq   reverse_indexselectedqueue	candidate
clean_depss                       r   check_for_dependencyz,CmfDatasourceFieldQuery.check_for_dependency   s    &)YY[
!
E$$U+''.2E:	 

 
 66<<8j1  !@A	 = 
 ( 	PK'EEM-:->->{B-OE+$$))*	P  #(++- D$ d;scUls;;L L C M#kkm 4
d 4C-/-/c*!#&--d344 05{{}[t@RVZ@Z[H[NE *!.!2!24!< 0I 0 Y/Y/0 !99T2. *C00SE\cQYFY S)S)**  48#!#J$T{ 3"44&--c23
 *4L&4 {
0 < \s/   ;H1H<	H7)H7-H<	II7H<c                 Z   | j                  g d       | j                  || j                  j                        \  }}| j                  j                  }|set
        j                  j                  |   }t        j                  |j                        }g }|rdddd| dgddd| dgg}|j                  |      S | j                  si S | j                  |||      }| j                  |      r>| j                  |d	   | j                   j                  | j                  j                        }|S )
N)search_sql_textsearch_sql_code_templatesearch_sql_name_templater?   rM   r
   ILIKE%rP   rQ   r4   r5   data)rA   r6   r   valuer   r^   CmfTaskr   r`   ra   rk   r!   r?   rB   _check_resultrl   r   )	r   relation_field_namer4   r5   r;   	field_cls	ref_modelsearch_filterrh   s	            r   bql_ext_options_listz,CmfDatasourceFieldQuery.bql_ext_options_list  s3    
 	 "&!9!9))//"

 $$**--.ABI11)//BIM!%W&m4W&m4!
 >>>77I!!%~!Vf%((v--33--33F r   c                    |r| j                  ||      S d|vrt        dd       |j                  d      }| j                  g d       | j                  r| j
                  si S | j                  || j                  j                        \  }}| j                  }t        j                  j                  ||d         }t        j                  j                  ||      }	| j                  | j
                  j                  |      }
| j                  |
|	||      }| j!                  |      r>| j#                  |d	   | j$                  j                  | j                  j                        }|S )
N	object_iduF   Для внешнего поля не передан id объектаTabort)option_list_sql_textr   option_list_code_templateoption_list_name_templater?   r   )idr   r   r   )r   rp   ry   rA   r?   r   r6   r   r   r   r^   r   r   build_query_paramr=   rB   r   rl   r   )r   r   
bql_editorr4   kwargsobj_idr5   r   r   rC   r;   rh   s               r   get_ext_options_listz,CmfDatasourceFieldQuery.get_ext_options_list5  sP   ,,-@&IIf$^fjkK( 
 	 d&?&?I!%!9!9**00"

 ::nn  F=3M N55GG][))$*C*C*I*I=Y!!%fUc!df%((v..44..44F r   c                 4    |d   st        d|d    d       y)Nsuccessu   <b>Возникла ошибка при обработке запроса, проверьте настройки параметров поля или источника данных.</b> <br/> messageTr   )rp   )r   rh   s     r   r   z%CmfDatasourceFieldQuery._check_result_  sE    i   Z  [a  bk  [l  Zm  n  vz  {r   c                 f   d }i }|d   j                         D ]  \  }}|d   j                         D ]  \  }}t        ||      }	t        |	t        j                  j
                        r;g }
|	D ].  } |||xs dg      }||
j                  |j                         0 |
||<   qt        |	t        j                  j                        r" ||	|xs dg      }||j                  nd||<   t        |	t        j                  j                        rt        d|        |	j                  ||<     |S )uN   
        Формирует значения параметров sql
        c                 <    | }|D ]  }t        ||d       }| |S  |S N)r   )r   attrsr   attrs       r   get_nested_attrzBCmfDatasourceFieldQuery.build_query_param.<locals>.get_nested_attrk  s8    E tT2=L	 Lr   r   r   rP   NuY   Данный тип поля нельзя использовать в SQL запросе )r9   r   
isinstancecmfr   
CmfM2MBasere   r   CmfRelationBaseCmfBackrefBaserp   )rE   r   r   r   query_param	param_keyr   r   r   field_name_valrw   itemvals                r   r   z)CmfDatasourceFieldQuery.build_query_parame  sF   	  -h 7 = = ? 	BIu%*8_%:%:%< B!
E!(j!9ncjj.C.CDF . 5-dE4EfXF?"MM#))45 .4K	*

0J0JK).%:KF8LC:=/SYYtK	*

0I0IJ y  {E  zF  G  H .<-A-AK	*%B	B* r   c                     t         j                  j                  |      }| r|st        dd       t         j                  j	                  || |      S )u  
        Превью пользовательского запроса
        
        todo:
        в jira elements connect есть возможность подстановки
        параметров через inputs для тестирования запроса
        r   u^   Не выбран источник данных или отсутствует sql запросTr   )r   )r^   CmfPluginDatasourcery   rp   rB   )r"   datasource_idr   r?   s       r   r   z)CmfDatasourceFieldQuery.sql_query_preview  sT     //33}3E
zv  C  D))55j(SY5ZZr   c                 *    t         |          g dz   S )N)r\   r   r   )supersave_preload_fields)r   	__class__s    r   r   z+CmfDatasourceFieldQuery.save_preload_fields  s    w*,/rrrr   c                     | j                   s| j                  s
i g d| _        | j                  j                  r,| j	                  | j                  j
                        }|| _        t        |   |i |S )Nr   )is_newr   r   
is_changedr*   r   r   save)r   argsr   r   r   s       r   r   zCmfDatasourceFieldQuery.save  sd    ;;d@@<>R1PD.$$// NN4+D+D+J+JKM1>D.w|T,V,,r   c                    | syt         j                  j                  |       }t         j                  j	                  |||rdnd      }t         j                  j                  |      }|D ]  }t         j                  j                  dd|gg d      }|j                  r|j                  sC|j                  j                  }|j                  |d	   |gz          t         j                  j                  ||      }|j                  |j                  j                  |      }	|j                  |	|      }
|j                  |
      s|j                  |
d
   |j                   j                  |j"                  j                        }
t%        ||      }|j&                  j(                  dk(  r;|r\|
D cg c]  }|d   |j*                  k(  s| }}t-        |||r|d   nd       n$|j&                  j(                  dk(  rO|r|
D ci c]  }|d   |
 }}|D cg c]   }|j*                  |v s||j*                     " }}t-        |||       n|j&                  j.                  rt-        |||
r|
d   d   nd       n|j&                  j(                  dv r/|
D cg c]  }||j                  k(  s| }}|sUt-        ||d       nG|j&                  j(                  dv r/|
D cg c]  }||j                  v s| }}t-        |||r|nd       |j1                  d        t3                yc c}w c c}w c c}w c c}w c c}w )uQ   
        Массовое обновление внешних полей
        Nr   FTr   r   )r   r   r   r   rJ   rI   r?   r   r   r   
choice_extrP   r   choice_multi_extr
   )rK   rU   rW   )rL   rV   rS   rT   )	only_data)r^   r   ry   r   r   r~   r?   r   r   r   rA   r   r=   rB   r   rl   r   r   r   r\   r]   rP   setattrrb   r   
cmf_commit)task_idr   r   r{   update_orderrn   dfqr   rC   r;   rh   cf_fieldr   resdict2s                  r   r   z)CmfDatasourceFieldQuery.recalc_ext_fields  s     nn  G ,55JJ'ET3
 55HHV! 7	)E0044%tU3 5 C >>)A)A==CCMOOM+6%@A!99KKCQ^_L,,S-E-E-K-K][E__UL9F  (++6N11771177 #3.:://<?06X$v,(--:WtXXUcCFtDZZ115GG@F Gft!3 G G<D[D		UZHZuTYY/[[UC0ZZ..CVq	&(9NZZ115QQ,2MDdhnn6L4MCMUD1ZZ115[[,2ODdx~~6N4OCOCs=4(o7	)r 	/ Y
 !H[ N
 Ps6   /L'L'L,L1*L1L6*L6L;0L;)Fr   )FN)NNN)NN)__name__
__module____qualname__r   api_methods	minijinjaEnvironmentrc   auto_escape_callbackstaticmethodr*   r/   r6   r=   rB   classmethodrG   rl   r~   r   r   r   r   r   r   r   r   r   __classcell__)r   s   @r   r   r      s   )559 K
 +Y**,N*;N' )
 )
V=& /1d m F F.` 0 0d C CJ'R(T $ $L [ [s- J Jr   r   )cmf.include4modules.datasource.fields.cmf_datasource_field_queryr   r   r	   r   r   <module>r      s     X l5 lr   