o
    h                     @   s  d dl Z d dlZd dlmZ d dlmZmZmZ d dlm	Z	m
Z
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mZmZmZmZ d dlmZ d dlmZm Z  zd dl!m"Z" W n e#ym   dZ"Y nw d	dl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ d dl,m-Z- d dl.m/Z/ d	dl0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 dd Z8dd Z9dd Z:dd Z;dd Z<dd  Z=d!d" Z>d#d$ Z?ed%d& Z@ed'd( ZAd)d* ZBed+d, ZCed-d. ZDed/d( ZAed0d1 ZEed2d3 ZFed4d5 ZGed6d7 ZHd8d9 ZId:d; ZJd<d= ZKd>d? ZLd@dA ZMdBdC ZNdDd* ZBedEdF ZOedGdH ZPedIdJ ZQedKdL ZRedMdN ZSedOdP ZTdQdR ZUdSdT ZVdUdV ZWedWdX ZXedYdZ ZYed[d\ ZZed]d^ Z[ed_d` Z\edadb Z]edcdd Z^ededf Z_dgdh Z`didj Zadkdl Zbedmdn ZcdS )o    N)	timedelta)renderredirectget_object_or_404)loginauthenticatelogout)login_required)QSum)now)csrf_exempt   )CartCartItemShippingAddressOrder	OrderItemShippingMethod)Shop)ProductCategory)Customer)AddToCartFormGuestCheckoutFormShippingAddressForm
SearchFormShippingMethodFormCustomerRegistrationFormCustomerLoginForm)JsonResponse)messages)MpesaSTKPush)model_to_dict)	Paginator)Userc           
      C   sX  t  }| jdd}|r6|t |dt |dB t |dB t |dB t |dB t |dB t |d	B t |d
B M }| jd}|rE|t |dM }| jd}|dkrW|t ddM }n|dkrkt tdd }|t |dM }n|dkrv|t ddM }| jd}|dkrd}n|dkrd}n	|dkrd}nd}tj||	 }t
j }	t| d||	d S )!Nq name__icontainsdescription__icontainsbarcode__icontainsvariant__icontainscategory__name__icontainsseo_title__icontainsseo_description__icontainspackaging_type__icontainscategory)category_idfiltersaleF)discount_price__isnullnewr   )weeks)created_at__gtebest_sellerT	is_activesort	price_ascselling_price
price_descz-selling_pricename-created_atzshop/product_list.html)products
categories)r
   GETgetr   r   r   objectsr:   order_bydistinctr   allr   )
requestquerysearch_queryr9   special_filterone_week_agosort_optionrN   rI   rJ    rW   #/var/www/html/kangema/shop/views.pyproduct_list   sZ   
rY   c                 C   s@   t t|d}tjj|jdj|jdd d }t| d||dS )Nid)r8      zshop/product_detail.html)productrecommended_products)r   r   rM   r:   r8   excluder[   r   )rQ   
product_idr]   r^   rW   rW   rX   product_detailO   s   "ra   c           	      C   s   | j dkrbt| j}| rbtt|jd d}|jd }| jjr+t	j
j| jd\}}n| jjp3| j }t	j
j|d\}}tj
j||d\}}|sP| j|7  _|  t| |j d td	S td
S )z$
    Add a product to the cart.
    POSTr`   rZ   quantityusersession_key)cartr]   z added to cart.shop:cart_detailrY   )methodr   rb   is_validr   r   cleaned_datare   is_authenticatedr   rM   get_or_createsessionrg   saver   rc   r!   successrG   r   )	rQ   formr]   rc   rh   _rg   	cart_itemcreatedrW   rW   rX   add_to_cartZ   s    


rv   c                 C   s   | j jrtjj| j d\}}n| jjs| j  | jj}tjj|dd\}}|j	d
 }tdd |D }t| d||dS )	zi
    Display the cart details for the user or guest.
    Creates a cart if it doesn't already exist.
    rd   N)rg   re   r]   c                 s   s    | ]}|  V  qd S )N)get_total_price).0itemrW   rW   rX   	<genexpr>   s    zcart_detail.<locals>.<genexpr>zshop/cart_detail.html)itemstotal_price)re   rm   r   rM   rn   ro   rg   creater{   select_relatedrP   sumr   )rQ   rh   ru   rg   r{   r|   rW   rW   rX   cart_detailw   s   
r   c                 C   sd   t t|d}| jjr|jj| jkrtdS n| jj}|jj|kr$tdS |  t	
| d tdS )z'
    Remove an item from the cart.
    rZ   r   ri   zItem removed from cart.)r   r   re   rm   rh   r   ro   rg   deleter!   rq   )rQ   cart_item_idrt   rg   rW   rW   rX   remove_from_cart   s   r   c                 C   sv   | j dkr7| jd}| jd}tt|d}|dkr#| jd7  _n|dkr3|jdkr3| jd8  _|  tdS )	Nrb   item_idactionrZ   	incrementr   	decrementri   )rj   rb   rL   r   r   rc   rp   r   )rQ   r   r   rt   rW   rW   rX   update_cart   s   
r   c              
   C   s0  | j jrtjj| j d }n| jjp| j }tjj|d }|r(|j	
 s2t| d tdS t| jp7d}tjjdd}d}| }g }d}| j jrgtjj| j d}tjj| j g d	d
 }	|	dk}| jdkr| jdd}
| jd}|rtt|d}||j7 }| jd}|r| j jrztjj|| j d}W nP tjy   t| d td Y S w | r| j jr|jdd}| j |_ |  n%|jdd}| jd|_|  nt| d t| d||||||dS |r|rtjj| j jr| j nd| j js|jnd||||
d}|j	 D ]}tjj||j |j!|" d q|
dkr[|s=t| d |#  tdS d|_$d|_%|  |j	 #  t&| d  td!|j'd"S |
d#krm|j'| jd$< td%|j'd"S | jd&}t(j }|st| d' t)d( |#  tdS t*|}zL|+||d)|j' }|d*d+krd,|_%|  |j	 #  |j'| jd$< t&| d- td.|j'd"W S |d/d0}t| d1|  td2|j'd"W S  t,y
 } zt)d3|j' d4|  t| d5 td2|j'd"W  Y d}~S d}~ww t| d||||||dS )6zE
    Handle checkout process for both logged-in and guest users.
    rd   rf   zYour cart is empty.ri   NTrA   F)	Delivered
ProcessingShipped)re   
status__in   rb   payment_methodmpesashipping_methodrZ   saved_addressr[   re   zSelected address not found.zshop:checkoutcommitemailz*Please provide valid shipping information.zshop/checkout.html)rh   shipping_methodsshipping_formsaved_addressesr|   payment_on_delivery_eligible)re   guest_emailshipping_addressr   r|   r   )orderr]   rc   pricepayment_on_deliveryz-You are not eligible for Payment on Delivery.r   zPayment on DeliveryzAOrder placed successfully! Payment will be collected on delivery.shop:order_confirmationorder_idcardpending_order_idshop:card_paymentphone_number!Payment configuration is missing.z0Checkout attempted without a Shop configuration.Order #ResponseCode0Pending9STK Push sent. Please complete the payment on your phone.shop:payment_statuserrorMessagePayment initiation failedPayment failed: shop:payment_retryzSTK Push failed for Order #: +Payment processing error. Please try again.)-re   rm   r   rM   r:   firstro   rg   rp   r{   existsr!   errorr   r   rb   r   rw   r   r   countrj   rL   r   costDoesNotExistrk   r   r   r}   rP   r   r]   rc   get_unit_pricer   statusmpesa_payment_statusrq   r[   r   loggingr"   initiate_stk_push	Exception)rQ   rh   rg   r   r   selected_shipping_methodr|   r   r   successful_ordersr   shipping_method_idsaved_address_idr   r   ry   r   shopr   response	error_msgerW   rW   rX   checkout   s   


		




r   c                 C   s   t t|d}t| dd|iS )z-
    Display order confirmation details.
    rZ   zshop/order_confirmation.htmlr   )r   r   r   rQ   r   r   rW   rW   rX   order_confirmationH  s   r   c                 C   &   t jj| jdd}t| dd|iS )5
    Display the logged-in user's order history.
    rd   rH   zshop/order_list.htmlordersr   rM   r:   re   rN   r   rQ   r   rW   rW   rX   
order_listR     r   c                 C       t t|| jd}t| dd|iS z.
    Display details of a specific order.
    r   zshop/order_detail.htmlr   r   r   re   r   r   rW   rW   rX   order_detail[     r   c                 C      | j dd}| j ddk}tj }|rFtjjt|dt|dB t|dB t|dB t|d	B t|d
B t|dB t|dB dd }|rqg }|dd D ]}||j	t
|jr]|jn|jd|j dd qPtd|iS t| d||dS zX
    Search for products by name, description, barcode, category, and other fields.
    r&   r'   ajax1r(   r*   r,   r.   r0   r2   r4   r6   TrA   Nr   z/shop/product//)rG   r   urlsuggestionszshop/search_results.html)rI   rR   rK   rL   r   rM   noner:   r
   rO   appendrG   strdiscount_pricerE   r[   r    r   rQ   rR   is_ajaxrI   r   r]   rW   rW   rX   searchf  D   


r   c                 C   s   | j }t| dd|iS )z+
    Display user account information.
    zshop/my_account.htmlre   )re   r   )rQ   re   rW   rW   rX   
my_account  s   r   c                 C   r   )r   rd   rH   zshop/my_orders.htmlr   r   r   rW   rW   rX   	my_orders  r   r   c                 C   r   r   r   r   rW   rW   rX   r     r   c                 C   s2   ddl m} |jj| jdd}t| dd|iS )z3
    Display the logged-in user's saved items.
    r   	SavedItemrd   r]   zshop/saved_items.htmlsaved_items)modelsr   rM   r:   re   r~   r   )rQ   r   r   rW   rW   rX   r     s   r   c                 C   s   | j dkr:ddlm} tt|d}|jj| j|d\}}|r)t	| |j
 d n
t| |j
 d td|d	S td
diS )z2
    Add a product to the user's saved items.
    rb   r   r   rZ   )re   r]   z added to saved items.z  is already in your saved items.T)rq   ru   rq   F)rj   r   r   r   r   rM   rn   re   r!   rq   rG   infor    )rQ   r`   r   r]   
saved_itemru   rW   rW   rX   add_to_saved_items  s   

r   c                 C   s`   | j dkr*ddlm} t||| jd}|jj}|  t	| | d t
ddiS t
ddiS )	z7
    Remove a product from the user's saved items.
    rb   r   r   r    removed from saved items.rq   TF)rj   r   r   r   re   r]   rG   r   r!   rq   r    )rQ   saved_item_idr   r   product_namerW   rW   rX   remove_from_saved_items  s   
r   c                 C   s   | j dkr>ddlm} z!|jj| j|d}|jj}|  t	
| | d tddiW S  |jy=   tdd	d
 Y S w tddiS )zE
    Remove a product from the user's saved items by product ID.
    rb   r   r   )re   r`   r   rq   TFzItem not found in saved items)rq   r   )rj   r   r   rM   rL   re   r]   rG   r   r!   rq   r    r   )rQ   r`   r   r   r   rW   rW   rX   remove_saved_item_by_product  s   
r   c                 C   
   t | dS )z
    About Us page.
    zshop/about_us.htmlr   rQ   rW   rW   rX   about_us     
r   c                 C   r   )z
    Help Center page.
    zshop/help_center.htmlr   r   rW   rW   rX   help_center  r   r   c                 C   r   )z"
    Terms & Conditions page.
    zshop/terms_and_conditions.htmlr   r   rW   rW   rX   terms_and_conditions  r   r   c                 C   r   )z
    Privacy Policy page.
    zshop/privacy_policy.htmlr   r   rW   rW   rX   privacy_policy  r   r   c                 C   r   )Nzshop/return_policy.htmlr   r   rW   rW   rX   return_policy      
r   c                 C   r   )Nzshop/cookie_policy.htmlr   r   rW   rW   rX   cookie_policy  r   r   c                 C   r   r   r   r   rW   rW   rX   r     r   c              
   C   s   | j dkroz>tjj|| jd}| jdi }|j D ]}t|j	j
}||v r1||  |j7  < q|j||< q|| jd< tdddW S  tjyT   tddd Y S  tyn } ztdt|dW  Y d	}~S d	}~ww tdd
dS )z+Add all items from a previous order to cartrb   r   rh   TzItems added to cart)rq   messageFzOrder not foundNzInvalid request)rj   r   rM   rL   re   ro   r{   rP   r   r]   r[   rc   r    r   r   )rQ   r   r   rh   ry   r`   r   rW   rW   rX   reorder_items)  s$   

r   c              
   C   s  | j dkrz]t| j}|di di d}|di di d}|dkrPtjj|d }|rHd|_	d|_
|  td	|j  td
ddW S td| d|  tdddW S  ty } ztd|  tdddW  Y d}~S d}~ww tdddS )z2
    Handle M-Pesa STK Push payment callback.
    rb   BodystkCallback
ResultCodeMerchantRequestIDr   )account_referencePaidzPayment successful for Order #rq   zPayment successful.r   r   z%Payment failed for MerchantRequestID z: ResultCode failurezPayment failed or cancelled.z"Error processing M-Pesa callback: r   zCallback processing failed.NInvalid request method.)rj   jsonloadsbodyrL   r   rM   r:   r   payment_statusr   rp   r   r   r[   r    warningr   r   )rQ   dataresult_codemerchant_request_idr   r   rW   rW   rX   mpesa_callbackA  s*   
r  c                 C   s"   t j }t }t| d||dS )zS
    List all shipping methods and display the form for creating a new method.
    zshop/shipping_method_list.html)r   rr   )r   rM   rP   r   r   )rQ   r   rr   rW   rW   rX   shipping_method_lista  s   
r  c                 C   sL   | j dkr"t| j}| r|  t| d tdS t| d tdS )zE
    Create a new shipping method and redirect to the list view.
    rb   z%Shipping method created successfully.3There were errors in the form. Please correct them.shop:shipping_method_list)	rj   r   rb   rk   rp   r!   rq   r   r   )rQ   rr   rW   rW   rX   shipping_method_createn  s   

r  c                 C   sp   t t|d}| jdkr.t| j|d}| r$|  t| d t
dS t	| d t
dS t	| d t
dS )z+
    Edit an existing shipping method.
    pkrb   instancez%Shipping method updated successfully.r  r  r	  )r   r   rj   r   rb   rk   rp   r!   rq   r   r   )rQ   r  r   rr   rW   rW   rX   shipping_method_edit}  s   
r  c                 C   sF   t t|d}| jdkr|  t| d tdS t| d tdS )zK
    Delete an existing shipping method and redirect to the list view.
    r  rb   z%Shipping method deleted successfully.r	  r  )r   r   rj   r   r!   rq   r   r   )rQ   r  r   rW   rW   rX   shipping_method_delete  s   
r  c              	   C   s   | j dkrqt| j}| rj|jdd}||jd  |  ddlm} |j	j
dd\}}|j| tr[ztj	j||j d	|j |j|jd
d|jddd W n   Y t| | t| d tdS t| d nt }t| dd|iS )Nrb   Fr   passwordr   )Groupr   )rG    phoner'   address)re   rG   r   r   r!  z3Account created successfully! Welcome to our store.shop:product_list Please correct the errors below.zshop/customer_register.htmlrr   )rj   r   rb   rk   rp   set_passwordrl   django.contrib.auth.modelsr  rM   rn   groupsaddr   r}   
first_name	last_namer   rL   r   r!   rq   r   r   r   )rQ   rr   re   r  customer_groupru   rW   rW   rX   customer_register  s4   



r+  c                 C   s   | j dkrIt| | jd}| rB|jd}|jd}t||d}|d urAt| | t	| d|j
 d | jdd	}t|S n
t| d
 nt }t| dd|iS )Nrb   )r  usernamer  )r,  r  zWelcome back, !nextr"  zInvalid username or password.zshop/customer_login.htmlrr   )rj   r   rb   rk   rl   rL   r   r   r!   rq   r(  rK   r   r   r   )rQ   rr   r,  r  re   next_urlrW   rW   rX   customer_login  s   

r0  c                 C   s   t |  t| d tdS )Nz&You have been logged out successfully.r"  )r   r!   rq   r   r   rW   rW   rX   customer_logout  s   r1  c                 C   sJ  d }t r0z t jj| jjd }|s#t jj| jj| jj| jjddd}W n t	y/   d }Y nw | j
dkrddlm} || j| jd}| rz|  |rp| jj|_| jj|_| jj|_|jdd|_|jd	d|_|  t| d
 tdS t| d nddlm} i }|r|j|d< |j|d	< || j|d}t| d||dS )Nr   r'   )r(  r)  r   r   r!  rb   r   )CustomerProfileFormr  r   r!  zProfile updated successfully!shop:customer_profiler#  )r  initialzshop/customer_profile.html)customerrr   )r   rM   r:   re   r   r   r}   r(  r)  r   rj   formsr3  rb   rk   rp   rl   rL   r   r!  r!   rq   r   r   r   )rQ   r6  r3  rr   initial_datarW   rW   rX   customer_profile  sR   





r9  c                 C   s    t jj| jd}t| dd|iS )z.
    List all addresses for the customer.
    rd   zshop/customer_addresses.html	addresses)r   rM   r:   re   r   )rQ   r:  rW   rW   rX   customer_addresses  r   r;  c                 C   s   | j dkr3ddlm} || j}| r,|jdd}| j|_|  t| d t	dS t
| d n	ddlm} | }t| d	|d
dS )z-
    Add a new address for the customer.
    rb   r   CustomerAddressFormFr   zAddress added successfully!shop:customer_addressesr#  shop/customer_address_form.htmlzAdd New Address)rr   title)rj   r7  r=  rb   rk   rp   re   r!   rq   r   r   r   )rQ   r=  rr   r!  rW   rW   rX   customer_address_add  s    

rA  c                 C   s   t t|| jd}| jdkr3ddlm} || j|d}| r,|  t	
| d tdS t	| d nddlm} ||d}t| d	||d
dS )z#
    Edit an existing address.
    r   rb   r   r<  r  zAddress updated successfully!r>  r#  r?  zEdit Address)rr   r!  r@  )r   r   re   rj   r7  r=  rb   rk   rp   r!   rq   r   r   r   )rQ   
address_idr!  r=  rr   rW   rW   rX   customer_address_edit3  s    

rC  c                 C   sF   t t|| jd}| jdkr|  t| d tdS t| dd|iS )z
    Delete an address.
    r   rb   zAddress deleted successfully!r>  z)shop/customer_address_confirm_delete.htmlr!  )	r   r   re   rj   r   r!   rq   r   r   )rQ   rB  r!  rW   rW   rX   customer_address_deleteN  s   
rD  c                 C   s|   | j dkr+ddlm} || j| j}| r$|  t| d t	dS t
| d nddlm} || j}t| dd|iS )	z#
    Change customer password.
    rb   r   )CustomerPasswordChangeFormzPassword changed successfully!r4  r#  z"shop/customer_change_password.htmlrr   )rj   r7  rE  re   rb   rk   rp   r!   rq   r   r   r   )rQ   rE  rr   rW   rW   rX   customer_change_password]  s   

rF  c              	   C   s$  t rnz>t jj| jjd }|rtjj| jdd}ntjj| jdd}t|d}| j	
d}||}t| d||dW S  tym   tjj| jdd}t|d}| j	
d}||}t| d|d d Y S w tjj| jdd}t|d}| j	
d}||}t| d|d dS )Nr2  rd   rH   
   pagezshop/customer_orders.html)r   r6  )r   rM   r:   re   r   r   r   rN   r$   rK   rL   get_pager   r   )rQ   r6  r   	paginatorpage_numberpage_objrW   rW   rX   customer_ordersq  s>   






rM  c              
   C   s   | j dkr[z*t| j}|dd  }|s tdddW S tj	j
|d }td|iW S  tjy@   tdd	d Y S  tyZ } ztdt|dW  Y d
}~S d
}~ww tdddS )zP
    Check if an email exists in the system for modern authentication flow.
    rb   r   r'   FzEmail is required)r   r   )email__iexactr   zInvalid JSONNInvalid request method)rj   r
  r  r  rL   striplowerr    r%   rM   r:   r   JSONDecodeErrorr   r   )rQ   r  r   user_existsr   rW   rW   rX   check_email  s   
rT  c           
   
   C   s  t t|d}| jjr|j| jkrt| d tdS | jjs+|js+t| d tdS | jdkr| j	
dd}|dkr| j	
d}tj }|sUt| d td	|jd
S t|}z9|||jd|j }|
ddkrd|_|  t| d td|jd
W S |
dd}t| d|  W n/ ty }	 ztd|j d|	  t| d W Y d}	~	nd}	~	ww |dkrtd|jd
S t| dd|iS )z3
    Handle payment retry for failed payments.
    rZ   Unauthorized access.r"  rb   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   z!STK Push retry failed for Order #r   r   Nr   r   zshop/payment_retry.htmlr   )r   r   re   rm   r!   r   r   r   rj   rb   rL   r   rM   r   r[   r"   r   r|   r   rp   rq   r   r   r   )
rQ   r   r   r   r   r   r   r   r   r   rW   rW   rX   payment_retry  sF   

rV  c                 C   sf   t t|d}| jjr|j| jkrt| d tdS | jjs+|js+t| d tdS t| dd|iS )z;
    Display payment status and allow retry if needed.
    rZ   rU  r"  zshop/payment_status.htmlr   )	r   r   re   rm   r!   r   r   r   r   r   rW   rW   rX   r    s   r  c              
   C   s  | j jst| d tdS tt|| j d}| jdkrzddl}d}d}t	|j
d	d
|j | j j| j j d| j j d| jd| jd| jd| jdd| d|j dd}d| dd}|j|||d}|jdkr| }	|	ddkrd|_d|_|  t| d td|jd W S t| d!|	d"d#  nt| d$ W n$ ty }
 ztd%|j d&|
  t| d' W Y d}
~
nd}
~
ww td(|jd S t| d)d*|iS )+z2
    Handle card payment with YellowCard API.
    z"Please log in to use card payment.zshop:customer_loginr   rb   r   Nz%https://api.yellowcard.io/v1/paymentsyour_yellowcard_api_keyKESorder_r  )r   rG   card_numberexpiry_monthexpiry_yearcvv)numberr[  r\  r]  z/shop/card-payment-callback/r   )amountcurrency	referencer6  r   callback_urlzBearer zapplication/json)AuthorizationzContent-Type)r
  headers   r   rq   r  r   zCard payment successful!r   r   zCard payment failed: r   zUnknown errorz1Card payment processing failed. Please try again.Card payment failed for Order #r   z5An error occurred while processing your card payment.r   zshop/card_payment.htmlr   )re   rm   r!   r   r   r   r   rj   requestsfloatr|   r[   r   r(  r)  rb   rL   build_absolute_uripoststatus_coder
  r   r   rp   rq   r   r   r   )rQ   r   r   rg  yellowcard_api_urlapi_keypayloadrd  r   resultr   rW   rW   rX   card_payment  s\   






rp  c              
   C   s   | j dkrkzEt| j}tjj|d}|ddkr4d|_d|_|	  t
d|j  tddiW S d	|_|	  t
d
|j  tddiW S  tyj } zt
d|  tddiW  Y d}~S d}~ww tdddS )z-
    Handle YellowCard payment callback.
    rb   rZ   r   
successfulr  r   z#Card payment successful for Order #rq   Failedrf  failedz(Error processing card payment callback: r   NrO  r  )rj   r
  r  r  r   rM   rL   r   r   rp   r   r   r[   r    r  r   r   )rQ   r   r  r   r   rW   rW   rX   card_payment_callback;  s(   
rt  )dr
  r   datetimer   django.shortcutsr   r   r   django.contrib.authr   r   r   django.contrib.auth.decoratorsr	   django.db.modelsr
   r   django.utils.timezoner   django.views.decorators.csrfr   r   r   r   r   r   r   r   settings.modelsr   inventory.modelsr   r   customers.modelsr   ImportErrorr7  r   r   r   r   r   r   r   django.httpr    django.contribr!   stk_pushr"   django.forms.modelsr#   django.core.paginatorr$   r%  r%   rY   ra   rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r+  r0  r1  r9  r;  rA  rC  rD  rF  rM  rT  rV  r  rp  rt  rW   rW   rW   rX   <module>   s     $4 



#
	

	
	


#





&
4





*
0B