3

\)                 @   sX   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G dd	 d	eZd
S )    )Decimal)gettext_lazy)
exceptions)	get_modelorderShippingEventQuantityPaymentEventQuantityc               @   s   e Zd ZdZd"ddZdd Zd#ddZd$d	d
Zdd Zd%ddZ	dd Z
dd Zdd Zd&ddZd'ddZdd Zd(ddZdd Zd)d d!ZdS )*EventHandlerz
    Handle requested order events.

    This is an important class: it houses the core logic of your shop's order
    processing pipeline.
    Nc             C   s
   || _ d S )N)user)selfr
    r   6/var/www/html/oscar2019/oscar/apps/order/processing.py__init__   s    zEventHandler.__init__c             K   s(   | j ||||f| | j||||f|S )a  
        Handle a shipping event for a given order.

        This is most common entry point to this class - most of your order
        processing should be modelled around shipping events.  Shipping events
        can be used to trigger payment and communication events.

        You will generally want to override this method to implement the
        specifics of you order processing pipeline.
        )validate_shipping_eventcreate_shipping_event)r   r   
event_typelinesline_quantitieskwargsr   r   r   handle_shipping_event   s    z"EventHandler.handle_shipping_eventc             K   s,   | j |||||f| | j|||||f|S )ap  
        Handle a payment event for a given order.

        These should normally be called as part of handling a shipping event.
        It is rare to call to this method directly.  It does make sense for
        refunds though where the payment event may be unrelated to a particular
        shipping event and doesn't directly correspond to a set of lines.
        )validate_payment_eventcreate_payment_event)r   r   r   amountr   r   r   r   r   r   handle_payment_event,   s    
z!EventHandler.handle_payment_eventc             C   s   |j | |r| j|| dS )a  
        Handle a requested order status change

        This method is not normally called directly by client code.  The main
        use-case is when an order is cancelled, which in some ways could be
        viewed as a shipping event affecting all lines.
        N)
set_statuscreate_note)r   r   
new_statusnote_msgr   r   r   handle_order_status_change;   s    
z'EventHandler.handle_order_status_changec       
      K   s\   g }x>t ||D ]0\}}|j||stdd|ji }	|j|	 qW |rXtjdj|dS )zp
        Test if the requested shipping event is permitted.

        If not, raise InvalidShippingEvent
        z8The selected quantity for line #%(line_id)s is too largeline_idz, N)zipis_shipping_event_permitted_idappendr   InvalidShippingEventjoin)
r   r   r   r   r   r   errorslineqtymsgr   r   r   r   J   s    z$EventHandler.validate_shipping_eventc             K   sd   |r`|r`g }x>t ||D ]0\}}	|j||	stdd|ji }
|j|
 qW |r`tjdj|d S )Nz8The selected quantity for line #%(line_id)s is too larger   z, )r    is_payment_event_permittedr"   r#   r$   r   InvalidPaymentEventr&   )r   r   r   r   r   r   r   r'   r(   r)   r*   r   r   r   r   ]   s    z#EventHandler.validate_payment_eventc             C   s.   x(t ||D ]\}}|j||k rdS qW dS )a  
        Test whether the passed lines and quantities have been through the
        specified shipping event.

        This is useful for validating if certain shipping events are allowed
        (ie you can't return something before it has shipped).
        FT)r    shipping_event_quantity)r   r   r   r   r   r(   Zline_qtyr   r   r    have_lines_passed_shipping_eventm   s    	z-EventHandler.have_lines_passed_shipping_eventc             C   s   t d}xt||D ]\}}|j|}|| |jkr:tjd}xh|jj jdD ]T}	||kr^P |	j| }
|
dkr|||	j8 }qPt	|| |
}|||	j
 7 }d}||7 }qPW qW |S )ai  
        Calculate the total charge for the passed event type, lines and line
        quantities.

        This takes into account the previous prices that have been charged for
        this event.

        Note that shipping is not including in this subtotal.  You need to
        subclass and extend this method if you want to include shipping costs.
        z0.00r   r#   )Dr    payment_event_quantityquantityr   r,   pricesallorder_byminprice_incl_tax)r   r   r   r   totalr(   Zqty_to_consumeZqty_to_skipZqty_consumedpriceZqty_availableZqty_to_includer   r   r    calculate_payment_event_subtotal~   s$    

z-EventHandler.calculate_payment_event_subtotalc             C   s@   x:t ||D ],\}}|j}|s"dS |js*q|j|sdS qW dS )a  
        Check whether stock records still have enough stock to honour the
        requested allocations.

        Lines whose product doesn't track stock are disregarded, which means
        this method will return True if only non-stock-tracking-lines are
        passed.
        This means you can just throw all order lines to this method, without
        checking whether stock tracking is enabled or not.
        This is okay, as calling consume_stock_allocations() has no effect for
        non-stock-tracking lines.
        FT)r    stockrecordcan_track_allocations"is_allocation_consumption_possible)r   r   r   r(   r)   recordr   r   r   are_stock_allocations_available   s    
z,EventHandler.are_stock_allocations_availablec             C   sN   |s|j j }|s dd |D }x(t||D ]\}}|jr,|jj| q,W dS )z
        Consume the stock allocations for the passed lines.

        If no lines/quantities are passed, do it for all lines.
        c             S   s   g | ]
}|j qS r   )r1   ).0r(   r   r   r   
<listcomp>   s    z:EventHandler.consume_stock_allocations.<locals>.<listcomp>N)r   r3   r    r:   consume_allocation)r   r   r   r   r(   r)   r   r   r   consume_stock_allocations   s    
z&EventHandler.consume_stock_allocationsc             C   sN   |s|j j }|s dd |D }x(t||D ]\}}|jr,|jj| q,W dS )z
        Cancel the stock allocations for the passed lines.

        If no lines/quantities are passed, do it for all lines.
        c             S   s   g | ]
}|j qS r   )r1   )r?   r(   r   r   r   r@      s    z9EventHandler.cancel_stock_allocations.<locals>.<listcomp>N)r   r3   r    r:   cancel_allocation)r   r   r   r   r(   r)   r   r   r   cancel_stock_allocations   s    
z%EventHandler.cancel_stock_allocationsc       
      K   sn   |j dd}|jj||d}y,x&t||D ]\}}	|jj||	d q*W W n  tjk
rh   |j   Y nX |S )N	reference )r   notes)r(   r1   )getshipping_eventscreater    r   r   r%   delete)
r   r   r   r   r   r   rE   eventr(   r1   r   r   r   r      s    
z"EventHandler.create_shipping_eventc             K   sR   |j dd}|jj|||d}|rN|rNx&t||D ]\}	}
|jj|	|
d q2W |S )NrE   rF   )r   r   rE   )r(   r1   )rH   payment_eventsrJ   r    r   )r   r   r   r   r   r   r   rE   rL   r(   r1   r   r   r   r      s    z!EventHandler.create_payment_eventc             C   s   |j j|dS )N)r   )communication_eventsrJ   )r   r   r   r   r   r   create_communication_event  s    z'EventHandler.create_communication_eventSystemc             C   s   |j j||| jdS )N)message	note_typer
   )rG   rJ   r
   )r   r   rQ   rR   r   r   r   r     s    zEventHandler.create_note)N)NN)N)NN)NN)NN)NN)rP   )__name__
__module____qualname____doc__r   r   r   r   r   r   r.   r9   r>   rB   rD   r   r   rO   r   r   r   r   r   r	      s&   
 

 
5

 

r	   N)decimalr   r/   django.utils.translationr   r"   oscar.apps.orderr   oscar.core.loadingr   r   r   objectr	   r   r   r   r   <module>   s   

