3

\(                 @   s   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 dd	lmZ ed
dZed
dZed
dZG dd deZG dd deZdS )    )Decimal)settings)Site)transaction)gettext_lazy)order_placed)	get_model   )
exceptionsorderOrderLineOrderDiscountc               @   s   e Zd ZdZdd ZdS )OrderNumberGeneratorz
    Simple object for generating order numbers.

    We need this as the order number is often required for payment
    which takes place before the order model has been created.
    c             C   s
   d|j  S )z;
        Return an order number for a given basket
        i )id)selfbasket r   1/var/www/html/oscar2019/oscar/apps/order/utils.pyorder_number   s    z!OrderNumberGenerator.order_numberN)__name__
__module____qualname____doc__r   r   r   r   r   r      s   r   c               @   sf   e Zd ZdZdddZdddZd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 )OrderCreatorz<
    Places the order by writing out the various models
    Nc             K   s  |j rttd|s&t }|j|}|	 r@ttdr@ttd}	tj	j
|dj rbttd| tj  | j|||||||||	|
f
|}x&|j D ]}| j|| | j| qW x:|jj D ],}|j|d\}}|j  s| rt|qW xh|jD ]^}|d j||||d< |d jrB|j|}|td	kr:q||d
< | j|| | j| qW x"|jj D ]}| j||| qhW W dQ R X tj | ||d |S )zz
        Placing an order involves creating all the relevant models based on the
        basket and session data.
        z!Empty baskets cannot be submittedOSCAR_INITIAL_ORDER_STATUS)numberz(There is already an order with number %s)useroffermessageresultz0.00discountN)senderr   r   )!is_empty
ValueError_r   r   hasattrr   getattrr   _default_managerfilterexistsr   atomiccreate_order_model	all_linescreate_line_modelsupdate_stock_recordsvouchersselect_for_updateis_available_to_user	is_activeoffer_applicationsapply_deferred_benefitaffects_shippingr!   Dcreate_discount_modelrecord_discountallrecord_voucher_usager   send)r   r   totalshipping_methodshipping_charger   shipping_addressbilling_addressr   statusrequestkwargs	generatorr   linevoucheravailable_to_usermsgapplicationshipping_discountr   r   r   place_order&   sF    




zOrderCreator.place_orderc          
   K   s   |||j |j|j|j|j|j|jd	}|r2||d< |r>||d< |rR|jrR|j|d< |	r^|	|d< |rl|j| d|krtj	j
|
|d< tf |}|j  |S )zCreate an order model.)	r   r   currencytotal_incl_taxtotal_excl_taxshipping_incl_taxshipping_excl_taxr>   shipping_coder@   rA   user_idrB   site)rM   incl_taxexcl_taxnamecodeis_authenticatedr   updater   r(   get_currentr   save)r   r   r   r@   r>   r?   rA   r=   r   rB   rC   Zextra_order_fieldsZ
order_datar   r   r   r   r,   e   s0    




zOrderCreator.create_order_modelc       	      C   s   |j }|j}|s tjd|j |j}|||j|j|||j |j	|j
|j|j|j|j|j|j|j|j|jjjd}|pxi }ttdr|od|ksttd|d< |r|j| tjjf |}| j||| | j||| | j||| |S )z
        Create the batch line model.

        You can set extra fields by passing a dictionary as the
        extra_line_fields value
        z"Basket line #%d has no stockrecord)r   partnerpartner_namepartner_skustockrecordproducttitleupcquantityline_price_excl_taxline_price_incl_tax$line_price_before_discounts_excl_tax$line_price_before_discounts_incl_taxunit_cost_priceunit_price_incl_taxunit_price_excl_taxunit_retail_priceest_dispatch_dateOSCAR_INITIAL_LINE_STATUSrB   ) ra   r`   r
   UnableToPlaceOrderr   r]   rW   r_   	get_titlerc   rd   "line_price_excl_tax_incl_discounts"line_price_incl_tax_incl_discountsre   rf   
cost_pricerj   rk   price_retailpurchase_infoavailabilitydispatch_dater&   r   r'   rZ   r   r(   createcreate_line_price_modelscreate_line_attributescreate_additional_line_models)	r   r   basket_lineZextra_line_fieldsra   r`   r]   Z	line_data
order_liner   r   r   r.      sH    

zOrderCreator.create_line_modelsc             C   s   |j j jr|jj|j dS )zG
        Update any relevant stock records for this order line
        N)ra   get_product_classtrack_stockr`   allocaterd   )r   rF   r   r   r   r/      s    z!OrderCreator.update_stock_recordsc             C   s   dS )z
        Empty method designed to be overridden.

        Some applications require additional information about lines, this
        method provides a clean place to create additional models that
        relate to a given line.
        Nr   )r   r   r}   r|   r   r   r   r{      s    z*OrderCreator.create_additional_line_modelsc             C   s4   |j  }x&|D ]\}}}|jj||||d qW dS )z5
        Creates the batch line price models
        )r   rd   price_incl_taxprice_excl_taxN)get_price_breakdownpricesrx   )r   r   r}   r|   Z	breakdownr   r   rd   r   r   r   ry      s    z%OrderCreator.create_line_price_modelsc             C   s2   x,|j j D ]}|j j|j|jj|jd qW dS )z4
        Creates the batch line attributes.
        )optiontypevalueN)
attributesr:   rx   r   rX   r   )r   r   r}   r|   attrr   r   r   rz      s
    z#OrderCreator.create_line_attributesc             C   sz   t ||d pd|d j|d |d d}|d }|jr@t j|_n|jrNt j|_|jdd	}|rn|j|_|j	|_
|j  d	S )
zk
        Create an order discount model for each offer application attached to
        the basket.
        r    r   freqr!   )r   r   offer_id	frequencyamountr    rG   N)r   r   r6   SHIPPINGcategoryaffects_post_orderDEFERREDget
voucher_idrX   voucher_coder\   )r   r   r!   Zorder_discountr    rG   r   r   r   r8      s     

z"OrderCreator.create_discount_modelc             C   s0   |d j | d|kr,|d r,|d j| d S )Nr   rG   )record_usager9   )r   r!   r   r   r   r9      s    zOrderCreator.record_discountc             C   s   |j || dS )zB
        Updates the models that care about this voucher.
        N)r   )r   r   rG   r   r   r   r   r;      s    z!OrderCreator.record_voucher_usage)NNNNNN)N)N)r   r   r   r   rL   r,   r.   r/   r{   ry   rz   r8   r9   r;   r   r   r   r   r   !   s     
>

:

r   N)decimalr   r7   django.confr   Zdjango.contrib.sites.modelsr   	django.dbr   django.utils.translationr   r%   oscar.apps.order.signalsr   oscar.core.loadingr   r   r
   r   r   r   objectr   r   r   r   r   r   <module>   s   


