
    n^jZ                     .   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	m
Z
mZ ddlmZmZ ddlmZmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZmZ ddlm Z  ddl!m"Z" ddl#m$Z$m%Z% ddl&m'Z' ddl(m)Z)m*Z* ddl+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZH d ZId2dZJd ZKd ZLd ZMd ZNe)d        ZOe) e*d      d               ZPe)d        ZQe)d         ZRe)d!        ZSd" ZTe)ed#               ZUe)ed$               ZVe)ed%               ZWe)ed&               ZXe)ed'               ZYe)d(        ZZe)d)        Z[e)d*        Z\e) e*d+      d,               Z]e) e*d-      d3d/              Z^e) e*d0      d3d1              Z_y.)4u  
expense/views.py
================
Function-based views for expense request submission, approval actions,
dashboard, and AJAX helpers.

NOTE: ``horilla.decorators`` (NOT ``horilla_views.cbv_methods``) must be
used here — the latter expects a CBV ``self`` first-argument.
    )datetime)messages)Group)transaction)CountQSum)HttpResponseJsonResponse)get_object_or_404redirectrender)render_to_string)reverse)timezone)gettext_lazy)require_http_methodsrequire_POST)notify)
Department)
BudgetItemBudgetSubHead)Employee)login_requiredpermission_required   )ApproveFormExpenseApprovalStageFormExpenseApprovalWorkflowFormExpenseDocumentFormSetExpenseRequestFormKIVForm
RejectFormResubmitForm)ACTION_APPROVEDACTION_CLOSEDACTION_DISBURSED
ACTION_KIVACTION_RECALLEDACTION_REJECTEDACTION_RESUBMITTEDACTION_SUBMITTEDSTATUS_APPROVEDSTATUS_CLOSEDSTATUS_DISBURSED
STATUS_KIVSTATUS_PENDINGSTATUS_REJECTEDSTATUS_RESUBMITTEDExpenseApprovalLogExpenseApprovalStageExpenseApprovalWorkflowExpenseRequest	KIVRecordc                 N    	 | j                   j                  S # t        $ r Y y w xY wN)useremployee_get	Exception)requests    1/var/www/python-projects/worksol/expense/views.py_get_employeer@   G   s)    ||((( s    	$$c                 L    t         j                  j                  | ||||       y )Nexpensestageactionactorcomment)r4   objectscreaterB   s        r?   _logrJ   N   s*    %% &     c           	          |sy|j                   j                  j                         D ]H  }t        j                  | j
                  j                  ||| j                   d| j                          J y)z;Send in-app notification to all members of the stage group.Nz: 	recipientverbdescription)	groupuser_setallr   sendemployeeemployee_user_idreference_numbertitle)rC   rD   rO   r;   s       r?   _notify_stagerY   X   sd    $$((* 
--"334Bw}}oF		

rK   c                     t        j                  | j                  j                  | j                  j                  || j                         y )NrM   )r   rT   rU   rV   rW   )rC   rO   s     r?   _notify_requesterr[   e   s8    
KK))""33,,	rK   c                     | j                         }|syddlm}  |d      | j                  z   |_        |j                  dg       y)z<Add expense amount to budget committed bucket on submission.Nr   )Fcommitted_amount)update_fields)get_current_allocationdjango.db.modelsr]   amountr^   save)rC   allocr]   s      r?   _add_to_budgetre   n   sB    **,E"12W^^CE	JJ01J2rK   c                      t        d      S )zCStandard HTMX response to close the open modal and reload the page.z<script>$('#genericModal').removeClass('oh-modal--show');$('#deleteConfirmation').removeClass('oh-modal--show');$('.reload-record').click();$('#reloadMessagesButton').click();location.reload();</script>)r
    rK   r?   _close_modal_reloadrh   x   s    	 rK   c           
      z   t        |       }|r2t        j                  j                  |      j	                  d      d d nt        j                  j                         }t        | j                  j                  j                  dd            }t        j                  j                  t        t        g|      j                  dd	d
      j	                  d      }t        j                  j                  t        dt        j                         j!                         |      j#                         }|rTt        j                  j                  |      j%                  t'        dt)        t        t        t        g                  nddi}||||j+                         |j+                         |d   d}t-        | d|      S )NrU   -submitted_at
   idTflat
status__incurrent_stage__group_id__inrU   budget_itemcurrent_stage)status kiv_records__recalled_at__isnullkiv_records__revisit_date__lterr   )rq   )filter)
my_pendingry   r   )my_requestsapproval_queuekiv_duepending_count	kiv_country   zexpense/dashboard.html)r@   r7   rH   rx   order_bynonelistr;   groupsvalues_listr1   r3   select_relatedr0   r   nowdatedistinct	aggregater   r   countr   )r>   rU   rz   user_group_idsr{   r|   	my_countscontexts           r?   expense_dashboardr      s   W%H  	%%x%8AA/RSVTVW##((*  ',,--99$T9JKN 	%%&(:;(6 	& 	
 

M?	C	/	"  	%%-1+3<<>+>+>+@(6	 	& 	
 
 $  	%%x%8	Q>;Mz*Z[ 
 

 A  #('--/]]_-G '3W==rK   zexpense.add_expenserequestc                    t        |       }|s*t        j                  | t        d             t	        d      S t        j                         }|s*t        j                  | t        d             t	        d      S |j                  j                  d      j                  d      j                         }|s*t        j                  | t        d             t	        d      S t        | j                  xs d |      }t        | j                  xs d | j                  xs d       }| j                  d	k(  r|j!                         r|j!                         rt#        j$                         5  |j'                  d
      }||_        ||_        ||_        t.        |_        	 |j2                  j4                  |_        |j9                         }|rg|j;                  |j<                        \  }}	|s/t        j                  | |	       t?        | d||d      cd d d        S |	rt        j@                  | |	       |j'                          tC        |       ||_"        |D ]e  }
|
jF                  s|
jF                  jI                  d      s,|
j'                  d
      }||_%        | jL                  |_'        |j'                          g tQ        ||tR        | jL                         tU        ||d|jV                          d d d        t        jX                  | t        d      djV                  iz         t	        d      S t?        | d||d      S # t6        $ r Y w xY w# 1 sw Y   bxY w)Nz7Your user account is not linked to an employee profile.zexpense-dashboardzCNo active approval workflow configured. Contact your administrator.T	is_activeorderz+The approval workflow has no active stages.rj   POSTF)commitzexpense/request_form.html)formdoc_formsetfilez,New expense request requires your approval: z/Expense request %(ref)s submitted successfully.refzexpense-my-requests)-r@   r   error_r   r6   get_defaultstagesrx   r   firstr!   r   r    FILESmethodis_validr   atomicrc   rU   workflowrt   r1   ru   employee_work_info
departmentr=   r`   check_overrunrb   r   warningre   instancecleaned_datagetrC   r;   uploaded_byrJ   r,   rY   rW   success)r>   rU   r   first_stager   r   rC   rd   allowedreasondoc_formdocs               r?   submit_expense_requestr      s    W%Hw"[ \]+,,&224HST	
 +,,//((4(8AA'JPPRKw"O PQ+,,gll2dXFD()=w}}?TPTUK~~DMMO8L8L8N! 1	iiui-G'G'G$/G!+GN%-%@%@%K%K"
 224E"'"5"5gnn"ENN7F3!3!%kB'1	 1	0 $$Wf5LLN 7# $+K ' ((X-B-B-F-Fv-N"--u-5C")CK&-llCOHHJ +'7F >w?W?W>XY[1	f 	?@E7KcKcCdd	
 -..#k2 _  1	 1	sE   &3MM5AMAM"M>A2M	M
MMMMc                     t        |       }t        j                  j                  |      j	                  ddd      j                  d      }t        | dd|i      S )Nrj   budget_item__sub_head__headrt   r   rk   zexpense/my_requests.htmlrequests)r@   r7   rH   rx   r   r   r   )r>   rU   qss      r?   my_expense_requestsr   #  sX    W%H%%x%8	5
	S	/	" 
 '5
B7GHHrK   c           
      P   t        t        |      }t        |       }t        | j                  j
                  j                  dd            }t        |j                  xr |j                  j                  |v       }t        |xr |j                  |k(        }|s?|s=| j                  j                  s'| j                  j                  d      st        d      S |j                  j                  dd	      j!                  d
      }|j"                  j%                         }|j&                  j)                  d      j+                         }	||||	|||xr |j,                  t.        t0        fv |j,                  t2        k(  xr |j5                  | j                        d}
t7        | d|
      S )Npkrm   Trn   zexpense.view_expenserequest  ru   rD   rF   
created_atrecalled_at__isnull)rC   logsdocskivis_approveris_ownercan_act
can_recallzexpense/request_detail.html)r   r7   r@   r   r;   r   r   boolrt   group_idrU   is_superuserhas_permr
   approval_logsr   r   	documentsrS   kiv_recordsrx   r   ru   r1   r3   r0   can_recall_kivr   )r>   r   rC   rU   r   r   r   r   r   r   r   s              r?   expense_request_detailr   3  sx   26GW%H',,--99$T9JKNR'"7"7"@"@N"RK H=!1!1X!=>H 	<<$$<<  !>?3''  //AJJ<XD  "D



$
$
$
>
D
D
FC " CNN~/ABBnn
2 1""7<<0G '8'BBrK   c                    t        t        |      }t        |       }t        | j                  j
                  j                  dd            }t        |j                  xr |j                  j                  |v       }t        |xr |j                  |k(        }ddddd	d
}||vrt        d      S |dv r&|r|j                  t        t        fv st        d      S |dk(  r|r|j                         st        d      S |dk(  r'|j!                  | j                        st        d      S |t#               t%               t'               t)               d}	t+        | ||   |	      S )zGRender the requested action modal (approve/reject/kiv/resubmit/recall).r   rm   Trn   z#expense/partials/approve_modal.html"expense/partials/reject_modal.htmlexpense/partials/kiv_modal.htmlz$expense/partials/resubmit_modal.htmlz"expense/partials/recall_modal.html)approverejectr   resubmitrecalli  r   )r   r   r   r   r   r   )rC   approve_formreject_formkiv_formresubmit_form)r   r7   r@   r   r;   r   r   r   rt   r   rU   r
   ru   r1   r3   can_resubmitr   r   r#   r"   r$   r   )
r>   r   rE   rC   rU   r   r   r   template_mapr   s
             r?   action_modalr   ^  sT     26GW%H',,--99$T9JKNR'"7"7"@"@N"RK H=!1!1X!=>H 960:6L \!3'' -->;M*NN3''X'2F2F2H3'''"8"8"F3'' #!|I%G '</99rK   c           	          |j                  | j                        s'dt        dt        t	        d            z   dz   d      fS y)z/Return (True, None) or (False, error_response).Fz'<div class='oh-alert oh-alert--danger'>z2You do not have permission to act on this request.z</div>r   r   )TN)is_approvable_byr;   r
   strr   )r>   rC   s     r?   _check_approverr     sQ    ##GLL1l5!HIJK 	
 
 	
 rK   c           	         t        t        |      }t        | |      \  }}|s|S t        | j                        }|j                         st        d      S |j                  j                  dd      }|j                  }t        j                         5  t        ||t        | j                  |       |j                         }|rX||_	        |j                   du r|j                   rt"        |_        |j'                          t)        ||d|j*                   d       n|j                   r)t,        |_        t        ||t.        | j                  |       nt"        |_        d |_	        |j'                          t1        |d	|j*                   d
|j3                          d       d d d        t5        j6                  | t9        d             t;               S # 1 sw Y   2xY w)Nr   i  r   rG    FzExpense z requires your action.Your expense request z
 has been .zRequest approved and forwarded.)r   r7   r   r   r   r   r
   r   r   rt   r   r   rJ   r%   r;   get_next_stageis_disbursement_stager-   ru   rc   rY   rW   r/   r'   r[   get_status_displayr   r   r   rh   )	r>   r   rC   okerrr   rG   rD   
next_stages	            r?   approve_expenser     s     26Ggw/GB
w||$D==?3''##Ir2G!!E				 We_gllGD))+
$.G!**e3
8X8X!0LLN73344JK **!1We%5w||WM!0$(G!LLN'(@(@'AGLfLfLhKiijk3< Wa ABC  ? s   D
GGc           	         t        t        |      }t        | |      \  }}|s|S t        | j                        }|j                         st        | d||d      S |j                  d   }t        j                         5  |j                  dk\  r3t        |_        t        ||j                  t        | j                   |       n2t"        |_        t        ||j                  t$        | j                   |       d |_        |j'                          t)        |d|j*                   d|j-                          d       d d d        t/        j0                  | t3        d	             t5               S # 1 sw Y   2xY w)
Nr   r   r   rC   r   r   r   z was r   zRequest rejected.)r   r7   r   r#   r   r   r   r   r   r   resubmit_countr.   ru   rJ   rt   r&   r;   r2   r*   rc   r[   rW   r   r   r   r   rh   )r>   r   rC   r   r   r   r   s          r?   reject_expenser     s?     26Ggw/GB
gll#D==?0g.
 	
 x(F				 
!!Q&*GN'//fU,GN'//',,PVW $#G$<$<#=U7C]C]C_B``ab	

 Wa 345  !
 
s   =B7E%%E.c           	         t        t        |      }t        | |      \  }}|s|S t        | j                        }|j                         st        | d||d      S t        j                         5  t        j                  j                  ||j                  | j                  |j                  d   |j                  d   |j                         t         |_        |j#                          t%        ||j                  t&        | j                  |j                  d          t)        |d|j*                   d|j                  d    d	       d d d        t-        j.                  | t1        d
             t3               S # 1 sw Y   2xY w)Nr   r   r   r   revisit_date)rC   rD   set_byr   r   status_before_kivr   z has been kept in view until r   zRequest placed on KIV.)r   r7   r   r"   r   r   r   r   r   r8   rH   rI   rt   r;   r   ru   r0   rc   rJ   r(   r[   rW   r   infor   rh   )r>   r   rC   r   r   r   s         r?   kiv_expenser     s_     26Ggw/GB
7<< D==?-g.
 	
 
			 
  ''<<$$X.**>:%nn 	! 	
 $!!LLh'	
 	#G$<$<#==Z[_[l[lm{[|Z}}~	
%
. MM'1567  1
 
s   .CE66E?c                    t        t        |      }|j                  | j                        st	        dd      S |j
                  j                  d      j                         }|s)t        j                  | t        d             t               S t        j                         5  t        j                         |_        | j                  |_        |j%                          |j&                  |_        |j%                          t+        ||j,                  t.        | j                         t1        ||j,                  d|j2                   d	       d d d        t        j4                  | t        d
             t               S # 1 sw Y   2xY w)Nr   	Forbiddenr   r   Tr   zNo active KIV record found.zKIV recalled: z is pending your action again.z&KIV recalled. Request is active again.)r   r7   r   r;   r
   r   rx   r   r   r   r   rh   r   r   r   r   recalled_atrecalled_byrc   r   ru   rJ   rt   r)   rY   rW   r   )r>   r   rC   r   s       r?   
recall_kivr     s*     26G!!',,/K44



$
$
$
>
D
D
FCw"? @A"$$				 
",,.!,,
..Wg++_gllK!!W5566TU	

 Wa HIJ  
 
s   #B'E;;Fc                    t        t        |      }t        |       }|r|j                  |k(  st	        dd      S |j                         s)t        j                  | t        d             t               S t        | j                        }|j                         s)t        j                  | t        d             t               S |j                  j                  j                  d      j!                  d	      j#                         }|s)t        j                  | t        d
             t               S t%        j&                         5  |xj(                  dz  c_        ||_        t,        |_        |j1                          t3        ||t4        | j6                  |j8                  j;                  dd             t=        ||d|j>                   d       d d d        t        j@                  | t        d             t               S # 1 sw Y   2xY w)Nr   r   r   r   z#This request cannot be resubmitted.zInvalid form.Tr   r   zWorkflow has no active stages.r   noter   zResubmitted expense z requires your review.z!Request resubmitted successfully.)!r   r7   r@   rU   r
   r   r   r   r   rh   r$   r   r   r   r   rx   r   r   r   r   r   rt   r3   ru   rc   rJ   r+   r;   r   r   rY   rW   r   )r>   r   rC   rU   r   r   s         r?   resubmit_expenser   8  s     26GW%H))X5K44!w"G HI"$$%D==?w/ 23"$$""))0040@II'RXXZKw"B CD"$$				 
!# ++LL!!&"-	
 	"7#;#;"<<RS	

$ Wa CDE  '
 
s   B
G??Hc                    t        | j                  j                  j                  dd            }t        j
                  j                  t        t        g|      j                  dddd      j                  d	      }t        | d
d|i      S )Nrm   Trn   rp   rU   r   rt   r   rk   zexpense/approval_queue.htmlqueue)r   r;   r   r   r7   rH   rx   r1   r3   r   r   r   )r>   r   r   s      r?   r{   r{   j  s    ',,--99$T9JKN%%&(:;(6 	& 	
 
5

 
/	" 
 '87E:JKKrK   c                     | j                   j                  d      }|st        d      S t        j                  j                  |d      j                  d      }ddj                  d |D              z   }t        |      S )Nbudget_head#<option value=''>---------</option>T)head_idr   namer   c              3   V   K   | ]!  }d |j                    d|j                   d # yw)<option value='z'>	</option>N)r   r  ).0ss     r?   	<genexpr>z!ajax_sub_heads.<locals>.<genexpr>  s,      ;89/!$$r!&&3;s   '))GETr   r
   r   rH   rx   r   join)r>   r  subshtmls       r?   ajax_sub_headsr    sy    kkoom,GABB  ''4'HQQRXYD0277 ;=A; 4 D rK   c                     | j                   j                  d      }|st        d      S t        j                  j                  |d      j                  d      }ddj                  d |D              z   }t        |      S )Nbudget_sub_headr  T)sub_head_idr   r  r   c              3   p   K   | ].  }d |j                    d|j                   d|j                   d 0 yw)r  z'>[z] r  N)r   coder  )r  is     r?   r	  z$ajax_budget_items.<locals>.<genexpr>  s6      ;CD/!$$s166("QVVHI>;s   46)r
  r   r
   r   rH   rx   r   r  )r>   sub_iditemsr  s       r?   ajax_budget_itemsr    sz    [[__./FABB%%&D%IRRSYZE0277 ;HM; 4 D rK   z#expense.add_expenseapprovalworkflowc                 |    t         j                  j                  d      j                  d      }t	        | dd|i      S )Nstages__groupr  zexpense/workflow_config.html	workflows)r6   rH   prefetch_relatedr   r   )r>   r  s     r?   workflow_configr    s?     (//@@QZZI '9K;STTrK   z&expense.change_expenseapprovalworkflowNc                 6   |rt        t        |      nd }t        | j                  xs d |      }| j                  dk(  rI|j                         r9|j                          t        j                  | t        d             t               S t        | d||d u d      S )Nr   )r   r   zWorkflow saved.z#expense/partials/workflow_form.html)r   	is_create)r   r6   r   r   r   r   rc   r   r   r   rh   r   )r>   r   r   r   s       r?   workflow_formr    s     EG !8R@DH&w||';thOD~~DMMO		!$5"67"$$-H$45 rK   z#expense.change_expenseapprovalstagec                 `   t        t        |      }|rt        t        |      nd }t        | j                  xs d |d|i      }| j
                  dk(  rI|j                         r9|j                          t        j                  | t        d             t               S t        | d|||d u d      S )Nr   r   )r   initialr   zStage saved.z expense/partials/stage_form.html)r   r   r  )r   r6   r5   r   r   r   r   rc   r   r   r   rh   r   )r>   workflow_pkr   r   r   r   s         r?   
stage_formr#    s     !!8[IHAC !5"=H#x*h9OD ~~DMMO		!N"34"$$*8(d:JK rK   )r   r:   )`__doc__r   django.contribr   django.contrib.auth.modelsr   	django.dbr   ra   r   r   r	   django.httpr
   r   django.shortcutsr   r   r   django.template.loaderr   django.urlsr   django.utilsr   django.utils.translationr   r   django.views.decorators.httpr   r   notifications.signalsr   base.modelsr   budget.modelsr   r   employee.modelsr   horilla.decoratorsr   r   formsr   r   r   r    r!   r"   r#   r$   modelsr%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r@   rJ   rY   r[   re   rh   r   r   r   r   r   r   r   r   r   r   r   r{   r  r  r  r  r#  rg   rK   r?   <module>r6     sG    # , ! * * 2 @ @ 3  ! 6 K ( " 3 $ B	 	 	     :

3
$ 2> 2>t 12T 3 Tx I I "C "CT &: &:\	 ,!  ,!^  !   !F &!  &!R !  !8 (!  (!` L L(      :;U < U => ?  :; < rK   