3

\v+                 @   s   d dl mZmZ d dlmZmZ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 d d
lmZ d dlmZ G dd dejZG dd dejZG dd dejZdS )    )modelsrouter)FValuesignals)Coalesce)cached_property)now)gettext_lazy)pgettext_lazy)InvalidStockAdjustment)AUTH_USER_MODEL)get_default_currency)AutoSlugFieldc               @   s   e Zd ZdZeedddddZeje	ddddd	Z
ejed
deddZedd Zedd Zdd ZG dd dZdd ZdS )AbstractPartneraV  
    A fulfillment partner. An individual or company who can fulfil products.
    E.g. for physical goods, somebody with a warehouse and means of delivery.

    Creating one or more instances of the Partner model is a required step in
    setting up an Oscar deployment. Many Oscar deployments will only have one
    fulfillment partner.
    Code   Tname)
max_lengthuniquepopulate_fromzPartner's nameName)r   blankpartnersZUsers)related_namer   verbose_namec             C   s   | j p
| jS )N)r   code)self r   =/var/www/html/oscar2019/oscar/apps/partner/abstract_models.pydisplay_name#   s    zAbstractPartner.display_namec             C   s:   | j j }t|dkrdS t|dkr.|d S tddS )a  
        Returns a partners primary address. Usually that will be the
        headquarters or similar.

        This is a rudimentary implementation that raises an error if there's
        more than one address. If you actually want to support multiple
        addresses, you will likely need to extend PartnerAddress to have some
        field or flag to base your decision on.
        r   N   zOscar's default implementation of primary_address only supports one PartnerAddress.  You need to override the primary_address to look up the right address)	addressesalllenNotImplementedError)r   r"   r   r   r   primary_address'   s    
zAbstractPartner.primary_addressc             C   s   | j S )z
        Stock might be coming from different warehouses. Overriding this
        function allows selecting the correct PartnerAddress for the record.
        That can be useful when determining tax.
        )r&   )r   stockrecordr   r   r   get_address_for_stockrecord=   s    z+AbstractPartner.get_address_for_stockrecordc               @   s,   e Zd ZdZdZd
ZdZedZedZ	d	S )zAbstractPartner.MetaTpartnerr   r   dashboard_accessCan access dashboardzFulfillment partnerzFulfillment partnersN)r   r   r*   r+   )r,   )
__name__
__module____qualname__abstract	app_labelorderingpermissions_r   verbose_name_pluralr   r   r   r   MetaE   s   r6   c             C   s   | j S )N)r    )r   r   r   r   __str__M   s    zAbstractPartner.__str__N)r-   r.   r/   __doc__r   r4   r   r   	CharFieldr   r   ManyToManyFieldr   userspropertyr    r&   r(   r6   r7   r   r   r   r   r      s   r   c               @   s|  e Zd ZdZejdejdeddZejdejedddZ	ej
ed	d
dZej
eddedZejeddddddZejeddddddZejeddddddZejeddddZejeddddZejeddddZejedddZejeddddZdd ZG dd  d Zed!d" Zed#d$ Zd%d& Z de _!d'd( Z"d)d* Z#de#_!d+d, Z$de$_!ed-d. Z%d/S )0AbstractStockRecorda!  
    A stock record.

    This records information about a product from a fulfilment partner, such as
    their SKU, the number they have in stock and price information.

    Stockrecords are used by 'strategies' to determine availability and pricing
    information for the customer.
    zcatalogue.ProductstockrecordsProduct)	on_deleter   r   zpartner.PartnerPartner)r@   r   r   zPartner SKUr   )r   Currency   )r   defaultzPrice (excl. tax)   T)decimal_places
max_digitsr   nullzPrice (retail)z
Cost PricezNumber in stock)r   rH   zNumber allocatedzLow Stock ThresholdzDate created)auto_now_addzDate updated)auto_nowdb_indexc             C   s*   d| j j| jf }| jr&d|| jf }|S )NzPartner: %s, product: %sz%s (%s))r)   r    productpartner_sku)r   msgr   r   r   r7      s
    zAbstractStockRecord.__str__c               @   s(   e Zd ZdZdZdZedZedZdS )zAbstractStockRecord.MetaTr)   rM   zStock recordzStock recordsN)r)   rM   )	r-   r.   r/   r0   r1   unique_togetherr4   r   r5   r   r   r   r   r6      s
   r6   c             C   s*   | j dkrdS | jdkr| j S | j | j S )a  
        The effective number in stock (eg available to buy).

        This is correct property to show the customer, not the num_in_stock
        field as that doesn't account for allocations.  This can be negative in
        some unusual circumstances
        Nr   )num_in_stocknum_allocated)r   r   r   r   net_stock_level   s
    	

z#AbstractStockRecord.net_stock_levelc             C   s   | j j jS )z5Return True if the Product is set for stock tracking.)rL   get_product_classtrack_stock)r   r   r   r   can_track_allocations   s    z)AbstractStockRecord.can_track_allocationsc          	   C   s   | j s
dS tjj| j| ddtj| j| dd | jjj| j	dj
ttdtd| d | jdkrjd| _|  j|7  _tjj| j| ddtj| j| dd dS )	z
        Record a stock allocation.

        This normally happens when a product is bought at checkout.  When the
        product is actually shipped, then we 'consume' the allocation.

        NF)instance)senderrV   createdrawusing)pkrQ   r   )rQ   )rU   r   pre_savesend	__class__r   db_for_writeobjectsfilterr[   updater   r   r   rQ   	post_save)r   quantityr   r   r   allocate   s(    	

zAbstractStockRecord.allocatec             C   s   |t | j| jkS )zC
        Test if a proposed stock consumption is permitted
        )minrQ   rP   )r   rd   r   r   r   "is_allocation_consumption_possible   s    z6AbstractStockRecord.is_allocation_consumption_possiblec             C   sH   | j s
dS | j|s ttd|  j|8  _|  j|8  _| j  dS )z
        Consume a previous allocation

        This is used when an item is shipped.  We remove the original
        allocation and adjust the number in stock accordingly
        Nz!Invalid stock consumption request)rU   rg   r   r4   rQ   rP   save)r   rd   r   r   r   consume_allocation   s    

z&AbstractStockRecord.consume_allocationc             C   s,   | j s
d S |  jt| j|8  _| j  d S )N)rU   rQ   rf   rh   )r   rd   r   r   r   cancel_allocation   s    z%AbstractStockRecord.cancel_allocationc             C   s   | j d krdS | j| j k S )NF)low_stock_thresholdrR   )r   r   r   r   is_below_threshold  s    
z&AbstractStockRecord.is_below_thresholdN)&r-   r.   r/   r8   r   
ForeignKeyCASCADEr4   rL   r)   r9   rM   r   price_currencyDecimalFieldprice_excl_taxZprice_retailZ
cost_pricePositiveIntegerFieldrP   IntegerFieldrQ   rk   DateTimeFielddate_createddate_updatedr7   r6   r<   rR   r   rU   re   alters_datarg   ri   rj   rl   r   r   r   r   r=   Q   sX   	





&r=   c               @   s   e Zd ZdZejdejdeddZej	edZ
d\ZZeedfeedffZejed	d
eedZejedddZejeddddZdd Zde_dd ZG dd dZdS )AbstractStockAlertzU
    A stock alert. E.g. used to notify users when a product is 'back in stock'.
    zpartner.StockRecordalertszStock Record)r@   r   r   Z	ThresholdOpenClosedStatusr   )r   rD   choiceszDate CreatedT)rI   zDate Closed)r   rH   c             C   s   | j | _t | _| j  d S )N)CLOSEDstatusr	   date_closedrh   )r   r   r   r   close  s    zAbstractStockAlert.closec             C   s   t d| j| jd S )Nz.<stockalert for "%(stock)s" status %(status)s>)Zstockr   )r4   r'   r   )r   r   r   r   r7   %  s    zAbstractStockAlert.__str__c               @   s(   e Zd ZdZdZdZedZedZdS )zAbstractStockAlert.MetaTr)   -date_createdzStock alertzStock alertsN)r   )	r-   r.   r/   r0   r1   r2   r4   r   r5   r   r   r   r   r6   )  s
   r6   N)rz   r{   )r-   r.   r/   r8   r   rm   rn   r4   r'   rr   	thresholdOPENr~   Zstatus_choicesr9   r   rt   ru   r   r   rw   r7   r6   r   r   r   r   rx     s$   
rx   N)	django.dbr   r   django.db.modelsr   r   r   django.db.models.functionsr   django.utils.functionalr   Zdjango.utils.timezoner	   django.utils.translationr
   r4   r   Zoscar.apps.partner.exceptionsr   oscar.core.compatr   oscar.core.utilsr   oscar.models.fieldsr   Modelr   r=   rx   r   r   r   r   <module>   s   B ;