Refactoring Order Status in Open Event

Refactoring Order Status in Open Event

This blog post will showcase the introduction of new Initializing status for orders in Open Event Frontend. So, now we have a total of six status. Let’s take a closer look and understand what exactly these order status means:

StatusDescriptionColor Code
InitializingWhen a user selects tickets and clicks on Order Now button on public event page, the user will get 15 minutes to fill up the order form. The status for order till the form is submitted is – initializingYellow
PlacedIf only offline paid tickets are present in order i.e. paymentMode belongs to one of the following – bank, cheque, onsite; then the status of order is placedBlue
PendingIf the order contains online paid tickets, the status for such order is pending. User gets 30 minutes to complete payment for such pending orders.         
If user completes the payment in this timespan of 30 minutes, the status of order is updated to completed.However if user fails to complete payment in 30 minutes, the status of the order is updated to expired.
Orange
CompletedThere are two cases when the status of order is completed –
1. If the ordered tickets are free tickets, the status of order is completed.
2. If the online payment for pending tickets is completed in timespan of 30 minutes, the status is updated to completed. 
Green
ExpiredThere are two cases when status of order is updated to expired.
1. If the user fails to fill up the order form in the 15 minutes allotted to the user, the status changes from initializing to expired.
2. If the user fails to complete the payment for online paid orders in timeframe of 30 minutes allotted, the status is updated from pending to expired. 
Red
CancelledWhen an organizer cancels an order, the order is given status of cancelled.Grey
  Placed Order
Completed Order

Pending Order
Expired Order

So, basically the status of code is set based on the value of paymentMode attribute. 

If the paymentMode is free, the status is set to completed.
If the paymentMode is bank or cheque or onsite, the status is set to placed.
Otherwise, the status is set to pending.

if (paymentMode === 'free') {
    order.set('status', 'completed');
} else if (paymentMode === 'bank' || paymentMode ===  'cheque' || paymentMode === 'onsite') {
    order.set('status', 'placed');
} else {
    order.set('status', 'pending');
}

We render the status of order at many places in the frontend, so we introduced a new helper order-color which returns the color code depending on the status of the order.

import { helper } from '@ember/component/helper';

export function orderColor(params) {
 switch (params[0]) {
   case 'completed':
     return 'green';
   case 'placed':
     return 'blue';
   case 'initializing':
     return 'yellow';
   case 'pending':
     return 'orange';
   case 'expired':
     return 'red';
   default:
     return 'grey';
 }
}

export default helper(orderColor);

This refactor was followed up on server also to accommodate changes:

  • Ensuring that the default status is always initializing. For this, we place a condition in before_post hook to mark the status as initializing.
  • Till now, the email and notification were sent out only for completed orders but as we now use placed status for offline paid orders so we send out email and notification for placed orders too. For this, I updated the condition in after_create_object hook
class OrdersListPost(ResourceList):
    ...
    def before_post(self, args, kwargs, data=None):
        ...
        if not has_access('is_coorganizer', event_id=data['event']):
           data['status'] = 'initializing'

    def after_create_object(self, order, data, view_kwargs):
       ...
       # send e-mail and notifications if the order status is completed
       if order.status == 'completed' or order.status ==  'placed':
           # fetch tickets attachment
           order_identifier = order.identifier
       ...
  • To ensure that orders with status as initializing and pending are updatable only, we introduced a check in before_update_object hook.
class OrderDetail(ResourceDetail):
    ...
    def before_update_object(self, order, data, view_kwargs):
               ...
        elif current_user.id == order.user_id:
           if order.status != 'initializing' and order.status != 'pending':
               raise ForbiddenException({'pointer': ''},  "You cannot update a non-initialized or non-pending order")
  • To allow a new status initializing for the orders, we needed to include it as a valid choice for status in order schema. 
class OrderSchema(SoftDeletionSchema):
     ...
     status = fields.Str(
       validate=validate.OneOf(
           choices=["initializing", "pending", "cancelled",
                    "completed", "placed", "expired"]
     ))

Resources:

Related work and code repo:

Close Menu