U
    nLieP                    @   s  d dl Zd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lT d dlm Z  d dl!m"Z" e# Z$dddZ%edd Z&G dd de j'Z'dS )    N)contextmanager)deepcopy)permutations)BeautifulSoup)Path)Queue)	unidecodecmf_context)*)cmf_plugin_kaiten)KaitenClientc                    s    fdd}|S )Nc                    s    fdd}|S )Nc              
      s   zTd k	r*| j jd d dd dd | j  r:W dS  | f||}t  |W S  tk
r } zBt  |  jd7  _| j drd nd d	|  W Y dS d }~X Y nX d S )
Nz===== T	anonymousr         Ошибка . )
cmf_importlog	is_cancel
cmf_commit	Exceptioncmf_rollback
has_errors	log_error)objargskwargsresexc)funcname ,./modules/kaiten/models/cmf_plugin_kaiten.pywrapper"   s     
$z3catch_exception.<locals>.decorator.<locals>.wrapperr$   )r"   r&   r#   )r"   r%   	decorator!   s    z"catch_exception.<locals>.decoratorr$   )r#   r(   r$   r'   r%   catch_exception    s    r)   c                	   c   s&   zdt jd< d V  W 5 dt jd< X d S )N1ZNO_CACHEr   )osenvironr$   r$   r$   r%   enable_cache6   s    

r-   c                       s  e Zd ZdZejjd Zejjdg Z fddZe	dd Z
e	dd	 Zed
d ZeeedddZedd Zedd ZeedddZdd Zdd Zdd ZdddZdd Zd d! Zd"d# Zd$d% Zd&d' Zed(d)d*Zd+d, Zdd/d0Zd1d2 Z d3d4 Z!d5d6 Z"d7d8 Z#d9d: Z$e%d;ed(d<d=Z&d>d? Z'd@dA Z(e%dBdCdD Z)e%dEdFdG Z*e%dHdIdJ Z+dKdL Z,dMdN Z-ddPdQZ.dRdS Z/dTdU Z0dVdW Z1dXdY Z2dZd[ Z3d\d] Z4d^d_ Z5d`da Z6ddcddZ7e%dedfdg Z8edhdidjZ9dkdl Z:dmdn Z;dodp Z<dqdr Z=e%dsdtdu Z>dvdw Z?dxdy Z@e%dzd{d| ZAe%d}d~d ZBdd ZCdd ZDdd ZEdd ZFdd ZGdd ZHdd ZIdd ZJdd ZKdd ZLdd ZMdd ZNdd ZOdddZPdd ZQe% dd ZRdd ZSdd ZTdd ZUdddZVdd ZWdd ZXdd ZYdd ZZdd Z[dd Z\dd Z]dd Z^dd Z_dd Z`dd Zae%dddÄ Zbddń ZcddǄ ZdddɄ Zedd˄ Zfe%d̃dd΄ Zge%dσdehdМdd҄ZiddԄ Zj  ZkS )CmfPluginKaitenN)clientkaiten_fieldsget_all_projectsc                    s   t  j|| i | _i | _i | _g | _d| _d| _d | _d | _	g | _
ddddddd	dd
dddd| _tjjdd| _tjjdd| _tjjdd| _tjjdd| _d S )Nr   F   ОчередьOPENz#a0a0a0)r#   typecolor   В работеIN_PROGRESSz#3f82d8   ГотовоCLOSEDz#23a055)r         Zsoftdevcodezproject.agile:defaultzdefault.system:defaultzlist.base:default)super__init__task_relationsZepicssubtasksselected_projectsr   update_fields_CmfPluginKaiten__kaiten_fields_archived_tasks_service_fields_status_type_mapmodelsZCmfActivityget_project_softdev_activityCmfLogicType_project_agile_typeCmfWorkflow_workflow_template_list_base_type)selfr   r   	__class__r$   r%   r?   J   s$    


zCmfPluginKaiten.__init__c                 C   sN   t tdsH| ddddg tt| jj| jj | jj	j
t dt_tjS )u5    Клиент для работы с Kaiten REST API r/   pluginzplugin.ext_urlzplugin.ext_tokenzplugin.verify_ssl)urltoken
verify_sslZsession)hasattr
thread_ctxload_fieldsr   strrS   Zext_urlZ	ext_tokenZdecryptrV   valuecmfutilZrequests_sessionr/   )rP   r$   r$   r%   r/   a   s    


zCmfPluginKaiten.clientc              	   C   s   | j r| j S | j d}| rN| jsNt|d}t|| _ W 5 Q R X n:| j	
 | _ t|d}tj| j |dd W 5 Q R X d| _| j S )Nzfields.jsonr+w+Fensure_ascii)rD   r   get_download_pathjoinpathexistsrC   openjsonloadr/   Z
get_fieldsdump)rP   	file_pathfr$   r$   r%   r0   s   s    zCmfPluginKaiten.kaiten_fieldsc                 C   sR   t | } |  } tdd| } tdd| } tdd| } tdd| } | dS )	N&z and z\+r   z[^\w\s-]r   z[\s_-]+-)r   lowerresubstrip)textr$   r$   r%   _slugify   s    zCmfPluginKaiten._slugify)datareturnc                 C   s   | d }|  dpd}|  d}tj| d| d}|d k	r`ttj|d}|j|d}n|jtjjd}|tjj}|	 S )	Ndatetimez00:00:00ZtzOffsetr   z%Y-%m-%d %H:%M:%Sminutes)Ztzinfo)
rI   dtdatetimestrptimetimezone	timedeltareplaceZutcZ
astimezoneZ	isoformat)rr   Zdate_strZtime_strZ	tz_offsetZdt_naiveZtzZdt_objZdt_utcr$   r$   r%   _dict_to_dt   s    
zCmfPluginKaiten._dict_to_dtc                  C   s   g } | S Nr$   )r    r$   r$   r%   calc_models_settings   s    z$CmfPluginKaiten.calc_models_settingsc                 C   sF   |sdS | dr8|dd}| dp*i }||}n
| |}|S )u`   
        Метод получает значение параметра объекта
        Ncf_id_
properties)
startswithr}   rI   )obj_dataattrproperty_idr   r[   r$   r$   r%   
_get_value   s    

zCmfPluginKaiten._get_value
field_namec                 C   s&   |sd S | j |gd}|r"|d S d S )N)Zfields_namer   )import_shop_fields)modelr   r    r$   r$   r%   _get_field_name   s    zCmfPluginKaiten._get_field_namec                 C   sB   ddddddddd	d
dd}||kr,|| S | j |i ddS )Nu   ИмяZEmailu(   Не работает/Уволенныйu   Наименованиеu   Описаниеu   Созданоu   Обновленоu   Срокu   Постановщикu   Исполнительu   Тип)	full_nameemail	activatedtitledescriptioncreatedupdateddue_dateowner_idmembersr4   r#   r   )r0   rI   )rP   r   mappingr$   r$   r%   _get_setting_title_by_attr   s    z*CmfPluginKaiten._get_setting_title_by_attrc              
   C   sn   ddddddddddd	dd
dddddddddddg}| j  D ]\}}|d||d qN|S )uO    Сопоставление настроек для модели models.CmfTaskr#   r   model_fieldr   rp   r   cmf_created_atr   cmf_modified_atr   Zdeadliner   	cmf_ownerr   responsibler   
logic_typer4   N)r   r   	ext_field)r0   itemsappend)rP   Ztask_settingsZcf_idcfr$   r$   r%   _get_task_import_settings   s     
z)CmfPluginKaiten._get_task_import_settingsc                 C   s    dddddddddg}|S )uQ    Сопоставление настроек для модели models.CmfPersonr#   r   r   r   does_not_workr   r$   )rP   Zuser_settingsr$   r$   r%   _get_user_import_settings   s
    z)CmfPluginKaiten._get_user_import_settingsc                    sX  | dr4|r4|d }|d kr2|dkr.dS |S |dkrD|d }n|d }|dkrg  |D ]F}|d	 t|}|d
 }	|r |	 q\tj|	ddd}
|
  S q\tjd|} fdd|D }|S |dkr g }|D ]}t	|t
kr|d }n|}zz| |}W n2 tk
r< } zt| dW 5 d }~X Y nX | j|ddd\}}|shtd| d|rz|| n
|W   S W q tk
r } zR|  jd7  _| jjd|d  d| d| d| ddd |sW Y 
 d S W 5 d }~X Y qX q|S |d krtd!d"t|S |d#krT| |S n |d$kr|d krL|S d%| j d%|d  d%}tjjd&d'd(| d(gd)}|S |d*kr|d kr|S | j d%|d+ d  d%|d  }tjjd&d,|gd-gd.}|S |d/kr"|d kr|S |D ]&}|d d0kr| |d   S qd S |d1krD|d kr:|S | |S |d2krT| S |S )3Nr   r4   checkboxFstring	multilinemulti_selectselectselectValuesr[   rk       seplengthCmfTaskc                    s   g | ]}|d   kr|qS r'   r$   ).0choiceZvalue_namesr$   r%   
<listcomp>  s      z4CmfPluginKaiten._normalize_value.<locals>.<listcomp>useriduJ   . Возможно пользователь был удален в Kaiten.)createupdateu   Пользователь UID 'u&   ' не найден в системе.r   u1   Не удалось присвоить полю 'r#   ' (u   ) значение ''. zERR-0002	CmfPersonobj_typephonez[^\d+]r   rt   r   ::ext_idLIKE%filterstatusproject=status_typer   fieldsr   r:   r   r   )r   rI   rZ   r   r\   translit_striprH   ZCmfCustomFieldChoiceZlist_choicer4   dict_get_user_data_from_dumpr   _process_personr   r   r   rm   rn   r~   source_hashrK   	CmfStatus_get_person)rP   r   r[   r   r   Zcustom_field_typeis_multiZvalue_idZ
value_data
value_name	value_keychoicesvaluesusers	user_datauser_idZ	user_infor!   person_logic_type_ext_idr   status_ext_idr   r   r$   r   r%   _normalize_value   s    





 





"



z CmfPluginKaiten._normalize_valuec           	      C   s   i }|D ]}|d sq| d}|d d }| ||d }| ||||}|||< |r|dr|r|d dkr|d r|d	g }|| q|S )
uC    Преобразование настроек для модели r   r   r   r   r   r4   r   r   deferred_text_fields)rI   r   r   r   
setdefaultr   )	rP   r   settingsZnormalized_objsettingr   r   r[   r   r$   r$   r%   _normalize_objZ  s6    

zCmfPluginKaiten._normalize_objc                    s  g  |_ j dg  fdd}d }d }j  d}| r D ]$}|d D ]} qjq`|rN qtqNdD ]} qq~|sdd jj	d	d
dD }|r|d }|st
d|s̈j }|st
dd_||jtj ||jtj  dg d  S )Nplugin.plugin.*c                    sj   | }|D ]H} | |d |d< ||d |d< |d |d< |j|d< q
 |j|d d S )Nr   r[   r   r   iconr#   r   )r   r   r   r   r   verbose_name)r   Zsettings_funcr   Zobj_settingsr   resultrP   r$   r%   _get_settings}  s    z<CmfPluginKaiten.tmplt_import_settings.<locals>._get_settingsprojectsr   r   c                 S   s   g | ]}|qS r$   r$   )r   r   r$   r$   r%   r     s     z9CmfPluginKaiten.tmplt_import_settings.<locals>.<listcomp>r   r   )additional_card_fieldslimitr   uT   Не найдено ни одной задачи, импорт невозможен!ub   Не найдено ни одного пользователя, импорт невозможен!TselectedObjects)r#   r[   )r   rY   ra   rb   rc   _get_projects_get_project_tasks_simple_getr/   	get_cardsr   Zget_current_userrC   r   rH   r   r   r   r   )rP   r   r   taskr   projects_dirr   tasksr$   r   r%   tmplt_import_settingsw  s<    	
z%CmfPluginKaiten.tmplt_import_settingsc              
   O   s  |  dg | jj| _g }z| j}| D ]}t|d }|d }|}|d rX|d7 }d| j d| d}	tjjddd	|	 d	gd
ddgd}
|
r|d7 }|
j	}n| 
|}tj|}||||d}|| q,W 5 Q R X W n0 tk
r } zt|  W 5 d }~X Y nX |S )Nzplugin.source_hashr   r   archivedu    (архивный)r   r   r   r   T--task_code_prefixr   include_deletedr   u    [импортирован])r   keyr#   original_name)rY   rS   r   r/   Z
get_spacesrZ   rH   
CmfProjectsgetr   rq   Zget_prefix_from_namer   r   gdebug)rP   r   r   r   r/   space
project_idproject_titleproject_nameproject_ext_idr   project_keyZproject_codeproject_datar!   r$   r$   r%   r1     s@    


z CmfPluginKaiten.get_all_projectsc                 C   s   t |}tjj}|| jj d| }|d k	r:t|S | 	dD ]}t |d|krb|  S |d|krx|  S |dd
 |
 kr|  S |dd
 |
 kr|  S |dd
 |
 krD|  S qDtd	| d S )
N:user:r   r   uidr   r   usernamer   uH   В дампе не найдены данные пользователя )rZ   APPREDIS_DBredisrI   r   r   pickleloadsr   rl   r   )rP   r   redis_dbr   r$   r$   r%   r     s"    

z(CmfPluginKaiten._get_user_data_from_dumpc                 C   s  t |}t |drd S z| |W S  tk
r   z|d}|  rt|d}|D ]}t|}t |d |kr|  W  5 Q R  W  Y S |	d|kr|  W  5 Q R  W  Y S |	dd
 |
 kr`|  W  5 Q R  W  Y S q`W 5 Q R X | j|}|rHt|d}|tj|d	d
d  W 5 Q R X |W  Y S W n8 tk
r } z| jjd|  W 5 d }~X Y nX Y nX d S )Nrk   
users.jsonrr   r  r   r   a+Fr_   
uS   Не удалось получить данные пользователя по ID )rZ   r   r   r   rb   rc   rd   re   r  rI   rl   r/   Zget_userwritedumpsr   loggerwarning)rP   r   Zdump_dir
users_fileri   rowr   r!   r$   r$   r%   _get_user_data  s6    


&"zCmfPluginKaiten._get_user_datar'   c              	   c   sN   | j  | d}| rJt|d}|D ]}t|V  q.W 5 Q R X d S )N.jsonr]   )r   ra   rb   rc   rd   re   r  )rP   r#   rh   ri   r  r$   r$   r%   r     s    zCmfPluginKaiten._simple_getc              
   c   sf   | j  d}| rbt|D ]>}|dr2q"t| d| dd}t	|V  W 5 Q R X q"d S )Nr   .dirtyz.meta/
/info.jsonr]   )
r   ra   rb   rc   r+   listdirendswithrd   re   rf   )rP   project_dirr  ri   r$   r$   r%   r     s    
zCmfPluginKaiten._get_projectsr   Fc              
   c   s  | j  dt|d}| s>| j jd| d|  d S d}t| D ]}|	 s\qN|j
}|drnqN|r|d sqN|d }	| jd	kr|	sqNn| jd
kr|	rqN||k r|d7 }qN|d k	r||| kr qt|dd}
t|
V  W 5 Q R X |d7 }qNd S )Nr   r   u   Каталог u    отсутствует. Возможно он был удален или еще не создан. Необходимо повторно запустить импорт проекта r   r   .processing	.archivedTFr   	info.jsonr]   )r   ra   rb   rZ   rc   r  r  r   iterdiris_dirr#   r%  rE   rd   re   rf   )rP   r  offsetr   only_processing	tasks_dircounttask_dirtask_idis_archivedri   r$   r$   r%   r     s@    
  
z"CmfPluginKaiten._get_project_tasksc              
   c   sN   | j  dt|d}|dD ]&}t|d}t|V  W 5 Q R X q"d S )Nr   boardsz*.jsonr  )r   ra   rb   rZ   globrd   re   rf   )rP   r  
boards_dir
board_fileri   r$   r$   r%   _get_project_boardsH  s    
  z#CmfPluginKaiten._get_project_boardsc              
   C   s   t |drtjS z| |}W nD tk
rf } z&| jj| dddd tj W Y S d }~X Y nX | |dd\}}|s| jj	j
drtjj| jj	d d}| jjd	| d
| tjd n.| jjd	| dddd tj}|  jd7  _|S )Nrk   uK   . Будет установлен пользователь 'Система'zERR-0003r   r   FZdefault_user_idr   u,   Не найден пользователь 'uU   '. Будет установлен пользователь по умолчанию: )leveluL   '. Будет установлен пользователь 'Система'zERR-0004r   )rZ   r   r  system_userr   r   r   r   r   json_settingsr[   rI   rH   r   r   loggingWARNINGr   )rP   r   r   r!   r   r   r$   r$   r%   r   P  s6    
zCmfPluginKaiten._get_personc              
   C   s  d}d}d}d}| j  dt|d}| rt| D ]}| sJq<|j	drXq<t
|dd}t|}	W 5 Q R X |d}
|	d}|r|d	7 }t
|
d
}|d W 5 Q R X n|d	7 }|
jdd |d r<|r|d	7 }q<|d	7 }q<|| || ||||f}|S )u  
        Возвращает статистику по сдампленным задачам проекта

        Args:
            project_id (int): ID проекта

        Returns:
            tuple: статистика задач проекта
        r   r   r   r   r)  r  r(  r   r   wr   T
missing_okr'  )r   ra   rb   rZ   rc   r   r*  r+  r#   r%  rd   re   rf   rI   r  unlink)rP   r  activer   unprocessed_activeunprocessed_archivedr.  r0  ri   	task_dataZarchived_flag_filer2  statsr$   r$   r%   _get_project_tasks_statsr  sJ    

  



z(CmfPluginKaiten._get_project_tasks_statsc                 C   s>  t jj}| jd g }t }| j d}| rt	|d}t
|dD ]\}}| }|sbqLz*t|}	|t|	d  ||	 W qL tk
r }
 z(| jd| d| d|
 d	|  W 5 d
}
~
X Y qLX qLW 5 Q R X |d }| |D ]
}t|d d}| sqd}t	|}t
|dD ]\}}| }|sHq.zNt|}	t|	d }||kr|| jj d| t|	 ||	 W nL tk
r }
 z,d}| jd| d| d|
 d	|  W 5 d
}
~
X Y nX q.W 5 Q R X |s|  qt	|d*}|D ]}	|tj|	ddd  qW 5 Q R X d
S )us    Собирает пользователей из файла users.json в каталогах документов u9   Сбор пользователей из объектовr  r  r   r   u   Ошибка в строке u    файла : r   Nr0  Fr  Tr^   r_   r  )r  r  r  r   r   setra   rb   rc   rd   	enumeratero   re   r  addrZ   r   r   r   r   r   r   r  r  rA  r  )rP   r
  r  Zcurrent_usersZcurrent_user_idsZall_users_fileri   Zline_numberliner   r!   r  r   Ztask_users_fileerrorr   r$   r$   r%   _collect_users  sb    
"



$
zCmfPluginKaiten._collect_usersc                 C   sF   t jj}| dD ].}|d}|| jj d| t	| qd S )Nr   r   r  )
r  r  r  r   rI   rI  r   r   r  r  )rP   r  r   r   r$   r$   r%   _cache_all_users  s    
z CmfPluginKaiten._cache_all_usersu   Дампc              	   C   s   | j  | d}| r(t| | j  | d}t|d:}| D ],}| j  jd7  _|t	j
|ddd  qPW 5 Q R X t|| | j jjdd	 d S )
Nr  z.json.dirtyr  r   Fr_   r  TZ	only_data)r   ra   rb   rc   r+   removerd   json_object_countr  re   r  shutilmover[   save)rP   Zapi_funcr#   rh   Zfile_tmp_pathri   r  r$   r$   r%   _simple_dump  s    

$zCmfPluginKaiten._simple_dumpc           
      C   s   t |d }|d }|d }||}| j d| d| }tjj|| jdddgd}	|	sntj|| j| jd}	||	_||	_||	_	|	j
s| sd	|	_||	_|	  t  d S )
Nr   r#   rT   r   hrefpath)
obj_ext_idr   r   )rY  r   r   F)rZ   rb   r   rH   CmfImportDownloadrI   r   r#   rW  rX  
is_changedrc   
downloadedimport_raw_jsonrU  r   )
rP   r1  
attachmentattachments_dirattachment_id	file_nameZdownload_urlattachment_fileattachment_ext_iddownload_jobr$   r$   r%   _dump_task_attachment  s0    
z%CmfPluginKaiten._dump_task_attachmentc                 C   sJ   t |d }|d}|jdd |dg D ]}| |d || q.d S )Nr0  attachmentsTexist_okfilesr   )r   rb   mkdirrI   re  )rP   r   r0  r_  r^  r$   r$   r%   _dump_task_attachments  s
    
z&CmfPluginKaiten._dump_task_attachmentsu.   Дамп комментариев задачиc              	   C   s   t |d }|d}| r(t| | j|d }t|dP}|D ]D}|drf| 	|d | |
tj|dddd	  | jd
 qHW 5 Q R X d S )Nr0  comments.jsonr   r  	author_idFTr`   	sort_keysr  comment)r   rb   rc   r+   rQ  r/   Zget_card_commentsrd   rI   r  r  re   r  r   inc_stat)rP   r   r0  comments_fileZcommentsri   rp  r$   r$   r%   _dump_task_comments  s    


z#CmfPluginKaiten._dump_task_commentsu/   Дамп журнала работ задачиc              	   C   s   t |d }|d}| r(t| | j|d }t|dD}|D ]8}|drf| 	|d | |
tj|dddd	  qHW 5 Q R X d S )
Nr0  timelogs.jsonr   r  rm  FTrn  r  )r   rb   rc   r+   rQ  r/   Zget_card_time_logsrd   rI   r  r  re   r  )rP   r   r0  time_logs_fileZ	time_logsri   time_logr$   r$   r%   _dump_task_time_logs&  s    


z$CmfPluginKaiten._dump_task_time_logsu)   Дамп чек-листов задачиc              	   C   s   t |d }|d}| r(t| t|dH}|dg D ]4}| j|d |d }|	t
j|dddd	  q@W 5 Q R X d S )
Nr0  checklists.jsonr  Z
checklistsr   FTrn  r  )r   rb   rc   r+   rQ  rd   rI   r/   Zget_card_checklistr  re   r  )rP   r   r0  checklists_fileri   	checklistchecklist_datar$   r$   r%   _dump_task_checklists3  s    

z%CmfPluginKaiten._dump_task_checklistsc              	      sf   t  }zBt|d( t fdddD ]}|| q(W 5 Q R X | W S  tk
r`   Y dS X dS )u:   
        Вычисляет MD5 хеш файла
        rbc                      s
     dS )Ni    )readr$   ri   r$   r%   <lambda>H      z1CmfPluginKaiten._calc_file_hash.<locals>.<lambda>r  N)hashlibZmd5rd   iterr   Z	hexdigestr   )rP   rh   Zhash_md5chunkr$   r  r%   _calc_file_hashA  s    
zCmfPluginKaiten._calc_file_hashc              	   C   s  i }| d}| rXz(t|ddd}t|}W 5 Q R X W n tk
rV   i }Y nX i }d}d}|D ]L}| |}	| |	}
d|
i||	j< |	j|krd}qh||	j d |
krhd}qh|rt|d	dd}tj||d
dd W 5 Q R X | d}t|d	}|	d W 5 Q R X dS )u!  
        Проверяем изменились ли файлы в каталоге задачи
        И при наличии изменений создает файл-флаг для обработки

        Args:
            task_dir (Path): каталог задачи
        zhashes.jsonr  utf-8encodingF)r)  rl  rt  rx  hashTr>  r:   )indentr`   r'  r   N)
rb   rc   rd   re   rf   r   r  r#   rg   r  )rP   r0  Zsaved_hashesZ	hash_fileri   Zcurrent_hashesZhas_changes
task_files	task_filerh   Z	file_hash	flag_filer$   r$   r%   _mark_as_updatedN  s2    





z CmfPluginKaiten._mark_as_updatedd   c                 C   s0  t dd | j d}|d }|d }| j | j}|  j|7  _W 5 Q R X zv| jj|| jd||d}|sxW q|D ]H}	t|	d }
|	d }| jj	d| d	|
 d
 |
|
}|
|
d }| rt|| |jdd t||	d< | |	 | |	 | |	 |	d r.| |	d | |	dg D ]}| |d | q:t|| t||	d< t|
dddd}tj|	|dddd W 5 Q R X |d7 }| jd | | | |	 q|W q, tk
r } z*| jjd| d	| d| dddd W 5 d }~X Y q,X q,W 5 Q R X W 5 Q R X d S )NFZinit_views_and_dsr   r   r   r   )Zspace_idr   r   r,  r   u   Задача 'r   )r!  Trg  r0  r   r   r)  r>  r  r  r:   )r  r`   ro  r   r   uB   Не удалось получить задачи проекта '). zERR-0005r   rg   )
error_coder   
error_type)r
   r/   _lock_offsetr   rE   rZ   r   r  inforb   rc   rS  rT  rj  rs  rw  r|  r  rI   rd   re   rg   rq  r  rk  r   r   )rP   r
  r.  r   
task_countr  r  r,  r   r   r1  Z	task_namer0  Ztask_tmp_dirmemberri   r!   r$   r$   r%   _dump_task_worker|  sb    






z!CmfPluginKaiten._dump_task_workerc                 C   s   d}t |d d}|jdd d| _t | _g }t| jD ]L}tj	| j
d|d  ||dd	}|| |  | jjd
|  q@|D ]}|  q| | |S )Nr   r&  r   Trg  Zdump_tasks_r   )r
  r.  targetr#   r   u$   Запущен обработчик )r   rb   rj  r  	threadingLockr  rangedownload_threading_max_forksThreadr  r   startr   r  r  joinrN  )rP   r
  errorsr.  threadsithreadr$   r$   r%   _dump_tasks  s*    



zCmfPluginKaiten._dump_tasksc           
   
   C   s   | d}| rt| |  | j|}|D ]x}|d }g |d< | jj|| jdD ]}|d 	t
|d  qZ| | d}t|d}	tj||	dd W 5 Q R X q4d S )	Nr3  r   cards)r   r  r^   Fr_   )rb   rc   rS  rmtreerj  r/   Zget_space_boardsZget_board_cardsrE   r   rZ   rd   re   rg   )
rP   r  r&  r5  Zboards_data
board_databoard_idZcardr6  ri   r$   r$   r%   _dump_project_boards  s    

z$CmfPluginKaiten._dump_project_boardsc              	   C   sd   | d}| rt| | j|}t|d(}|D ]}|tj	|ddd  q8W 5 Q R X d S )Nr  r  Fr_   r  )
rb   rc   r+   rQ  r/   Zget_space_usersrd   r  re   r  )rP   r  r&  r  Z
users_datari   r   r$   r$   r%   _dump_project_users  s    

z#CmfPluginKaiten._dump_project_usersc                 C   sP  | j  d}|jdd t| j}td| }| jD ]}|d }|d }|d }z| j  rlW  d S | j  jd7  _| j j	
d	| d
| d ||}|| d}	| rt||	 n|	jdd | j|}
t|
d |
d< ||
d< t|	|
d< | ||	 |
dr6| |
d | j  |
d< | ||	 t , | j  j|7  _| j jjdd t  W 5 Q R X t|	| t||
d< |
d  d}t|d}tj|
|dd W 5 Q R X d}|| j|
d7 }|  j|7  _W q8 tk
r< } z2|  jd7  _| j j d| d| dddd W 5 d }~X Y q8X q8| j !d d S )Nr   Trg  P   r   r   r   r   u   Дамп проекта 'r   r  r!  r&  Z
author_uidauthorrP  r#  r^   Fr_   r   )r
  u2   Не удалось получить проект r   zERR-0006r   rg   )r   r  u*   Дамп проектов завершен)"r   ra   rb   rj  lenrB   intr   rR  r  r  rc   rS  rT  r/   Z	get_spacerZ   r  rI   r  r  r-   progressr[   rU  r   rd   re   rg   r  r   r   r   r   )rP   r   Zcntstepr   r  r	  r  r&  Zproject_tmp_dirr
  Z	data_fileri   Zdump_task_errorsr!   r$   r$   r%   _dump_projects  sd    


zCmfPluginKaiten._dump_projectsc              
   C   s"  t d}| jjj|_|| jjj | j }t	|\}}}|| d }| jj
d| d | jj
d | j | jj
d | | jjd | jj
d | | jjd	 | jj
d
 | | jjd t   d| j_| jj  t  W 5 Q R X | jj
d |   W 5 Q R X dS )u^   
        Загружает все данные из API, кроме вложений
        z'modules.kaiten.kaiten_client.connectionr  u   Свободно места: r   u5   Скачивание данных через API ... u#   Дамп пользователейr   u   Дамп типов задач
task_typesu   Дамп метокtags   u,   Дамп выбранных проектовN)r<  Z	getLoggerr   r  ZhandlersZsetLevelr9  ra   rS  
disk_usager  r/   rV  Zget_company_usersZget_card_typesZget_tagsr-   r  r[   rU  r   r  )rP   r  Zdownload_pathtotalusedfreeZfree_percentr$   r$   r%   download_data8  s*    

zCmfPluginKaiten.download_datac                 C   s  t  j}t  j}d}d}d}d}d}	tdd | j | j rNq| }
|
dkrbqt	
tdd zztjj|
dd	d
ddgd}t|j}t|j}t|j}t|jd}t|dkrd|d  dnd}d| d}|}|jj}|r>|d}|r>t|tr>|d }|d|dd| d7 }| jj| d| d| d t	 }| jj||tjd t	 }|}t|}|  j!}|d }|d|dd| d7 }| jj| d| d| d d|_"|#  t$  | j%d |d7 }||7 }|	|| 7 }	W n^ t&k
rt } z>t'  |d7 }| jj(| d | d| d!| d"d#d$|d% W 5 d }~X Y nX W 5 |d7 }X q@|d }|	dkr||	 nd}|||||	f}|)| | jjd&| d'| d(| d)| d*| d+|d,d-|dd.| d/ W 5 Q R X W 5 Q R X d S )0Nr   Fr  DONEg?      ?r   r#   rW  rX  rY  r]  r   r   r   u   [Задача ID: z] r   'size    (.3fu    MБ / u
    байт)u   Скачивание z: ')timeoutu	   Файл u    сохранен в 'Tr^  u"   Ошибка скачивания r   zERR-0007rZ  rg   )r  r   r  Zext_hrefu   Поток 'z' (ID: uU   ) завершен. Скачано файлов (успешно/неуспешно): r"      из 8   . Средняя скорость скачивания: .2f)    МБ/с. Скачанный объем:     МБ / 	    байт)*r  current_threadr#   identr
   r/   r   r   rI   ru   sleeprandomZuniformrH   rZ  rZ   rW  rX  rY  splitr  r]  r[   
isinstancer  r  r  perf_counterZdownload_fileconfigZIMPORT_DOWNLOAD_TIMEOUTr   statst_sizer\  rU  r   rq  r   r   r   put)rP   download_queueresult_queueZthread_nameZ	thread_iderror_countdownloaded_counttotal_countdownloaded_bytestotal_download_timeZdownload_job_idZdownload_objra  Zfile_urlrh   Zext_id_splitZtask_id_msgZfile_msgZ	file_dataZfile_size_bytesZfile_size_mbr  endZdownloaded_filer!   Zdownloaded_mb
speed_mb_srF  r$   r$   r%   _download_file_workerY  s    






 
 

8z%CmfPluginKaiten._download_file_workerc                 C   sp  dd| j gdddgg}| j d}d}g }| jD ]r}t|d }||}t|dsht|d }d	d
| dgg}|| }	tjj	|	d}
|
r4||
7 }|
|	 q4|s| jjd dS | jjd|  t }t }d}d}d}d}d}g }t| jD ]N}tj| jd|d  ||dd}|
| |  | jjd|  q |D ].}tjj|ddgdD ]}||j qlqTt  |D ]}|d q|D ]}|  q| j r| jjd | s| \}}}}}||7 }||7 }||7 }||7 }||7 }q|d }|dkr0|| nd}| jjd| d| d| d|dd|dd| d  |S )!Nr   ==r\  Fr   r   r   r"  rX  r   r   r   u3   Нет вложений для скачиванияu'   Скачивание вложений: Z_download_file_worker_r   )r  r  r  u   Запущен поток r   r   r  u   Импорт прерванr  uj   Скачивание завершено. Скачано файлов (успешно/неуспешно): r  r  r  r  r  r  r  )r   r   ra   rb   rB   rZ   r%  rH   rZ  r/  r   r  r  r   r  r  r  r  r  r  Zslistr  r   r   r  r   r  emptyrI   )rP   Zmain_filterZprojects_pathZattachment_countfiltersr
  r  Zproject_pathZpath_filterZdownload_filterZdownload_countr  r  Z
main_countZtotal_downloadedZtotal_errorsZtotal_downloaded_bytesr  r  r  r  filter_rd  r  r  r  r  Zdownload_timeZtotal_downloaded_mbr  r$   r$   r%   download_files  s    




,zCmfPluginKaiten.download_filesc                 C   s:   | j d d d }|d s"tddd |d D | _d S )	Nr   r[   r   	isCheckedu8   Не выбраны проекты для импортаc                 S   s$   g | ]}|d  r|d r|d  qS )r   r  r$   )r   sr$   r$   r%   r   $  s    z:CmfPluginKaiten._set_selected_projects.<locals>.<listcomp>children)r   r   rB   )rP   Zroot_selectedr$   r$   r%   _set_selected_projects  s    z&CmfPluginKaiten._set_selected_projectsTc              	   C   s  |  || jtjj d }d| j d|d  d}|d dd}d}|D ]}t||krJt|}qJttjj	j
tjjj
tjjj
}	||	krt|dkr|d |d	< d
|d< d
|d< n`t|dkr|d |d	< |d |d< d
|d< n2t|dkr|d |d	< |d |d< |d |d< ddg}
tjjddd| dg|
d}|sdddd| j dgddd gg}tjjdd|d g|g|
d}|stjjdd|d g|g|
d}t|dkrg }|sdd|d g|g}tjj||
d}|sdg}t|t|D ]}t|dkrd	d|d g}nnt|dkrL|dd|d gd	d|d gg n<t|dkr|d	d|d gdd|d gdd|d gg q||g}tjj||
d}|r|d }d}|s:|r2d}d}|d }tjjdd| g|
dr |d d\}}| d| d| }|d7 }qtj||dd }nd |fS |rtd!t|j}d"d# |D }t|dkrz|d |d< |jr|D ]}t||||  q|jr||jkr|j | |_n||_d|_|jr|jdd$ ||fS )%Nr   r   r   r#   r   r:   r   r   	last_namer   
first_namesecond_namer;   r   Zrg_member_ofr   r   r   r   ORzNOT LIKE%::::%r  loginILIKEr   FT@+)r   r  import_originalz[,;\s]+c                 S   s   g | ]}|  r|  qS r$   ro   )r   r   r$   r$   r%   r     s      z3CmfPluginKaiten._process_person.<locals>.<listcomp>Zsave_import)r   r   rH   r   r   r   r  r  minr  
max_lengthr  r  rI   listr   r   rl   rm   rZ   r  r  setattrr   Z
user_localr[  rU  )rP   r   r   r   Z	user_dictr   r   Zcurrent_length_namer#   Zmax_length_namer   r   Znot_source_hash_filterZpersonsZ_filterZ
name_combo
is_creatednr  Zprefix_emaildomainZemailsr   r$   r$   r%   r   )  s    




zCmfPluginKaiten._process_personu-   Обработка пользователейc              	   C   s   | j jjdds$| j jd d S t }| dD ]}z^| j  rLW  d S | 	|\}}| j  j
d7  _
|jr|js|jds|r||jj W q4   |  jd7  _| j jd| dd	d
 Y q4X q4|r| j jjddrttjjt|gd d S )NZ
load_usersTu8   Отключен импорт пользователейr   r   z.evateam.ruu@   Не удалось загрузить пользователя zERR-0008r   r   Zsend_invitesF)r   )r   r;  r[   rI   r  r  rI  r   r   r   imported_object_countr   r   r%  rK  r   r   Zschedule_deferred_jobrH   r   Zregister_personsr  )rP   Znew_user_emailsr   r   r  r$   r$   r%   _process_users  s8    

zCmfPluginKaiten._process_users)r   c              	   C   s   |d }|dkr|d }n|d }|dkr8|r2dnd}n|dkrFd}n|dkrTd}n|d	krbd	}n|d
krx|rrdnd}nl|dkrd}n^|dkrd}nP|dkr|rdnd}n:|dkrd}n,t d|d  d|d  d|d  d| |S )Nr4   r   r   r   rp   rZ   rT   r   r   r   choice_multi
choice_strnumberfloatrt   ry   r   r   r   u<   Не удалось сопоставить тип поля 'r#   r   r   u   ). Тип 'u%   ' не поддерживается: )r   )rP   r   Zext_field_typer   field_custom_typer$   r$   r%   _map_field_type  s4    
&zCmfPluginKaiten._map_field_typec              	   C   s   ddddddddd	iid
dddddi g ddddiid
g| _ | j D ]}|d d }|d d }tjj|d}|s| jjd| d| d tjf |d }d|_| j|_d|_|j	dd d| _
n| jjd| d| d ||d< qH| j
rt  dS )u]   
        Создает служебные пользовательские поля
        cf_kaiten_card_idz	Kaiten IDu   ID карточки в KaitenTrZ   )r#   captionrp  field_readonlyr  positionorderno  )paramsscreencf_kaiten_board_laneu   Дорожкаu(   Дорожка на доске в KaitenFr  )r#   r  rp  r	  r  r   disabled_choicesafter_fieldlistsr  r  r#   r'      Создание поля 'r   r  r     Найдено поле 'fieldN)rF   rH   CmfCustFieldrI   r   r  r  dirtyr  rU  _gen_field_metar  r   )rP   Z
field_dataZfield_captionr   service_fieldr$   r$   r%   _process_service_fields  sN     
 

z'CmfPluginKaiten._process_service_fieldsc                    sd  d| _ |   d | _| jD ]D}| jtjj d D ],}d|kr>q0|d d |kr0| j| |d< q0q| jj	
d dd tj D }g }g }| jtjj d D ]4}|d }|d}|s| jj	d	| d
 q|d r| jj	d	| d qz| |}W nL tk
rJ }	 z,|  jd7  _| jj|	ddd W Y qW 5 d }	~	X Y nX |d }d| d| j  }
|
|d< | j d| }tjj|ddddddgdd}|stj||d |d|| jdd}|j}|jr| jj	d	|j d|j d q|
|kr||
 d |jjkrf|  jd7  _| jjd |d  d|d  d!|j d"||
 d  d#| 
d$dd q||
 |d< | jj	d%| d|
 d& n| jj	
d'| d|
 d& |jr||_||_|d(krj|jjpi }i  t }|d)   D ]>}|d* }t!j"|d+d,d-}| |< |d. d/kr|#| q fd0d1|D }|$| |$  ||_t%t&||_'n|d2kr~|(| |j)rd|_*|(| |j+dd3 |d4kr|rd5|_,|j,|_|j+dd6 t-  q|rd| _ | j rV| jj	
d7 tj.t/j01 2d8d9dd: tj3d;d9i d<d tj D }|D ]}||d  |d< q>|D ]}tjj4|d d=  }t5t|j6 }|d d)   D ]N}|d* }|j|d>}|s||d>}t7|d.d/k|_8|j)r|+  qqZ| jj9j}|d? D ].}|d tjjkr| jtjj d |d< q|| j_9t: & d| jj9_)| jjj+dd6 t-  W 5 Q R X d S )@NFr   r   r   u>   Обработка пользовательских полейc                 S   s   i | ]}|d  |qS r   r$   r   ri   r$   r$   r%   
<dictcomp>S  s      z:CmfPluginKaiten._process_custom_fields.<locals>.<dictcomp>r   u
   Поле 'u'   ' не пользовательскоеr   u!   ' уже сопоставленоr   zERR-0009	CmfUiFormr   r   r   r#   r   widgetr   r  r  cmf_deletedr]  Tr   r   r   )r  r#   r  r  r   r   r  r   u   ) удаленоu5   Не удалось сопоставить поле 'u   ). widget поля 'u7   ' не совпадает с существующим 'z': zERR-0010r  r  r  r  r   r[   rk   r   r   Z	conditionrB  c                    s   h | ]}| kr|qS r$   r$   )r   r   default_choicesr$   r%   	<setcomp>  s   z9CmfPluginKaiten._process_custom_fields.<locals>.<setcomp>r  r  rp   Z	CmfMarkuprP  u&   Генерация меты полей%Y%m%d%H%M%Sr   Zmeta_versionZ
model_nameforcecmf_model_namec                 S   s   i | ]}|d  |qS r   r$   r  r$   r$   r%   r    s      r   r'   import_settings);r  r  rD   r0   r   rH   r   r   r   r  r  r   rI   r  r  r   r   r   r   rl   r  is_newr  r  r#   r  r  r[   r  r]  r   rI  r   r\   r   rK  r   sortedr  r  r   r[  r  rU  Z
field_typer   custom_fields_gen_metarx   ry   nowstrftimecustom_field_sync_update_modelsr   varsr   boolZ
cmf_hiddenr;  r-   )rP   Zext_field_idr  shop_fieldsZ
new_fieldsZ
m2m_fieldsZfield_titler   r  r!   r   cust_field_ext_id
cust_fieldZis_new_cust_fieldZcurrent_choicesdefault_disabled_choicesr[   r   r   r  Zfield_classZchoice_modelr   r   r  r$   r!  r%   _process_custom_fieldsB  s(   

	
2









z&CmfPluginKaiten._process_custom_fieldsc                 C   s   dddddddddd	d
dg}|D ]|}|d }|d }| j jd| d| d dd|gdd|gg}tjj|d}|stj||| j dd}|jdd |  S t  d S )Nr   r2   r3   )r   r#   r4   r:   r6   r7   r;   r8   r9   r#   r4   #   Обработка статуса 'r   r  r   r   r   Tr#   r   r   r  r  )r   r  r  rH   CmfStatusCoderI   rU  r   )rP   statuses_datastatus_datastatus_namer   status_filterglobal_statusr$   r$   r%   _process_global_statuses  s,    


z(CmfPluginKaiten._process_global_statusesc           	      C   s  dddddddddddddddddddddddddd	ddd	ddd	dd
ddd
ddd
ddd}|  dD ]}| jjd|d  d | j d|d  }tjjddd| dgd}|rq||d }|r>tjjdd|d gdgd}|jr"d| |j |_nd| d|_|j	dd qdd|d 
 g}tjj|dgd}|r|jrd| |j |_nd| d|_|j	dd q| jjd|d  d d}tjjdd|gd gd}tj|d |d!t|jd| d| jd"}|j	dd# qt  d$S )%u#    Маппинг Type в logic_type    Подзадачаztask.sub:default)r#   r=   Z	UserStoryztask.userstory:defaultz
Task Agileztask.agile:defaultBugztask.bug:defaultEpicztask.epic:default)r?  ZSubtaskzSub-tasku   ИсторияZStoryu   Задачаu   ЗаданиеZTaskr   u   Багr@  u   Эпикu   ВехаrA  r  u*   Обработка типа задачи 'r#   r  r   r   r   r   r  r  r   r=   r  r   TrP  r  u   Тип 'u.   ' не найден и будет созданui_colorr   )r#   templater'  rB  r   r   r  N)r   r   r  r  r   rH   rK   rI   r   rU  ro   rZ   rB  r   )	rP   Z	name2code	task_typer   r   Zlogic_type_dictr  Ztemplate_codeZlogic_type_templater$   r$   r%   _process_task_types  s~    
z#CmfPluginKaiten._process_task_typesu   Обработка теговc           
      C   s  ddl m} | dD ]}|d }|d }z|dddd	}||d
dd}ddd|gddd| dgddd| dgg}tjj|d}|stj|d}|jdd t  W q t	k
r }	 z.t
  | jjd| d| d|	 ddd W 5 d }	~	X Y qX qd S )Nr   translitr  r   r#   r   r   #r   ruTZlanguage_codereversedr  r  alias""%r   r'   r  u+   Не удалось создать тег 'r   r  zERR-0011CmfTagr  r   )transliteraterG  r   r}   rH   rO  rI   rU  r   r   r   r   r   )
rP   rG  Ztag_dataZtag_idZtag_namer#   rL  Z
tag_filterZtag_objr!   r$   r$   r%   _process_tagsj  s0    
zCmfPluginKaiten._process_tagsc              	   C   s   | j d }dd | dD }i }| j d p.g }|D ]<}||}|s^| jjd| d q4||i dd	||< q4| |D ]z}|d
 }||d |d |d |d pi dd	}	|dpi }
|
 D ]}||	d krd|	d |< q|	d  d7  < q||S )uh   
        Получает все используемые в проекте типы задач
        r   c                 S   s   i | ]}|d  |d qS )r   r#   r$   )r   rD  r$   r$   r%   r    s    z;CmfPluginKaiten._get_project_task_types.<locals>.<dictcomp>r  allowed_card_type_idsu=   Не удалось найти разрешенный тип u5   . Возможно он был удален в Kaitenr   )r   r#   r   r  r4   r#   r   Fr  r   )	_project_datar   rI   r   r  r  r   r   keys)rP   r  Zall_task_typesr  rS  Ztype_id	type_namerE  rD  task_type_dataZtask_propertiesr   r$   r$   r%   _get_project_task_types  sD    



z'CmfPluginKaiten._get_project_task_typesc                    sv  dd t j D }| jd }| jd }|d }|d }|dkrJd| }| j d| d| }t jj|d	d
gd}| d| }	|s| jj	d|	 d t j|	d|| jdd}|
  dddddddddg	}
t jj|d}|D ]"}|j|
krqd|_|j
dd q|jr ||_|
  n| jjd| d ddd ddd ddd ddd d!d"d d#}| D ]N\}}dd$|gd%d$|d% gd&d$|gg}t jj||d' d%gd(}||| d)< ql| jD ] }|d*}|sܐq|d+ }|d, }t jjd-d$|gd&d$|ggdd.}|st j||j||d d) | jdd/}d }|d0rN|d0 }nR|d1rt jjdd$|d1 gd&d$|gd2d$|d d) ggd0gd3}|r|jd4 }|d k	r||_|j
dd | jj	d5| d6|j d7|j d8 q|d9  D ]n\ } d:d; d<  d=| j  }||kr,qt fd>d?| jt jj d@ D d }|s\q| j d|dA d  }t jj|dBdCgd}t jjd-d$|gd&d$|ggdDgd3}|r|js| jjdE| dF|j dG|jj dH q|sXt jjd-d$|gd&d$|gdId$dgd
dJd ggdd.}|rB| jjdE| dF|j dK qt j|||| jddL}|jdMkrt|d d) |_n|jdNkr|d d) |_nh|jdOkr|dP d)st jdPd!|| jddQ}|j
dd ||dP d)< |dP d) |_n|d d) |_||_|j r|jj!}|jj}| jj	d5| dR|d!kr4dSndT dU| dV|j d7| d8 |j
dd q|"  t#  |S )WNc                 S   s   i | ]}|d  |qS r   r$   r  r$   r$   r%   r    s      z3CmfPluginKaiten._process_screen.<locals>.<dictcomp>r   r   r#   default   для типа r   r   r   r   r   u   : Экран задач u   Создание экрана 'r  r   T)r#   r'  r   r   r  _main   Участники   Датыu   Планu   Разработкаu
   СвязиZ_addon_customZ_descrparentr  u   Экран u|    был изменен пользователем. Изменения из импорта не будут примененыgroup)r4   systemZtabF)r\  r]  r^  r_     Дополнительноеr   r4   ra  rc  )r   rc  r   r   r  r  r
  r3  r   r   )r3  r#   ra  ui_form_groupr   r  r  r  rf  r   i  u   На экран uA    в группу 'Основные' добавлено поле 'r   z) r   r   r   r   r   c                 3   s0   | ](}| d r|d  d t kr|V  qdS )r   r   N)rI   r  )r   r  r   r$   r%   	<genexpr>H  s   
 z2CmfPluginKaiten._process_screen.<locals>.<genexpr>r   r   r  r  zui_form_group.typeu   На экране u    поле 'um   ' было изменено или уже добавлено пользователем во вкладку 'uL   '. Изменения из импорта не будут примененыr  !=u   ' было удалено пользователем. Изменения из импорта не будут применены)r3  r#   ra  r   r  )r   r   )rt   ry   rp   rd  )r#   r4   ra  r   r  r   u   во вкладкуu   в группуz 'u   ' добавлено поле ')$rH   r   r   rT  r   r  rI   r   r  r  rU  ZCmfUiFormGroupr  r#   rc  r  r]  r  r   rF   ZCmfUiFormFieldr  r  r}   rl   nextr   r   r  rf  r  Zrequired_changer[  r4   invalidate_cacher   )rP   rW  r1  r  r	  task_type_idtask_type_nameZscreen_ext_idui_formZscreen_nameZdefault_groupsZui_form_groupsrf  Z
group_nameZ
group_datar  Zservice_field_datar  r  Zscreen_positionZui_form_fieldr  r  requiredr   r  r2  r3  Z
group_typer$   rg  r%   _process_screen  sn   












			2zCmfPluginKaiten._process_screenu,   Обработка схемы экрановc                 C   s^  | j d }| j d }| j d }| j d| }tjj|dgd}|sntj| d| || jdd	}|jdd
 |jrF|jstj	j
|dD ]}|jdd qd}d }	t|}ddi d|d< | D ]T\}
}|d }|
dkrN|dsqd| j d|
 d}tjjddd| dgd}|sD| jjd| d|
 dddd qd| }z| |}W nJ tk
r } z*| jjd| d| d dd W Y qW 5 d }~X Y nX ||d!d| jd"}tj	jf |d#d$d%gi}|stj	f |}|
dkr|j| n|}	|jdd
 t|j|}q|	rZ|	j|k rZ|d& |	_|	jdd
 n| jj| d' |S )(Nr   r   r   r   r   r[  u+   : Схема экранов проекта Tr#   r   r   r  r  )ui_form_schemeZTEXKOM_db_deleter   rY  u   по умолчанию)r   r#   r   r#   r   r   r   r   r   <   Не удалось найти логический тип 'r   r  ERR-0012CmfUiFormSchemer   rZ  u:   Не удалось импортировать экран r   zERR-0013r   )rr  r  r'  Zcrud_choicer   r   logic_typesr  r  e    была изменена. Изменения из импорта не будут применены)rT  r   rH   rv  rI   r   rU  r  r)  ZCmfUiFormSchemeRuler  deleter   r   rK   r   rp  r   rw  r   maxr  r  r  )rP   r  r  r	  r  Zui_form_scheme_ext_idrr  ruleZmax_ordernoZdefault_rulerl  rW  rm  r   r   rn  r!   Z	rule_dictr$   r$   r%   _process_screen_scheme  s    








z&CmfPluginKaiten._process_screen_schemeuA   Обработка схемы конфигурации полейc           	      C   s  | j d }| j d }| j d }| j d| }tjj|dgd}|stj| d| || jdd	}|jdd
 tjj|dgd}|stj| d|d| jd}|jdd
 tjdd|d| jd}|  tj	||g | jddd}|jdd
 |
  |jdd
 |  |S )Nr   r   r   r   r   r[  u@   : Схема конфигурации полей проекта Trq  r  u=   : Конфигурация полей по умолчанию)r#   r   r  r      Спискиr  )r  r#   ra  ro  r   r   )Zcust_field_confra  rw  r   r  r  )rT  r   rH   ZCmfCustFieldConfSchemerI   r   rU  CmfCustFieldConfCmfCustFieldConfFieldZCmfCustFieldConfSchemeRuleZ
calc_cacherk  )	rP   r  r	  r  r   Zfield_config_schemafield_configZfield_config_fieldr{  r$   r$   r%   _process_field_config_schema	  sV    


z,CmfPluginKaiten._process_field_config_schemac                 C   s  | j d }| j d }| j d| d}tjj|d}|sVtj| d| j|| jdd}|jrh|jdd	 | jj	
d
|  | ddddd| ddddd| dddddg}g }|D ]0}| j|d |d< | ||}	||	j qtjjdd|gdd|gddd ggdgdd}
|
D ]B}tjjdd|jgdd|jgdd|ggdsVq"|jdd q"n| jj	d| d  | j d| }tjj|d}|stjjd!d"}tj| d#||| jdd}|jr||_||_||_d$}g }| D ]\}}|d% }|d& }d| j d| d}tjjdd'd(| d(gd}|sh| jjd)| d*| d+d,d-d. q|| ||kr|}||_q||_|jdd	 tjj|d/D ]}|jdd0 qn| jj	d1| d2 |S )3Nr   r   r   z	::defaultr   u@   : Бизнес-процесс задач по умолчаниюT)r#   rC  r   r   r  r  B   Обработка статусов бизнес-процесса z::1r2   r   )r   r   r4   
sort_orderz::2r6   r:   z::3r8   r;   r4   NOT INworkflowr   r   r   r   r   r   ri  r   r&     Бизнес-процесс a    был изменен. Изменения из импорта не будут примененыzsoftdev:defaultr<   u@   : Simple-схема бизнес-процесса проектаr   r#   r  r   r   rt  r   r  ru  CmfSchemeWfr   )	scheme_wfrs  u)   Схема бизнес-процесса rx  )rT  r   rH   rM   rI   rN   r   r  rU  r  r  rG   _process_workflow_statusr   r   r   r  r   ry  r  r  Zdefault_epic_workflowdefault_task_workflowZdefault_subtask_workflowr   rK   r   default_task_logic_typestrict_task_logic_typeZCmfSchemeWfRule)rP   r  r  r	  workflow_ext_idr  r9  current_statusesr:  workflow_statusworkflow_statusesr   Zscheme_ext_idschemeZscheme_templateZmax_tasks_countr  rl  rW  rm  r  r   r   r{  r$   r$   r%   _process_workflow_schemaC	  s    

	






z(CmfPluginKaiten._process_workflow_schemac                 C   s  | d}|sd S | jjtj ddd t|d d}|D ]}|d rPq@zt|d }|d	 }| j d
| }||}	|		 st
dtjj |d}
|
stj||| jdd}
|
jrJ||
_| d|
_| dr| |d |
_ntj|
_|
j|
_||
_|
jdd t|	d*}|
j| dd d|
_|
jdd W 5 Q R X t  | jdd W q@ t
k
r } zBt  | jjtj d| d| d| d|d t jd7  _W 5 d }~X Y q@X q@d S )Nri  u$    Обработка вложенийTr   r0  rf  
comment_idr   r#   r   w   Не найден файл вложения. Возможно при скачивании возникли ошибкиr  ra  r   r   r  r   rm  r  r}  Zsmart_backupr^  	processedu<    Не удалось обработать вложение 'r   r  zERR-0014r   r   )rI   r   r   rX   task_msgr   rb   rZ   r   rc   r   rH   CmfAttachmentr  r#   r   r   
cmf_authorr  anonymous_userr   r]  rU  rd   upload_filer~  r   rq  r   r   r  )rP   task_objrE  r  r_  attachment_datar`  attachment_namerc  rb  r^  ri   r!   r$   r$   r%   _process_task_attachments	  s`    



z)CmfPluginKaiten._process_task_attachmentsc                 C   sx   | dg }|r(| jjtj ddd g }|D ]B}| |d }|sHq0||jks0||jks0||jkrhq0|	| q0|S )Nr   u,    Обработка наблюдателейTr   r   )
rI   r   r   rX   r  r   r   r  r   r   )rP   r  rE  Ztask_members
spectatorsr  r   r$   r$   r%   _get_task_spectators	  s(    
z$CmfPluginKaiten._get_task_spectatorsc                 C   s  ddl m} |dg }|r4| jjtj ddd g }|D ]}|d dd	d
d}||ddd}z^dddd| dgdd|gddd| dgg}tj	j|d}	|	st
d| d||	 W q< t
k
r }
 z0| jjtj d|
 d|d t jd7  _W 5 d }
~
X Y q<X q<|S )Nr   rF  r  u    Обработка теговTr   r#   r   r   rH  r   rI  rJ  r  rL  r  rM  rN  r   u   Тег 'u   ' не найденzERR-0015r  r   r   )rQ  rG  rI   r   r   rX   r  r}   rH   rO  r   r   r   r  )rP   r  rE  rG  Z	task_tagsr  ZlabelrL  r  tagr!   r$   r$   r%   _get_task_tags
  s:    
"zCmfPluginKaiten._get_task_tagsc           
      C   s  t |d d}| sL| jjtj d| dd|d t jd7  _d S | j	dkr| jj
tj d	d
d t|dJ}z|D ]}t|}| j d|d  ||ddd|d |d d|| jd	}|dr| |d|d< |d |d< |dr| |d|d< tjj|d d}|sXtjf |}|jjtj|jjd |_|jd
d qt  W nV tk
r }	 z6t  | jjtj d|	 d|d t jd7  _W 5 d }	~	X Y nX W 5 Q R X d S ) Nr0  rt  u7    Файл журнала работ не найден 'u]   '. Возможно при дампе журнала работ возникли ошибкиzERR-0016r  r   r   u-    Обработка журнала работTr   r]   r   r   rp  r   closedZfor_date
time_spent)	r   ra  rp   r   
start_dater  Zremaining_estimater]  r   rm  r  r   Z
updater_idZcmf_modified_byr   r  rv   r  uC    Не удалось обработать журнал работ. zERR-0017)r   rb   is_filer   r   rX   r  r  r  r  r   rd   re   r  r   rI   r   rH   ZCmfTimeTrackerHistoryr  r[   rx   r|   r  Zend_daterU  r   r   r   )
rP   r  rE  ru  ri   r  rv  Ztimetracker_historyhistoryr!   r$   r$   r%   _process_task_worklog%
  s^    




z%CmfPluginKaiten._process_task_worklogc                 C   s  | d}|sd S |d }tj d| }| jj| ddd t|d d}g }|D ]}	|	d	 |krnqZz"t|	d }
|	d
 }| j d|
 }||
}|	 st
dtjj |d}|stj||| jdd}|jrj||_|	 d|_|	 dr| |	d |_ntj|_|j|_|	|_|jdd t|d*}|j| dd d|_|jdd W 5 Q R X t  |t|  | jdd W qZ t
k
r } z@t  | jj| d| d|
 d| d|d t j d7  _ W 5 d }~X Y qZX qZ|S )Nri  r   u    Комментарий u%   . Обработка вложенийTr   r0  rf  r  r#   r   r  r  r  r   rm  r  r}  r  r^  r  u=   . Не удалось обработать вложение 'r   r  zERR-0018r  r   )!rI   rX   r  r   r   r   rb   rZ   r   rc   r   rH   r  r  r#   r   r   r  r  r  r   r]  rU  rd   r  r~  r   r   Zcreate_preview_tagrq  r   r   r  )rP   Zcomment_objcomment_datarE  r  r  r  r_  rf  r  r`  r  rc  rb  r^  ri   r!   r$   r$   r%   _process_comment_attachments\
  sp    


"z,CmfPluginKaiten._process_comment_attachmentsc                 C   sD  t |d d}| sL| jjtj d| dd|d t jd7  _d S | j	dkr@| jj
tj d	d
d t|d}|D ]}zHt|}| j d|d  }tjj|d}|stj||| jd
d}n|dg |jsW q|dpd|_|dr | |d |_|j|_|d |_|d |_||_||_|jd
d t  | |||}	|d dkrrdnd}
| |jj |||
}|	r|d d!|	 |_n||_|j"r|jd
d t  | j#dd W q t$k
r2 } z<t%  | jjtj d| d| d |d t jd7  _W 5 d }~X Y qX qW 5 Q R X d S )!Nr0  rl  u6    Файл комментариев не найден 'u\   '. Возможно при дампе комментариев возникли ошибкиzERR-0019r  r   r   u,    Обработка комментариевTr   r]   r   r   r  r  z**rp   r   rm  r   r   r  r4   markdownZhtmlz<p></p>rp  r  uB    Не удалось обработать комментарий: r   zERR-0020)&r   rb   r  r   r   rX   r  r  r  r  r   rd   re   r  r   rH   
CmfCommentrI   rY   r  rp   r   r  r   r   r   ra  r]  rU  r   r  _convert_textr[   r  r[  rq  r   r   )rP   r  rE  rr  ri   r  r  Zcomment_ext_idrp  rf  	text_typerp   r!   r$   r$   r%   _process_task_comments
  s|    




z&CmfPluginKaiten._process_task_commentsc                 C   s  t |d d}| sL| jjtj d| dd|d t jd7  _d S tj	j
j}| jdkr| jjtj d	d
d t|d(}|D ]}zt|}| j d|d  }tjjdd|gddd gdd|ggd
dgd}	|	r|	jr|	jrW qn&|	s tj||| jd
d}	|	jd
d tj	jdd|	gddddgddd
gggd
d}
|
rVW qtj	j|	dD ]}|jd
d qdd}d}t|dg dd  d!}|D ]}|d7 }|d" r|d7 }tj	||	|d" sd#nd$d
|d%}|d& }t||kr|d | |_
||_n||_
|jd
d q|d' |	_
||	_||	_||	_ |	jd
d t!  W q t"k
r } z<t#  | jjtj d(| d)| d*|d t jd7  _W 5 d }~X Y qX qW 5 Q R X d S )+Nr0  rx  u1    Файл чек-листов не найден 'uW   '. Возможно при дампе чек-листов возникли ошибкиzERR-0021r  r   r   u'    Обработка чек-листовTr   r]   r   r   ra  r   r   ri  r   r  r   r  r  r  r  Fre  r`  rs  r   c                 S   s   | d S Nr  r$   )xr$   r$   r%   r  $  r  z:CmfPluginKaiten._process_task_checklists.<locals>.<lambda>r   checkedr3   r  )Z
cache_taskra  r   r  r]  rp   r#   u;    Не удалось обработать чек-лист: r   zERR-0022)$r   rb   r  r   r   rX   r  r  rH   ZCmfChecklistItemr#   r  r  r  r   rd   re   r  r   ZCmfChecklistrI   r  r  rU  r  r  ry  r*  r  rp   Zchecklist_items_countZchecklist_items_done_countr]  r   r   r   )rP   r  rE  ry  Zmax_item_name_lengthri   r  r{  r   rz  Zmodified_itemitemZitems_countZitems_done_countZ
items_dataZ	item_dataZ	item_textr!   r$   r$   r%   _process_task_checklists
  s    



	



z(CmfPluginKaiten._process_task_checklistsc                 C   sh  | d}|sd S | jjtj ddd tjjj}| j	j
d}td| d}|D ]}|d }||}	|	rvqXz| j d	|d
  }
tjj |
d}|stj||
| jdd}|jr|d }t||kr|d | |_n||_||_
||_|jdd t  W qX tk
r` } z<t  | jjtj d| d| d|d t jd7  _W 5 d }~X Y qXX qXd S )Nexternal_linksu=    Обработка ссылок на веб-страницыTr   r"  ^/(\d*)$rT   r   r   r  r  r  uU    Не удалось обработать ссылку на веб-страницу 'r   zERR-0023r  r   )rI   r   r   rX   r  rH   ZCmfLinkr#   r  r/   rT   rstriprm   compilematchr   r  r  r]  rU  r   r   r   r   r  )rP   r  rE  r  Zmax_link_name_lengthapp_urlpatternexternal_linkrT   r  Zexternal_link_ext_idlinkZlink_urlr!   r$   r$   r%   _process_task_remotelinksI  sT    





z)CmfPluginKaiten._process_task_remotelinksc                 C   s   |j dkrd}nd}|jdddidD ]}zb|drF| |d }ntd	t|jt|jt|j	t|j
t|jd
d}||j W q& tk
r } z0t jd7  _| jjd| d| d|d W 5 d}~X Y q&X q&dS )uA   
        Упоминания пользователей
        r  a  
                <a
                    class="external"
                    href="{person_href}"
                    rel="noopener"
                    target="_blank"
                    data-macros="mentions"
                    data-mention-type="person"
                    data-object-id="{person_id}"
                    data-title="{person_login}"
                    cmf_converted="true"
                >
                    @{person_name}
                </a>
            u	  
                <span class="macros-panel mentions-macros" contenteditable="false" data-id>
                    <span class="extension-container" data-layout="default" data-id>
                        <span class="extension-title" data-id>
                            @Упоминания <span class="excerpt-title" data-id>| {person_login}</span>
                        </span>
                        <span class="macros-actions" data-id>
                            <span class="macros-delete" data-id>
                                <svg viewbox="0 0 18 18" class="ng-star-inserted" style="width: 14px; height: 14px; color: #222222;">
                                    <path fill="#222" d="M16.5 3H12.75V1.5C12.75 1.10218 12.592 0.720644 12.3107 0.43934C12.0294 0.158035 11.6478 0 11.25 0L6.75 0C6.35218 0 5.97064 0.158035 5.68934 0.43934C5.40804 0.720644 5.25 1.10218 5.25 1.5V3H1.5V4.5H3V15.75C3 16.3467 3.23705 16.919 3.65901 17.341C4.08097 17.7629 4.65326 18 5.25 18H12.75C13.3467 18 13.919 17.7629 14.341 17.341C14.7629 16.919 15 16.3467 15 15.75V4.5H16.5V3ZM6.75 1.5H11.25V3H6.75V1.5ZM13.5 15.75C13.5 15.9489 13.421 16.1397 13.2803 16.2803C13.1397 16.421 12.9489 16.5 12.75 16.5H5.25C5.05109 16.5 4.86032 16.421 4.71967 16.2803C4.57902 16.1397 4.5 15.9489 4.5 15.75V4.5H13.5V15.75Z" stroke="none" stroke-width="1" class="ng-star-inserted"></path>
                                    <path fill="#222" d="M8.25 7.5H6.75V13.5H8.25V7.5Z" stroke="none" stroke-width="1" class="ng-star-inserted"></path>
                                    <path fill="#222" d="M11.25 7.5H9.75V13.5H11.25V7.5Z" stroke="none" stroke-width="1" class="ng-star-inserted"></path>
                                </svg>
                            </span>
                        </span>
                    </span>
                    <span class="ak-renderer-wrapper" data-id>
                        <a class="external" data-macros="mentions" data-mention-type="person" data-object-id="{person_id}" data-title="{person_login}" rel="noopener" data-id cmf_converted="true">
                            <span class="lds-ring" data-id>
                                <span data-id></span>
                                <span data-id></span>
                                <span data-id></span>
                                <span data-id></span>
                            </span>
                        </a>
                    </span>
                </span>
            spanclasszuser-mentionattrszdata-user-nameuY   Не найден аттрибут для определения пользователя)Z	person_idZperson_loginZperson_hrefZperson_namehtml.parserr   uR   Ошибка конвертации упоминания пользователя rH  zERR-0024r  N)
class_namefind_allrI   r   r   r   formatrZ   r   r  rW  r#   replace_with
currentTagrX   r  r   r   )rP   	text_soupr   TMPLr  r   new_tager$   r$   r%   _convert_mentionsz  s2    

	z!CmfPluginKaiten._convert_mentionsc              
      s  t j| jj}|dd D ]}|jdr2q|drN|jd 	drNq| j
jtj d|  |dr~|jd }n
|jd }t j|}|j}|r|dkrqtj|  r d	krq|d
g }t fdd|D d }	|	r
t|	d }
| j d|
 }nd }dg}|r,tjj||d}ntjjddd  dg|d}|r6|dr|jd |jd< |j|jd< d|jd< t|jd }|r|d r|d 	drd|_d|jd< d|jd< d|jd< |dr|jd |jd< |j|jd< d|jd< | j
jtj d| d t j|j d! q|jrN|j|jkrNqtd"|j}|r|d#}| j d| }tj j|d$}|r|jd |jd< |j!|jd< d|jd< | j
jtj d| d |j! d! q||d%< qd S )&Nc                 S   s   |  dp|  dS )NrW  src)has_attr)r  r$   r$   r%   r    r  z0CmfPluginKaiten._convert_links.<locals>.<lambda>Zcmf_convertedrW  rH  u2    Конвертация ссылки в теге: r  r"  ).z..ri  c                 3   s   | ]} |d  kr|V  qdS )rT   Nr$   )r   Zattra  r$   r%   rh    s      z1CmfPluginKaiten._convert_links.<locals>.<genexpr>r   r   rT   r[  r]  r   z%"url":"http%/rN  r   Zsrc_origTr   ZvideoZcontrolsz100%widthZheightZ	href_origu    URL заменен: 'u   ' на 'r  z	/(\d+)/?$r   r  zdata-issue-id)"urllibparseurlparser/   rT   r  r  rI   r  r   r   r  r  rX   r  rX  r+   basenamerj  rZ   r   rH   r  r  	mimetypesZ
guess_typer#   unquote_plushostnamerm   searchrb  r   rW  )rP   r  rE  Z
kaiten_urlr  rT   Z
parsed_urlZurl_pathrf  r  r`  rc  Zattachment_fieldsZ
attach_objZ	mime_typeZ
path_matchr1  task_ext_idr   r$   r  r%   _convert_links  s    


 



 

zCmfPluginKaiten._convert_linksc                 C   s>   | dD ].}|d}|r
|dr
|d |d< |d= q
dS )uF   
        Конвертирует "Фрагмент кода"
        prer=   r  N)r  findr  )rP   r  r  r=   r$   r$   r%   _convert_code_block  s
    
z#CmfPluginKaiten._convert_code_blockc           
      C   s   d}|j dddidD ]}zX|jdddid}|jdd}tj|t|j}t|j	d	||d
d}|
|j W q tk
r }	 z6| jjtj d| d|	 d|d t jd7  _W 5 d }	~	X Y qX qd S )Nu  
        <div class="macros-panel plantuml" contenteditable="false" data-macros-parameters="{params}"
            style="display: inline-flex; flex-direction: column; position: relative; width: 100%;"
            data-rendered="true" data-macros="plantuml">
            <div data-layout="default" class="extension-container" contenteditable="false">
                <span role="img" aria-label="Макрос PlantUML">
                    <svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="16" height="16">
                        <path d="M22,15h2v7h-7v-2h5v-5Zm2-10v6.731l-2-1.976v-.755H7v11h4.738c.033,.036,.057,.078,.092,.113l1.887,1.887H0V5c0-1.654,1.346-3,3-3H21c1.654,0,3,1.346,3,3ZM2,5v2h3v-3H3c-.551,0-1,.448-1,1Zm3,4H2v11h3V9Zm17-2v-2c0-.552-.448-1-1-1H7v3h15Zm-9.715,9.292c-.38,.391-.38,1.025,0,1.416l2.715,2.792v-2.5h2c1.654,0,3-1.346,3-3v-2.023h2.455l-2.756-2.711c-.386-.386-1.012-.386-1.398,0l-2.756,2.711h2.455v2.023c0,.552-.448,1-1,1h-2v-2.5l-2.715,2.792Z"></path>
                    </svg>
                </span>
                <span class="extension-title">
                    <span class="excerpt-title">PlantUML</span>
                </span>
                <span class="macros-actions">
                    <span class="macros-refresh">
                        <svg viewBox="0 0 24 24" style="width: 14px; height: 14px; color: rgb(32, 32, 32);"><path fill="#202020" d="M12,2a10.032,10.032,0,0,1,7.122,3H16a1,1,0,0,0-1,1h0a1,1,0,0,0,1,1h4.143A1.858,1.858,0,0,0,22,5.143V1a1,1,0,0,0-1-1h0a1,1,0,0,0-1,1V3.078A11.981,11.981,0,0,0,.05,10.9a1.007,1.007,0,0,0,1,1.1h0a.982.982,0,0,0,.989-.878A10.014,10.014,0,0,1,12,2Z"></path><path fill="#202020" d="M22.951,12a.982.982,0,0,0-.989.878A9.986,9.986,0,0,1,4.878,19H8a1,1,0,0,0,1-1H9a1,1,0,0,0-1-1H3.857A1.856,1.856,0,0,0,2,18.857V23a1,1,0,0,0,1,1H3a1,1,0,0,0,1-1V20.922A11.981,11.981,0,0,0,23.95,13.1a1.007,1.007,0,0,0-1-1.1Z"></path></svg>
                    </span>
                    <span class="macros-edit" style="margin-right: 7px;">
                        <svg _ngcontent-aiw-c17="" viewbox="0 0 24 24" class="ng-star-inserted" style="width: 14px; height: 14px; color: #444444;">
                            <path _ngcontent-aiw-c17="" fill="#444" d="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z"></path>
                        </svg>
                    </span>
                    <span class="macros-delete">
                        <svg viewbox="0 0 18 18" class="ng-star-inserted" style="width: 14px; height: 14px; color: #222222;">
                            <path fill="#222" d="M16.5 3H12.75V1.5C12.75 1.10218 12.592 0.720644 12.3107 0.43934C12.0294 0.158035 11.6478 0 11.25 0L6.75 0C6.35218 0 5.97064 0.158035 5.68934 0.43934C5.40804 0.720644 5.25 1.10218 5.25 1.5V3H1.5V4.5H3V15.75C3 16.3467 3.23705 16.919 3.65901 17.341C4.08097 17.7629 4.65326 18 5.25 18H12.75C13.3467 18 13.919 17.7629 14.341 17.341C14.7629 16.919 15 16.3467 15 15.75V4.5H16.5V3ZM6.75 1.5H11.25V3H6.75V1.5ZM13.5 15.75C13.5 15.9489 13.421 16.1397 13.2803 16.2803C13.1397 16.421 12.9489 16.5 12.75 16.5H5.25C5.05109 16.5 4.86032 16.421 4.71967 16.2803C4.57902 16.1397 4.5 15.9489 4.5 15.75V4.5H13.5V15.75Z" stroke="none" stroke-width="1" class="ng-star-inserted"></path>
                            <path fill="#222" d="M8.25 7.5H6.75V13.5H8.25V7.5Z" stroke="none" stroke-width="1" class="ng-star-inserted"></path>
                            <path fill="#222" d="M11.25 7.5H9.75V13.5H11.25V7.5Z" stroke="none" stroke-width="1" class="ng-star-inserted"></path>
                        </svg>
                    </span>
                </span>
            </div>
            <div data-fabric-macro="null" data-macro-body="" class="ak-renderer-wrapper" contenteditable="true">
                <textarea class="puml-code">{uml}</textarea>
            </div>
            <div class="macros-preview" contenteditable="true">
                {svg}
            </div>
        </div>
        Zdivr  zplantuml-diagramr  zplantuml-codeTr  z{})r  Zumlsvgr  u/    Не удалось получить svg из r   zERR-0025r  r   )r  r  Zget_textrH   ZCmfDocumentZconvert_uml2svgrZ   r   r   r  r  r  r   r   r   rX   r  r  )
rP   r  r   r  r  Zuml_code_tagZuml_coder  r  r!   r$   r$   r%   _convert_plantuml$  s$    (z!CmfPluginKaiten._convert_plantumlr  c           	   
   C   s   |s|S z||dkr$t j || jd}n|}t|d}| || | || | || | | |jr~ddd |jj	D n|}W nj t
k
r } zLt|jdk}| jjtj d|rd	nd d
| d|d t jd7  _W 5 d }~X Y nX |S )Nr  
extensionsZlxmlr   c                 S   s   g | ]}t |qS r$   rZ   )r   cr$   r$   r%   r   s  s     z1CmfPluginKaiten._convert_text.<locals>.<listcomp>r  u4    Не удалось обработать текстu    комментарияr   zERR-0026r  r   )r  _markdown_extensionsr   r  r  r  r  Zbodyr  r  r   r0  r  r   r   rX   r  r  )	rP   rp   r   rr   r  Z	html_textr  r!   Z
is_commentr$   r$   r%   r  _  s0    

& zCmfPluginKaiten._convert_textc                 C   s  t |d }| j d| }| || jtjj d }|| jd||j	j
|||ddd |d |d	< tjjj}t|d
 |kr|d
 d| |d
< |d d }|d d }| j d| d}	tjj|	d}
|
r^|
|d< |d d }|d d }| j d| }tjj|dgd}|r2||d< |j|d< n*| jjtj d| d| d|
 ddd n&| jjtj d| d| dddd |d  }|d rt |d nd}||d!< |S )"u
  
        Нормализует данные задачи

        Args:
            task_data (dict): сырые данные
            project_obj (CmfProject): проект

        Returns:
            dict: нормализованные данные
        r   r   r   Tr   F)activityZapprovedra  r  r   r  cmf_archivedr   r  r#   Nboardr   ::boardr  r  columnr   r[  r   Zcache_status_typeu!    Не найден статус 'r   u#   ) в бизнес-процессе zERR-0028r   rP  u=    Не найден бизнес-процесс списка 'r  zERR-0027rM   laner  )rZ   r   r   r   rH   r   r   r   Zdefault_activityr  r[   rI   r#   r  r  rM   r   r   r   r   rX   r  )rP   rE  project_objr1  r  normalized_dataZmax_task_name_lengthr  board_titler  r  	status_idZstatus_titler   r   Z	task_laneZboard_lane_keyr$   r$   r%   _get_normalized_data  s\    
	
z$CmfPluginKaiten._get_normalized_datac              	   C   sn  dt _t|d }d| dt _| jjt j ddd | j d| }tjj	|dd	}|sptj|| jd|d
}|j
r| ||}|dg }| jt j d|jrdnd d|  |dd |D  | D ]\}}	t|||	 q| |||_| |||_||_|jdd t  | || | || | || | || | |jjp^d||}
t|d tjj j!krd|d  d|
 }
|
|_|D ],}t"||j}| |||}t||| q|j#r|jdd | $|| n| jj%&t j d | jjt j dt j dd | j'dd t jsht(|d )d}t*|d}|+d W 5 Q R X t jS )Nr   r   u   [Задача ]u     Начало обработкиTr   r   r   include_archived)ra  r   r  r   r   r   u   Созданиеu   ОбновлениеrH  c                 S   s   g | ]}|qS r$   r$   )r   r   r$   r$   r%   r     s     z1CmfPluginKaiten._process_task.<locals>.<listcomp>r  r   r   z<p><strong>z</strong></p><p></p>u    была изменена пользователем. Изменения из импорта не будут примененыu8    Завершение обработки. Ошибок: r   r  r0  .successr>  ),rX   r  rZ   r  r   r   r   rH   r   rI   r  r  popr)  rY   r   r  r  r  r  r  r]  rU  r   r  r  r  r  r  rp   r[   r  r#   r  getattrr[  r  r  r  rq  r   rb   rd   r  )rP   rE  r  r1  r  r  r  r   r   r[   rp   Z
text_fieldZfield_valueZconverted_textr  ri   r$   r$   r%   _process_task  sv    
zCmfPluginKaiten._process_taskc           	   
   C   s   d}t ddd | j rqn| }|dkr.qnt|d}t|d}t|}W 5 Q R X || 	||7 }qW 5 Q R X |
| d S )Nr   Fr  r  r)  r]   )r
   r   r   rI   r   rb   rd   re   rf   r  r  )	rP   
task_queuetask_queue_errorsr   r  r   r  ri   rE  r$   r$   r%   _process_task_thread  s    
z$CmfPluginKaiten._process_task_threadc              
   C   s  ddl m} ddlm} d}t  t  ddd| | |	 g| _
tjj|ddgd	| _| jjjj| _| | jjd
 | _| jjjdtj| _| jjjdtj| _t }d| d}	| jj|	 d| d| d | j d| }
tjjddd|
 dgddgd}|s0td|
 t | j!|}| jj|	 d|  t" }t" }g }t#$ }t%|D ]V}t&j'| j(d| d| |||dd}|)| |*  | jj|	 d |  qtd}| j+|||| jd!}|D ].}| j, r q|-|d"  |d#7 }q|D ]}|-d$ q| jj|	 d%|  |D ]}|.  qJt#$ | }| jj|	 d&|| d'd( d}|/ s|| 7 }q| jj|	 d)|  ||7 }W 5 Q R X W 5 Q R X |S )*Nr   r	   r  ZextraZ
sane_listsZtocr   r   r  r(  process_new_or_updatedarchived_tasks[PID r  u'    Процесс запущен (offset=, limit=r  r   r   r   r  r  r  r]  r   u)   Не найден проект с ext_id uE    Обработка задач в несколько потоков: Z_process_task_thread_r   )r  r  r   r  u>    Запущен параллельный обработчик )r,  r   r-  r0  r   r  u1    Ожидание обработки задач: u%    Скорость обработки r  u    задач в секундуuA    Обработка задач завершена. Ошибок: )0cmf.appr
   Zmodules.kaiten.markdownr  r\   Zdisable_aclZdisable_notifyZPlantUMLExtensionZMentionExtensionZStrikethroughExtensionr  rH   Z	CmfImportrI   r   rS   r   _normalize_settingsr;  r   r[   r  IMPORT_ONLY_NEW_OR_UPDATED_process_new_or_updatedIMPORT_ARCHIVED_TASKSrE   r+   getpidr  r  r   ZCmfErrorr  threading_max_forksr   ru   r  r  r  r  r  r   r  r   r   r  r  r  )rP   Zcmf_import_idr  r,  r   r
   r  r  Zprocess_pidZprocess_msgr  r   Zthread_countr  r  Ztask_threadst1r  r  r  r   r   t2r   r$   r$   r%   process_task_fork2  s    	

	
 
z!CmfPluginKaiten.process_task_forkc                 C   sx   dd l }|jdddd| jjj d| jj d| d| d	| d
gdd|j|jd}| jd|j d| d| d |S )Nr   z/usr/bin/python3z	manage.pyshellz(plugin = models.CmfPluginKaiten.get(id='z'');retcode = plugin.process_task_fork('z', 'z', z, z);T)Z	close_fdsZstart_new_sessionstdoutstderrr  u(   ] Запуск процесса (offset=r	  r  )
subprocessPopenr   rS   r   ZDEVNULLr   pid)rP   r  r,  r   r  procr$   r$   r%   _execute_task  s       ,zCmfPluginKaiten._execute_task   r  c                 C   s   ||krd|fgS t || }tdt || }t|t||}t||}|| }	|| }
g }d}t|D ]8}|	}||
k r|d7 }t||}|||f ||7 }qn|S )u  
        Рассчитывает распределение задач между процессами

        Args:
            total_tasks (int): количество задач
            max_processes (int): максимальное количество одновременных процессов
            threads_per_process (int, optional): количество потоков в процессе. Defaults to 25.
            max_tasks_per_process (int, optional): максимальное количество задач
                                                   обрабатываемых в процессе. Defaults to 1000.

        Returns:
            list[tuple]: список кортежей (offset, limit)
        r   r   )mathZceilrz  Zfloorr  r  r   )rP   Ztotal_tasksmax_processesZthreads_per_processZmax_tasks_per_processZmin_processes_by_limitZprocesses_by_threadsZmin_processes_to_useZprocesses_to_useZ
base_tasks	remainderdistributionr,  r  r   r$   r$   r%   _calc_task_distribution  s$    



z'CmfPluginKaiten._calc_task_distributionc           	      C   s   d}d}| j  dt|d}| rt| D ]}| sBq4|j	drPq4|d }| j
dkrp|spq4n| j
dkr|rq4|d rd	D ]}||}|jdd
 q|d7 }|d r4|d7 }q4||fS )u  
        Получает количество успешно и неуспешно обработанных задач.
        Неуспешно - были ошибки при обрабоке саймой задачи или
        связанных объектов(комментарии, чек-листы, журнал работ и т.д.).

        Для успешно обработанных задач удаляет файл-флаги.
        r   r   r   r   r(  TFr  )r'  r  r?  r   r'  )r   ra   rb   rZ   rc   r   r*  r+  r#   r%  rE   rA  )	rP   r  Zsuccess_countZfailed_countr.  r0  r2  Zfile_flag_namer  r$   r$   r%   _get_processed_count  s4    
  

z$CmfPluginKaiten._get_processed_countc           #      C   s  | j d }| j d }d| d| d}|  }| |\}}}}}	}
| jj| d| d| d|	 d	| d| d|
 dd
d | jjd | jd
kr| jr|
n|	}n(| jdkr| jr|n|}n| jr|n|}|s| jj| dt	j
d
d d S d}| js| jd k	rJ|d7 }| jr |d7 }| jd
kr6|d7 }n| jdkrJ|d7 }|d| d| 7 }| jj| d| t	j
d
d | jj| d| t	j
d
d | ||| jtj}tj}dd |D }| }i }t }|s|rt||k r|r|d}|| d }| jjd| d| d|  |\}}z&| |||}||f||< |||< W n tk
r } zh||k r| jjd|d  d | d!|  || n*| jjd"|j d#| d$| d%| d&d' W 5 d }~X Y nX td( qg }| D ]\}\}}| }|d k	r|| |dkrR| jd"|j d)| d |  nd||k r| jjd|d  d | d*|  || n*| jjd"|j d#| d$| d+| d&d' q|D ]}||= q|s|rtd, qt }|| }t|d-\}}t|d.\}} | |\}!}"| jj| d/t |d0d1t |d0d1| d2 | jjd3|! d|" d|  | jjd4|| d5d6 | jjd7|  d S )8Nr   r      Проект 'r   r  uT   . Всего выгруженных задач (активных/архивных): r  r"  uA   ). Необработано (активных/архивных): Tr   u   Для настройки обработки задач измените параметры 'IMPORT_ONLY_NEW_OR_UPDATED' и 'IMPORT_ARCHIVED_TASKS'Fu-   . Нет задач для обработки)r9  r   u0   Будет выполнена обработкаu    толькоu"    новых/обновленныхu    архивныхu    активныхu    задач: r  r   u[   . Ограничение одновременных процессов обработки: c                 S   s   i | ]
}|d qS )r   r$   )r   
task_chunkr$   r$   r%   r  c  s      z2CmfPluginKaiten._process_tasks.<locals>.<dictcomp>r   r   u   Попытка rH  u0   Повторный запуск (попытка z): u4   . Ошибка предыдущей попытки: r  uC   ] Процесс завершился с ошибкой после u    попыток: u   . Ошибка: zERR-0034r  r  uE   ] Процесс завершился успешно (попытка u?   . Код возврата предыдущей попытки: u   . Код возврата:    i  <   u8   . Обработка задач завершена за Z02d:z06.3fuE   Обработано задач (успешно/неуспешно): u%   Скорость обработки: r  u    задач/секu)   Всего задач в проекте: )!rT  r  rG  r   r   r  r  rE   r  r<  r=  r!  r  r  ZIMPORT_OBJ_CNTZIMPORT_PROCESS_RETRYcopyru   r  r  r   r  r   r  r   r   r  r  r   Zpolldivmodr"  r  )#rP   r  r  Zproject_msgr  r  ZunprocessedrB  rC  r   rD  r  Zprocess_tasks_msgr   Zmax_retriesZtask_chunk_attemptsZpending_task_chunksZactive_processesr  r$  Zattemptr,  r   Zprocessr!   Zprocesses_to_removeZreturn_coder  ZdiffZhoursr  rw   ZsecondsZsuccess_tasksZfailed_tasksr$   r$   r%   _process_tasks  s    

	,


	
 






&zCmfPluginKaiten._process_tasksc                 C   sJ   dd|gdd|gg}t jj|d}|sFt j||| jdd}|jdd |S )u,  
        Возвращает глобальный статус

        Args:
            status_name (str): имя статуса
            status_type (str): тип статуса (OPEN, IN_PROGRESS, CLOSED)

        Returns:
            CmfStatusCode: глобальный статус
        r#   r   r   r   Tr7  r  )rH   r8  rI   r   rU  )rP   r;  r   r<  r=  r$   r$   r%   _get_global_status  s    z"CmfPluginKaiten._get_global_statusc           	      C   s$  |d }|d }|d }| j jd| d| d|  | j d| }tjj|d}|sd	d
|gdd
|gdd
dgg}tjj|d}|stj|| j dd}|js|js||_	| 
||d |_d|_|d |_||_t|d d d|_||_d|_|jdd n| j jd| d| d |S )u  
        Обрабатывает статус бизнес-процесса

        Для бизнес-процессов для списков:
            Колонка доски в Kaiten, это статус бизнес-процесса
            Каждая колонка имеет тип:
            1 - очередь (OPEN)
            2 - в работе (IN_PROGRESS)
            3 - готово (CLOSED)

        Args:
            status_data (dict): сырые данные статуса
            workflow (CmfWorkflow): бизнес-процесс

        Returns:
            CmfStatus: статус бизнес-процесса
        r   r   r4   r6  r   u    ) бизнес-процесса r   r  r#   r   r  r   Nr   T)r  r   r  r5   r  r     r  u   Статус u    бизнес-процесса r  )r   r  r  r   rH   r   rI   r  r   r#   r,  status_codeZallow_empty_transitionr5   r  roundr  rU  r  )	rP   r:  r  r  r;  r   r   r  r<  r$   r$   r%   r    sD    
z(CmfPluginKaiten._process_workflow_statusc                 C   s  |d }|d }|d }| j jd| d| d | j d| d}tjj|d	}|sntj| j|| j d
d}|jrn| j	d }| j	d }| d| |_
d| d| d| |_|jd
d | j jd|  g }	|D ]}
| |
|}|	|j qtjjdd|	gdd|gdddggdgd
d}|D ]B}tjjdd|jgdd|jgdd|ggds\q(|jd
d q(n| j jd| d |S )u  
        Обрабатывает бизнес-процесс для задач списка

        Args:
            board_data (dict): сырые данные доски(списка)

        Returns:
            CmfWorkflow: бизнес-процесс для задач
        r   r   columnsuQ   Обработка бизнес-процесса задач для списка 'r   r  r   r  r  T)rC  r   r   r  r   u%   : Бизнес-процесс для u0   Бизнес-процесс для списка u    проекта rH  r  r  r  r  r   r   Nr   r  ri  r   r  r  r  )r   r  r  r   rH   rM   rI   rN   r  rT  r#   rp   rU  r  r   r   r   r  r   ry  r  )rP   r  r  r  r9  r  r  r	  r  r  r:  r  r  r   r$   r$   r%   _process_list_task_workflow  s^    


	


z+CmfPluginKaiten._process_list_task_workflowc                 C   s   |  |}|d }|d }| jjd| d| d | j d| }tjj|d}|sjtj|| jdd	}|jr||_	| j
|_||_||_|d
 }|dkrd| j d| d}	tjjddd|	 dgd}
|
|_|jdd n| jjd| d |S )u  
        Обрабатывает список задач для доски

        Args:
            board_data (dict): сырые данные доски(списка)
            list_folder (CmfRegistry): каталог для списков задач в структуре проекта

        Returns:
            CmfList: список задач для доски
        r   r   u3   Обработка списка для доски 'r   r  r   r  Tr   r   r  default_card_type_idr   r   r   r   r   r  u   Список r  )r1  r   r  r  r   rH   CmfListrI   r  r#   rO   r   r  tree_parentrK   r  rU  r  )rP   r  list_folderZtask_workflowr  r  list_ext_id
board_listr3  r   r   r$   r$   r%   _process_board_list^  s:    

z#CmfPluginKaiten._process_board_listc              	   C   sD   t jjd| jdgd}|s@t jd| j| jdd| jdd}|  |S )u   
        Получает/Создает каталог для досок в структуре проекта

        Returns:
            CmfFolder: объекта каталога для досок
        u
   Доскиtree_node_is_branch)r#   r5  r   Ni_ T)r#   ra  r5  Zsys_typer  r   r  )rH   Z	CmfFolderrI   _projectr   rU  )rP   board_folderr$   r$   r%   _get_board_folder  s"    	z!CmfPluginKaiten._get_board_folderc                 C   s   | j jd| d| d | j d| }tjj|ddgd}|sVtj|| j dd	}|jrd
| |_| j	|_
d|_d|_d| j	j d|j |_dddt| j	jggddt|jggg}tj|dd|_|jdd n| j jd| d |S )u  
        Обрабатывает основной фильтр для доски
        Фильтр по списку (поле lists)

        Args:
            board_id (int, str): id доски
            board_title (str): название доски
            board_list (CmfList): список задач для доски

        Returns:
            CmfBqlFilter: основной фильтр для доски
        u5   Обработка фильтра для доски 'r   r  r   r#   r  r[  Tr2  u   Фильтр для Zfullcommonproject in (z) and lists = ANDproject.codeIN
lists.codeFr_   r  u   Фильтр r  )r   r  r  r   rH   CmfBqlFilterrI   r  r#   r;  ra  perm_policy
view_scoper=   ubqlrZ   re   r  bqlrU  r  )rP   r  r  r8  Zboard_filter_ext_idboard_filterrH  r$   r$   r%   _process_board_filter  s<    
z%CmfPluginKaiten._process_board_filterc                 C   s  |d }|d }t |d dd dd}| jjd| d	| d
 g }t|dD ]B\}}|d }	|d }
|
spqP| jjd|
 d	|	 d| d	| d
	 | d|
 }t|	}|| j|< | j d| d|	 }tj	j
|ddgd}|stj	|| jdd}|jrn|
|_d|_d|j d| d|_dddt|jggdd|gg}tj|dd|_|d |_||_|jdd  n| jjd!| d"| d# || qP|S )$u  
        Обрабатывает дорожки доски
        Фильтр по списку (поле lists) и полю Дорожка (поле cf_kaiten_board_lane)

        Args:
            board_data (dict): сырые данные доски(списка)
            board_list (CmfList): список задач для доски

        Returns:
            list: список дорожек
        r   r   Zlanesc                 S   s   | d S r  r$   )r  r$   r$   r%   r    r  z:CmfPluginKaiten._process_board_swimlanes.<locals>.<lambda>T)r   reverseu.   Обработка дорожек доски 'r   r  r   u#   Обработка дорожки 'u   ) доски 'z / r   r#   r  r[  r2  Zembeddedzlists = z and cf_kaiten_board_lane = "rM  r@  rC  rB  r  r   Fr_   r  r  u   Дорожка u    доски 'uf   ' была изменена. Изменения из импорта не будут применены)r*  r   r  r  rJ  rZ   
_swimlanesr   rH   rD  rI   r  r#   rF  r=   rG  re   r  rH  r  r]  rU  r  r   )rP   r  r8  r  r  Zboard_lanes	swimlanesr  Z	lane_dataZlane_idZ
lane_titleZswimlane_valueZswimlane_keyZswimlane_ext_idZswimlanerH  r$   r$   r%   _process_board_swimlanes  sf    

z(CmfPluginKaiten._process_board_swimlanesc                 C   s  |d }|d }| j jd| d| d|  | j d| }tjj|ddgd	d
}|sntj||| j d	d}|jr||_tj	j|dgd}|r|j
|jj q| j jd| d| dddd n| j jd| d| d t|d d d|_|jd	d dS )u   
        Обработка колонки доски

        Args:
            column_data (dict): сырые данные колонки
            board (CmfKanbanBoard): доска
        r   r   u#   Обработка колонки 'r   u   ) доски r   mapped_status_codesr  Tr   r  r.  r[  u>   Не найден статус бизнес-процесса 'r  zERR-0029r   rP  u   Колонка u    доски rx  r  r  r-  r  N)r   r  r  r   rH   ZCmfKanbanBoardColumnrI   r  r#   r   rO  r   r.  r[   r   r  r/  r  rU  )rP   column_datar  Z	column_idZcolumn_nameZcolumn_ext_idZboard_columnr   r$   r$   r%   _process_board_column+  sF    z%CmfPluginKaiten._process_board_columnc                 C   s  |d }|d }|  |||}| ||}| jjd| d| d | j d| }tjj|ddd	d
gd}	|	stjd|| jdd}	|	j	r||	_
| j|	_||	_||	_||	_|rdnd|	_|	jdd n| jjd|	 d | jjd| d| d |d D ]}
| |
|	 qdS )u>  
        Обрабатывает доску

        Args:
            board_data (dict): сырые данные доски
            board_list (CmfList): список задач для доски
            board_folder (CmfFolder): каталог для досок в структуре проекта
        r   r   u   Обработка доски 'r   r  r   ra  r5  kanban_bql_filterZkanban_board_columnsr[  zboard.kanban:defaultT)r   r   r   r  z	1 queriesz7 noner  u   Доска rx  u.   Обработка колонок доски 'r0  N)rJ  rN  r   r  r  r   rH   CmfKanbanBoardrI   r  r#   r;  ra  r5  rR  Zswimlane_bql_filtersZswimlane_typerU  r  rQ  )rP   r  r8  r<  r  r  rI  rM  Zboard_ext_idr  rP  r$   r$   r%   _process_board`  sF    		
zCmfPluginKaiten._process_boardu   Обработка досокc                 C   sx  |   }tjjdd| jgdddgdddgdddggd	gd
}| | jd D ]}|d }|d }|d }|D ]0}| j|d |d< |d sl|d d |d< ql||d< z$| ||}| 	||| t
  W qL tk
r }	 z.t  | jjd| d| d|	 ddd W 5 d }	~	X Y qLX qL|tjf|tjfg}
|
D ]>\}}dd|g}t|j|dgd
|_|jr4|jdd q4d S )Nr5  r   r#   r}  r4   r4  rc  Tr:  r   r   r   r0  u/   Не удалось создать доску 'r   r  zERR-0033rP  r   r  )r=  rH   ZCmfRegistryrI   r;  r7  rT  rG   r9  rT  r   r   r   r   r   rS  r4  r0  r  r:  r[  rU  )rP   r<  r6  r  r  r  Zboard_columnsrP  r8  r!   ZfoldersZfolderr   Zmodel_filterr$   r$   r%   _process_boards  sJ    



zCmfPluginKaiten._process_boardsc                 C   s  | j d }| j d| }tjj|dgd}tjjddddd	gd
}tjj||d}|sltj||| jdd}|jr|j	j
p~i }t|jj
pt }dd | D }| j D ]n\}	}
|	|kr||	 }||kr|| |	kr||= |
||	< n*|
|kr||
 }||= |
||	< n|
||	< |	||
< q| j D ]}|| q(tt| dd d|_	t||_|jrxd|_|jdd | j|_	g |_|  |jrtjtj dddd tjddi n| jjd| d dS )u   
        Обрабатывает конфигурацию для поля 'Дорожка'
        Собранные значения дорожек добавляются в конфигурацию поля
        r   r   r   r[  r  r  r   r  r  r   )r3  ra  T)r3  ra  r   r  c                 S   s   i | ]\}}||qS r$   r$   )r   kvr$   r$   r%   r    s      zBCmfPluginKaiten._process_swimlane_field_config.<locals>.<dictcomp>c                 S   s   | d S )Nr   r$   )r  r$   r$   r%   r     r  z@CmfPluginKaiten._process_swimlane_field_config.<locals>.<lambda>r  r  r$  r   Fr%  r'  u"   Конфигурация поля rx  N) rT  r   rH   r~  rI   r  r  r   r  r   r[   rI  r  r   rL  rU  rK  r   r*  r  r[  r  rU  r   r+  rx   ry   r,  r-  r.  r  r  )rP   r  Zfield_config_ext_idr  r3  Zconfig_cust_fieldr"  r4  Zvalue_to_keyZnew_keyZ	new_value	old_valueZold_keyr   r$   r$   r%   _process_swimlane_field_config  sv    
	





z.CmfPluginKaiten._process_swimlane_field_configc           
   	   C   s*  t  }| | jd D ]}|d }|d }| j d| }tjj|d}|sn| jjd| d| ddd	d
 q| jj	
d| dt|d   |d D ]V}| j d| }tjj|dd}	|	r|j|	 q| jjd| d| dd|d q|jdd |t|j t  qtjjt|d dS )uC   
        Добавляет задачи в списоки
        r   r   r   r  u   Список 'r   u   ) не найденzERR-0030r4  rP  u0   Добавление задач в список rH  r  Tr  u   В список u3    не удалось добавить задачу u"   . Задача не найденаzERR-0031r  r  )list_idsN)rI  r7  rT  r   rH   r4  rI   r   r   r  r  r  r   r   r   rU  rK  rZ   r   r   Zrecalculate_count_cacher  )
rP   rZ  r  Zlist_idZ
list_titler7  r8  Zcard_idr  r   r$   r$   r%   _add_tasks_to_list  s<    z"CmfPluginKaiten._add_tasks_to_listc                 C   s   t jjdd| jgdddggdd}|r| jjd|  t| jj}t j	j
|d}|sdd	d
t| jjggdddgg}t j	d| jddd| jj dtj|ddd|| jdd
}|  d| j_d| j_| jjdd dS )u  
        Проверяет наличие архивных задач и настраивает их отображение
        Для отображения архивных задач создается фильтр в разделе "Архив"
        r   r   r  T)r   r  u8   Импортировано архивных задач: r  r@  rA  rB  ri  Fu   Задачиreadonlyr?  z) and cmf_archived is not emptyr_   )
r#   r5  rE  rF  rG  rH  r  r   r   r  r  N)rH   r   r/  r;  r   r  r  rZ   r   rD  rI   r=   re   r  rU  Zshow_archiveZhas_children_archived)rP   Zarchived_tasks_countZfilter_ext_idZarchived_tasks_filterrH  r$   r$   r%   _configure_archived_tasksD  s>    
z)CmfPluginKaiten._configure_archived_tasksc                 C   sZ  | j jd| jd   tjjdd|d gddgd}|r|j|d ks^|jr|d |jkr|d  d|d  d	|d< | j j	d
|j
 d|d   n|js|d |_|  d|d< d|d< d|d< d|d< |  }| ||d< | ||d< |  |d< tjjddd|d  dg| d}|sLtj|d |d | j dd}|j}|jr|D ]$}|dkrpq^t||||  q^| jddsd|_|  |jg|_d|_d|_d|_d|_d|_|jdd n| j j	d| d |rtjj|dD ]}|jdd qt  || _ i | _!| "  | #  | $  | %  | &  t  |S )Nu"   Обработка проекта r   r#   r  r   r   r   r  r  u   Проект с именем u8    уже существует! Переименуем в TZtask_allow_multiple_sprintsFZsl_only_owner_approveZsl_deny_no_approveZsl_task_only_owner_closer  rr  Zcust_field_conf_schemer   r   rq  Z	is_publicZprivater  u"   Настройки проекта u    были изменены пользователем. Изменения из импорта не будут примененыr`  rs  )'r   r  r  rT  rH   r   rI   r   r   r  r#   rU  rX  r  r|  r  rU  r)  r  r  rE  r   Zcmf_project_adminsZ
show_listsZ	show_blogZ
show_pfeedZ	show_diskZ	show_chatr   r  ry  r   r;  rL  rU  rY  r+  r[  r]  )rP   project_structr  r  r)  r   r   r$   r$   r%   _process_projectn  s    



z CmfPluginKaiten._process_projectu#   Обработка проектовc              
   C   s6  dd | j D }|  D ]}t|d }|d }zz| j rLW W  d S ||kr\W W q|drz| |d d }nt	j
}d| j d| d}||d< d|| j| j|d	 |||d
}|| _| | t  W nJ tk
r   t  |  jd7  _| jjd| d| dddd Y nX W 5 d | _d | _X qd S )Nc                 S   s   g | ]}t |d  qS r8  r  r   pr$   r$   r%   r     s     z5CmfPluginKaiten._process_projects.<locals>.<listcomp>r   r   r  r   r   r   r   )Zproject_typer#   r   r  r   r   r   r]  r   u=   Не удалось импортировать проект 'r   r  zERR-0032r   r   )rB   r   rZ   r;  rT  r   r   rI   r   r  r:  r   rL   rJ   r_  r   r   r   r   r   )rP   Zselected_projects_idsr
  r  r  r   r  r^  r$   r$   r%   _process_projects  sH    



z!CmfPluginKaiten._process_projectsu3   Обработка связей всех задач
is_processc           #      C   s2  |s| j jd d S | jjd}td| d}tj	j
dd}tj	j
dd}|  D ].}|d }| |D ]}| j  r  d S |d }	t|
d	g D ]\\}
}|d }|
d
kr| j
|g }||	 || j|< q| d|	 }||	|d| j|< q|
dg D ]z}|d }||}|s,q|d}|	 d| }|| jkrTq| d|	 }|| jkrrq||	|d| j|< qqrqZt| j}tdd | j D }| j d| d|  t| j dD ]\}
\}}|
d d
kr| j jd|
 d|  | j d| }tjj
|dgd}|sN| j jd| d q|D ]4}| j d| }tjj
|ddgd}|s| j jd| d qRz|j|jkr||_|jr<|jdd  nt| j jd!| d"| d# tj j
|||d$}|s<tj |||| j d%}|jdd  | j j!d&| d'| d(|  W nF t"k
r } z&| j j#d)| d*| d+| d,d- W 5 d }~X Y nX qRt$  qt| j% }| j d.|  t| j dD ]`\}
\}}|
d d
kr | j jd/|
 d|  t$  z|d0 }|d1 }|d2 } tjj
| j d| d3}!|!sV| j jd4| d W qtjj
| j d|  d3}"|"s| j jd5|  d W qtj j
|!|"|d$}|stj |!|"|| j d%}|jdd  | j j!d&| d'|! d(|"  W n6 t"k
r"   | j jd6| d7| d8|   Y nX qt$  d S )9NuF   Отключена обработка связей всех задачr"  r  r  zsystem.additional_parentr<   zsystem.linkr   parentsr   z:additional_parent:)r4   
outward_id	inward_idr  rT   r   z:link:c                 s   s   | ]}t |V  qd S r   )r  )r   rA   r$   r$   r%   rh  J  s     z5CmfPluginKaiten._process_relations.<locals>.<genexpr>u%   Родительских задач: u   . Подзадач: 2   u9   Обработано родительских задач r  r   r   r[  uE   Не удалось найти родительскую задачу u   . Возможно задача не попала в импорт или находится в проекте, который еще не импортирован.parent_tasku=   Не удалось найти дочернюю задачу Tr  u!   У дочерней задачи u'    родительская задача uy    из другого проекта. Будет создана связь 'Дополнительный родитель')in_linkout_linkrelation_type)rj  rk  rl  r   u   Создана связь. rH  z - u   Не удалось создать связь между родительской и дочерней задачами. Родительская: u   , Дочерняя: u   Ошибка: zERR-0035r%  u   Связи задач: u"   Обработано связей r4   rf  rg  r  u=   Не удалось найти входящую задачу u?   Не удалось найти исходящую задачу u.   Не удалось создать связь z. in_link: z, out_link: )&r   r  r  r/   rT   r  rm   r  rH   ZCmfRelationTyperI   r   r   r   rJ  rA   r   r@   r  rb  r  sumr   r   r   r  r   r   r   ri  r[  rU  ZCmfRelationOptionr  r   r   r   rU  )#rP   rd  r  r  Zadditional_parent_typeZ	link_typer   r  rE  r1  r  ra  Z	parent_idZ	child_idsZrelation_idr  rT   r  Zlinked_task_idZtotal_parent_tasksZtotal_subtasksZparent_ext_idri  Zchild_idZchild_ext_idZ
child_taskZrelation_optionr!   Ztotal_relationsZtask_relationrl  rf  rg  rj  rk  r$   r$   r%   _process_relations  s   











z"CmfPluginKaiten._process_relationsc              	   C   s  d| _ || _t   d| j_| jj  t  W 5 Q R X | jj| _| jj	j	j
| _
| | jjd | _| jjjdtj| _| jjjdtj| _|   | jjjdtjpg }td|k}td|k}td	|k}|s|   n| jjd
 |s|   n| jjd |s|   |   |   |   |   |    | !  | j"| jjjddd | jjjddr|  j | j# 7  _ n| jjd n| jjd t   d| j_$| jj  t  W 5 Q R X |s| j%d dd | j&D }| ' D ]}|d }||krqd| j
 d| d}	t(j)j*ddd|	 dgdd}
|
rv| jj+d|d  d| d n | jjd|d  d| d  q| j%d!| jj,  | j  S )"Nr   u   Импорт из Kaitenr(  r  r  
skip_stager   r:   r;   u&   Пропуск дампа данныхuA   Пропуск скачивания файлов вложенийZprocess_task_linksTrc  Zprocess_linksu2   Отключена обработка ссылокu.   Пропуск обработки данныхr  z2--------------------------------------------------c                 S   s   g | ]}|d  qS r8  r$   r`  r$   r$   r%   r     s     z2CmfPluginKaiten.process_import.<locals>.<listcomp>r   r   r   r   r   re  r#  r   r   u   ) импортированu6   ) сдамплен, но не импортированu-   Импортировано объектов: )-r   r   r-   r#   r[   rU  r   Zget_max_processesr  rS   r   r  r;  r   rI   r  r  r  r  rE   r  ZIMPORT_SKIP_STAGEr0  r  r  r  r  rO  r   r5  r>  rE  rR  rb  rn  Zprocess_cross_linksr  r   rB   r   rH   r   r  r  r  )rP   r   ro  Z	skip_dumpZskip_downloadZskip_processZselected_project_idsr   r  r  r  r$   r$   r%   process_import  s    





zCmfPluginKaiten.process_import)N)r   NF)r  )TT)r  )r  r  )T)l__name__
__module____qualname__Z_CmfPluginKaiten__clientr   r.   Zui_meta_skipZapi_methodsr?   propertyr/   r0   staticmethodrq   r   rZ   r~   r   r   r   r   r   r   r   r   r   r1   r   r  r   r   r   r7  r   rG  rN  rO  r)   rV  re  rk  rs  rw  r|  r  r  r  r  r  r  r  r  r  r  r  r   r   r  r  r5  r>  rE  rR  rX  rp  r|  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r!  r"  r+  r,  r  r1  r9  r=  rJ  rN  rQ  rT  rU  rY  r[  r]  r_  rb  r0  rn  rp  __classcell__r$   r$   rQ   r%   r.   @   s   


	

 
o6)"   
*"6:


.
@
D!mY

 
!64 :P
; n
_
3r7"7?Fh1KU
;
!J
Sq  
6' )<J22O57
3N+*n
0 <r.   )N)(ry   rx   r  r  r  r+   rm   rS  ru   r  r  r  r  r  
contextlibr   r)  r   	itertoolsr   Zbs4r   pathlibr   Zqueuer   Ztext_unidecoder   r
  r
   Zcmf.includeZmodules.kaiten.fieldsr   Zmodules.kaiten.kaiten_clientr   localrX   r)   r-   r.   r$   r$   r$   r%   <module>   s8   

	