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dSd
dZedT fdd	Zed	d	d	d	dddZ	edUddZ
dd ZdVddZedd Zdd ZdWddZedd	d fdd 
Zd!d" Zd#d$ Zed%d& ZedX 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)  Z*S )Y
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jdk r*d }|jj r|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sV|jjrV|jrV|jd
 j |_|jsrtjjrrtjj|_|jr||  d S )Ni  cmf_owner_id==project_typeprojectfiltersection	executorsINr   )is_newZlists
is_changedparentZresponsibleZcmf_created_atZageZdefault_projectloadmodelsr   getidgZcurrent_personZ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r/   )	Exceptiondictvarsr"   r#   appendr$   valuer*   r!   _get_node_models
class_name_get_tree_dataZ_create_tree)r'   Z	obj_modelZ
obj_filterr0   r/   kwargsobjr    Z
parents_idZparent_filtermodel
model_namemodel_filter	tree_datar   r   r   get_obj_treep   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.   r/   r   r$   r0   )r3   r4   r8   r9   r#   r   get_tree_leaf)	r'   r/   r   r0   r;   Zparent_filtr=   r>   r?   r   r   r   rB      s      

zCmfProject.get_tree_leaf)r,   r0   r   r1   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_assistant_idZ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+   )	r3   r#   popr"   r   listr5   CmfListZtree_fields)r'   r,   r0   r   r1   argsr;   Zproject_filterZproject_fieldsr@   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 )NrR   show_TrK   )
r   
tree_nodesr7   r,   getattrrR   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	   rD   )r^   r   r   r   <lambda>       z+CmfProject._get_tree_root.<locals>.<lambda>)key:r   rY   )r3   r#   r"   	CmfFolderr9   rR   rY   r7   sortsplitr$   hasattrr\   r   )r'   r@   r/   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*   )rY   r\   allitemssaver7   r6   )r*   
node_classnode_filter_kwargsnode_create_kwargsr^   r   ro   r   add_node_if_not_exists  s    
$
z;CmfProject.scaffold_backlog.<locals>.add_node_if_not_existsu   Задачиproject.agileZBacklogbacklog)rR   順 )rD   filter_parentrC   )r*   ru   rv   rw   r`   u   Тэгиra   Zdatesu   Даты
   )rD   rC   r   ZfalseZnot_assigned)filter_responsible_setrR   u   #НеНазначено)rD   r|   Ztz   )monthdayhourminutesecondZmicrosecondc                    s   g | ]} j |d qS ))r   )replacerl   rp   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   ^  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_maxrR   #Zno_alarm_date)r~   Zfilter_plan_start_date_setZfilter_alarm_date_setrR   u   #БезДатыFZnot_approved)Zfilter_approvedrR   u   #Согласоватьu  В фильтр "#Согласовать" попадают все идеи, пожелания, задачи от пользователей.
Руководитель проекта обрабатывает список и переносит задачи в другие списки.
В идеале этот список должен быть обработан, то есть оставаться пустым к концу рабочего дня руководителя проекта.

примеры  списков, куда можно перенести задачи из "#Согласовать":
todo0 Срочно до мвп
todo1 В течение года
todo2 Через год
Отклонено
Версия октябрь 2021)rD   r|   text)NNNN)logic_prefixr"   rf   r4   rY   r\   CmfActiveEntityFilter
filter_tagrP   Zcache_select_countr7   r[   r   nowr   utcr   rangezipr   )r   rW   r;   rx   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/ra   r   rD   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	   )rD   r   r   existsr   r   r   r   is_project_dir_exist  s    zCmfProject.is_project_dir_existr   r0   c                   sB   t dd S t jf ||d|}|D ]}|  |  q(|S )Nr)   r   )r3   r4   r   get_full_treer   r   )r'   r   r0   rW   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 |_|  || _	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jd:| j-d;|_.t j| d<d|_/t j0|j/d=d|_1t j0|j/d>d|_2t j| d?d|_3d@|j._dA|j(_dB|j"_d|j&_d|j$_d |j_dC|j_d!|j_dD|j_dE|j_dF|j,_dG|j/_dH|j3_|j D ]}	|	  qd#| _4d#| _5d#| _6d#| _7d#| _8d#| _9d#| _d#| _d#| _ d#| _!| jd#d% t j:j;j<}
|
D ],}t j:|
| |j3||j1dI|_=|j=  q| jdJkrt j| dKdd|_>t j|j>dLd3|d/|_?t j| dMdd|_@t j|j@dNd.|d/|_At j| ddd|_t j|jdd|_+t j| d8|d9|_,t jjd:| j-d;|_.t j| d<d|_/t j0|j/d=d|_1t j0|j/d>d|_2t j| d?d|_3d@|j._dA|j>_dB|j@_d|j_d|j_d |j_d!|j_d"|j_dE|j,_dF|j/_dG|j3_|j D ]}	|	  qhd#| _4d#| _5d#| _d#| _d#| _ d#| _!| jd#d% t j:j;j<}
|
D ],}t j:|
| |j3||j1dI|_=|j=  qdS )OuU    Добавляем структуру папок в новый проект
        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	   Гант u   Дискdisk)r*   rD   rR   u
   Архивarchiveu
   Лентаu   Лента проекта pfeed)r*   rD   r   	list_typer
   u   Чат )r*   r   rD   u   Документ1)r*   rD   u   ДокументыNu   Документ2i i" iI i i  TFZ	only_datary   ZEpicsepiczEpic 1)r    r*   rD   r
   ZSprintssprintzSprint 1Zkanban)r*   rD   r   r
   ZReleasesreleaseu   Релиз 1ZclassicZRoadmapsroadmapu   Roadmap Проекта)r*   rD   systemu   Совещания)r*   rD   r
   rz   )rR   r/   u   Фильтрыu   Фильтр 1u   Фильтр 2u   Отчетыr{   i i i q i0 i@ iP4 i`[ ip )rD   r*   report_typeZreport_filterzproject.baseZTodou   Список1u   В работеu   Канбан1)Br"   ZCmfLogicTyper#   ZlogginginfoZdataclassesr   r   r   Zmain_gantt_projectCmfTaskr
   r    rD   rt   rf   r   r   rV   r   r]   chatCmfDocumentZdoc1ZdocsZ
docs__doc2rC   rQ   __dict__valuesrJ   rH   rI   rK   ZepicsZepics__epic1ZsprintsZsprints__sprint1ZreleasesZreleases__release1ZroadmapsZ
CmfRoadmapZroadmaps__roadmap1Z
docs__doc1Zmeetingsr$   rz   r0   ZCmfTaskFilterZfilters__filter1Zfilters__filter2ZreportsrG   rF   rO   rL   rN   rM   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_projectrn   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 )NrD   rS   r$   !=r   u   Проект с именем uA    уже существует. Укажите другое имя.Tabortu-   Раздел на диске с именем uF    уже занят. Укажите другое имя проекта.)r"   r   ZslistrD   r$   	cmf_alertr   r   r   r   r   _check_project_dir_conflictv  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.   rD   r   r   r   u7    с таким именем уже существуетTr   )r6   r#   r   Zverbose_name)r'   rD   r   Z
prj_filterr   r   r   _check_unique|  s
    zCmfProject._check_uniquec                    s$   |  || t j|||d|S )N)rD   r   )r   r   r   )r'   rD   r   rW   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   rf   r   rX   	parent_idr   rR   r   rz   Tr   r   zlist.r/   rS   )r   r   r5   r"   r#   r$   r7   rQ   rt   rV   rK   r]   )r   Z	sys_typesZnode_modelsrR   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   r/   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_convertr7   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 )NrD   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#   rD   r$   r   r   r   r   r   renamer   r   r   r   oldr   r   r   r   rt   r   Z
CmfLicenserU   r   )
r   rW   r;   r   Zproject_dir_rfileZshould_be_scaffoldedZ	old_rfileresultZonboardingsZ
onboardingr   r   r   rt     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 )	Nre   r   rC   )r$   r,   r   i  Tr   )	rZ   r"   rh   r#   rC   r7   Zcheck_owner_permsintrt   )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   )	rD   r7   r   deleter   r"   r   r#   Zmove_to_trash)r   r   rW   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   r   
alarm_dater   r+   )	r   r   r   r   r   r"   r   rU   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_idrD   r<   msgpriority)auto_alarm_dater   printrE   rD   r7   r"   Z	CmfNotifyZplace_notifyr$   Zcaption)r   r   r   r   r   '_notify_project_owner_not_planned_tasks4  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   rU   r   r   r   rt   )r'   r   r   r   r   r   r   _cron_auto_alarm_dateL  s
    z CmfProject._cron_auto_alarm_datec                 C   s    | j dgdD ]}|  qd S )Nz**r-   )rU   r   )r'   r   r   r   r   &notify_project_owner_not_planned_tasksU  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$   r7   )rl   tagr   r   r   
<dictcomp>c  s      z5CmfProject.hook_task_tags_changed.<locals>.<dictcomp>rz   )r   rR   r`   c                 S   s   i | ]}|j j|qS r   )rD   r7   )rl   rj   r   r   r   r   h  s    r2   filter_tag_idr/   r   r   rR   r   )r,   r   )r    r*   rD   z: Create new filter for z with category r   )r*   rD   rR   r|   r   )r"   rf   r#   r$   rU   r   r   r7   rT   Ztag_categoryr!   rD   rt   r/   rs   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_changedZ  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'   rW   r;   r   r   r   public_list  s    zCmfProject.public_list)NN)r   N)N)N)N)NN)+__name__
__module____qualname__r   r   classmethodr(   rA   rB   r:   rk   r   r   staticmethodr   r   r   r   r   r   r   r   r   r&   r   r   r   rt   r   r   r   r   r   r   r   r   rU   r   r   r   r   r   __classcell__r   r   r   r   r   
   sh   X :& '


 (
(
*



=
r   c                   C   s
   t j S r	   )r"   r   r   r   r   r   r   rb     rc   rb   c                   C   s
   t j S r	   )r"   r   r   r   r   r   r   rb     rc   )r   r   r   r   Zcalendarr   Zcmf.includeZ"modules.project.fields.cmf_projectmodulesr   r,   Zcmf_projectr   ZAPPZHOOK_CRON_DAILYr6   r   r   r   r   <module>   s          %