A forum for sharing django-oscar recipes?

257 views
Skip to first unread message

shafiqu...@gmail.com

unread,
Jul 6, 2014, 6:01:01 PM7/6/14
to django...@googlegroups.com
Hello all, 

What would be the best way to share django-oscar recipes? It would be great if there were something like https://djangosnippets.org for django-oscar. Or maybe it would be best to just post there? For example, here is some code I wrote that I think others might find useful:

1. Configure shipping for free shipping over $X

# methods.py

from decimal import Decimal as D

from oscar.apps.shipping import methods
from oscar.core import prices
from django.conf import settings # settings.OSCAR_FREE_SHIPPING_THRESHOLD is 100

class Standard(methods.Base):
    code = 'standard'
    name = 'Standard Local'
    description = '$5 per delivery for orders under $100. Free for orders of $100 or more.'

    def calculate(self, basket):
    if basket.total_excl_tax < settings.OSCAR_FREE_SHIPPING_THRESHOLD:
        return prices.Price(currency=basket.currency, excl_tax=D('5.00'), incl_tax=D('5.00'))
        else:
        return prices.Price(currency=basket.currency, excl_tax=D('0.00'), incl_tax=D('0.00'))

2. Set the OSCAR_ORDER_STATUS_CASCADE automatically from OSCAR_ORDER_STATUS_PIPELINE (if OSCAR_LINE_STATUS_PIPELINE = OSCAR_ORDER_STATUS_PIPELINE):

def create_OSCAR_ORDER_STATUS_CASCADE(OSCAR_ORDER_STATUS_PIPELINE_in):
    OSCAR_ORDER_STATUS_CASCADE_out = {}
    for status in OSCAR_ORDER_STATUS_PIPELINE_in:
        OSCAR_ORDER_STATUS_CASCADE_out[status] = status
    return OSCAR_ORDER_STATUS_CASCADE_out

OSCAR_ORDER_STATUS_CASCADE = create_OSCAR_ORDER_STATUS_CASCADE(OSCAR_ORDER_STATUS_PIPELINE)

3. An alternative specification for OSCAR_ORDER_STATUS_PIPELINE that allows you to specify what happens to number in stock and number allocated during the transition from one order status to another, and a function to allow backward compatibility:

OSCAR_ORDER_STATUS_PIPELINE2 = {
    'Being processed': 
        {'Out for delivery':(0,0),
         'Delivered':(-1,-1), 
         'Cancelled':(0,-1), 
         'Delivery unsuccessful':(0,0)},
    'Out for delivery': 
        {'Being processed':(0,0),
         'Delivered':(-1,-1), 
         'Cancelled':(0,-1), 
         'Delivery unsuccessful':(0,0)},
    'Delivered': 
        {'Out for delivery':(1,1),
         'Being processed':(1,1), 
         'Cancelled':(1,0), 
         'Delivery unsuccessful':(0,0)},
    'Delivery unsuccessful': 
        {'Out for delivery':(0,0),
         'Delivered':(-1,-1), 
         'Cancelled':(0,-1), 
         'Being processed':(0,0)},
    'Cancelled': 
        {'Out for delivery':(0,1),
         'Delivered':(-1,0), 
         'Being processed':(0,1), 
         'Delivery unsuccessful':(0,0)},
}

def create_OSCAR_ORDER_STATUS_PIPELINE(OSCAR_ORDER_STATUS_PIPELINE2_in):
    OSCAR_ORDER_STATUS_PIPELINE_out = {}
    for from_status in OSCAR_ORDER_STATUS_PIPELINE2_in:
        OSCAR_ORDER_STATUS_PIPELINE_out[from_status] = OSCAR_ORDER_STATUS_PIPELINE2_in[from_status].keys()
    return OSCAR_ORDER_STATUS_PIPELINE_out

OSCAR_ORDER_STATUS_PIPELINE = create_OSCAR_ORDER_STATUS_PIPELINE(OSCAR_ORDER_STATUS_PIPELINE2)

So with this new specification OSCAR_ORDER_STATUS_PIPELINE2 indicates that when the order status goes from 'Being processed' to 'Delivered', the number in stock is decremented (by the actually quantity of the line item ordered, not -1. The -1 only indicates the direction of quantity change), and the number allocated is also decremented. When an order status goes from 'Being processed' to 'Cancelled', the number in stock does not change (0) but the number allocated is decremented. To implement:

# yourproject/order/processing.py

from oscar.apps.order.processing import EventHandler as CoreEventHandler

class EventHandler(CoreEventHandler):

    def change_stock_allocations(self, lines, stockChanges, allocationChanges):
        """
        Change the stock allocations for the passed lines
        """
        
        for line, stockChange, allocationChange in zip(lines, stockChanges, allocationChanges):
            if line.stockrecord:
                line.stockrecord.change_allocation_and_stock(stockChange, allocationChange)

# yourproject/dashboard/orders/views.py (this would go under class OrderListView() along with other changes I have put in a pull request) 

def change_order_status(self, request, order):
new_status = request.POST['new_status'].strip()
if not new_status:
messages.error(request, _("The new status '%s' is not valid")
  % new_status)
return self.reload_page_response()
if not new_status in order.available_statuses():
messages.error(request, _("The new status '%s' is not valid for"
 " this order") % new_status)
return self.reload_page_response()

handler = EventHandler(request.user)
old_status = order.status
try:
handler.handle_order_status_change(order, new_status)
except PaymentError as e:
messages.error(request, _("Unable to change order status due to"
 " payment error: %s") % e)
else:
msg = _("Order status changed from '%(old_status)s' to"
" '%(new_status)s'") % {'old_status': old_status,
'new_status': new_status}
messages.info(request, msg)
order.notes.create(user=request.user, message=msg,
  note_type=OrderNote.SYSTEM)

# Now change allocations appropriately
# get the line ids, so that the line quantities are available
lines = order.lines.all()
stockChanges = []
allocationChanges = []
for line in lines:
stockChanges += [settings.OSCAR_ORDER_STATUS_PIPELINE2[old_status][new_status][0]*line.quantity]
allocationChanges += [settings.OSCAR_ORDER_STATUS_PIPELINE2[old_status][new_status][1]*line.quantity]
handler.change_stock_allocations(lines, stockChanges, allocationChanges)
return self.reload_page_response(fragment='activity')

I found this useful for managing stock and allocation levels in light of order status changes. Maybe there are better ways to do this, happy to hear suggestions.

Reply all
Reply to author
Forward
0 new messages