o
    'h&w                     @   sH  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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! d dl"Z"d dl#Z#d dl$m%Z%m&Z&m'Z'm(Z(m)Z) e#*e+Z,G dd dee	Z-edd Z.edd Z/edd Z0edd Z1edd Z2edd  Z3ed!d" Z4ed#d$ Z5eed%gd&d' Z6eed%gd(d) Z7eed%gd*d+ Z8eed%gd,d- Z9eed%gd.d/ Z:eed%gd0d1 Z;eed%gd2d3 Z<eed%gd4d5 Z=ed6d7 Z>ed8d9 Z?ed:d; Z@dS )<    )renderget_object_or_404redirect)login_required)LoginRequiredMixin)ListView)JsonResponseHttpResponse)csrf_exempt)require_http_methods)messages)	Paginator)QSum)modelstimezone   )PaymentUnreconciledPaymentCustomer)InvoiceN)has_financial_accessEmployeeRequiredMixinCustomerRequiredMixinhas_permissionget_user_permissionsc                       s4   e Zd ZeZdZdZdZdd Z fddZ	  Z
S )PaymentListViewzpayments/payment_list.htmlpayments   c                 C   sz   t jddd}| jjd}|r,|t	|dt	|dB t	|dB t	|dB }| jjd	}|r;|j|d
}|S )Ncustomerinvoice-created_atsearch)payment_id__icontains)customer__first_name__icontains)customer__last_name__icontains)mpesa_receipt_number__icontainsstatusr)   )
r   objectsselect_relatedprefetch_relatedorder_byrequestGETgetfilterr   )selfquerysetsearch_querystatus_filter r7   ./var/www/html/optinet_system/payments/views.pyget_queryset#   s    zPaymentListView.get_querysetc                    sz   t  jdi |}| jjdd|d< | jjdd|d< tj|d< |  }| |d< |j	t
dd	d
 p8d|d< |S )Nr$    r5   r)   r6   status_choicestotal_paymentsamount)totalr>   r   total_amountr7   )superget_context_datar/   r0   r1   r   STATUS_CHOICESr9   count	aggregater   r   )r3   kwargscontextr4   	__class__r7   r8   rA   7   s   
z PaymentListView.get_context_data)__name__
__module____qualname__r   modeltemplate_namecontext_object_namepaginate_byr9   rA   __classcell__r7   r7   rG   r8   r      s    r   c                 C   sj   t | dst| d tdS | jdkrt| d tdS tj }t	jj
dd}||d}t| d	|S )
zCreate a new payment recordcreate_paymentz.You do not have permission to create payments.payments:payment_listPOSTzPayment created successfully.sentr*   )	customersinvoicespayments/payment_form.htmlr   r   errorr   methodsuccessr   r+   allr   r2   r   r/   rU   rV   rF   r7   r7   r8   rQ   G   s   


rQ   c                 C   sl   t | dst| d tdS | jdkrt| d tdS tj }t	jj
dd}||dd	}t| d
|S )zRecord a cash paymentrecord_cash_paymentz3You do not have permission to record cash payments.rR   rS   z#Cash payment recorded successfully.rT   r*   cash)rU   rV   payment_typerW   rX   r]   r7   r7   r8   r^   ]   s   


r^   c              
   C   sP  t | dstdddS | jdkr!zddl}|| j}|d}|d	d
 }|dd
 }|dd}|r>|r>|sFtdddW S zddlm	} |j
j|d}W n |jyg   tddd Y W S w zt|}	|	dk su|	dkr~tdddW W S W n ty   tddd Y W S w ddlm}
 |
 }|j|t|	|j|d}|ddkrddlm} |j
j|d|dd
|	||j|d tdd|dd W S |d!|d"d#}tdd$| dW S  |jy   tdd%d Y S  ty  } ztd&t|  tdd't| dW  Y d}~S d}~ww tdd(dS ))z%Initiate M-Pesa STK Push for customerinitiate_stk_pushF0You do not have permission to initiate STK push.)r[   messagerS   r   Ncustomer_idphone_numberr:   r=   descriptionzAccount Top-upz=Missing required fields: customer_id, phone_number, or amountr   idzCustomer not foundr   ip z+Amount must be between KES 1 and KES 70,000zInvalid amount format)MpesaService)re   r=   account_referencetransaction_descResponseCode0MpesaTransactionCheckoutRequestIDMerchantRequestID)checkout_request_idmerchant_request_idr=   re   rj   rk   TzQSTK Push sent successfully! Customer should receive M-Pesa prompt on their phone.)r[   rc   rr   errorMessageResponseDescriptionzUnknown errorz Failed to send STK Push. Error: zInvalid JSON datazSTK Push error: zError processing STK Push: Invalid request method)r   r   rZ   jsonloadsbodyr1   stripcustomers.modelsr   r+   DoesNotExistfloat
ValueErrorpayments.servicesri   stk_pushintrd   payments.modelsro   createJSONDecodeError	ExceptionloggerrY   str)r/   rw   datard   re   r=   rf   r   r!   amount_floatri   mpesa_serviceresponsero   error_messageer7   r7   r8   customer_stk_pusht   s   



	

r   c                 C   s>   t | dstdddS | jdkrtdddS tdddS )	zInitiate M-Pesa STK Pushra   rY   rb   r)   rc   rS   r[   zSTK Push initiatedrv   )r   r   rZ   r/   r7   r7   r8   mpesa_stk_push   s
   

r   c                 C   s&   t | dstdddS tdddS )zCheck M-Pesa account balancecheck_mpesa_balancerY   z3You do not have permission to check M-Pesa balance.r   r[   z0.00)r)   balancer   r   r   r7   r7   r8   r         
r   c                 C   s&   t | dstdddS tdg dS )zGet M-Pesa balance historyview_mpesa_balance_historyrY   z:You do not have permission to view M-Pesa balance history.r   r[   )r)   historyr   r   r7   r7   r8   get_mpesa_balance_history   r   r   c                 C   s   t | dst| d tdS tjjddd}| j	d}|r=|t
|dt
|d	B t
|d
B t
|dB t
|dB }| j	d}|rK|j|d}t|d}| j	d}||}|||tjd}t| d|S )zList unreconciled paymentsview_unreconciled_paymentsz9You do not have permission to view unreconciled payments.zdashboard:homependingr*   z-transaction_timer$   )transaction_id__icontains)phone_number__icontains)account_reference__icontainsfirst_name__icontainslast_name__icontainsr)   r    page)unreconciled_paymentsr5   r6   r;   z#payments/unreconciled_payments.html)r   r   rY   r   r   r+   r2   r.   r0   r1   r   r   get_pagerB   r   )r/   r   r5   r6   	paginatorpage_numberpage_objrF   r7   r7   r8   unreconciled_payments_list   s:   
	

r   c                 C   s   t | dst| d tdS tt|d}| jdkr4d|_| j|_	t
 |_|  t| d tdS tjt|jdt|jd	B t|jd
B }||d}t| d|S )zResolve an unreconciled paymentresolve_unreconciled_paymentz<You do not have permission to resolve unreconciled payments.z#payments:unreconciled_payments_listrg   rS   resolvedzPayment resolved successfully.re   r   r   )paymentpotential_customersz"payments/resolve_unreconciled.html)r   r   rY   r   r   r   rZ   r)   userresolved_byr   nowresolved_atsaver[   r   r+   r2   r   re   
first_name	last_namer   )r/   
payment_idr   r   rF   r7   r7   r8   r     s,   





r   rS   c                 C   sT  t | dstd tdddS zt| j}tdtj|dd  |	d	i 	d
i }|	d}|	d}|dkr|	di 	dg }i }|D ]}|	d}|	d}	|	||< qM|	dd}
|	dd}|	dd}|	d}d}zddl
m} |jj|d }|r|jrtjj|jd }|rtd|j d ntd|j  ntd|  |s.td |g}|d r|d!|d"d   |d#|  n6|d!r|d |dd   |d$|dd   n|d$r||dd  |d!|d%d   |D ]}tjj|d& }|r,td|j d'|   nqW n tyL } ztd(t|  W Y d}~nd}~ww |rz<tjj||
d)d*|||d+| d,| t d-
}dd.lm} |j||
d/| t|jdd0 td1|j d2|
  W n# ty } ztd3|j d4t|  d}W Y d}~nd}~ww |sdd5lm} zt jj|||
|| d6d7d8|d9	 td:| d;|  W n& ty } ztd<t|  W Y d}~nd}~ww ntd=|  tdd>dW S  ty) } ztd?t|  tdd@dW  Y d}~S d}~ww )AzHandle M-Pesa STK callbackprocess_mpesa_callbackz1Permission denied for M-Pesa callback processing.r   Permission Denied
ResultCode
ResultDesczM-Pesa callback received:    indentBodystkCallbackr   rp   r   CallbackMetadataItemNameValueAmountMpesaReceiptNumberr:   PhoneNumberTransactionDateNrn   )rr   rd   Found customer z from STK account referencezNo customer found with ID: z2No STK transaction found for checkout_request_id: z(Falling back to phone number matching...254rm      ++254   r   z with phone format: zError finding customer: mpesa	completedzSTK-zSTK Push payment - 
r!   r=   payment_methodr)   mpesa_receipt_numbermpesa_phone_numbermpesa_callback_datareference_numbernotescompleted_atCustomerBalanceServicezM-Pesa payment - r!   r=   rf   reference_idprocessed_byz*Payment created successfully for customer : KES z$Error creating payment for customer : r   UnknownzSTK Pushaccount_not_found)	transaction_idre   r=   rj   transaction_timer   r   reasoncallback_datazCustomer not found for phone z,, created unreconciled payment with receipt z%Error creating unreconciled payment: z!STK Push failed with result code SuccesszM-Pesa callback error: Error)!r   r   warningr   rw   rx   ry   infodumpsr1   r   ro   r+   r2   firstrj   r   rd   
startswithappendr   rY   r   r   r   r   r   customers.servicesr   add_balancer   django.utilsr   )r/   r   r   result_coderr   callback_metadatar   itemnamevaluer=   r   re   transaction_dater!   ro   mpesa_transactionphone_formatsphone_formatr   r   r   payment_errordjango_timezoneunreconciled_errorr7   r7   r8   mpesa_callback<  s   












  r   c                 C   s  t | dstd tdddS zt| j}tdtj|dd  |	d	d
}|	dd
}|	dd}|	dd
}|	dd
}|	dd
}|	dd
}|	dd
}	|	dd
}
|	dd
}|	dd
}|	dd
}|rr|std tdddW S d}|rz{t
jj|d }|s|
g}|
dr|d|
dd   |d|
  n5|
dr|d|
dd   |d|
dd   n|
dr||
dd  |d|
d d   |D ]}t
jj|d! }|rtd"|j d#|   nqW n ty } ztd$t|  W Y d}~nd}~ww |rz<tjj||d%d&||
|d'| d(| t d)
}dd*lm} |j||d+| t|jdd, td-|j d.|  W n# ty } ztd/|j d0t|  d}W Y d}~nd}~ww |sz%tjj||
||pd1t ||||rd2nd3|d4
 td5| d6 W n ty } ztd7t|  W Y d}~nd}~ww tdd8dW S  ty } ztd9t|  tdd:dW  Y d}~S d}~ww );zHandle M-Pesa Paybill callbackprocess_mpesa_paybill_callbackz9Permission denied for M-Pesa paybill callback processing.r   r   r   z"M-Pesa paybill callback received: r   r   TransIDr:   	TransTimeTransAmountr   BusinessShortCodeBillRefNumberInvoiceNumberOrgAccountBalanceThirdPartyTransIDMSISDN	FirstName
MiddleNameLastNamez;Invalid paybill callback - missing transaction ID or amountzInvalid dataNr   r   rm   r   r   r   r   )phoner   z by phone: z$Error finding customer for paybill: r   r   zPAYBILL-zPaybill payment - Account ref: r   r   zM-Pesa paybill payment - r   z'Paybill payment processed for customer r   z,Error creating paybill payment for customer r   UNKNOWNr   invalid_account)
r   re   r=   rj   r   r   middle_namer   r   r   z'Customer not found for paybill payment z, created unreconciled paymentz-Error creating unreconciled paybill payment: r   zM-Pesa paybill callback error: r   )r   r   r   r   rw   rx   ry   r   r   r1   r   r+   r2   r   r   r   rd   r   rY   r   r   r   r   r   r   r   r   r   r   )r/   r   trans_id
trans_timetrans_amountbusiness_short_codebill_ref_numberinvoice_numberorg_account_balancethird_party_trans_idmsisdnr   r  r   r!   r   r   r   r   r   r   r   r7   r7   r8   mpesa_paybill_callback  s   





  r  c              
   C      t | dstd tdddS zt| j}td|  tdddW S  tyJ } zt	d	t
|  tdd
dW  Y d}~S d}~ww )z Handle M-Pesa Paybill validationvalidate_mpesa_paybillz0Permission denied for M-Pesa paybill validation.r   r   r   zM-Pesa validation received: r   r   zM-Pesa validation error: RejectedNr   r   r   r   rw   rx   ry   r   r   rY   r   r/   r   r   r7   r7   r8   mpesa_paybill_validationB     

r  c              
   C   s   t | dstd tdddS zt| j}tdtj|dd  t	| W S  t
yL } ztd	t|  tdd
dW  Y d}~S d}~ww )z"Handle M-Pesa Paybill confirmationconfirm_mpesa_paybillz2Permission denied for M-Pesa paybill confirmation.r   r   r   z&M-Pesa paybill confirmation received: r   r   z#M-Pesa paybill confirmation error: r   N)r   r   r   r   rw   rx   ry   r   r   r  r   rY   r   r  r7   r7   r8   mpesa_paybill_confirmationT  s   


r!  c              
   C   r  )zHandle M-Pesa balance callbackprocess_mpesa_balance_callbackz9Permission denied for M-Pesa balance callback processing.r   r   r   z"M-Pesa balance callback received: r   r   zM-Pesa balance callback error: r   Nr  r  r7   r7   r8   mpesa_balance_callbacki  r  r#  c              
   C   r  )zHandle M-Pesa B2C callbackprocess_mpesa_b2c_callbackz5Permission denied for M-Pesa B2C callback processing.r   r   r   zM-Pesa B2C callback received: r   r   zM-Pesa B2C callback error: r   Nr  r  r7   r7   r8   mpesa_b2c_callback{  r  r%  c              
   C   r  )zHandle M-Pesa B2B callbackprocess_mpesa_b2b_callbackz5Permission denied for M-Pesa B2B callback processing.r   r   r   zM-Pesa B2B callback received: r   r   zM-Pesa B2B callback error: r   Nr  r  r7   r7   r8   mpesa_b2b_callback  r  r'  c              
   C   r  )zHandle M-Pesa reversal callbackprocess_mpesa_reversal_callbackz:Permission denied for M-Pesa reversal callback processing.r   r   r   z#M-Pesa reversal callback received: r   r   z M-Pesa reversal callback error: r   Nr  r  r7   r7   r8   mpesa_reversal_callback  r  r)  c                 C   sT   t | dst| d tdS tt|d}tjj|d	d}||d}t
| d|S )	z%List payments for a specific customerview_customer_paymentsz5You do not have permission to view customer payments.zcustomers:customer_listr   )r!   r#   )r!   r   zpayments/customer_payments.html)r   r   rY   r   r   r   r   r+   r2   r.   r   )r/   rd   r!   r   rF   r7   r7   r8   customer_payments  s   
r+  c                 C   >   t | dst| d tdS tt|d}d|i}t| d|S )zGenerate payment receiptview_payment_receiptz4You do not have permission to view payment receipts.rR   r   r   zpayments/payment_receipt.htmlr   r   rY   r   r   r   r   r/   r   r   rF   r7   r7   r8   payment_receipt     
r1  c                 C   r,  )zView payment detailsview_payment_detailz3You do not have permission to view payment details.rR   r.  r   zpayments/payment_detail.htmlr/  r0  r7   r7   r8   payment_detail  r2  r4  )Adjango.shortcutsr   r   r   django.contrib.auth.decoratorsr   django.contrib.auth.mixinsr   django.views.genericr   django.httpr   r	   django.views.decorators.csrfr
   django.views.decorators.httpr   django.contribr   django.core.paginatorr   django.db.modelsr   r   	django.dbr   r   r   r   r   r{   r   billing.modelsr   rw   loggingaccounts.permissionsr   r   r   r   r   	getLoggerrI   r   r   rQ   r^   r   r   r   r   r   r   r   r  r  r!  r#  r%  r'  r)  r+  r1  r4  r7   r7   r7   r8   <module>   s    
*


`



&
  v

