U
    [SewN                     @   s>   d dl mZ d dlT ddlmZ d dlZG dd dejZdS )    )fields)*   )cmf_approveNc                       s   e Zd ZdZedd Zedd Zed!d	d
Zedd Zedd Z	edd Z
dd Zdd Zdd Zd"ddZedd Zdd Z fddZedd  Z  ZS )#
CmfApproveu   
        Модель для утверждения объектов в системе.
        Утверждает объекта его конкретную cmf_version
    c                 C   s   g }t jjdd}|D ]d}|jdkr|jr|j|krt jj|j|jd|jj d|d|jj	 d|jj dd |
|j qd S )	Ntask.doc_need_approve)codepersonu(   Необходимо утвердить u   Утвердите: <a href="z">z</a>)Zresponsibleparentnamelogic_prefix
logic_typetext)modelsZCmfLogicTypegetapprove_typeapproverCmfTaskZcreateobjr   Zhrefappend)clsapprovesZexisting_approversr   approve r   (./modules/settings/models/cmf_approve.py_create_tasks   s    
zCmfApprove._create_tasksc                 C   s8   t jj|ddgd}|D ]}|jd|_|  qd S )Nr   workflow)r
   r   r   ZCLOSED)r   r   listr   Zget_default_statusstatussave)r   r   ZtasksZtaskr   r   r   _delete_tasks$   s    zCmfApprove._delete_tasksr	   Nstandartc           
   	   C   s   dd|gdd|gdd|gdd|gdd|gdd|gdd|gg}t jj|d	}	|	sft j|||||||d
}	d|	_d |	_d|	_|	  |	S )Nr   z==r   obj_version
obj_statusapprove_groupr   approver_level)filter)r   r   r"   r#   r$   r   r%   open )r   r   r   r   
resolutionr   r   )
r   r   r   r"   r#   r%   r   r$   r&   r   r   r   r   _create_or_update_approve/   s(    
   z$CmfApprove._create_or_update_approvec           
      C   s  | ddddddddd	g	 g }| jd
|||jd}|jjD ]\}t|tjrf| jd|||jd|d}n(|j D ]}| jd|||jd|d}qp|	| q<|jj
D ]}| jd|||j|d}|jdkr|j}|sd}t|D ]&}	| jd|||jd|d}|	| q|d|jj|D ]*}| jd|||j|d|d}|	| q|d|jj|D ]*}| jd|||j|d|d}|	| qVqt|tjs| | t|drdd |D D ]}|j	| q|jdd d S )Nr
   root_parentzstatus.master_approverszstatus.approve_groupsz#status.approve_groups.min_approverszstatus.approve_groups.approversz&status.approve_groups.master_approversz*status.approve_groups.approvers.rg_membersz1status.approve_groups.master_approvers.rg_membersfull)r   r   r"   r#   r	   grand_master)r   r   r"   r#   r%   r   r$   )r   r   r"   r#   r$   custom   r!   )r   r   r"   r#   r%   r$   	approvers)r   r   r"   r#   r$   r%   r   master_approversmasterapprovers_forc                 S   s"   g | ]}|j d kr|jr|jqS )r	   )r   r   ).0r   r   r   r   
<listcomp>   s     
  z/CmfApprove._create_approves.<locals>.<listcomp>T)Z	only_data)load_fieldsr*   r   r1   
isinstancer   	CmfPersonZdefault_membersloadr   approve_groupsrequired_signsmin_approversrangeZget_all_approversr+   valuer   r   hasattrr3   r   )
r   r   r"   created_approvesr   r   r	   app_grZmin_apprir   r   r   _create_approvesK   s      	
zCmfApprove._create_approvesc                 O   s   | j ||f|| d S N)rC   )r   r   r"   argskwargsr   r   r   start_approve_process   s    z CmfApprove.start_approve_processc                 O   s   |  | d S rD   )r    )r   r   rE   rF   r   r   r   cancel_approve_process   s    z!CmfApprove.cancel_approve_processc                 C   s    t jj| j| jddgd}|jS )Nr,   r)   r   r"   r   r   )r   r   r   r   r"   r)   )selfZaggregr   r   r   approve_aggreg_result   s    z CmfApprove.approve_aggreg_resultc                 C   s8   |    |  }|dkr"| j  |dkr4| j  dS )u   
        Рассчитывает агрегаты и, если надо, двигает статусы объекта по БП
        approvedrejectedN)approve_calc_aggreg_resultrK   r   Z_approve_approvedZ_approve_rejected)rJ   Z
app_resultr   r   r   _calc_status   s    
zCmfApprove._calc_statusc           
   
   C   s0  |  ddg | j}|j ddddddd	d
g |jjs<dS tjj| j| jdddddgd}tjj| j| jdd}dd |D }dd |D D ]}|j	|_	|
  qd}|jjD ]^}tjj| j| jd|d}| ||}	|	|_	|	dkrd}|
  |	dkrd|_	|
   dS q|rd|_	nd|_	|
  dS )u  
        Вычисляет статус результата утверждения всего объекта исходя из аппрувов и заполняет аппрувы-агрегаты
        :result: строка approved/rejected/in_approve
        TODO Есть возможность немного оптимизировать запихав все в один запрос, а так же не перезаполняя аггрегаты если они не менялись
        Пока что ТЗ постоянно меняется так что оставляю более читаемый вариант
        r   
obj.statusr0   need_approver1   r:   zapprove_groups.approverszapprove_groups.master_approverszapprove_groups.min_approverszapprove_groups.required_signsNr	   r%   r)   r$   r   rI   r,   )r   r"   r   c                 S   s.   g | ]&}|j d kr|jdk	r|jdkr|qS )r-   Nr,   )r%   r)   r   r4   ar   r   r   r5      s
     
 
 
 z9CmfApprove.approve_calc_aggreg_result.<locals>.<listcomp>c                 S   s$   g | ]}|j d ks|j dkr|qS )rM   rL   r)   rR   r   r   r   r5      s     
 
 T)r   r"   r   r$   rL   FrM   
in_approve)r6   r   r   rQ   r   r   r   r"   r   r)   r   r:   get_approve_group_status)
rJ   r   r   Zaggreg_fullZfull_master_approver   Zall_approvedr$   Zaggreg_groupZapprove_group_statusr   r   r   rN      s>       
z%CmfApprove.approve_calc_aggreg_resultc              
   K   sf   |  ddddddddg | js4| jjd	kr4tj| _d
| _tj | _	|| _
|| _|   |   | S )u  
        Аппрувит текущего пользователя
        :params:
        approve_group - Аппрув группа, которой принадлежит аппрув. Один чел может аппрувить за разные группы.
        text - Комментарий пользователя при утверждении/отклонении
        r   rP   zobj.workflowzobj.approve_groupr%   r"   r   zapprove_group.required_signsr.   closed)r6   r   r$   r;   gZcurrent_userr   datetimeZnowZapproved_atr)   r   r   rO   )rJ   r)   r   rF   r   r   r   _approve_one   s    zCmfApprove._approve_onec                    s    fdd|D }dd |D D ]}|j   S  fdd|D rDdS  fdd|D } jjdkr jdkrrd	}q jd
krt j}n j}t||krdS dS dS )u<  
        Получает статус аппрув-группы, исходя из списка собранных подписей
        :param app_gr:   Аппрувгруппа
        :param approves: Все подписи объекта:
        :rtype: str
        :return:
            approved - Утверждено (Все необходимые подписи собраны)
            rejected - Отклонено
            in_approve- В процессе утверждения
            None - Утверждение не требуется
        c                    s$   g | ]}|j d kr|j kr|qS )r2   )r%   r$   rR   rA   r   r   r5     s     
 
 z7CmfApprove.get_approve_group_status.<locals>.<listcomp>c                 S   s.   g | ]&}|j d ks&|j dks&|j dkr|qS )rM   acceptedrL   rT   rR   r   r   r   r5     s
     
 
 
 c                    s$   g | ]}|j  kr|jd kr|qS )rM   )r$   r)   rR   r[   r   r   r5      s     
 
 rM   c                    s0   g | ](}|j  kr|jd ks&|jdkr|jqS )r\   rL   )r$   r)   r   rR   r[   r   r   r5   #  s
     
 
 
 Nr.   r/   ZfixedrL   rU   )r)   r<   r>   r;   lenr0   )r   rA   r   Zmaster_approvesr   Zapproved_approversr<   r   r[   r   rV     s     


z#CmfApprove.get_approve_group_statusc                 C   sf   |  dddg | jdkrd S | js(d S | js:| jjs:d S d| jj }tjj	| j| j|||d d S )Nr   r   r   r	   u&   Требуется утвердить )r   r	   r   msgr   )
r6   r   r   Zis_newZ
is_changedr   r   r   Z	CmfNotifyZplace_notify)rJ   messager   r   r   _place_notify6  s    
zCmfApprove._place_notifyc                    s   |    t j||S rD   )r`   superr   )rJ   rE   rF   	__class__r   r   r   S  s    zCmfApprove.savec           
      K   s  t jj|d}|dg ||}t jj|d}g }|dd }|dkrt jj|d}t jf d||j	|j
d||dd	|d

|}	|	  ||	 nb|dkrt jj|d}|j D ]@}t jf d||j	|j
d||dd	|d

|}	|	  ||	 qt|t js| | dS )u  
        Добавляет либо один аппрув, если пришла персона, либо аппрувы всех членов группы персон или еще там какого орг.юнита
        :param obj_id: Объект, который аппрувим:
        :param approver_id: Персона или группа персон\подразделение итп:
        :param approve_group_id:   Аппрувгруппа
        )idr   :r   r8   r	   r'   Nr!   )
r   r   r"   r#   r   r   r
   r)   r%   r$   CmfPersonGroup)r   ZCmfDocumentr   r6   Zget_in_approveZCmfApproveGroupsplitr8   r   Zdoc_versionr   r   r   rf   Z
rg_membersZ
all_nestedr7   r   r   )
r   r   r   r$   r"   rF   Zdoc_histr@   Zappr_prefixr   r   r   r   add_approverY  sV    


zCmfApprove.add_approver)r	   NNNr!   NN)N)__name__
__module____qualname____doc__classmethodr   r    r*   rC   rG   rH   rK   rO   rN   rZ   rV   r`   r   rh   __classcell__r   r   rb   r   r      s<   



       
]

/

(r   )Zcmfr   Zcmf.includer   rY   r   r   r   r   r   <module>   s   