U
    Nh                     @   s  d Z ddlmZmZmZ ddlmZ ddlmZ ddlZddlm	Z	m
Z
mZmZ ddlmZ eejZdadag Zej d	Zd
d ZeedddZdd Zdd Zedd ZeeeedddZee	jee dddZ!ee	j"e dddZ#edd Z$e	j%d d!d"Z&dYd$d%Z'dZe	j(d'd(d)Z)d[e	j(d'd*d+Z*ed\e	j(d'd,d-Z+d]ee	j(e	j,ed.d/d0Z-d1d2 Z.d^e	j(pe	j%d3d4d5Z/d_e	j(pe	j%ed6d7d8Z0d`ee	j(e	j1ed9d:d;Z2daee	j(e	j1ed9d<d=Z3e	j(e	j4ed>d?d@Z5ee	j6e	j4pde	j(e	j7pddAdBdCZ8e	j9e dDdEdFZ:eeedGdHdIZ;dJdK Z<edLdM Z=eeee	j>dNdOdPZ?eeee	j>dNdQdRZ@eeeAdSdTdUZBeeee	j>e	jCe	j6dVdWdXZDdS )bu7  
Изначальная постановка:
    1. Найти по email CmfPerson
    2. Создать проект P
    3. Создать внутри проекта P список L
    4. Создать внутри списка L задачу T
    5. Выставить задаче T kanban-статус S

projects:
 project:
  folder: # входящие - сразу канбан, в работе — папка с канбанами.
   kanban:
    status:
     task:
      comment1

Почему YAML, а не тупо восстановление дампа:
- нужно назначить в нужных местах правильного Person, созданного при assign
- восстановление дампа отвалится с первым же рефакторингом схемы.
    )datetime	timedeltatimezone)Path)randomN)modelsgconfigAPP)set_current_person   z/custom/greetings_doc_id.txtc                    s    fdd}|S )u   
    Декоратор для логирования вызова функции и её аргументов
    :param func: функция для вызова
    c               	      sB   t dt  d  d|  d| d td7 a | |}td8 a|S )u   
        Косим под bash -x, если захочется — можно где-то тут реализовывать вложенность:
        ++ create
        +++ create_project
        ++++ create_folders
        + (z, )r   )printTRACE_OFFSET)argskwargsresfunc ./cmf/demo_data.pywrapper.   s
    $
ztrace.<locals>.wrapperr   )r   r   r   r   r   trace(   s    r   )emailc           !   	   C   s  ddl m}m} ddlm} |  |  tjj	dd| gt
jd}|sXtd|  d t| tjj	d	dd
gd}|dk	r||_|jdd tjj	dd|jgd}|stj|d  ttj d}t| }W 5 Q R X |	dt }	|	D ]}
t|
|	|
  q|	dt }|D ]}
t|
||
 d q|	dt  D ].\}}|d  D ]\}}t||| qXqD|	dt  D ]\}}t|| q|	dt  D ]L\}}tj|d}|  |	drt| |	dst !|jj" q|	dt  D ]\}}t#|| q|	d D ]:\}}t$|||}tj%|d d d}|  |d 	dd st !|jj" tj&|d! d |d! d" |||d# }|d! 	dd st !|jj" |	dt  D ]8\}}tj'j(|jj"d$}|D ]}|j)d *| qq|	d%g D ]F}tj+j	|	d&d}tj,j	d	d|	d'd(gd}t-||d|| q$q2t.  ttj/d)} | 0t1t  W 5 Q R X dS )*uK   
    Точка входа
    :param email: учётка админа
    r   )	CMF_CACHEcmf_pycharm_debug)REDIS_SETTINGS_MANAGERZlogin==filterfieldsu%   Не найден CmfPerson с login=uH   , вероятно init_demo_data запустили ДО acrm_assign.shnamezdefault.companyr"   NTZ	only_data	person_id)personz/cmf/contrib/demo_data.jsonu   ПроектыZWikisectionu   Чатыcommentsu   Продуктыu   Воронкиr$   is_favoritedemo_dont_delu   Клиентыu   Пользователиu#   Штатное расписание   ИмяFu   Должностьu   Ставка)r$   Zratecompanyr(   job)Z
contact_id   Задачиproject_namestatus w+)2cmf.includer   r   cmf.appr   Z
init_redisZflushdbr   	CmfPersongetr
   Zcurrent_person_fieldsAssertionErrorr   
CmfCompanyr/   saveCmfPersonVaridopenr	   PROJECT_DIRjsonloadsreaddict_create_projectitems_create_topic_create_productCmfPipeline_add_object_to_favoritesDEMO_IDS_LISTappendvalue_create_company_create_userCmfJobCmfRoleCmfChatGroupZp2p_chattopicssend_message
CmfProject	CmfStatus_create_taskcleanupZDEMO_IDS_FILEwritedumps)!r   r   r   r   adminmain_companyZ
person_varfddataZprojectsr2   ZwikichatZ	chat_datatopicr*   productcostpipeline_nameoptionspipeliner/   Zcompany_dataZ	user_nameZ	user_datar(   r0   Zrolecommenttaskprojectr3   fr   r   r   create>   s|    
 
  
rj   c                 C   s@   t jjddtjjgdgd}|s(td|j|  |	  d S )Nr'   r    	favoritesr!   uS   У администратора ещё не созданы предпочтения)
r   r=   r9   r   current_personr>   r:   rk   rL   r<   )Zobject_Zperson_varsr   r   r   rJ      s    rJ   c                 C   s0   d| j jkr,d| j jdd | j _|   d S )Nu   (Демо) r4   )r$   rM   replacer<   )objr   r   r   demo_fix_name   s    ro   c                 C   sF   t j|d  |dkr| }nt|d ||}t j|||d  d S )Nr+   u   Менеджерr.   )r$   r/   r(   )r   rP   r<   _create_contactrQ   )r[   r0   Zjob_datar\   r(   r   r   r   _create_worker   s
    rq   )r$   
topic_name
topic_dictc                 C   s|   |d | }t jjddgdD ]X}|d dd |jD kr| |_|jdd	 |d
dsft|j	j
 t|||  qxqdS )u   
    Находит нужный чат и пишет в первую его тему список сообщений
    :param name: имя по которому ищем группу чатов
    r*   rS   zexecutors.name)r#   	executorsc                 S   s   g | ]
}|j qS r   r+   ).0executorr   r   r   
<listcomp>   s     z!_create_topic.<locals>.<listcomp>Tr&   r-   FN)r   rR   listrt   r$   r<   r9   rK   rL   r>   rM   __add_or_create_topic)r$   rr   rs   r*   r_   r   r   r   rG      s    rG   )r_   rr   r*   c                 C   sp   |dkr | j d }|sbtdnBtj }|s6tdtj|| |gd }| j   |sbtdt|| |S )Nu   Чат группыr   zsomehow not foundu;   Не нашлось группы пользователей)r$   grouprt   zcreate failed)	rS   r:   r   CmfPersonGroupZ
user_groupCmfChatTopicr<   load_add_comments)r_   rr   r*   r`   Zusersr   r   r   ry      s    



ry   )r`   r*   c                 C   s.   |D ]$}|  |}tjtj|| d  qd S )N)r(   messageZ
chat_topic)rT   r   ZCmfChatTopicUnreadMessager   rl   r<   )r`   r*   rf   Z
message_idr   r   r   r~      s    
r~   c                  C   sN   t j  t jjddD ]} | jdd qt jjddD ]}|jdd q8d S )Nu   Канбан1r+   T)	recursiveu   Документ1)r   Z	CmfNotifyZclose_open_notifiesCmfListrx   deleteCmfDocument)kanbandocr   r   r   rX      s
    
rX   )r   c              
   C   s>  dd l }ddlm} ||d}|jdddddd}|D ]n}|d}|r:t|j d	| d
*}tj	| |d}	|	
|  |	  W 5 Q R X |	jj|d< |	j|d< q:|jddddddd}
|
D ]j}|d}|rt|j d	| d
0}tj	| d| d}	|	
|  |	  W 5 Q R X |	jj|d< qt|}|S )Nr   r	   html.parserZimgT)data-attach-iddata-idsrcZattrsr   z/cmf/contrib/demo_data/rbparentr$   r   div)data-drawio-titlezdata-drawio-typer   r   r   u   Диаграмма: )bs4r6   r	   BeautifulSoupfind_allr9   r?   r@   r   CmfAttachmentupload_filerC   r<   r>   rM   urlstr)r   Z	html_textr   r	   soupZimagesZimageZ	image_srcimg_pathnew_attachmentZdrawio_schemesZdrawioZdrawio_fileZdrawio_pathZmodified_htmlr   r   r   _create_document_attachments   s0    

r   rh   c              	   K   s  | dd}| dd}| dd}| d}| d|}| dd}| d	d}	| d
d}
tjj f | |||d|}|s*tjf | |||||
d|}| d}tjj |dd}|r||_|  |	rd|_|  |r*ttj	 | }|
 }W 5 Q R X |j}t|||_|  |  |r8t| | dd}|sXt|jj t||d | | dd}|rt||d | | dd}|rt||d | |S )u   
    :param name: название проекта
    :param folders: список папок с задачами и канбанами внутри
    
is_defaultFr,   logic_prefixzproject.basetask_code_prefixproject_typehomepageshow_roadmapdescriptionN)r$   r   r   r   )r$   r   r   r   r   r   z:defaultTcodeZcache_inmemoryr-   folderstasksgantt)r9   r   rU   CmfLogicType
logic_typer<   r   r?   r	   r@   rC   Zdescr_documentr   
text_draft
do_publishrJ   rK   rL   r>   rM   _create_folders_create_tasks_create_gantt_relation)r$   Zproject_dictr   r   r   r,   r   r   r   r   r   rh   Zlogic_type_coder   r]   textr   r-   r   r   r   r   r   rE      sh    
    
rE   F)rh   c           
      C   s   |  D ]z\}}tjj|d}|s0td| |D ]L}tjj|dd}tjj|dd}|r4|r4tj|||d}	|	  q4qd S )Nr   u)   Отсутствует тип связи Zin_task_namer+   Zout_task_name)in_linkout_linkrelation_type)rF   r   ZCmfRelationTyper9   r:   CmfTaskZCmfRelationOptionr<   )
rh   r   r-   Zrelation_codeZ	relationsr   Zrelationr   r   Zrelation_optionr   r   r   r   ,  s    r   c           "   	      s   fdd}ddl m   tj}| D ]\}}tjjdd|gd}|sTtd| |D ]}|d	d }	|d
d }
|dd }|dd }|dd }|dd }|dd }|dd }|dd }|dd }tjj|	| d}tj	j|
| d}tjj|| d}tj
jd| | d}tjj|| d}tjj|d}tj
|d|d| d}|rh|j| |rz|j| |r||_|r|j| |r|j| |r||_||_||_||_| }t|jj |j}|r|||_|r|||_|  t|jj |rX| D ]\}}tjjdd|gd}|sTtd| |D ]}|dd }|dd }|dd }tj
| ||d} |  }!t|!jj |!j}|r|||_|r|||_|  t|jj qXq&qXq&d S )Nc                    s     | dS )Nz%Y-%m-%d)strptime)Zdtr   r   r   to_date_time=  s    z#_create_tasks.<locals>.to_date_timer   r   r$   r    r%   #   Не нашлось статуса sprint	componentreleaseepicregistry_listr   sched_start_datesched_finish_datepriority
child_task)r$   rh   zEpic r   titler   )r$   r   r   )r   parent_taskr$   )r   r   rl   rF   r   rV   r9   r:   r   CmfComponentr   r   listsrL   Zfix_versionsr   
componentsr   r   r3   responsibler<   rK   r>   rM   op_gantt_taskr   r   )"rh   r   r-   r   r   status_name_tasksr3   rg   Ztask_sprintZtask_componentZtask_releaseZ	task_epicZtask_registry_listZtask_logic_typeZtask_sched_start_dateZtask_sched_finish_dateZtask_priorityZtask_child_tasksr   r   r   r   r   r   Z_taskr   Z_child_tasksZ_child_taskZ_child_task_titleZ_child_task_sched_start_dateZ_child_task_sched_finish_dater   Zch_tskr   r   r   r   <  s    




r   c                 C   sD  |  D ]4\}}|dkr,| }t||| q|dkrttjjdd| jgdddggd}|sftd|  t||| q|dkrtjjdd| jgdd|ggd}|stj|| | d		 }|  D ]\}}t
|| ||| qq|d
krtjjdd| jgdd|ggd}	|	stj|| | d		 }	|  D ]\}
}t|
| |	|| q"qdS )u   
    :param project: ID проекта
    :param folders: список папок с задачами и канбанами внутри
    Zdocsu   Документыtree_parent_idr    r$   r%   uB   Не нашлась папка sys_type == docs у проекта )r1   ZBacklogSprintsEpicsReleases   КомпонентыRoadmapsr$   rh   tree_parentu   СпискиN)rF   _create_documentsr   r   r9   r>   r:   _create_documents_new	CmfFolderr<   _create_kanban_newCmfRegistry_create_registry_list)rh   r   r-   r$   r^   r   folderZkanban_namekanban_settingsregistryregistry_nameregistry_settingsr   r   r   r     s,      r   )r$   rh   r   r   c           
   	   C   s   d }ddl m} |dd}|rFt|j | }| }	W 5 Q R X tj| |||	d}|  |d|}|s~t	
|jj |S )Nr   r   fileF)r$   r   r   r   r-   )r6   r	   r9   r?   r@   rC   r   r   r<   rK   rL   r>   rM   )
r$   rh   r   r   r-   r   r	   filenamer]   r   r   r   r   r     s"       r   c                 C   s   dd l }ddlm} ||jjd}|jdddddd}|D ]B}|d}|r>|| jkr>| j	j|d	< t
||_|  |  q>d S )
Nr   r   r   r   T)zdata-macrosdata-param-page-labeldata-param-pageidr   r   r   )r   r6   r	   r   r   rM   r   r9   r$   r>   r   r<   r   )r   r   r   r	   r   ZmacrosesZmacrosZdocument_namer   r   r   _create_document_include  s    

r   )r   c              
   C   s  ddl m} d }| D ]\}}|d }|dd }|dd}	|dd}
|dd}|d	d }|d
d}|d|}t|j | F}| }|ds|dr|d krddlm	} | }|
|}W 5 Q R X tjjdd| jgdd|ggd}|stj|| |d}|r||_|
r.t||  t|||_|rTtjjdd}||_|  |  |rttd}||jj W 5 Q R X |	rt||	| |st|jj qd S )Nr   r   r   orderno
child_docsFinclude_parentfull_screenworkflowgreetings_docr-   mdmarkdownMarkdownr   r    r$   r%   )r$   r   r   zdocument.approve:defaultr   r5   )r6   r	   rF   r9   r?   r@   rC   endswithr   r   convertr   r   r>   r   r   r   r   ZCmfWorkflowr   r<   r   GREETINGS_DOC_ID_PATHrY   rM   r   rK   rL   )r   r   r-   r	   r   r   Z	documentsr   r   r   r   r   r   r   r]   r   r   Zwfri   r   r   r   r     sL     
r   )r   r   c                 C   s  ddl m} d }| D ]\}}|d|}t|j dt }| }tds^tdr|d krxddl	m
} | }||}tjjdd	| jgd
d	|ggd}	|	stj||| d}	|	  |	  |drttd}
|
|	jj W 5 Q R X |st|	jj W 5 Q R X qd S )Nr   r   r-   /r   r   r   r   r    r$   r%   )r$   r   r   r   r5   )r6   r	   rF   r9   r?   r@   r   rC   r   r   r   r   r   r   r>   r<   r   r   rY   rM   rK   rL   )r   r   r-   r	   r   r   Zsettingsr]   r   r   ri   r   r   r   r     s*    
 
r   )r$   rh   r   r   c              	   C   s  d }|j }|dkr|dd}|dd }|dd}	|sB|j}ntjj|d}|dkrdd	lm}
 |d
d}|rt|
j | }|	 }W 5 Q R X |r|}tj
| ||d||d}|	rt|_|jtdd |_|  |	r|  n|dkrtj| ||d}|  n`|dkr2tj| ||d}|  n<|dkrn|dd}tj||| |tjjddd}|  |r|dd}|d|}|st|jj |rt| |S )N)r   r   r   Fr   launchedr   r   r   r   r   r   )r$   rh   r   	list_typer   r      Zdaysr   r   r   r   ztask.epic:default)r   r   r$   r   r   r,   r-   )r$   r9   r   r   r   r6   r	   r?   r@   rC   r   TODAYZplan_start_dater   Zplan_end_dater<   Zdo_startr   Z
CmfRoadmapr   rK   rL   r>   rM   rJ   )r$   rh   r   r   r-   Zstructure_objectZfolder_namer   r   r   r	   r   r]   r   r,   r   r   r   r   "  s~         





    r   c                 C   s   t j| ||dd}|jdkr6t jjddd}|r6||_|  |dd}|d	|}|sht|j	j
 |rtt| d
|krt|||d
  |S )Nr   )r$   rh   r   r   zproject.agilezlist.agile_sprint:defaultTr   r,   Fr-   r   )r   r   r   r   r9   r   r<   rK   rL   r>   rM   rJ   _add_tasks_to_kanban)r$   rh   r   r   r-   r   r   r,   r   r   r   _create_kanbann  s    
r   )rh   r   r   c                 C   s~   |dk	st dt|ts*t dt| | D ]F\}}tjjdd|gd}|s^t d| |D ]}t|||| d qbq2dS )u   
    :param project: проект к которому привязана задача
    :param kanban: список задач (CmfList), в который надо добавить
    :param tasks: список задач (в dict/list)
    Nu;   Почему-то нет объекта для спискаuR   Неожиданные задачи в виде списка без статусаr$   r    r%   r   )	r:   
isinstancerD   r   rF   r   rV   r9   rW   )rh   r   r   r   r   r3   rg   r   r   r   r     s    r   )rg   r3   r   rh   r   c              
   C   sz  t | tstdt|  | dd}| dd}| dg }| dg }t}	tdk rptd7 a|	tt d }	n|	td	d }	|st	j
}tj||	|||d
}
d}|D ]`}ttj| }t|d>}tj|
|jd}||  |  |d|j d }W 5 Q R X q|| |
_t |tj|
_|
jr4|
j| n||
_|
  d|
_|
  |r`t|
| |
  t|
jj  dS )u   
    :param task: заголовок задачи
    :param status: статус задачи в CRM
    :param kanban: объект списка в который это надо добавить (или None для входящих)
    :param project: объект проекта
    u@   Передан task не являющийся словарем: r   r4   contentr*   picturesr   r      )r   
alarm_dater$   rh   r3   r   r   z<p><img src="z"/></p>FN)!r   rD   r:   r   r9   r   MY_TASK_COUNTr   r   r   rl   r   r   r   r	   r@   r?   r   r$   r   rC   r<   r   r   r   Zapprovedr   rL   r   _create_commentsrK   r>   rM   )rg   r3   r   rh   r   r   r   r*   r   r   Ztask_objZcontent_imgr   Zimg_path_objZimg_readr   r   r   r   rW     sN        

rW   )rg   r*   c                 C   s   | d k	st dt|trR| D ],\}}|dks@t d| || _|   q"nt|tsjt d| |D ]}|dkrntj|| d  qnd S )Nu:   Передана несуществующая задачаZdescu,   Не поддерживаемое поле: uL   Комментарии не являются списком, странно )r   r   )	r:   r   rD   rF   r   r<   rx   r   Z
CmfComment)rg   r*   keyrM   r   r   r   r   r     s    
r   )r$   r^   c                 C   s   t j| |ddd }t|jj |dt 	 D ]\}}t
||| q:|dt 	 D ]\}}t jj|d}|std| |	 D ]\\}}	t jj|j|dgd	}
|
std
|d t j||d}
|
  t|
 t||	||
j qqbdS )u   
    :param name: Название компании
    :param data: Сделки, Контакты и прочее пока не знаю как организованное
    u   Типr/   )r$   typeu   Контактыu   Сделкиr+   u   Не нашли воронку r3   )Zwork_list_idr$   r#   u    Не нашёлся статусu3   создадим, он нам очень нужен)Z	work_listr$   N)r   r;   r9   r<   rK   rL   r>   rM   rD   rF   rp   rI   r:   ZCmfStatusOptr   _init_auto_assign_create_dealsr3   )r$   r^   r/   contactZcontact_datarc   Zstatusesre   r   dealsoptr   r   r   rN     s    rN   c                 C   s   t d tdtjjdd| jgd}|r8t d| d S tj| jddd	d
dddddtjjtjjdtjjitjjdgdgdd| jiig dd}t d| |	  t d| d S )NuM   Для первичного контакта создаём триггер...u_   Требуется доработка готу Антон DEL cache_status_opt_id use status.idZcache_status_opt_idr    r%   u*   Триггер вроде уже есть:CmfDealZdistribution_personu=   Сменить ответственного по сделкеr<   )captionrM   u   Сменить наr   Zmodel_m2m_choicer>   )r>   r$   rn   Zverbose_item_name)r  Z	fieldNameZ	modelNamer   rM   Zchanged_fieldscache_status_optu   При попадании на данный этап воронки автоматически будет меняться отвественный у сделки.)r  Z	cmf_modelZ	func_nameZjson_actionZ	json_dataZjson_entry_pointZjson_filterr   u   Объект в памятиu   Объект после .save())
r   	Exceptionr   Z
CmfTriggerr9   r>   r   rl   r$   r<   )r  Zauto_assignr   r   r   r    sJ    
   
r  c                 C   s&   |  D ]\}}t||| || qd S N)rF   _create_deal)r/   r  re   r3   dealZ	deal_datar   r   r   r  "  s    r  )r$   r^   r/   c                 C   s8   || | dd}tjf |}|  t|jj |S )u  
    Наверное contact_data можно сразу кидать как **kwargs + company=cmp, name=name, но лень
    :param name: имя, либо имя-фамилия (по пробелу раздробится и пропишется в нужные поля)
    :param data: набор данных, пока dict из Почта: email@example.com
    :param company: компания, к которой принадлежит человек
    
   Почта)r/   r$   r   )r9   r   r8   r<   rK   rL   r>   rM   r$   r^   r/   r   r(   r   r   r   rp   (  s
    rp   c                 C   sN   || | dtj gd}tjf |}|  | ddsJt|jj	 |S )Nr  )r/   r$   r   Zrg_member_ofr-   F)
r9   r   r{   Zguest_groupr8   r<   rK   rL   r>   rM   r  r   r   r   rO   7  s      
rO   r$   rb   c                 C   s(   t j| |d}|  t|jj d S )Nr  )r   Z
CmfProductr<   rK   rL   r>   rM   )r$   rb   ra   r   r   r   rH   D  s    rH   )r$   r^   r/   re   r3   c           	      C   s   t jj|d d}|s.td|d  d|  |d sDtd|  tdd |d  D \}}t j| |||||gd	}|  t	|j
j d
S )u  
    :param pipeline: воронка продаж, в которой окажется сделка
    :param name: название сделки
    :param data: {
        Контакт: Василий Рыбин,
        Продукт: {
            Пельмени с говядиной: 400
        }
    }
    :param company: компания с которой проводится сделка
    u   Контактr+   u#   Не нашёлся контакт u    для сделки u   Продуктu5   Не указан продукт для сделки c                 s   s   | ]\}}||fV  qd S r
  r   )ru   kvr   r   r   	<genexpr>\  s     z_create_deal.<locals>.<genexpr>)r$   r/   totalre   r3   ZcontactsN)r   r8   r9   r:   nextrF   r  r<   rK   rL   r>   rM   )	r$   r^   r/   re   r3   r  ra   r  r  r   r   r   r  K  s    r  )rh   )F)F)F)F)F)F)F)F)E__doc__r   r   r   pathlibr   r   rA   r6   r   r   r	   r
   r7   r   ZnowZutcr   r   r   rK   r@   r   r   r   rj   rJ   ro   rq   rD   rG   rR   rx   ry   r|   r~   rX   r   r   rE   rU   r   r   r   r   r   r   r   r   r   r   r   r   r   rV   r8   rW   r   r   rN   r  r  r;   rp   rO   intrH   rI   r  r   r   r   r   <module>   s   K
	
	 
8[$    *    M    

:,
    