B
    `q                 @   s  d dl 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
 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 ddlmZ eddddg\ZZZeddZeddZeddddg\Z Z!Z"eddZ#eddZ$eddZ%ed d!Z&ed"d#Z'ed"d$Z(ed%d&Z)ed%d'Z*e +d(Z,G d)d* d*e%ej-Z.G d+d, d,e%ej-Z/G d-d. d.e%ej0Z1G d/d0 d0e%ej2Z3G d1d2 d2e%ej-Z4G d3d4 d4e%ej5Z6G d5d6 d6e$ej5Z7G d7d8 d8ej8Z9dS )9    N)quote)http)settings)messages)login)redirect)reversereverse_lazy)gettext)generic)	get_classget_classes	get_model   )signalszcheckout.formsShippingAddressFormShippingMethodFormGatewayFormzaddress.formsUserAddressFormzshipping.repository
Repositoryzpayment.exceptionsRedirectRequiredUnableToTakePaymentPaymentErrorzorder.exceptionsUnableToPlaceOrderzcheckout.mixinsOrderPlacementMixinzcheckout.sessionCheckoutSessionMixinzshipping.methodsNoShippingRequiredorderOrderShippingAddressaddressUserAddressCountryzoscar.checkoutc                   sT   e Zd ZdZdZeZedZddgZ	 fddZ
 fdd	Zd
d Zdd Z  ZS )	IndexViewz
    First page of the checkout.  We prompt user to either sign in, or
    to proceed as a guest (where we still collect their email address).
    zoscar/checkout/gateway.htmlzcheckout:shipping-addresscheck_basket_is_not_emptycheck_basket_is_validc                s4   |j jr tjj| |d |  S t j|f||S )N)senderrequest)useris_authenticatedr   start_checkoutsend_robustget_success_responsesuperget)selfr'   argskwargs)	__class__ H/home/dcms/DCMS/lib/python3.7/site-packages/oscar/apps/checkout/views.pyr.   2   s
    
zIndexView.getc                s(   t   }| j }|r$d|i|d< |S )Nusernameinitial)r-   get_form_kwargscheckout_sessionZget_guest_email)r/   r1   email)r2   r3   r4   r7   =   s
    

zIndexView.get_form_kwargsc             C   s   |  s| rr|jd }| j| tjj| | j|d | rt	
| jtd dtdtdt|f | _n&| }t| j| tjj| | jd t|  S )Nr5   )r&   r'   r9   zPCreate your account and then you will be redirected back to the checkout processz%s?next=%s&email=%szcustomer:registerzcheckout:shipping-address)r&   r'   )Zis_guest_checkoutZis_new_account_checkoutcleaned_datar8   Zset_guest_emailr   r*   r+   r'   r   info_r   r   success_urlZget_userr   r   get_success_url)r/   formr9   r(   r3   r3   r4   
form_validF   s$    

zIndexView.form_validc             C   s   t |  S )N)r   r>   )r/   r3   r3   r4   r,   e   s    zIndexView.get_success_response)__name__
__module____qualname____doc__template_namer   
form_classr	   r=   pre_conditionsr.   r7   r@   r,   __classcell__r3   r3   )r2   r4   r#   &   s   	r#   c                   sh   e Zd ZdZdZeZedZdddgZ	dgZ
dd	 Z fd
dZdd Z fddZ fddZ  ZS )ShippingAddressViewa5  
    Determine the shipping address for the order.

    The default behaviour is to display a list of addresses from the users's
    address book, from which the user can choose one to be their shipping
    address.  They can add/edit/delete these USER addresses.  This address will
    be automatically converted into a SHIPPING address when the user checks
    out.

    Alternatively, the user can enter a SHIPPING address directly which will be
    saved in the session and later saved as ShippingAddress model when the
    order is successfully submitted.
    z$oscar/checkout/shipping_address.htmlzcheckout:shipping-methodr$   r%   check_user_email_is_capturedZ$skip_unless_basket_requires_shippingc             C   sN   | j  }|rJ| }ytjj|dd|d< W n tjk
rH   Y nX |S )NZ
country_id)Ziso_3166_1_a2Zcountry)r8   Znew_shipping_address_fieldscopyr"   Zobjectsr.   popDoesNotExist)r/   r6   r3   r3   r4   get_initial   s    
zShippingAddressView.get_initialc                s(   t  jf |}| jjjr$|  |d< |S )N	addresses)r-   get_context_datar'   r(   r)   get_available_addresses)r/   r1   ctx)r2   r3   r4   rP      s    
z$ShippingAddressView.get_context_datac             C   s   | j jjjdddS )NT)Zcountry__is_shipping_countryz-is_default_for_shipping)r'   r(   rO   filterZorder_by)r/   r3   r3   r4   rQ      s    
z+ShippingAddressView.get_available_addressesc                s   | j jjrld| j jkrltjj| j jd | j jd}| j jdd }|dkrb| j| t	| 
 S t S nt j|f||S d S )NZ
address_id)pkr(   actionZship_to)r'   r(   r)   POSTr!   _default_managerr.   r8   Zship_to_user_addressr   r>   r   HttpResponseBadRequestr-   post)r/   r'   r0   r1   r    rU   )r2   r3   r4   rY      s    

zShippingAddressView.postc                s2   t dd |jj D }| j| t |S )Nc             s   s$   | ]\}}| d s||fV  qdS )r<   N)
startswith).0kvr3   r3   r4   	<genexpr>   s    z1ShippingAddressView.form_valid.<locals>.<genexpr>)dictinstance__dict__itemsr8   Zship_to_new_addressr-   r@   )r/   r?   Zaddress_fields)r2   r3   r4   r@      s    zShippingAddressView.form_valid)rA   rB   rC   rD   rE   r   rF   r	   r=   rG   skip_conditionsrN   rP   rQ   rY   r@   rH   r3   r3   )r2   r4   rI   n   s   rI   c                   sD   e Zd ZdZdZeZedZdd Z	 fddZ
 fdd	Z  ZS )
UserAddressUpdateViewz
    Update a user address
    z%oscar/checkout/user_address_form.htmlzcheckout:shipping-addressc             C   s   | j jj S )N)r'   r(   rO   all)r/   r3   r3   r4   get_queryset   s    z"UserAddressUpdateView.get_querysetc                s   t   }| jj|d< |S )Nr(   )r-   r7   r'   r(   )r/   r1   )r2   r3   r4   r7      s    
z%UserAddressUpdateView.get_form_kwargsc                s   t | jtd t  S )NzAddress saved)r   r;   r'   r<   r-   r>   )r/   )r2   r3   r4   r>      s    z%UserAddressUpdateView.get_success_url)rA   rB   rC   rD   rE   r   rF   r	   r=   rf   r7   r>   rH   r3   r3   )r2   r4   rd      s   rd   c                   s4   e Zd ZdZdZedZdd Z fddZ  Z	S )UserAddressDeleteViewz7
    Delete an address from a user's address book.
    z'oscar/checkout/user_address_delete.htmlzcheckout:shipping-addressc             C   s   | j jj S )N)r'   r(   rO   re   )r/   r3   r3   r4   rf      s    z"UserAddressDeleteView.get_querysetc                s   t | jtd t  S )NzAddress deleted)r   r;   r'   r<   r-   r>   )r/   )r2   r3   r4   r>      s    z%UserAddressDeleteView.get_success_url)
rA   rB   rC   rD   rE   r	   r=   rf   r>   rH   r3   r3   )r2   r4   rg      s
   rg   c                   s   e Zd ZdZdZeZdddgZedZ	 fddZ
 fd	d
Z fddZ fddZdd Zdd Z fddZdd Z  ZS )ShippingMethodViewa  
    View for allowing a user to choose a shipping method.

    Shipping methods are largely domain-specific and so this view
    will commonly need to be subclassed and customised.

    The default behaviour is to load all the available shipping methods
    using the shipping Repository.  If there is only 1, then it is
    automatically selected.  Otherwise, a page is rendered where
    the user can choose the appropriate one.
    z$oscar/checkout/shipping_methods.htmlr$   r%   rJ   zcheckout:payment-methodc                s   |   | _t j|f||S )N)get_available_shipping_methods_methodsr-   rY   )r/   r'   r0   r1   )r2   r3   r4   rY      s    
zShippingMethodView.postc                s   |j  s"| jt j |  S | j sDt	|t
d tdS |  | _t| jdkrtt|t
d tdS t| jdkr| j| jd j |  S t j|f||S )Nz Please choose a shipping addresszcheckout:shipping-addressr   zGShipping is unavailable for your chosen address - please choose anotherr   )basketZis_shipping_requiredr8   use_shipping_methodr   coder,   Zis_shipping_address_setr   errorr<   r   ri   rj   lenwarningr-   r.   )r/   r'   r0   r1   )r2   r3   r4   r.      s     



zShippingMethodView.getc                s   t  jf |}| j|d< |S )Nmethods)r-   rP   rj   )r/   r1   )r2   r3   r4   rP   !  s    
z#ShippingMethodView.get_context_datac                s   t   }| j|d< |S )Nrq   )r-   r7   rj   )r/   r1   )r2   r3   r4   r7   &  s    

z"ShippingMethodView.get_form_kwargsc             C   s(   t  j| jj| jj| | jj| jdS )zT
        Returns all applicable shipping method objects for a given basket.
        )rk   r(   Zshipping_addrr'   )r   Zget_shipping_methodsr'   rk   r(   Zget_shipping_address)r/   r3   r3   r4   ri   +  s    z1ShippingMethodView.get_available_shipping_methodsc             C   s   | j |jd  |  S )NZmethod_code)r8   rl   r:   r,   )r/   r?   r3   r3   r4   r@   8  s    zShippingMethodView.form_validc                s   t | jtd t |S )Nz/Your submitted shipping method is not permitted)r   rn   r'   r<   r-   form_invalid)r/   r?   )r2   r3   r4   rr   >  s    zShippingMethodView.form_invalidc             C   s   t |  S )N)r   r>   )r/   r3   r3   r4   r,   C  s    z'ShippingMethodView.get_success_response)rA   rB   rC   rD   rE   r   rF   rG   r	   r=   rY   r.   rP   r7   ri   r@   rr   r,   rH   r3   r3   )r2   r4   rh      s   $rh   c               @   sB   e Zd ZdZddddgZdgZedZdd	 Zd
d Z	dd Z
dS )PaymentMethodViewa0  
    View for a user to choose which payment method(s) they want to use.

    This would include setting allocations if payment is to be split
    between multiple sources. It's not the place for entering sensitive details
    like bankcard numbers though - that belongs on the payment details view.
    r$   r%   rJ   check_shipping_data_is_capturedskip_unless_payment_is_requiredzcheckout:payment-detailsc             O   s   |   S )N)r,   )r/   r'   r0   r1   r3   r3   r4   r.   \  s    zPaymentMethodView.getc             C   s   t |  S )N)r   r>   )r/   r3   r3   r4   r,   b  s    z&PaymentMethodView.get_success_responsec             C   s
   t | jS )N)strr=   )r/   r3   r3   r4   r>   e  s    z!PaymentMethodView.get_success_urlN)rA   rB   rC   rD   rG   rc   r	   r=   r.   r,   r>   r3   r3   r3   r4   rs   L  s   rs   c                   s   e Zd ZdZdZdZddddgZdZ fd	d
Z fddZ	dd Z
dd Zdd Zdd Zdd Zdd ZdddZdd Z  ZS )PaymentDetailsViewa  
    For taking the details of payment and creating the order.

    This view class is used by two separate URLs: 'payment-details' and
    'preview'. The `preview` class attribute is used to distinguish which is
    being used. Chronologically, `payment-details` (preview=False) comes before
    `preview` (preview=True).

    If sensitive details are required (e.g. a bankcard), then the payment details
    view should submit to the preview URL and a custom implementation of
    `validate_payment_submission` should be provided.

    - If the form data is valid, then the preview template can be rendered with
      the payment-details forms re-rendered within a hidden div so they can be
      re-submitted when the 'place order' button is clicked. This avoids having
      to write sensitive data to disk anywhere during the process. This can be
      done by calling `render_preview`, passing in the extra template context
      vars.

    - If the form data is invalid, then the payment details templates needs to
      be re-rendered with the relevant error messages. This can be done by
      calling `render_payment_details`, passing in the form instances to pass
      to the templates.

    The class is deliberately split into fine-grained methods, responsible for
    only one thing.  This is to make it easier to subclass and override just
    one component of functionality.

    All projects will need to subclass and customise this class as no payment
    is taken by default.
    z#oscar/checkout/payment_details.htmlzoscar/checkout/preview.htmlr$   r%   rJ   rt   Fc                s   | j r| jdg S t |S )NZcheck_payment_data_is_captured)previewrG   r-   get_pre_conditions)r/   r'   )r2   r3   r4   ry     s    z%PaymentDetailsView.get_pre_conditionsc                s   | j sdgS t |S )Nru   )rx   r-   get_skip_conditions)r/   r'   )r2   r3   r4   rz     s    z&PaymentDetailsView.get_skip_conditionsc             O   s4   | j st S |jdddkr*| |S | |S )NrU    Zplace_order)rx   r   rX   rV   r.   handle_place_order_submission!handle_payment_details_submission)r/   r'   r0   r1   r3   r3   r4   rY     s
    
zPaymentDetailsView.postc             C   s   | j f |  S )a  
        Handle a request to place an order.

        This method is normally called after the customer has clicked "place
        order" on the preview page. It's responsible for (re-)validating any
        form information then building the submission dict to pass to the
        `submit` method.

        If forms are submitted on your payment details view, you should
        override this method to ensure they are valid before extracting their
        data into the submission dict and passing it onto `submit`.
        )submitZbuild_submission)r/   r'   r3   r3   r4   r|     s    z0PaymentDetailsView.handle_place_order_submissionc             C   s
   |  |S )a  
        Handle a request to submit payment details.

        This method will need to be overridden by projects that require forms
        to be submitted on the payment details view.  The new version of this
        method should validate the submitted form data and:

        - If the form data is valid, show the preview view with the forms
          re-rendered in the page
        - If the form data is invalid, show the payment details view with
          the form errors showing.

        )render_preview)r/   r'   r3   r3   r4   r}     s    z4PaymentDetailsView.handle_payment_details_submissionc             K   s   d| _ | jf |}| |S )a  
        Show a preview of the order.

        If sensitive data was submitted on the payment details page, you will
        need to pass it back to the view here so it can be stored in hidden
        form inputs.  This avoids ever writing the sensitive data to disk.
        T)rx   rP   render_to_response)r/   r'   r1   rR   r3   r3   r4   r     s    z!PaymentDetailsView.render_previewc             K   s   d| _ | jf |}| |S )z
        Show the payment details page

        This method is useful if the submission from the payment details view
        is invalid and needs to be re-rendered with form errors showing.
        F)rx   rP   r   )r/   r'   r1   rR   r3   r3   r4   render_payment_details  s    z)PaymentDetailsView.render_payment_detailsc             C   s<   | j jjsdS y| j jjjddS  tjk
r6   dS X dS )a6  
        Return default billing address for user

        This is useful when the payment details view includes a billing address
        form - you can use this helper method to prepopulate the form.

        Note, this isn't used in core oscar as there is no billing address form
        by default.
        NT)Zis_default_for_billing)r'   r(   r)   rO   r.   r!   rM   )r/   r3   r3   r4   get_default_billing_address  s    

z.PaymentDetailsView.get_default_billing_addressNc          
   C   s  |dkri }|	dkri }	|j s&td|j s4td| |}| j| td||j | | | j	| t
d}tjj| | d y| j||f| W n4 tk
r } ztd||j t|jS d}~X Y  n tk
r. } z6t|}td|| |   | j| jfd	|i|S d}~X Y n tk
r } z:t|}tjd
||dd |   | j| jfd	|i|S d}~X Y nN tk
r } z.td|| |   | j| jfd	|i|S d}~X Y nX tjj| | d td| y$| j||||||||fd|
i|	S  t k
rn } z:t|}tjd||dd |   | j| jfd	|i|S d}~X Y nV tk
r } z6td|| t
d}|   | j| jfd	|i|S d}~X Y nX dS )a  
        Submit a basket for order placement.

        The process runs as follows:

         * Generate an order number
         * Freeze the basket so it cannot be modified any more (important when
           redirecting the user to another site for payment as it prevents the
           basket being manipulated during the payment process).
         * Attempt to take payment for the order
           - If payment is successful, place the order
           - If a redirect is required (e.g. PayPal, 3D Secure), redirect
           - If payment is unsuccessful, show an appropriate error message

        :basket: The basket to submit.
        :payment_kwargs: Additional kwargs to pass to the handle_payment
                         method. It normally makes sense to pass form
                         instances (rather than model instances) so that the
                         forms can be re-rendered correctly if payment fails.
        :order_kwargs: Additional kwargs to pass to the place_order method
        Nz7Basket tax must be set before a user can place an orderz@Shipping charge tax must be set before a user can place an orderz6Order #%s: beginning submission process for basket #%dzA problem occurred while processing payment for this order - no payment has been taken.  Please contact customer services if this problem persists)r&   viewzOrder #%s: redirecting to %sz9Order #%s: unable to take payment (%s) - restoring basketrn   zOrder #%s: payment error (%s)T)exc_infoz8Order #%s: unhandled exception while taking payment (%s)z,Order #%s: payment successful, placing order
surchargesz%Order #%s: unable to place order - %sz7Order #%s: unhandled exception while placing order (%s)zNA problem occurred while placing this order. Please contact customer services.)!Zis_tax_knownAssertionErrorZgenerate_order_numberr8   Zset_order_numberloggerr;   idZfreeze_basketZset_submitted_basketr<   r   Zpre_paymentr+   Zhandle_paymentr   urlr   ZHttpResponseRedirectr   rv   rp   Zrestore_frozen_basketr   r'   r   rn   r   	Exception	exceptionZpost_paymentZhandle_order_placementr   )r/   r(   rk   Zshipping_addressZshipping_methodZshipping_chargeZbilling_addressZorder_totalZpayment_kwargsZorder_kwargsr   order_number	error_msgemsgr3   r3   r4   r~     s|    


 
 "
 zPaymentDetailsView.submitc             C   s   | j r| jgS | jgS )N)rx   template_name_previewrE   )r/   r3   r3   r4   get_template_names  s    z%PaymentDetailsView.get_template_names)NNN)rA   rB   rC   rD   rE   r   rG   rx   ry   rz   rY   r|   r}   r   r   r   r~   r   rH   r3   r3   )r2   r4   rw   n  s&   
 rw   c                   s:   e Zd ZdZdZdZdd ZdddZ fd	d
Z  Z	S )ThankYouViewzR
    Displays the 'thank you' page which summarises the order just submitted.
    zoscar/checkout/thank_you.htmlr   c             O   s6   |   | _| jd krttjS | j| jd}| |S )N)object)
get_objectr   r   r   ZOSCAR_HOMEPAGErP   r   )r/   r'   r0   r1   contextr3   r3   r4   r.     s
    


zThankYouView.getNc             C   s   d }| j jjr^i }d| j jkr0| j jd |d< nd| j jkrL| j jd |d< tjjf | }|sd| j jkrtjj| j jd d }|S )Nr   numberZorder_idr   Zcheckout_order_id)rT   )	r'   r(   Zis_superuserGETr   rW   rS   firstsession)r/   Zquerysetr   r1   r3   r3   r4   r     s    
zThankYouView.get_objectc                sP   t  j||}d|d j}| jj|dsDd| jj|< d|d< nd|d< |S )Nzorder_{}_thankyou_viewedr   FTZsend_analytics_event)r-   rP   formatrT   r'   r   r.   )r/   r0   r1   rR   key)r2   r3   r4   rP     s    
zThankYouView.get_context_data)N)
rA   rB   rC   rD   rE   Zcontext_object_namer.   r   rP   rH   r3   r3   )r2   r4   r     s   
r   ):loggingurllib.parser   Zdjangor   Zdjango.confr   Zdjango.contribr   Zdjango.contrib.authr   Zdjango.shortcutsr   Zdjango.urlsr   r	   Zdjango.utils.translationr
   r<   Zdjango.viewsr   Zoscar.core.loadingr   r   r   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r!   r"   	getLoggerr   ZFormViewr#   rI   Z
UpdateViewrd   Z
DeleteViewrg   rh   ZTemplateViewrs   rw   Z
DetailViewr   r3   r3   r3   r4   <module>   sH   










HOf"  $