
    Ki{                         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*dedededed ed!ef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    r   hrefanchortarget	view_modeoriginal_urlc           	         ddl }ddl}ddlm}	 t          j        j        }
 |	d          }t          | j                  }t          | j	                  }t          | j
                  }| j        }| j        }|p| j        }|r|d| z  }|j                            t!          d          |          }|j                            t!                      |          }|d	v r=|||||d
}|                    |dd          }|                    d          }d|d<   ||d<   ||d<    |
            |d<   d|d<   |r||d<   |r||d<   |dk    rd|d<   |dk    rd|d<   |dk    r|p||_        nd |
             d  |
             d! |
             d"}d#d$d%} |	|                    ||                    |d&          |dk    r| j	         d'| n|(          d          j        }|dk    r|                     d)g           |                    d*          }d+|d,<    |
            |d<   d-| j        j         d.|d<   t          | j        j
                  |_        |                    |           d/|d,<   |                    |           |                    d*          }d0|d<   d1|d,<    |
            |d<   d0|d2<   d|d3<   d4|d5<   ||d6<   |                    |           |dk    r<|                    d7          }d8|d,<    |
            |d<   |                    |           nl||d9}|                    |dd          }|                    d          }d:|d,<   ||d<   d;|d<<   d|d3<   d=|d><   ||d?<   d|d<   |r||d<   |r||d<   |p||_        |S )@u?  
        Создает макрос ссылки на объект

        Args:
            obj (CmfTask, CmfDocument, CmfProject): объект на который ведет ссылка
            text (str, optional): текст ссылки. Defaults to None.
            href (str, optional): ссылка (адрес URL). Defaults to None.
            anchor (str, optional): якорная ссылка. Defaults to None.
            view_mode (str, optional): режим отображения ссылки:
                                       url - URL-адрес (полный);
                                       text - Встроенный текст (заголовок объекта);
                                       card - Карточка (описание объекта или фрагмент контента).
                                       Defaults to "text".
            original_url (str, optional): оригинальный URL-адрес. Defaults to None.

        Returns:
            BeautifulSoup: тег макроса
        r   N)BeautifulSoupzhtml.parser)featuresz##T)full_url)CmfTaskCmfDocument)viewModer   titleobjId	modelNameF),:)ensure_ascii
separatorsainheritcontenteditabler   zdata-object-idzdata-idtruecmf_convertedr   	href_origr   taskzdata-mention-typecardzdisplay: none;styleurlz]
                <span class="inline-card-icon-and-title link-view" title="{title}" data-id="z&">
                    <span data-id="aD  ">
                        <svg viewbox="0 0 24 24" class="ng-star-inserted" style="width: 20px; height: 20px; margin-bottom: -4px;">
                            <path fill="currentColor" d="{icon_path}"></path>
                        </svg>
                    </span>
                    <span class="card-name" data-id="z=">{card_name}</span>
                </span>
                ztM6,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)r   r   r|   z: )r   	icon_path	card_namezstatus.colorspanzcard-statusclasszbackground-color: z; color: #fff;zwiki-card-textfalsezwiki-link-wrapzdata-renderedzdata-internal-linkzwiki-link-presentationzdata-macroszdata-macros-parameterszapp-wiki-link-presentationzng-star-inserted)r   ui_nameplugin_linknoopenerrellinkzdata-link-typezdata-params)jsonurllibbs4r   r   r   get_data_idrG   r   r   r!   r   r  r   r   urljoinapp_base_hrefdumpsnew_tagstringformatr   r  load_fieldsstatuscolorr   )objr   r   r   r   r   r   r  r  r   data_idsoupobj_idobj_code	obj_title	obj_modelobj_ui_nameobj_hrefabsolute_urlrelative_urlmacro_params_datamacro_paramsa_tagTMPLr  link_view_tag
status_taglink_taglink_presentation_tags                                r   create_tag_linkzCmfImportPlugin.create_tag_linkx  s   8 	%%%%%%$0}m444SVsx==MM	N	k#38 	&V%H |++M4,H,H,H(SS|++MOOXFF222 &$"&! !  ::!"% &  L LL%%E'0E#$(E&M&,E"#&wyyE)%+E/" )"(h 2%1k"I%%-3)*F""!1gE!!#3|	_f_f_h_h	 	$+GII	 	 7>gii	 	 	 $Z  k 	 !.KK'"+--	2">">@IY@V@VSX"<"<"<"<"<\e    
 +! ! !   	))OO^$4555!%f!5!5J*7Jw',3GIIJy)*_sz?O*_*_*_Jw'(+CJO(<(<J%!((444!1g]+++ ||F++H*1H&' 0HW")'))HY(/H_%-3H)*&>H]#1=H-. OOE""" F""(,5Q(R(R%1C%g.3:799%i0 5666 !&! !  ::!"% &  L ||C((H -HW+HV(HUO-3H)*)/H%&&2H]#(.H_% ,%+" 5(4%"2lHO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   )r2  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:  r  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   r9  )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?  rQ  )r;  cmf_deletedry   -rA   )	from_codeoffsetFAKE_rB   r@  rB  )!rD  r:  
sqlalchemyrM  rN  rO  r   r   dp_modeldpdata_driverSessionqueryr   r   r   op
project_idr   rI   r>  	substringdescfirstrF  r   intr   r   import_raw_jsonget_code_prefixr   rG  )r;  rU  r:  rM  rN  rO  rX  sessiontask_with_max_codelatest_task	fake_taskcode_numberr   rJ  s                 r   _hack_create_fake_taskz&CmfImportPlugin._hack_create_fake_taskQ  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    )NFF)NNNNr   Nr   )&r^   
__module____qualname__r   staticmethodrG   r>   rb  rE   rN   rW   ri   ru   classmethodr   r   rj   anyboolr   r   r   r   r   r   r   r   r   r   r   r+  r.  r1  r
   r7  rK  rj  __classcell__)r   s   @r   r   r      sm       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 : : : : : : :
 #( < < < < < < <         \         g gg g 	g
 g g g g g \gR     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>rv     s           				           + + + + + + . . . . . . . . . . . . . . . . . .k
 k
 k
 k
 k
'7 k
 k
 k
 k
 k
r    