
    yiGi                         d dl mZ d dlZd dlZd dlT d dlmZ d dlmZ d dl	m
Z
 d dl mZmZmZmZ  G d d	ej                  ZdS )
    )OptionalN)*)fields)cmf_import_plugin)	CmfImport)DictUnionListr   c                       e Zd Z fdZededefd            Zededefd            Zed             Z	ededefd            Z
ededeeeffd	            Ze	 	 	 d#dededee         deeffd            Zd Zdd
d
d
d fd
Zdd fd
Zd Zd Zd Zed             Zd Zd Zd Zed             Zd Zd Z ede!e         defd             Z"ed!             Z#ed$d"            Z$ xZ%S )%CmfImportPluginc                      t                      j        |i | t          j                            d          | _        t          j        | _        t          j	        | _
        d S )Nsoftdev)code)super__init__modelsCmfActivitygetdefault_activityconfigIMPORT_THREADSthreading_max_forksIMPORT_DOWNLOAD_THREADSdownload_threading_max_forks)selfargskwargs	__class__s      $./common/models/cmf_import_plugin.pyr   zCmfImportPlugin.__init__   sW    $)&))) & 2 6 6I 6 F F#)#8 ,2,J)))    namereturnc                     g dg dddgg dd}|                                 D ]&\  }}|D ]}||                                 v r|c c S 'dS )N)u   открытopenu   к выполнениюtodonewpausedu
   зарегsubmit)u
   работprogressindeterminateactive
inProgressu   обсуждdiscusreviewu
   ревью)closeu   закрытu
   готовdonearchived	cancelled)OPENIN_PROGRESS	IN_REVIEWCLOSEDr3   itemslower)r!   mappingstatus_typewordswords        r   calc_status_typez CmfImportPlugin.calc_status_type   s    	 	 	   
  3!
 !
F #*--// 	' 	'K ' '4::<<''&&&&&& (' vr    c                     dgdgddgddgg dd}|                                 D ]&\  }}|D ]}||                                 v r|c c S 'd	S )
u+    Поиск priority по синониму u   минu   низкu
   обычнu   нормальнu   срокu
   высок)u   блокирующu
   большu   крит)r         r   r7   )r!   r:   priorityr<   r=   s        r   calc_priorityzCmfImportPlugin.calc_priority?   s     
01L)>>>
 
  '}} 	$ 	$OHe $ $4::<<''#OOOOO ($ qr    c                    | r|sdS t          |                                                                           }|                                D ]q\  }}|t          |                                                                          t          |                                                                          fv r|c S r| S )u  
        Находит ключ по значению или ключу в атрибуте choices у field
        Args:
            value: Значение для поиска
            choices: значения поля
        
        Returns:
            Найденный ключ или исходное значение, если ничего не найдено
        N)strstripr9   r8   )valuechoices	str_valuekeychoice_values        r   calc_choiceszCmfImportPlugin.calc_choicesO   s      	G 	FJJ$$&&,,..	 ") 	 	CS..4466<<>>C@P@P@V@V@X@XYYY


 Zr    c                     dgg ddgdgdgd}|                                 D ]&\  }}|D ]}||                                 v r|c c S 'dS )ue    Поиск программных типов workflow для проектов по синониму agile)baseu   основнu   классическhelpdeskservicedeskwiki)project.agilezproject.basezproject.helpdeskzproject.servicedeskzproject.wikirU   r7   )r!   r:   logic_prefixr<   r=   s        r   calc_logic_typezCmfImportPlugin.calc_logic_typee   s     &YLLL!+$1?#H
 
 $+==?? 	( 	(L% ( (4::<<'''''''' (( r    
obj_fieldsc                     i }i }i }|                                 D ]\  }}t          |t          t          f          r| j                            |          }|dk    r%d |                                D             d         }nC|dv r%d |                                D             d         }n|                                d         }t          |t          j        j	                  r	||d||<   ||d||<   |||<   |||fS )Nparentc                 (    g | ]}|j         d k    |S )
CmfProject__name__.0ms     r   
<listcomp>z9CmfImportPlugin._get_any_table_fields.<locals>.<listcomp>   s%    $j$j$j1qz]iOiOiQOiOiOir    r   )	executors
spectatorsc                 (    g | ]}|j         d k    |S )	CmfPersonr]   r_   s     r   rb   z9CmfImportPlugin._get_any_table_fields.<locals>.<listcomp>   s%    $i$i$i1qz]hOhOhQOhOhOhr    )modelr   )
r8   
isinstancedictlistr   r   related_models
issubclasscmf
CmfM2MBase)	rg   rX   related_objscurrent_objm2m_objs
field_namerI   
main_fieldrelated_models	            r   _get_any_table_fieldsz%CmfImportPlugin._get_any_table_fieldsu   s4   !+!1!1!3!3 	0 	0J%$.. 0"\--j99
))$j$j
0I0I0K0K$j$j$jkl$mMM#>>>$i$i
0I0I0K0K$i$i$ijk$lMM$.$=$=$?$?$BMj#**?@@ Y5Be+T+THZ((9FRW/X/XL,,*/J''[(22r    NF
cmf_import
filter_objc           
      (   |                      ||          \  }}}	|                                D ]1\  }
}|                     ||d         |d                   \  }}|||
<   2|	                                D ]	\  }
}|                    |
          g ||
<   g d}|D ]}|d                             |d          }|rt	          j        d|          }|D ]}||                                i}|
                    d          }|                     ||d         ||	          \  }}|<|                    d
|                                 d|
 dd|d         j	                   ||
         
                    |            n|t          j        k    ry|swd|d<   d |                    dg           D             }d|v r
d|d<   d|d<   d|v r@d|vr<t          j                            dd|d         gdg          }|r|dfS |d         |d<   |t          j        k    rIdd|d         gdd|d         gg}|                    d          r|
                    dd|d         g           |t          j        k    rIdd|d         gd d|d          gd!dt          j                            |d!         d"          gd#d|d#         gg}|r|}ng }g d}|D ]Y}|                    |d          }|r?|d$k    r|
                    d%|d|gd&d|gg           n|
                    |d|g            nZ|s|                                D ]{\  }}|rtt%          |t&          j        j                  s(t+          t-          ||          t.          j                  r-|
                    | d'dt3          |j                  g           |d}|r|                    d          r8|t          j        t          j        fv r|
                    dd(|d         g           d) |D             }|
                    d*           |                    ||          }|s2|t          j        k    r"d|vr|                    d+| d,d-d.           d/S |rdnd}|r|r||fS i }|                    d          r|d         |d<   |r|n |d3||                    d          dd0|}|                                D ]\  }}t;          |||           |rS|j        rLd} |d3||                    d          dd0|}|                                D ]\  }}t;          |||           |j        rC|j        r<|j         r|j	        d1k    r|!                                 |!                    d2           |}||fS )4u  
        Создание объектов на основании моделей при импорте
        :param CmfImport cmf_import: Объект импорта для хранения настроек, статуса по текущему импорту
        :param model: Модель по которой создается объект
        :param dict obj_fields: Параметры объекта
        :param Optional[list] filter_obj: Фильтр для проверки на существование объекта в БД
        :param bool dont_create: Не создавать объект
        :param bool dont_update: Не обновлять объект
        rg   r   )rg   rX   N)ext_idr   r!   emaillogin z[,;]cf_)rg   rX   dont_createu&   Не найдено значение 'u   ' поля ''zERR-0135)obj_typeT
user_localc                 &    g | ]}|j         j        S  )r   rI   )r`   pgs     r   rb   z<CmfImportPlugin.process_any_table_fields.<locals>.<listcomp>   s     ] ] ]2 ] ] ]r    rg_member_ofServiceDeskClientFemail_if_self_changesrz   r{   ILIKEz**filterr   r;   ==workflowr!   rZ   
cmf_authorcmf_created_at)dayfirsttextry   ORr   _id=c                     g | ]}|S r   r   )r`   rr   s     r   rb   z<CmfImportPlugin.process_any_table_fields.<locals>.<listcomp>   s    @@@jz@@@r    r   uN   Не удается найти или создать пользователя uf   . Проверьте правильность ввода логина/email пользователя. zERR-0115rf   )NF)rv   r!   import_originalr\   )save_importr   )"ru   r8   process_any_table_fieldsr   resplitrH   
startswith	log_error
class_nameappendr   rf   	CmfStatus
CmfCommentdateutilparserparserh   rm   	CmfEntityrl   getattrr   
CmfRelBaserG   idCmfComponentCmfListsetattr
is_changedr   is_newsave) clsrv   rg   rX   rw   r~   dont_updatero   rp   rq   main_field_namerelated_inforelated_obj_field_namesrr   field_valuevaluesrI   related_obj_fieldsrelated_dont_createrg_member_of_codeexisted_person_filteruniq_field_namesuniq_field_nameuniq_field_valueexisting_obj_fieldsr   r   new_objs                                    r   r   z(CmfImportPlugin.process_any_table_fields   sv   & /2.G.Gz.Z.Z+k8 .:-?-?-A-A 	7 	7)O\ 99*LY`LaEQRZE[ : ] ]NK+6K((-5^^-=-= 	 	)O\//7/1O,FFFK)  
*8488RHH Xg{;;F!' I I.8%++---H*.=.H.H.O.O+),)E)E&".w"7'9(;	 *F * *Q '.&00 v v vds v v v *)5g)>)I 1   
 $O4;;KHHHHE'* F$$$Z$(,K% ] ]Y[9\9\ ] ] ]"&777,1L)7<34+%%g.D.D!'!1!5!5gwP[\cPd=eosnt!5!u!u! 1)500'27';G$F$$$k-&@AT;z#:;J v&& G!!64V1D"EFFFF%%%4X!67t[%>?!4)>)>{K[?\gk)>)l)lm{623	J  	R GGGKKK#3  #.???B#G#G # &(22FV.WZ`bfhxYy'z{{{{?O'PQQQE  R)4):):)<)< R R%J R*UCJ4H"I"I R%/z0J0JFL]%^%^R:(:(:(:D#eh--'PQQQ 	Ex(( GUv7JFN6\-\-\#{8/DEFFF@@K@@@GNN3 99GG9DDL 	))){**   xak x x x$	 !    ;&0D 	(6 	(''??8$$ 	5*84F8 #/ 
,,EE 5
!(( 5
 5
 	5
 5
 "-!2!2!4!4 	0 	0JGZ//// 		47- 		4Fe % __V,, $  	 G &1%6%6%8%8 4 4!
EU3333 	+'"9 	+~ %"2l"B"BLLTL*** V##r    c           
          | j         rdS t          j        d| j        | j        | j        |||d|}|                                 || _         dS )u3   
        Дает доступ из вне
        N)r!   typetokenext_url	ext_login	ext_tokenr   )pluginr   	CmfPluginr   r   r   r   )r   r   r   r   r   r   s         r   _init_secretzCmfImportPlugin._init_secret=  sh     ; 	F! gtytdg*1YR[g g_eg gr    r   )depthr   r   r   c                v    | j         r|                     |||            t                      j        |d|i|S )Nr   )r   r   r   r   )r   r   r   r   r   r   r   r   s          r   r   zCmfImportPlugin.saveH  sE    ; 	=gy)<<<uww|T99&999r    )forcec                    t           j                            dd| j        gg d          }|                                  t                      j        |d|i|S )Nr   r   )r   r   r   r   r   r   )r   r   r   r   deleter   )r   r   r   r   r   r   s        r   r   zCmfImportPlugin.deleteM  sc    !%%gtTW-E-[-[-[ & ] ]uww~t;5;F;;;r    c                     t                      )uJ   
        Формирование шаблона настроек
        NotImplementedr   rv   s     r   tmplt_import_settingsz%CmfImportPlugin.tmplt_import_settingsS       r    c                     t                      )u9   
        Предпросмотр импорта
        r   r   s     r   previewzCmfImportPlugin.previewY  r   r    c                     t                      )u-   
        Запуск импорта
        r   r   s     r   process_importzCmfImportPlugin.process_import_  r   r    c                      t                      )uC   
        Маппинг полей по умолчанию
        r   r   r    r   calc_models_settingsz$CmfImportPlugin.calc_models_settingse  s    
 r    c                     t                      )uK   
        Тестирование подключения к апи
        r   )r   r   r   s      r   testzCmfImportPlugin.testl  r   r    c                     t                      Nr   r   s    r   download_datazCmfImportPlugin.download_datar      r    c                     t                      r   r   r   s    r   download_fileszCmfImportPlugin.download_filesu  r   r    c                    ddl m dd l}dd l}fd}t	          | j        | j        j        d| j        j        | j	                  } d          }|
                    dd	|d
         d          }|                    |          }|
                    dd          }d|d<   d|d<   d|d<   ||d<   d|d<   d|d<   |                    |           |
                    dd| j        j                  }	|
                    d          }
|
                     || j	                             |
                    dd          }|                    | j        j         d| j        j                    |	                    |
           |	                    |           |                    |	           t          | t          j                  rv|
                    dd| j                                        j        j        j         d          }d |d<   | j        j        j        j        |_        |	                    |           |S )!Nr   )BeautifulSoupc                 L    ddd}d}| |v r||          } d| dd          S )	NztM6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Za	  M19,3H14.82C14.4,1.84 13.3,1 12,1C10.7,1 9.6,1.84 9.18,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M12,3A1,1 0 0,1 13,4A1,1 0 0,1 12,5A1,1 0 0,1 11,4A1,1 0 0,1 12,3M7,7H17V5H19V19H5V5H7V7M7.5,13.5L9,12L11,14L15.5,9.5L17,11L11,17L7.5,13.5Z)CmfDocumentCmfTaska  M6.2 12.3a1 1 0 011.4 1.4l-2.1 2a2 2 0 102.7 2.8l4.8-4.8a1 1 0 000-1.4 1 1 0 111.4-1.3 2.9 2.9 0 010 4L9.6 20a3.9 3.9 0 01-5.5-5.5l2-2zm11.6-.6a1 1 0 01-1.4-1.4l2-2a2 2 0 10-2.6-2.8L11 10.3a1 1 0 000 1.4A1 1 0 119.6 13a2.9 2.9 0 010-4L14.4 4a3.9 3.9 0 015.5 5.5l-2 2zz<svg viewBox="0 0 24 24" class="ng-star-inserted" style="width: 20px; height: 20px; margin-bottom: -4px;"><path fill="currentColor" d="z"></path></svg>html.parserfeaturesr   )
model_name	icon_pathpathr   s      r   get_icon_modelz7CmfImportPlugin.create_tag_link.<locals>.get_icon_model}  s{     $Z  k I aDY&& , =  "A  lp  "A  "A  "A  KX  Y  Y  Y  Yr    r   )hreftitleviewModeobjId	modelNamer   r   ainheritr   T)contenteditabler   cmf_convertedspanfalse)r   zdata-renderedtruezdata-internal-linkzwiki-link-presentationzdata-macroszdata-macros-parameterszwiki-link-wrapclasszwiki-card-textz$inline-card-icon-and-title link-view)class_r   zpadding-right: 5px;)stylez: zbackground-color: z; color: #fff;zcard-status)bs4r   jsonrandomri   r   r!   rI   r   r   new_tagdumpsr   r   rh   r   r   statusloadcolorstring)objr   r  r   link_paramssouplinklink_params_strspan_wrapperr   	icon_span	name_spanstatus_spanr   s                @r   create_tag_linkzCmfImportPlugin.create_tag_linkx  sv   %%%%%%	Y 	Y 	Y 	Y 	Y WZW]Wcoro}~~~}m444||CVATdh|ii**[11||# $ 
 
 )0_%-3)*&>]#1@-. 0W(WD!!! ||F+QY\YaYg|hhLL((	77888LL/DLEE	CHN>>chn>>???IID c6>** 	%,,^3:??+<+<+B+H+N^^^ '  K $1K !$!1!6!<KKK$$$r    c                     d S r   r   r   r  s     r   calc_ext_hrefzCmfImportPlugin.calc_ext_href      tr    c                     d S r   r   r  s     r   calc_dump_pathzCmfImportPlugin.calc_dump_path  r  r    settingsc                     d | D             S )Nc                      i | ]}|d          |S )r!   r   )r`   ss     r   
<dictcomp>z7CmfImportPlugin._normalize_settings.<locals>.<dictcomp>  s    ///&	1///r    r   )r  s    r   _normalize_settingsz#CmfImportPlugin._normalize_settings  s    //h////r    c                 f   ddl m} |                     dg           | j        }t          j                            dd| gdd|j        ggdgd	dgd
          }|rV|j        |j        j	        k     rC|j         |d          z
  }||_        |
                    d
           t                       dS dS dS )u{  
        При поиске свободного кода, задачи сортируются по дате создания cmf_created_at
        и не учитываю порядок цифровой части кода в методе CmfTask._get_current_code_number_from_db.
        При такой сортировке у импортированных из других систем проектов
        самой последней по дате задачей является Гант задача проекта с числовым кодом 0,
        так как она была создана при создании проекта в дату проведения импорта.
        Соответственно поиск свободного кода начнется с 1 и
        продолжится, пока не найдет первый свободный код задачи,
        которая могла быть не импортирована, так как удалена в другой системе.

        HACK: Для исправления такого поведения, заменяем дату создания у Гант задачи на дату,
        более раннюю чем у самой старой задачи проекта.

        Args:
            project (CmfProject): Объект проекта
        r   	timedeltaz!main_gantt_project.cmf_created_atprojectr   r   z!=r   --Tr   order_byr   include_deletedrB   seconds	only_dataN)datetimer   load_fieldsmain_gantt_projectr   r   sgetr   r   rI   r   
cmf_commit)r!  r   gantt_projectoldest_task
created_ats        r   _hack_replace_creation_datez+CmfImportPlugin._hack_replace_creation_date  s    $ 	'&&&&&@ABBB2n))C)t]-. ''*+  * 
 
  	;58T8ZZZ$3ii6J6J6JJJ+5M(...LLLLL		 	ZZr    c                    ddl m} ddlm}m}m} t          j        j        }t          j        j	        j
                                        }|                    |j        |j                                       |j                            d          d          |j        | j        j        k                                   ||                    |j        d          |                                                                                    }|sdS t          j                            g dd	d
| ggdgg dd          }	|j        |	j        k    r|sdS t          j                            d	d
| gg dgd          }
|
st                              | dd          }
t5          |j                            d          d                   }|
j        r|r||z  }|j        |d|
_        d|
                                 d| }||
_        |
j        |	j        k    r|	j         |d          z   }||
_        |
                    d           tA                       dS )u  
        Создает фиктивную задачу для коррекции генерации кода задач в проекте.

        Создает скрытую (удаленную) задачу с максимальным числовым
        кодом, чтобы "зарезервировать" текущий номер и предотвратить конфликты при
        последующих импортах.

        Основные сценарии использования:
        1. Когда задачи импортируются не в хронологическом порядке создания
        2. Когда требуется сместить нумерацию
        3. Для предотвращения дублирования кодов задач

        Фиктивная задача помечается как удаленная (cmf_deleted=True) и имеет
        специальный идентификатор ext_id="import::fake" для последующей идентификации.

        Args:
            project (CmfProject): Объект проекта, для которого создается фиктивная задача
            offset (int, optional): Сдвиг цифрового значения кода задачи. Используется для
                корректировки нумерации при импорте. Например, offset=100 увеличит числовую
                часть кода на 100. По умолчанию None (без сдвига).

        Returns:
            CmfTask or None: Объект созданной фиктивной задачи или None, если создание
                не требуется (когда задача с максимальным кодом уже является самой
                последней по дате создания и offset не указан).
        r   r  )funccastInteger~z^.*-[0-9]+$z	([0-9]+)$N)r   z
SIMILAR TOz
%-[0-9]+\Zr!  r   z-cmf_created_at)r"  r   r   Tr#  )ry   r   import::fake)r   r%  r8  )r!  cmf_deletedry   -rA   )	from_codeoffsetFAKE_rB   r&  r(  )!r*  r   
sqlalchemyr4  r5  r6  r   r   dp_modeldpdata_driverSessionqueryr   r   r   op
project_idr   rI   r$  	substringdescfirstr-  r   intr   r   import_raw_jsonget_code_prefixr   r.  )r!  r<  r   r4  r5  r6  r?  sessiontask_with_max_codelatest_task	fake_taskcode_numberr   r1  s                 r   _hack_create_fake_taskz&CmfImportPlugin._hack_create_fake_task  s   8 	'&&&&&2222222222>*.#/7799 %]]M#
 
 &!HMS!!-007:#33
 
 (Dx}k::  dff	
 

 %'' 	 " 	F n))444C) ((333  * 
 
 "k&666v6F N&&C)/// ! ' 
 
	  	 % '  I ,177<<R@AA  	 	6!K 04 ) )I% Cy0022BB[BB	 >[---$3ii6J6J6JJJ'1I$&&&r    )NFFr   )&r^   
__module____qualname__r   staticmethodrG   r>   rI  rE   rN   rW   ri   ru   classmethodr   r   rj   anyboolr   r   r   r   r   r   r   r   r   r   r   r  r  r  r
   r  r2  rQ  __classcell__)r   s   @r   r   r      s
       K K K K K )s )s ) ) ) \)V C C    \   \* c c    \ 3 34t:L 3 3 3 \30  &*l$ l$l$ 	l$
 TNl$ tl$ l$ l$ [l$\	 	 	 !"444 : : : : : : :
 #( < < < < < < <         \       0 0 \0f     0d4j 0T 0 0 0 \0 " " \"H e e e \e e e e er    r   )typingr   r   r   cmf.includerm   r   common.fieldsr   common.models.cmf_importr   r   r	   r
   r   r   r    r   <module>r]     s           				           + + + + + + . . . . . . . . . . . . . . . . . .u u u u u'7 u u u u ur    