U
    
@hcJ                     @   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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/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   t jdrd S |jsn|jjrn|jjjdkrntj	|
 krntj	tjkrn|jsn|jjddd}|rn||_td |jr|jjjdkr|jd|_td |jjdkr|jstd	 d S )
NimportclosedZ	in_reviewF)Zraise_erroru   Спасибо! Статус установлен в "Подтверждение закрытия", для проверки постановщиком или руководителем проектаu   Спасибо! Статус изменен на «Закрыто» т.к установлен флаг «Без подтверждения».Zin_progressum   Внимание! Вы взяли задачу без согласования с руководителем.)osenvirongetZ
no_controlstatus
is_changednewZstatus_typegcurrent_personZ
get_ownersZsystem_personis_newZworkflowZget_default_status	cmf_alertapproved)clsr   Zin_review_statusr   r   r   _calc_task_status   s8    

zCmfProject._calc_task_statusc                 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   )r   Zlistsr   parentZresponsibleZcmf_created_atZageZdefault_projectloadmodelsr   r   idr   r   Zload_fieldssave_preload_fields)r"   r   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r6   ORtree_parent_idr,   r0   T)filtersfilter_projectr9   )	Exceptiondictvarsr/   r   appendr0   valuer4   r.   _get_node_models
class_name_get_tree_dataZ_create_tree)r"   Z	obj_modelZ
obj_filterr:   r9   kwargsobjr-   Z
parents_idZparent_filtermodel
model_namemodel_filter	tree_datar   r   r   get_obj_tree   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 )Nr3   r8   r9   r%   r0   r:   )r=   r>   rB   rC   r   r   get_tree_leaf)	r"   r9   r&   r:   rE   Zparent_filtrG   rH   rI   r   r   r   rL      s      

zCmfProject.get_tree_leaf)r6   r:   r&   r;   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 )!Nr3   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)   r6   Zorder_bysys_type=r5   )	r=   r   popr/   r   listr?   CmfListZtree_fields)r"   r6   r:   r&   r;   argsrE   Zproject_filterZproject_fieldsrJ   rH   rG   rI   r   r   r   rD      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 )Nr3   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 )Nr\   show_TrU   )
r   
tree_nodesrA   r6   getattrr\   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	   rN   )rh   r   r   r   <lambda>      z+CmfProject._get_tree_root.<locals>.<lambda>)key:r   rc   )r=   r   r/   	CmfFolderrC   r\   rc   rA   sortsplitr0   hasattrrf   r   )r"   rJ   r9   ri   folderrF   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>0  s     zNCmfProject.scaffold_backlog.<locals>.add_node_if_not_exists.<locals>.<genexpr>r4   )rc   rf   allitemssaverA   r@   )r4   
node_classnode_filter_kwargsnode_create_kwargsrh   r   ry   r   add_node_if_not_exists)  s    
$
z;CmfProject.scaffold_backlog.<locals>.add_node_if_not_existsu   Задачиproject.agileZBacklogbacklog)r\   順 )rN   filter_parentrM   )r4   r   r   r   rj   u   Тэгиrk   Zdatesu   Даты
   )rN   rM   r   ZfalseZnot_assigned)filter_responsible_setr\   u   #НеНазначено)rN   r   Ztz   )monthdayhourminutesecondZmicrosecondc                    s   g | ]} j |d qS ))r   )replacerv   rz   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_maxr\   #Zno_alarm_date)r   Zfilter_plan_start_date_setZfilter_alarm_date_setr\   u   #БезДатыFZnot_approved)Zfilter_approvedr\   u   #Согласоватьu  В фильтр "#Согласовать" попадают все идеи, пожелания, задачи от пользователей.
Руководитель проекта обрабатывает список и переносит задачи в другие списки.
В идеале этот список должен быть обработан, то есть оставаться пустым к концу рабочего дня руководителя проекта.

примеры  списков, куда можно перенести задачи из "#Согласовать":
todo0 Срочно до мвп
todo1 В течение года
todo2 Через год
Отклонено
Версия октябрь 2021)rN   r   text)NNNN)logic_prefixr/   rp   r>   rc   rf   CmfActiveEntityFilter
filter_tagrZ   Zcache_select_countrA   re   r   nowr   utcr   rangezipr   )r   ra   rE   r   Zfld_tasks_nameZ	fld_tasksZfld_tagsZ	fld_datesrh   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/rk   r   rN   r   r   r   project_dir  s    zCmfProject.project_dirc                 C   s   t jjj }|| S r	   )r/   Z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	   )rN   r   r   existsr   r   r   r   is_project_dir_exist  s    zCmfProject.is_project_dir_existr&   r:   c                   sB   t dd S t jf ||d|}|D ]}|  |  q(|S )Nr3   r   )r=   r>   r   get_full_treer   r   )r"   r&   r:   ra   rE   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|   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 ]}|  qjd"| _d"| _d"| _d"| _| jd!d# | jd$krt j	| d%d&d|_t j| |jd'|d(|_ t j	| d)d*d|_!t j|j!d+d,|d-|_"t j	| d.d/d|_#t j|j#d0d1|d-|_$t j	| d2d3d|_%t j&|j%d4d!d5|_'t j	| ddd|_t j|jdd|_(t j| d6|d7|_)t j	jd8| j*d9|_+t j	| d:d|_,t j-|j,d;d|_.t j-|j,d<d|_/t j	| d=d|_0d>|j+_d?|j%_d@|j_d|j#_d|j!_d|j_dA|j
_d|j_dB|j_dC|j_dD|j)_dE|j,_dF|j0_|j D ]}|  qHd!| _1d!| _2d!| _3d!| _4d!| _5d!| _6d!| _d!| _d!| _d!| _| jd!d# t j7j8j9}	|	D ],}
t j7|	|
 |j0|
|j.dG|_:|j:  q| jdHkrt j	| dIdd|_;t j|j;dJd1|d-|_<t j	| dKdd|_=t j|j=dLd,|d-|_>t j	| ddd|_t j|jdd|_(t j| d6|d7|_)t j	jd8| j*d9|_+t j	| d:d|_,t j-|j,d;d|_.t j-|j,d<d|_/t j	| d=d|_0d>|j+_d?|j;_d@|j=_d|j_d|j
_d|j_d|j_d |j_dC|j)_dD|j,_dE|j0_|j D ]}|  q(d!| _1d!| _2d!| _d!| _d!| _d!| _| jd!d# t j7j8j9}	|	D ],}
t j7|	|
 |j0|
|j.dG|_:|j:  qvdS )MuU    Добавляем структуру папок в новый проект
        zlist.pfeed:default)codeztask.epic:defaultzlist.agile_sprint:defaultzlist.release:defaultzlist.base:defaultuc   Вызываем разворачивание чтобы появилась папка задачиr   )make_dataclassZ	DataEmptyzproject.wikiu   Дискdisk)r4   rN   r\   u
   Архивarchiveu
   Лентаu   Лента проекта pfeed)r4   rN   r   	list_typer
   u   Чат )r4   r+   rN   u   Документ1)r4   rN   u   ДокументыNu   Документ2i i" iI i i  TFZ	only_datar   ZEpicsepiczEpic 1)r-   r4   rN   r
   ZSprintssprintzSprint 1Zkanban)r4   rN   r   r
   ZReleasesreleaseu   Релиз 1ZclassicZRoadmapsroadmapu   Roadmap Проекта)r4   rN   systemu   Совещания)r4   rN   r
   r   )r\   r9   u   Фильтрыu   Фильтр 1u   Фильтр 2u   Отчетыr   i i i q i0 i@ iP4 i`[ ip )rN   r4   report_typeZreport_filterzproject.baseZTodou   Список1u   В работеu   Канбан1)?r/   ZCmfLogicTyper   ZlogginginfoZdataclassesr   r   r   rp   r   r   r`   rN   r   rg   chatCmfDocumentZdoc1ZdocsZ
docs__doc2rM   r[   __dict__valuesr~   rT   rR   rS   rU   ZepicsCmfTaskZepics__epic1ZsprintsZsprints__sprint1ZreleasesZreleases__release1ZroadmapsZ
CmfRoadmapZroadmaps__roadmap1Z
docs__doc1Zmeetingsr0   r   r:   ZCmfTaskFilterZfilters__filter1Zfilters__filter2ZreportsrQ   rP   rY   rV   rX   rW   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   trx   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 )NrN   r]   r0   !=r(   u   Проект с именем uA    уже существует. Укажите другое имя.Tabortu-   Раздел на диске с именем uF    уже занят. Укажите другое имя проекта.)r/   r   ZslistrN   r0   r    r   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 )	Nr8   rN   r%   r   r(   u7    с таким именем уже существуетTr   )r@   r   r    Zverbose_name)r"   rN   r   Z
prj_filterr   r   r   _check_unique  s
    zCmfProject._check_uniquec                    s$   |  || t j|||d|S )N)rN   r   )r   r   r   )r"   rN   r   ra   rE   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tasksr!   r   r   r   r   r   r   r   r   rp   r   rb   	parent_idr%   r\   r(   r   Tr   r   zlist.r9   r]   )r   r   r?   r/   r   r0   rA   r[   r~   r`   rU   rg   )r   Z	sys_typesZnode_modelsr\   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   r1   r   r   r   r   r1     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   r4   r    r&   r   r9   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_convertrA   r0   r   r   r   r   
_calc_text  s    zCmfProject._calc_textc           
         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 )NrN   r%   r0   r   r(   u   Проект u    уже существуетTr   r   _%Y-%m-%d-%H%M%SFu<   Имя проекта не может быть пустым.onboarding_statuszNOT INr   cancelr5   r   )r   r/   r   r   rN   r0   r    r   r   r   r   renamer   r   r   r   oldr   r   r   r   r~   r   Z
CmfLicenser_   r   )
r   ra   rE   r   project_dir_rfileZshould_be_scaffoldedZ	old_rfileresultZonboardingsZ
onboardingr   r   r   r~     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 )	Nro   r   rM   )r0   r6   r   i  Tr   )	rd   r/   rr   r   rM   rA   Zcheck_owner_permsintr~   )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                   s^   | j j}t j|d|i|}| |rZ| | |}|jrZ|d| dt	
 d |S )Nr   z/.trash_r   r   )rN   rA   r   deleter   r   r   r   r   r   r   )r   r   ra   rE   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   r5   )	r   r   r   r   r   r/   r   r_   r0   )r   r   r   r   r   r   _list_tasks_need_to_start8  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_idrN   rF   msgpriority)auto_alarm_dater   printrO   rN   rA   r/   Z	CmfNotifyZplace_notifyr0   Zcaption)r   r   r   r   r   '_notify_project_owner_not_planned_tasksI  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   r_   r   r   r   r~   )r"   r'   r   r   r   r   r   _cron_auto_alarm_datea  s
    z CmfProject._cron_auto_alarm_datec                 C   s    | j dgdD ]}|  qd S )Nz**r7   )r_   r   )r"   r'   r   r   r   &notify_project_owner_not_planned_tasksj  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   )r0   rA   )rv   tagr   r   r   
<dictcomp>x  s      z5CmfProject.hook_task_tags_changed.<locals>.<dictcomp>r   )r   r\   rj   c                 S   s   i | ]}|j j|qS r   )rN   rA   )rv   rt   r   r   r   r   }  s    r<   filter_tag_idr9   r   r%   r\   r   )r6   r)   )r-   r4   rN   z: Create new filter for z with category r   )r4   rN   r\   r   r   )r/   rp   r   r0   r_   r   r   rA   r^   Ztag_categoryr.   rN   r~   r9   r}   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_changedo  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"   ra   rE   r   r   r   public_list  s    zCmfProject.public_list)NN)r'   N)N)N)N)NN)+__name__
__module____qualname__r   r   classmethodr#   r2   rK   rL   rD   ru   r   r   staticmethodr   r   r   r   r   r   r   r   r   r1   r   r   r~   r   r   r   r   r   r   r   r   r_   r   r   r   r   r   __classcell__r   r   r   r   r   
   sj   #V :& '


 
(
*


=
r   c                   C   s
   t j S r	   )r/   r   r   r   r   r   r   rl     rm   rl   c                   C   s
   t j S r	   )r/   r   r   r   r   r   r   rl     rm   )r   r   r   r   Zcalendarr   Zcmf.includeZ"modules.project.fields.cmf_projectmodulesr'   r6   Zcmf_projectr   ZAPPZHOOK_CRON_DAILYr@   r   r   r   r   <module>   s          :