B
    `0                 @   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m	Z	 d dl
mZ d dlmZm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dZeddZeddZe dZG dd deZdS )    N)Site)ObjectDoesNotExist)HttpResponseRedirect)NoReverseMatchreverse)post_checkout)	get_class	get_modelzorder.utilsOrderCreatorOrderDispatcherzcheckout.sessionCheckoutSessionMixinorderBillingAddressShippingAddressOrderNumberGeneratorPaymentEventTypePaymentEventPaymentEventQuantityaddressUserAddressbasketBasketzoscar.checkoutc               @   s   e Zd ZdZdZdZeZdd Zdd Z	d.dd	Z
d
d Zd/ddZd0ddZdd Zdd Zd1ddZdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- ZdS )2OrderPlacementMixinz
    Mixin which provides functionality for placing orders.

    Any view class which needs to place an order should use this mixin.
    Nc             K   s   dS )a  
        Handle any payment processing and record payment sources and events.

        This method is designed to be overridden within your project.  The
        default is to do nothing as payment is domain-specific.

        This method is responsible for handling payment and recording the
        payment sources (using the add_payment_source method) and payment
        events (using add_payment_event) so they can be
        linked to the order when it is saved later on.
        N )selforder_numbertotalkwargsr   r   I/home/dcms/DCMS/lib/python3.7/site-packages/oscar/apps/checkout/mixins.pyhandle_payment0   s    z"OrderPlacementMixin.handle_paymentc             C   s    | j dkrg | _ | j | dS )z8
        Record a payment source for this order
        N)_payment_sourcesappend)r   sourcer   r   r   add_payment_source>   s    
z&OrderPlacementMixin.add_payment_source c             C   s@   t jj|d\}}| jdkr"g | _t|||d}| j| dS )zN
        Record a payment event for creation once the order is placed
        )nameN)
event_typeamount	reference)r   objectsZget_or_create_payment_eventsr   r!   )r   Zevent_type_namer'   r(   r&   __eventr   r   r   add_payment_eventF   s    
z%OrderPlacementMixin.add_payment_eventc             C   s   t  |S )z+
        Return a new order number
        )r   r   )r   r   r   r   r   generate_order_numberW   s    z)OrderPlacementMixin.generate_order_numberc
             K   s6   | j f |||||||||	d	|
}|  | |S )a   
        Write out the order models and return the appropriate HTTP response

        We deliberately pass the basket in here as the one tied to the request
        isn't necessarily the correct one to use in placing the order.  This
        can happen when a basket gets frozen.
        )	r   userr   shipping_addressshipping_methodshipping_chargeorder_totalbilling_address
surcharges)place_orderZsubmithandle_successful_order)r   r   r/   r   r0   r1   r2   r4   r3   r5   r   r   r   r   r   handle_order_placement]   s    z*OrderPlacementMixin.handle_order_placementc
             K   s   |  ||}| j|||f|
}d|
kr2| |}n
|
d}d|
krRt| dd}n
|
d}t jf |||||||||||	d|
}| | |S )zM
        Writes the order out to the DB including the payment models
        statusrequestN)r/   r   r   r0   r1   r2   r   r4   r9   r:   r5   )create_shipping_addresscreate_billing_addressget_initial_order_statuspopgetattrr
   r6   save_payment_details)r   r   r/   r   r0   r1   r2   r3   r4   r5   r   r9   r:   r   r   r   r   r6   p   s0    


zOrderPlacementMixin.place_orderc             C   s&   |sdS |   |jr"| || |S )z
        Create and return the shipping address for the current order.

        Compared to self.get_shipping_address(), ShippingAddress is saved and
        makes sure that appropriate UserAddress exists.
        N)saveis_authenticatedupdate_address_book)r   r/   r0   r   r   r   r;      s    	z+OrderPlacementMixin.create_shipping_addressc             C   s|   y|j j| d}W n( tk
r>   t|d}|| Y nX t|trX| jd7  _t|t	rp| j
d7  _
|  dS )zR
        Update the user's address book based on the new shipping address
        )hash)r/      N)	addressesgetZgenerate_hashr   r   Zpopulate_alternative_model
isinstancer   Znum_orders_as_shipping_addressr   Znum_orders_as_billing_addressrA   )r   r/   addrZ	user_addrr   r   r   rC      s    


z'OrderPlacementMixin.update_address_bookc             K   s&   |sdS |   |jr"| || |S )zK
        Saves any relevant billing data (e.g. a billing address).
        N)rA   rB   rC   )r   r/   r4   r0   r   r   r   r   r<      s    z*OrderPlacementMixin.create_billing_addressc             C   s   |  | | | dS )z
        Saves all payment-related details. This could include a billing
        address, payment sources and any order payment events.
        N)save_payment_eventssave_payment_sources)r   r   r   r   r   r@      s    
z(OrderPlacementMixin.save_payment_detailsc             C   sT   | j s
dS xD| j D ]:}||_|  x&|j D ]}tjj|||jd q0W qW dS )zB
        Saves any relevant payment events for this order
        N)r,   linequantity)	r*   r   rA   linesallr   r)   createrM   )r   r   r,   rL   r   r   r   rJ      s    z'OrderPlacementMixin.save_payment_eventsc             C   s,   | j s
dS x| j D ]}||_|  qW dS )z
        Saves any payment sources used in this order.

        When the payment sources are created, the order model does not exist
        and so they need to have it set before saving.
        N)r    r   rA   )r   r   r"   r   r   r   rK      s
    z(OrderPlacementMixin.save_payment_sourcesc             C   s   d S )Nr   )r   r   r   r   r   r=      s    z,OrderPlacementMixin.get_initial_order_statusc             C   sB   |  | | j  |j| jjd< t|  }| | j|| |S )z
        Handle the various steps required after an order has been successfully
        placed.

        Override this view if you want to perform custom actions when an
        order is submitted.
        Zcheckout_order_id)	send_order_placed_emailcheckout_sessionflushidr:   sessionr   get_success_urlsend_signal)r   r   responser   r   r   r7      s    	

z+OrderPlacementMixin.handle_successful_orderc             C   s   | j j| ||j||d d S )N)Zsenderr   r/   r:   rX   )view_signalsendr/   )r   r:   rX   r   r   r   r   rW     s    zOrderPlacementMixin.send_signalc             C   s   t dS )Nzcheckout:thank-you)r   )r   r   r   r   rV     s    z#OrderPlacementMixin.get_success_urlc             C   s$   |  |}ttd}||| d S )N)logger)get_message_contextr   r[   Z send_order_placed_email_for_user)r   r   Zextra_context
dispatcherr   r   r   rQ     s    

z+OrderPlacementMixin.send_order_placed_emailc             C   s   | j j||j d}y:| j jjr6tdd|jid}ntd|j| dd}W n tk
rd   Y n"X t	j
| j }d|j|f |d< |S )	N)r/   r   rN   zcustomer:orderr   )r   zcustomer:anon-order)r   rD   zhttp://%s%sZ
status_url)r:   r/   rN   rO   rB   r   numberZverification_hashr   r   r)   Zget_currentdomain)r   r   ctxpathsiter   r   r   r\     s    
z'OrderPlacementMixin.get_message_contextc             C   s   | j  }tjj|dS )N)pk)rR   Zget_submitted_basket_idr   Z_default_managerrG   )r   Z	basket_idr   r   r   get_submitted_basket+  s    
z(OrderPlacementMixin.get_submitted_basketc             C   s   |   dS )zC
        Freeze the basket so it can no longer be modified
        N)freeze)r   r   r   r   r   freeze_basket/  s    z!OrderPlacementMixin.freeze_basketc             C   sb   y|   }W n tjk
r"   Y n<X |  | jjj|jkr^|| jj | jjj|_|| j_dS )z
        Restores a frozen basket as the sole OPEN basket.  Note that this also
        merges in any new products that have been added to a basket that has
        been created while payment.
        N)	rd   r   ZDoesNotExistZthawr:   r   rT   mergeZstrategy)r   Z
fzn_basketr   r   r   restore_frozen_basket9  s    z)OrderPlacementMixin.restore_frozen_basket)r$   )N)NN)NN)__name__
__module____qualname____doc__r    r*   r   rY   r   r#   r-   r.   r8   r6   r;   rC   r<   r@   rJ   rK   r=   r7   rW   rV   rQ   r\   rd   rf   rh   r   r   r   r   r      s4   
	

' 

r   )loggingZdjango.contrib.sites.modelsr   Zdjango.core.exceptionsr   Zdjango.httpr   Zdjango.urlsr   r   Zoscar.apps.checkout.signalsr   Zoscar.core.loadingr   r	   r
   r   r   r   r   r   r   r   r   r   r   	getLoggerr[   r   r   r   r   r   <module>   s&   











