U
    Eh                     @   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} |  tjjdd| gtjd}|sDt	d|  d t
| tjjddd	gd
}|dk	rz||_|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||| qDq0|dt  D ]\}}t|| qr|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spt|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qt+  ttj,d(}|-t.t W 5 Q R X dS ))uK   
    Точка входа
    :param email: учётка админа
    r   )	CMF_CACHEcmf_pycharm_debugZ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+)/cmf.includer   r   Z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   adminmain_companyZ
person_varfddataZprojectsr1   ZwikichatZ	chat_datatopicr)   productcostpipeline_nameoptionspipeliner.   Zcompany_dataZ	user_nameZ	user_datar'   r/   Zrolecommenttaskprojectr2   fr   r   r   create>   sx    
 
  
rh   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;   r7   r   current_personr<   r8   ri   rJ   r:   )Zobject_Zperson_varsr   r   r   rH      s    rH   c                 C   s0   d| j jkr,d| j jdd | j _|   d S )Nu   (Демо) r3   )r#   rK   replacer:   )objr   r   r   demo_fix_name   s    rm   c                 C   sF   t j|d  |dkr| }nt|d ||}t j|||d  d S )Nr*   u   Менеджерr-   )r#   r.   r'   )r   rN   r:   _create_contactrO   )rY   r/   Zjob_datarZ   r'   r   r   r   _create_worker   s
    ro   )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)   rQ   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   rP   listrr   r#   r:   r7   rI   rJ   r<   rK   __add_or_create_topic)r#   rp   rq   r)   r]   r   r   r   rE      s    rE   )r]   rp   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#   grouprr   zcreate failed)	rQ   r8   r   CmfPersonGroupZ
user_groupCmfChatTopicr:   load_add_comments)r]   rp   r)   r^   Zusersr   r   r   rw      s    



rw   )r^   r)   c                 C   s.   |D ]$}|  |}tjtj|| d  qd S )N)r'   messageZ
chat_topic)rR   r   ZCmfChatTopicUnreadMessager   rj   r:   )r^   r)   rd   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CmfListrv   deleteCmfDocument)kanbandocr   r   r   rV      s
    
rV   )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   Диаграмма: )bs4r5   r	   BeautifulSoupfind_allr7   r=   r>   r   CmfAttachmentupload_filerA   r:   r<   rK   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   rf   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)r7   r   rS   CmfLogicType
logic_typer:   r   r=   r	   r>   rA   Zdescr_documentr   
text_draft
do_publishrH   rI   rJ   r<   rK   _create_folders_create_tasks_create_gantt_relation)r#   Zproject_dictr   r   r   r+   r   r   r   r   r   rf   Zlogic_type_coder   r[   textr   r,   r   r   r   r   r   rC      sh    
    
rC   F)rf   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)rD   r   ZCmfRelationTyper7   r8   CmfTaskZCmfRelationOptionr:   )
rf   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#   rf   zEpic r   titler   )r#   r   r   )r   parent_taskr#   )r   r   rj   rD   r   rT   r7   r8   r   CmfComponentr   r   listsrJ   Zfix_versionsr   
componentsr   r   r2   responsibler:   rI   r<   rK   op_gantt_taskr   r   )"rf   r   r,   r   r   status_name_tasksr2   re   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   9  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 у проекта )r0   ZBacklogSprintsEpicsReleases   КомпонентыRoadmapsr#   rf   tree_parentu   СпискиN)rD   _create_documentsr   r   r7   r<   r8   _create_documents_new	CmfFolderr:   _create_kanban_newCmfRegistry_create_registry_list)rf   r   r,   r#   r\   r   folderZkanban_namekanban_settingsregistryregistry_nameregistry_settingsr   r   r   r     s,      r   )r#   rf   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,   )r5   r	   r7   r=   r>   rA   r   r   r:   rI   rJ   r<   rK   )
r#   rf   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   r5   r	   r   r   rK   r   r7   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   r4   )r5   r	   rD   r7   r=   r>   rA   endswithr   r   convertr   r   r<   r   r   r   r   ZCmfWorkflowr   r:   r   GREETINGS_DOC_ID_PATHrW   rK   r   rI   rJ   )r   r   r,   r	   r   r   Z	documentsr   r   r   r   r   r   r   r[   r   r   Zwfrg   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   r4   )r5   r	   rD   r7   r=   r>   r   rA   r   r   r   r   r   r   r<   r:   r   r   rW   rK   rI   rJ   )r   r   r,   r	   r   r   Zsettingsr[   r   r   rg   r   r   r   r     s*    
 
r   )r#   rf   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#   rf   r   	list_typer   r      Zdaysr   r   r   r   ztask.epic:default)r   r   r#   r   r   r+   r,   )r#   r7   r   r   r   r5   r	   r=   r>   rA   r   TODAYZplan_start_dater   Zplan_end_dater:   Zdo_startr   Z
CmfRoadmapr   rI   rJ   r<   rK   rH   )r#   rf   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#   rf   r   r   zproject.agilezlist.agile_sprint:defaultTr   r+   Fr,   r   )r   r   r   r   r7   r   r:   rI   rJ   r<   rK   rH   _add_tasks_to_kanban)r#   rf   r   r   r,   r   r   r+   r   r   r   _create_kanbank  s    
r   )rf   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   )	r8   
isinstancerB   r   rD   r   rT   r7   rU   )rf   r   r   r   r   r2   re   r   r   r   r     s    r   )re   r2   r   rf   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   r3   contentr)   picturesr   r      )r   
alarm_dater#   rf   r2   r   r   z<p><img src="z"/></p>FN)!r   rB   r8   r   r7   r   MY_TASK_COUNTr   r   r   rj   r   r   r   r	   r>   r=   r   r#   r   rA   r:   r   r   r   Zapprovedr   rJ   r   _create_commentsrI   r<   rK   )re   r2   r   rf   r   r   r   r)   r   r   Ztask_objZcontent_imgr   Zimg_path_objZimg_readr   r   r   r   rU     sN        

rU   )re   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   )	r8   r   rB   rD   r   r:   rv   r   Z
CmfComment)re   r)   keyrK   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   Не нашли воронку r2   )Zwork_list_idr#   r"   u    Не нашёлся статусu3   создадим, он нам очень нужен)Z	work_listr#   N)r   r9   r7   r:   rI   rJ   r<   rK   rB   rD   rn   rG   r8   ZCmfStatusOptr   _init_auto_assign_create_dealsr2   )r#   r\   r.   contactZcontact_datara   Zstatusesrc   r   dealsoptr   r   r   rL     s    rL   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:   )captionrK   u   Сменить наr   Zmodel_m2m_choicer<   )r<   r#   rl   Zverbose_item_name)r  Z	fieldNameZ	modelNamer   rK   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
CmfTriggerr7   r<   r   rj   r#   r:   )r  Zauto_assignr   r   r   r     sJ    
   
r   c                 C   s&   |  D ]\}}t||| || qd S N)rD   _create_deal)r.   r  rc   r2   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   )r7   r   r6   r:   rI   rJ   r<   rK   r#   r\   r.   r   r'   r   r   r   rn   %  s
    rn   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)
r7   r   ry   Zguest_groupr6   r:   rI   rJ   r<   rK   r  r   r   r   rM   4  s      
rM   r#   r`   c                 C   s(   t j| |d}|  t|jj d S )Nr  )r   Z
CmfProductr:   rI   rJ   r<   rK   )r#   r`   r_   r   r   r   rF   A  s    rF   )r#   r\   r.   rc   r2   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   )rs   kvr   r   r   	<genexpr>Y  s     z_create_deal.<locals>.<genexpr>)r#   r.   totalrc   r2   ZcontactsN)r   r6   r7   r8   nextrD   r  r:   rI   rJ   r<   rK   )	r#   r\   r.   rc   r2   r  r_   r  r
  r   r   r   r	  H  s    r	  )rf   )F)F)F)F)F)F)F)F)E__doc__r   r   r   pathlibr   r   r?   r5   r   r   r	   r
   Zcmf.appr   ZnowZutcr   r   r   rI   r>   r   r   r   rh   rH   rm   ro   rB   rE   rP   rv   rw   rz   r|   rV   r   r   rC   rS   r   r   r   r   r   r   r   r   r   r   r   r   r   rT   r6   rU   r   r   rL   r   r   r9   rn   rM   intrF   rG   r	  r   r   r   r   <module>   s   H
	
	 
8[$    *    M    

:,
    