U
    c]                     @   sx   d dl m Z  d dlmZmZmZ d dlmZ d dlT d dlZG dd dej	j
jjZejdd	  ejd
d	  dS )    )copy)datetimetimezone	timedelta)
monthrange)*Nc                       s  e Zd Z fddZ fddZeddddZedXd
dZedY fdd	Zed	d	d	d	dddZ	edZddZ
dd Zd[ddZedd Zdd Zd\ddZedd	d fdd 
Zd!d" Zd#d$ Zed%d& Zed] fd'd(	Zd)d* Z fd+d,Zd-d. Zd/d0 Zd1d2 Z fd3d4Zed5d6 Zd7d8 Zd9d: Zd;d< fd=d>
Zd?d@ Z dAdB Z!edCdD Z"edEdF Z#e$dGdHdIZ%dJddKdLZ&edMdN Z'dOdP Z(edQdR Z)dSdTe*dU fdVdWZ+  Z,S )^
CmfProjectc                    s   | j r
d S t   d S N)
logic_typesuper_calc_logic_typeself	__class__ './modules/project/models/cmf_project.pyr      s    zCmfProject._calc_logic_typec                    s   | j r
d S t   d S r	   )Z	scheme_wfr   _calc_scheme_wfr   r   r   r   r      s    zCmfProject._calc_scheme_wfzmodels.CmfTask)taskc                 C   s  |j s"|jjs"|jjs"|jjs"d S |jjr@|js@|jr<g |_d S |jjr$|jr$|js$|js$d }|jj rz|jj}|stjj	dd|jj
gdddggd}|stjj	dd|jj
gdddggd}|stjj	dddgdd|jj
gggd}|stjj	dddgdd|jj
gggd}|r$||_|jsP|jjrP|jrP|jd	 j |_|jsltjjrltjj|_|jr||  d S )
Ncmf_owner_id==project_typeprojectfiltersection	executorsINr   )is_newZlists
is_changedparentZresponsibleZdefault_projectloadmodelsr   getidgZcurrent_personload_fieldssave_preload_fields)clsr   Z
tmp_parentr   r   r   _calc_task_parent   sh    

zCmfProject._calc_task_parentNc                 K   s   t ddS tt| j|dgd}|s,g S |}g }|rX||jj |jj	dgd}q4ddd|gd	d|gg}	| 
 D ]2}
|
j}||}|r|| |	g||< qv|	||< qv| jf |d
d|}| j||dS )u_   
        Построение дерева от не корневого обьекта
        
DepricatedNtree_parentr   fieldsr-   ORtree_parent_idr   r$   T)filtersfilter_projectr0   )	Exceptiondictvarsr"   r#   appendr$   valuer+   r!   _get_node_models
class_name_get_tree_dataZ_create_tree)r(   Z	obj_modelZ
obj_filterr1   r0   kwargsobjr    Z
parents_idZparent_filtermodel
model_namemodel_filter	tree_datar   r   r   get_obj_trees   s*      

zCmfProject.get_obj_treer   c           	         sx   t dd S ddd|gdd|gg}|  D ]2}|j}||}|rT|| |g||< q*|||< q*t j||fd|i|S )Nr*   r/   r0   r   r$   r1   )r4   r5   r9   r:   r#   r   get_tree_leaf)	r(   r0   r   r1   r<   Zparent_filtr>   r?   r@   r   r   r   rC      s      

zCmfProject.get_tree_leaf)r-   r1   r   r2   c                O   s   t dd S |rdd|g}|drF|r8||dg}n|rF|d}dtjj||| ddgdi}	|D ]H}
tt|
 }||
 pg }|tjkr|ddd gg}|j||jd |	|
< qh|	S )!Nr*   ordernonamer   	cmf_ownerr   show_approved
show_tasksshow_archive
show_pfeed	show_disk	show_chat	show_epicshow_sprintshow_releaseshow_roadmapactivityZcmf_owner_assistantsZhas_tree_nodestree_hiddenZ	is_publicZsharelink_hashZperm_policy_anonymousZperm_policy_guestZperm_policy_sharelinkZperm_policyr   r   )r   r-   Zorder_bysys_type=r,   )	r4   r#   popr"   r   listr6   CmfListZtree_fields)r(   r-   r1   r   r2   argsr<   Zproject_filterZproject_fieldsrA   r?   r>   r@   r   r   r   r;      sh                                 


 
zCmfProject._get_tree_datac                 C   s   t dd S D ]"}|jdkr|jjjdd d q|r||	dd	  D ]>}|j
|krHt|d
shg   S t|tjr||| |g  S qHg S |tjj D ]}|| q|tjj S )Nr*   c                 S   s   t | jjD ]~}d|jkrZt|dd rZd|j | jkrZt| d|j dsZ| jj| t|tj	rd| jkrt| dds| jj| qd S )NrS   show_TrL   )
r   
tree_nodesr8   r-   getattrrS   remove
isinstancer"   CmfChatGroup)r   noder   r   r   hide_project_parts   s"    


z5CmfProject._get_tree_root.<locals>.hide_project_partstagsc                 S   s   | j S r	   rE   )r_   r   r   r   <lambda>       z+CmfProject._get_tree_root.<locals>.<lambda>)key:r   rZ   )r4   r#   r"   	CmfFolderr:   rS   rZ   r8   sortsplitr$   hasattrr]   r   )r(   rA   r0   r`   folderr=   r   r   r   r   _get_tree_root   s$     



zCmfProject._get_tree_rootc                    s  d8dd}d}| j dkrd}|| tjtddt|| dd	d
}||tjtddtddd
}||tjtddtdddd
}|jD ]<}t|tjr|jr|jj| jkr|j	dkr|jj
| q||tjtdddtd| dd
 tjtjd}	|	jddddddd  fddtddD }
dd |
D }t|
|}dd d!d"d#d$d%d&d'd(d)d*d+}|D ]:\}}||tjt||d,d-td.||j  | dd
 qX||tjtd ddd/d0td1| dd
 ||tjtd2d3d4td5| d6d7d
 d S )9Nc                    sf   | j D ]0 t |rt fdd| D r   S q|f d| i||}|  | j j| |S )Nc                 3   s   | ]\}} | |kV  qd S r	   r   ).0kvir   r   	<genexpr>  s     zNCmfProject.scaffold_backlog.<locals>.add_node_if_not_exists.<locals>.<genexpr>r+   )rZ   r]   allitemssaver8   r7   )r+   
node_classnode_filter_kwargsnode_create_kwargsr_   r   rp   r   add_node_if_not_exists
  s    
$
z;CmfProject.scaffold_backlog.<locals>.add_node_if_not_existsu   Задачиproject.agileZBacklogbacklog)rS   順 )rE   filter_parentrD   )r+   rv   rw   rx   ra   u   Тэгиrb   Zdatesu   Даты
   )rE   rD   r   ZfalseZnot_assigned)filter_responsible_setrS   u   #НеНазначено)rE   r}   Ztz   )monthdayhourminutesecondZmicrosecondc                    s   g | ]} j |d qS ))r   )replacerm   rq   Zstart_of_yearr   r   
<listcomp>`  s     z/CmfProject.scaffold_backlog.<locals>.<listcomp>   c                 S   s,   g | ]$}|j t|j|jd  ddddqS )r      ;   )r   r   r   r   )r   r   Zyearr   r   r   r   r   r   a  s   u   Январьu   Февральu   Мартu   Апрельu   Майu   Июньu   Июльu   Августu   Сентябрьu   Октябрьu   Ноябрьu   Декабрь)r                        	   r~         date)Zfilter_plan_start_date_minZfilter_plan_start_date_maxrS   #Zno_alarm_date)r   Zfilter_plan_start_date_setZfilter_alarm_date_setrS   u   #БезДатыFZnot_approved)Zfilter_approvedrS   u   #Согласоватьu  В фильтр "#Согласовать" попадают все идеи, пожелания, задачи от пользователей.
Руководитель проекта обрабатывает список и переносит задачи в другие списки.
В идеале этот список должен быть обработан, то есть оставаться пустым к концу рабочего дня руководителя проекта.

примеры  списков, куда можно перенести задачи из "#Согласовать":
todo0 Срочно до мвп
todo1 В течение года
todo2 Через год
Отклонено
Версия октябрь 2021)rE   r}   text)NNNN)logic_prefixr"   rg   r5   rZ   r]   CmfActiveEntityFilter
filter_tagrQ   Zcache_select_countr8   r\   r   nowr   utcr   rangezipr   )r   rX   r<   ry   Zfld_tasks_nameZ	fld_tasksZfld_tagsZ	fld_datesr_   r   Zstarts_of_monthsZends_of_monthsZmonth_rangesZmonth_namesZmonth_startZ	month_endr   r   r   scaffold_backlog  s        


	
     

zCmfProject.scaffold_backlogc                 C   s   |s
| j }d| S )N/rb   r   rE   r   r   r   project_dir  s    zCmfProject.project_dirc                 C   s   t jjj }|| S r	   )r"   CmfRFileZdpZdata_driverZget_rdZ	get_rfile)pathZrdiskr   r   r   
_get_rfile  s    zCmfProject._get_rfilec                 C   s   |  |  jdddd dS )u   Создадим папку проекта, если её нет. Может так же нужно проверять "Документы"? T)is_direxist_okparentsN)r   r   creater   r   r   r   ensure_project_dir  s    zCmfProject.ensure_project_dirc                 C   s   |s
| j }| | |jS r	   )rE   r   r   existsr   r   r   r   is_project_dir_exist  s    zCmfProject.is_project_dir_existr   r1   c                   sB   t dd S t jf ||d|}|D ]}|  |  q(|S )Nr*   r   )r4   r5   r   get_full_treer   r   )r(   r   r1   rX   r<   resr   r   r   r   r     s      
zCmfProject.get_full_treec                 C   s
  t jjdd}t jjdd}t jjdd}t jjdd}t jjdd}td dd	lm} |d
g  }| jdkrz|   | j	st 
 }t jjdd|_| |_d| j |_d|_|  || _	t j| ddd|_t j| ddd|_t j| dd| j d|d|_t j| | gd| j d|_| jdkrt j| dd|_t j| ddd|_t j|jdd|_d|j_d |j_d!|j_d"|j_d#|j_d|j_d|j_d|j_d|j_|j D ]}	|	  qd$| _d$| _ d$| _!d$| _"| jdd% | jd&kr<t j| d'd(d|_#t j
| |j#d)|d*|_$t j| d+d,d|_%t j|j%d-d.|d/|_&t j| d0d1d|_'t j|j'd2d3|d/|_(t j| d4d5d|_)t j*|j)d6dd7|_+t j| ddd|_t j|jdd|_,t j-| d8|d9|_.t j| d:|d9|_/t jjd;| j0d<|_1t j| d=d|_2t j3|j2d>d|_4t j3|j2d?d|_5t j| d@d|_6dA|j1_dB|j)_dC|j#_d|j'_d |j%_d!|j_dD|j._d"|j_d#|j_dE|j_dF|j_dG|j/_dH|j2_dI|j6_|j D ]}	|	  qd| _7d| _8d| _9d| _:d| _;d| _<d| _d| _ d| _!d| _"| jdd% t j=j>j?}
|
D ],}t j=|
| |j6||j4dJ|_@|j@  q| jdKkrt j| dLdd|_At j|jAdMdN|d/|_Bt j| dOdd|_Ct j|jCdPd.|d.dQ|_Dt j| ddd|_t j|jdd|_,t j| d:|d9|_/t jjd;| j0d<|_1t j| d=d|_2t j3|j2d>d|_4t j3|j2d?d|_5t j| d@d|_6dA|j1_dB|jA_dC|jC_d|j_d |j_d!|j_d"|j_d#|j_dF|j/_dG|j2_dH|j6_|j D ]}	|	  qd| _7d| _8d| _d| _ d| _!d| _"| jdd% t j=j>j?}
|
D ],}t j=|
| |j6||j4dJ|_@|j@  qdS )RuU    Добавляем структуру папок в новый проект
        zlist.pfeed:default)codeztask.epic:defaultzlist.agile_sprint:defaultzlist.release:defaultzlist.base:defaultuc   Вызываем разворачивание чтобы появилась папка задачиr   )make_dataclassZ	DataEmptyzproject.wikiztask.gantt_project:defaultu	   Гант Tu   Дискdisk)r+   rE   rS   u
   Архивarchiveu
   Лентаu   Лента проекта pfeed)r+   rE   r   	list_typer
   u   Чат )r+   r   rE   u   Документ1)r+   rE   u   ДокументыNu   Документ2i i" iI i i  FZ	only_datarz   ZEpicsepiczEpic 1)r    r+   rE   r
   ZSprintssprintzSprint 1Zkanban)r+   rE   r   r
   ZReleasesreleaseu   Релиз 1rV   ZRoadmapsroadmapu   Roadmap Проекта)r+   rE   systemu   Доска Канбан)r+   rE   r
   u   Совещанияr{   )rS   r0   u   Фильтрыu   Фильтр 1u   Фильтр 2u   Отчетыr|   i i i q i0 i@ iP4 i`[ ip )rE   r+   report_typeZreport_filterzproject.baseZTodou   Список1Zclassicu   В работеu   Канбан1)r+   rE   r   r
   Zui_view_form)Er"   ZCmfLogicTyper#   ZlogginginfoZdataclassesr   r   r   Zmain_gantt_projectCmfTaskr
   r    rE   r   ru   rg   r   r   rW   r   r^   chatCmfDocumentZdoc1ZdocsZ
docs__doc2rD   rR   __dict__valuesrK   rI   rJ   rL   ZepicsZepics__epic1ZsprintsZsprints__sprint1ZreleasesZreleases__release1ZroadmapsZ
CmfRoadmapZroadmaps__roadmap1Z
docs__doc1ZCmfKanbanBoardZkanban_boardZmeetingsr$   r{   r1   ZCmfTaskFilterZfilters__filter1Zfilters__filter2ZreportsrH   rG   rP   rM   rO   rN   ZCmfTaskReportr   choicesZreports__report1ZtodoZtodo__list1Zin_workZin_work__kanban1)r   Zlt_pfeedZlt_epicZ	lt_sprintZ
lt_releaseZlt_baser   tZgantt_projectro   r   itemr   r   r   scaffold  s@   

              
 
 zCmfProject.scaffoldc                 C   sZ   t jjdd| jgdd| jggdr8td| j ddd	 |  rVtd
| j ddd	 d S )NrE   rT   r$   !=r   u   Проект с именем uA    уже существует. Укажите другое имя.Tabortu-   Раздел на диске с именем uF    уже занят. Укажите другое имя проекта.)r"   r   ZslistrE   r$   	cmf_alertr   r   r   r   r   _check_project_dir_conflict|  s    "z&CmfProject._check_project_dir_conflictc                 C   sF   ddd|gg}|r"| dd|g | j|drBt| j ddd d S )	Nr/   rE   r   r   r   u7    с таким именем уже существуетTr   )r7   r#   r   Zverbose_name)r(   rE   r   Z
prj_filterr   r   r   _check_unique  s
    zCmfProject._check_uniquec                    s$   |  || t j|||d|S )N)rE   r   )r   r   r   )r(   rE   r   rX   r<   r   r   r   r     s    zCmfProject.createc              
   C   sD  ddddddddd	d
g
}ddg}|D ]}d| }| j | jr$|D ]|}tt| jdd| jgdd|ggd}|s|dkrtt| jdd| jgdddggd}|rB| j | j |_|jdd qBtj	jdd| jgddd| ggd}|r$| j | j |_|jdd q$| j
jr@tjjdd| jgd}| j
j |_|jdd d S )NtasksZapprovedr   r   r   r   r   r   r   r   rg   r   rY   	parent_idr   rS   r   r{   Tr   r   zlist.r0   rT   )r   r   r6   r"   r#   r$   r8   rR   ru   rW   rL   r^   )r   Z	sys_typesZnode_modelsrS   Z	fieldnameZ	nodeclassZsysnoder   r   r   _calc_hidden_nodes  sH    

zCmfProject._calc_hidden_nodesc                    s   t   dddddddg S )NZdefault_list_workflowZdefault_epic_workflowZdefault_subproject_workflowZdefault_release_workflowZdefault_sprint_workflowZdefault_document_workflowZdefault_task_workflow)r   r'   r   r   r   r   r'     s    zCmfProject.save_preload_fieldsc                 C   sN   | j js| jjrtd | jdkr(d| _| jdkr:d| _n| jdkrJd| _d S )Nu<   Нельзя менять родителя у проектаr   zCmfWiki:Classr   zCmfProject:Class)r    r   r+   r   r   r   r0   r   r   r   r   _calc_parent  s    


zCmfProject._calc_parentc                 C   s(   | j jsd S tj| j j| jj| _ d S r	   )r   r   r"   r   Zconfluence_convertr8   r$   r   r   r   r   
_calc_text  s    zCmfProject._calc_textc                 C   s   |    d S r	   )Z_check_simple_permr   r   r   r   check_simple_perm  s    zCmfProject.check_simple_permc           
         s`  | j r~tjjdd| jgdd| jggd}|rDtd| j ddd	 n:|  r~| | 	 }|j
r~|d
| j dt d d}| jjr| jstd |   | jjr| | jjr| | 	| jj}|| 	  | j r| js| j| _d}| j s|   |   t j||}|r"|   tjjddddggdgd}|D ]}	d|	_|	jdd qB|S )NrE   r   r$   r   r   u   Проект u    уже существуетTr   r   _z%Y-%m-%d-%H%M%SFu<   Имя проекта не может быть пустым.onboarding_statuszNOT INclosedcancelr,   r   )r   r"   r   r#   rE   r$   r   r   r   r   r   renamer   r   r   r   oldr   r   r   r   ru   r   Z
CmfLicenserV   r   )
r   rX   r<   r   Zproject_dir_rfileZshould_be_scaffoldedZ	old_rfileresultZonboardingsZ
onboardingr   r   r   ru     s>    "zCmfProject.savec                 C   s   t t|dd }|j|dgd}|o:t t|dd }|oN|j|dgd}|r\|jjp^d}|ovt t|dd }	|	o|	j|dgd}
|
r|
jjpd}|  |r|r|t|| d  |_n|r|d |_n|r|d |_|jdd d S )	Nrf   r   rD   )r$   r-   r   i  Tr   )	r[   r"   ri   r#   rD   r8   Zcheck_owner_permsintru   )r(   Zitem_idZ	anchor_idZnext_idZ
item_modelr   Zanchor_modelZanchorZanchor_ordernoZ
next_modelZ	next_itemZnext_ordernor   r   r   	move_item  s     
zCmfProject.move_itemc                 C   s   d S r	   r   r   r   r   r   
_calc_code  s    zCmfProject._calc_codec                 C   s   d S r	   r   r   r   r   r   get_code_prefix  s    zCmfProject.get_code_prefixT)	recursivec                   sD   | j j}t j|d|i|}| |r@tj|}|r@|  |S )Nr   )	rE   r8   r   deleter   r"   r   r#   Zmove_to_trash)r   r   rX   r<   Zcur_namer   r   r   r   r   r     s    
zCmfProject.deletec                 C   sT   t jtjd}|tdd7 }tjjdd| jgdd|gdd	d
gddd ggdgd}|S )Nr   r   )Zhoursr   r   plan_start_date<Zcache_status_typer   ZCLOSED
alarm_dater   r,   )	r   r   r   r   r   r"   r   rV   r$   )r   r   r   r   r   r   _list_tasks_need_to_start)  s    
z$CmfProject._list_tasks_need_to_startc              	   C   s`   | j r
d S |  }|sd S td| jjj  tjj| jj	d| d| j d| j j
 ddd d S )Nu&   Отправляем карточку u   Рекомендацияu   
            В проекте u(   есть задачи с планом, но без будильника.
            Назначьте будильник, или список с планом,
            чтобы задачи появились у исполнителя в ленте.
            (сброшен флаг "z")
            r   )Z	person_idrE   r=   msgpriority)auto_alarm_dater   printrF   rE   r8   r"   Z	CmfNotifyZplace_notifyr$   Zcaption)r   r   r   r   r   '_notify_project_owner_not_planned_tasks:  s"    z2CmfProject._notify_project_owner_not_planned_tasksc                 C   s:   t jjddD ]&}| }|D ]}|j|_|  qqd S )NT)r   )r"   r   rV   r   r   r   ru   )r(   r   r   r   r   r   r   _cron_auto_alarm_dateR  s
    z CmfProject._cron_auto_alarm_datec                 C   s    | j dgdD ]}|  qd S )Nz**r.   )rV   r   )r(   r   r   r   r   &notify_project_owner_not_planned_tasks[  s    z1CmfProject.notify_project_owner_not_planned_tasks)	task_tagsc           
      C   s  |sdS dd |D }t jj| jdd}t jj| jdd}|rB|sFdS dd t jj|jdD }t jjd	d
gdd| jgdddggdD ]}|jj|kr||jj}|j	
 r
||j	jj}|st j| ||j	jd }|||j	jj< |j|jkr&|j|_|  q|j|jkr|j|_|  q| D ]\}	}|j	rt|  d| d|j	  ||j	jj}|st j| ||j	jd }|||j	jj< t j|d|j d| |d}|  n8t|  d|  t j|d|j d| |d}|  q0dS )u   
        Вызывается если у задачи проекта изменяются тэги.
        Если появился тэг, для которого нет фильтра - создадим его.
        TODO
        Nc                 S   s   i | ]}|j j|qS r   )r$   r8   )rm   tagr   r   r   
<dictcomp>i  s      z5CmfProject.hook_task_tags_changed.<locals>.<dictcomp>r{   )r   rS   ra   c                 S   s   i | ]}|j j|qS r   )rE   r8   )rm   rk   r   r   r   r   n  s    r3   filter_tag_idr0   r   r   rS   r   )r-   r   )r    r+   rE   z: Create new filter for z with category r   )r+   rE   rS   r}   r   )r"   rg   r#   r$   rV   r   r   r8   rU   Ztag_categoryr!   rE   ru   r0   rt   r%   debug)
r   r   Ztask_tags_id_dictZtasks_filterZtags_folderZcategory_foldersZ	ae_filterr   Zcategory_folderZtag_idr   r   r   hook_task_tags_changed`  sv    
  


  
 
  
 
   z!CmfProject.hook_task_tags_changedr   c                 C   s   d S r	   r   )r   r   r   r   r   hook_task_save  s    zCmfProject.hook_task_savec                 C   s   d S r	   r   )r(   r   r   r   r   hook_new_tag  s    zCmfProject.hook_new_tagc                 C   s   dS )NTr   r   r   r   r   has_tree_nodes_hook  s    zCmfProject.has_tree_nodes_hookc                 O   s   d S r	   r   )r(   rX   r<   r   r   r   public_list  s    zCmfProject.public_listr   )	recursion)returnc             	      sf   t  }| dddddddg | jr8|t |   n|| j| jh t j|d|i||S )	Nzfollowers.personzfollowers.notify_volumezfollowers.follow_childrenr+   notify_all_personsrF   cmf_owner_assistantr   )	setr&   r   unionZall_relation_personsrF   r   r   get_all_followers)r   r   rX   r<   r   r   r   r   r     s       zCmfProject.get_all_followers)NN)r   N)N)N)N)NN)-__name__
__module____qualname__r   r   classmethodr)   rB   rC   r;   rl   r   r   staticmethodr   r   r   r   r   r   r   r   r   r'   r   r   r   ru   r   r   r   r   r   r   r   r   rV   r   r   r   r   r   r   r   __classcell__r   r   r   r   r   
   sj   [ :& '


 +
(
*



=

r   c                   C   s
   t j S r	   )r"   r   r   r   r   r   r   rc     rd   rc   c                   C   s
   t j S r	   )r"   r   r   r   r   r   r   rc     rd   )r   r   r   r   Zcalendarr   Zcmf.includeZ"modules.project.fields.cmf_projectmodulesr   r-   Zcmf_projectr   ZAPPZHOOK_CRON_DAILYr7   r   r   r   r   <module>   s          7