def get(self, request): """ summary: Get agents if they are logged in or a complete list. Parameters are optional. --- serializer: AgentDetailSerializer parameters: - name: is_available required: False type: boolean - name: agent_type required: False type: string """ try: agent_type = ( [request.query_params["agent_type"]] if "agent_type" in request.query_params else [type[0] for type in AGENT_TYPE] ) if "is_available" in request.query_params: agents = Agent.objects.filter( agent_type__in=agent_type, is_logged_in=request.query_params["is_available"] ) else: agents = Agent.objects.filter(agent_type__in=agent_type) return JSONResponse(AgentDetailSerializer(instance=agents, many=True).data, status=200) except (UnboundLocalError, KeyError) as e: beam(e) return JSONResponse({"Error": "No such active agents exist or parameters missing"}, status=200)
def post(self, request): """ summary: Operator confirms order from customer and places order on the crm description: Restaurant needs to be notified of the order and we need a confirmation of the same. \n\n Choose closest available delivery boy and assign order \n Send gcm notification to delivery boy \n Possible failure points are not able to find a delivery boy and push a notification to delivery boy --- parameters: - name: order_id type: integer required: true """ try: order_id = request.data["order_id"] # radius = request.data["radius"] if 'radius' in request.data else 100 order = Order.objects.get(id=order_id) order.restaurant_notified = True order.status = "confirmed" order.save() # try: # delivery_boy = DeliveryBoy.objects.get(pk=request.data["delivery_boy_id"]) # except Exception as e: # delivery_boy = DeliveryBoy.get_available_delivery_boy(order=order, radius = radius) # # if delivery_boy: # order.delivery_boy = delivery_boy # order.delivery_boy.is_available= False # order.status = 'assigned' # order.save() # order.delivery_boy.save() # try: # delivery_boy.notify({"order_id":order.id, "status": "new"}) # OrderLog.objects.create(order=order, message=dict(STOCK_MESSAGES)['delivery_boy_notified'], # owner_type='system', owner_id=order.agent.id) # Ticket.objects.filter(id=request.data["ticket_id"]).update(resolved_at = datetime.datetime.now()) # return JsonResponse({"Success": 'Delivery boy Notified'}, status=200) # except Exception as e: # beam(e) # Logger.log_ticket(order=order, owner= order.agent, message= dict(STOCK_MESSAGES)['failed_to_notify_delivery_boy'], # owner_type='system', ticket_type='failed_to_notify_delivery_boy') # return JsonResponse({"Success": 'Delivery boy assigned but not notified'}, status=200) # else: OrderLog.objects.create( order=order, message=dict(STOCK_MESSAGES)["confirmed"], owner_type="system", owner_id=order.agent.id ) # Logger.log_ticket(order=order, owner= order.agent, message= dict(STOCK_MESSAGES)['failed_to_assign_delivery_boy'], # owner_type='system', ticket_type='no_delivery_boy_available') return JsonResponse({"Success": "Order placed, please assign delivery boy."}, status=200) except (KeyError, ObjectDoesNotExist, Exception) as e: beam(e) return JsonResponse({"Error": "Something went wrong!"})
def post(self, request): """ summary: Logs a agent in to the system, returns token and other agent details. description: "headers: X-DEVICE-ID X-DEVICE-TYPE X-PUSH-ID" Auth: Doesn't require auth token in headers --- parameters: - name: contact_number required: true type: string """ try: agents = Agent.objects.filter(contact_number=request.data["contact_number"]) if len(agents): agent = agents[0] token = agent.login(headers=request.META) agent_json = AgentInfoSerializer(instance=agent).data agent_json["auth_token"] = token return JSONResponse(agent_json, status=200) else: return JSONResponse({"Message": "Invalid credentials!"}, status=403) except Exception as e: beam(e, request) return JSONResponse({"Message": "Could not authenticate user. Check your request headers"}, status=403)
def put(self, request): """ summary: Change the status of a ticket --- parameters: - name: ticket_id required: false type: integer - name: is_active required: false type: boolean """ try: is_active = request.data["is_active"] ticket_id = request.data["ticket_id"] resolved_at = datetime.datetime.now() if not is_active else None Ticket.objects.filter(id=ticket_id).update(is_active=is_active, resolved_at=resolved_at) return JSONResponse({"Success": "Ticket status updated"}, status=200) except (KeyError, ObjectDoesNotExist) as e: beam(e) return JSONResponse({"Error": "Missing parameters"}, status=400)
def get(self, request): """ summary: Get a customers details by id or primary number --- serializer: CustomerDetailSerializer parameters: - name: customer_id required: false type: integer - name: primary_number required: false type: string """ try: try: customer = Customer.objects.get(pk=request.query_params["customer_id"]) except Exception as e: customer = Customer.objects.get(primary_number=request.query_params["primary_number"]) customer_json = CustomerDetailSerializer(instance=customer) return JSONResponse(customer_json.data, status=200) except (ObjectDoesNotExist, KeyError) as e: beam(e) return JSONResponse( {"Error": "Customer does not exist or you haven't provided the right parameters"}, status=400 )
def get(self, request): """ summary: Fetch details of an address by id or get all adresses of a particular customer --- serializer: ContactNumberSerializer parameters: - name: address_id required: false type: string - name: customer_id required: false type: integer """ many = True try: if "address_id" in request.data: address = Address.objects.get(pk=request.query_params["address_id"]) many = False else: address = Address.objects.filter(customer_id=request.query_params["customer_id"]) return JSONResponse(AddressSerializer(instance=address, many=many).data, status=200) except (KeyError, ObjectDoesNotExist, UnboundLocalError) as e: beam(e) return JSONResponse({"Error": "Address does not exist/Bad request"}, status=200)
def post(self, request): """ summary: Post lat/long of a delivery boy --- serializer: DeliveryBoyLocationSerializer parameters: - name: delivery_boy required: true type: integer - name: latitude required: true type: decimal - name: longitude required: true type: decimal """ try: request.data["delivery_boy"] = DeliveryBoy.objects.filter(agent=request.user)[0] location = DeliveryBoyLocationSerializer() location.create(validated_data=request.data) return JSONResponse({"Success": "location logged successfully"}) except KeyError as e: beam(e) return JSONResponse({"Error": "No delivery boy found"}, status=200)
def get(self, request): """ summary: Get tickets for a particular order, type or all tickets in the system which are active --- serializer: TicketSerializer parameters: - name: order_id required: false type: integer - name: ticket_type required: false type: string """ try: if "order_id" in request.query_params: tickets = Ticket.objects.filter(order_id=request.query_params["order_id"], is_active=True) elif "ticket_type" in request.query_params: tickets = Ticket.objects.filter(ticket_type=request.query_params["ticket_type"]) else: tickets = Ticket.objects.filter(is_active=True) return JSONResponse(TicketViewSerializer(instance=tickets, many=True).data, status=200) except UnboundLocalError as e: beam(e) return JSONResponse({"Error": "Missing parameters in request"}, status=400)
def post(self, request): """ summary: Reassign a delivery to a new delivery boy --- parameters: - name: order_id required: true type: integer - name: delivery_boy_id requireds: true type: integer """ try: order = Order.objects.get(pk=request.data["order_id"]) boy = DeliveryBoy.objects.get(pk=request.data["delivery_boy_id"], is_available=True) if boy: order.assign_delivery_boy(delivery_boy=boy) OrderLog.objects.create( order=order, message=dict(STOCK_MESSAGES)["assigned_manually"], owner_id=request.user.id, owner_type="oe", ) boys = DeliveryBoy.objects.filter(is_available=True, agent__in=Agent.objects.filter(is_logged_in=True)) boys_json = DeliveryBoyDetailSerializer(instance=boys, many=True).data if boy.notify(payload={"order_id": order.id, "status": "new"}): return JSONResponse( {"Success": "Delivery boy was assigned and notified successfully", "boys": boys_json}, status=200, ) else: return JSONResponse( { "Success": ( "Delivery boy assigned but failed to notify." " Please do it via call - %s" % boy.agent.contact_number ), "boys": boys_json, }, status=200, ) else: return JSONResponse({"Message": "Delivery boy not available anymore"}, status=403) # if order.delivery_boy: # order.delivery_boy.is_available = request.data["make_available"] except Exception as e: beam(e) return JSONResponse({"Error": "Order does not exist or delivery boy is not available anymore"}, status=400)
def get(self, request): """ summary: Returns list of orders by id, status or restaurant_id and status --- serializer: OrderViewSerializer parameters: - name: order_id required: false type: integer - name: status required: false type: string - name: resturant_id required: false type: integer """ try: many = True if "order_id" in request.query_params: orders = Order.objects.get(pk=request.query_params["order_id"]) many = False elif "status" in request.query_params: start_index = request.query_params.get("start_index", 0) end_index = request.query_params.get("end_index", 100) if request.query_params["status"] == "all": orders = Order.objects.all().order_by("-created_on")[start_index:end_index] elif request.query_params["status"] == "delayed": orders = ( Order.objects.filter(delayed_by__gt=0) .exclude(status__in=["delivered", "cancelled"]) .order_by("-created_on")[start_index:end_index] ) else: orders = Order.objects.filter(status=request.query_params["status"]).order_by("-created_on")[ start_index:end_index ] elif "restaurant_id" in request.query_params: orders = Order.objects.filter( restaurant_id=request.query_params["restaurant_id"], status=request.query_params["status"] ).order_by("-created_on") try: if request.META["HTTP_X_DEVICE_TYPE"] == "android": return JSONResponse(OrderViewSerializer(instance=orders).data, status=200) except: pass return JSONResponse(OrderDetailViewSerializer(instance=orders, many=many).data, status=200) except (ObjectDoesNotExist, KeyError, UnboundLocalError) as e: beam(e, request) return JSONResponse({"Error": "No such order exists or bad request with missing parameters"}, status=400)
def post(self, request): """ Summary: Returns the search according to parameters --- parameters: - name: doc_type required: false type: string - name: query_terms required: false type: json Array - name: filters required: false type: json Array - name: boosters required: false type: json Array - name: latlong type: json Array required: false - name: offset type: integer required: false - name: count type: integer required: false """ try: doc_type = request.data.get("doc_type", 'restaurant') query_terms = request.data.get("query_terms",[]) filters = request.data.get("filters",[]) boosters = request.data.get("boosters",[]) latlong = request.data.get("latlong",[28.3169,77.2090]) offset = request.data.get("offset", 0) count = request.data.get("count", 0) search = QueryManager(index_name='nomnom', doc_type=doc_type, query_terms=query_terms, filters=filters, latlong= latlong, boosters=boosters) result = json.loads(search.get_results(offset=offset, count=count)) if 'hits' in result.get("hits", {}): result_dict = result['hits']['hits'] result_dict = json.dumps(result_dict) return JSONResponse(data=result_dict, search=True, status=200) else: return JSONResponse(result, status=400) except Exception as e: beam(e) print traceback.format_exc(e) return JSONResponse({"Error": "Missing parameters in request"}, status=400)
def push(self, message): url = self.get_base_url() + self.channel try: response = requests.post(url, message, headers={"content-type": "application/json"}) try: if response.status_code != 200: raise Exception("Status code %s" % str(response.status_code)) except Exception as e: beam(e) except Exception as e: beam(e)
def get_results(self, offset=0, count=10): url = self.BASE_URL + self.index_name + "/" + self.doc_type + "/_search/" try: response = requests.get(url, data=json.dumps(self.query_json)) # print 'Result text: \n\n\n\n' # print response.text return response.text except Exception as e: beam(e) return False
def notify(self, payload): push_id = self.get_push_id() if push_id: gcm = GCM() gcm.send_message([push_id], payload) try: s = SMS() s.send(mobile_number=self.agent.contact_number, sms_text= "Order Id: %s" % payload["order_id"]) print 'Sms sent' except Exception as e: beam(e)
def watchdog(): try: orders = Order.objects.exclude(status__in=['delivered', 'cancelled']) delayed_orders = [] ontrack_orders = [] pusher = PushMessage(channel="order_list") for order in orders: # Get expected time for the current status to have changed expected_time = window[order.status] log = OrderLog.objects.filter(order=order, message=dict(STOCK_MESSAGES)[order.status]) if len(log): assigned_time = log[0].created_on #Time aware timestamp fubar current_time = datetime.utcnow().replace(tzinfo=pytz.utc) if current_time - assigned_time > timedelta(minutes=expected_time): delayed_by = int((current_time - assigned_time).total_seconds()) - (expected_time*60) #If an alarm exists for the current status update the delay time otherwise create a new alarmnom alarm = Alarm.objects.get_or_create(order=order, for_status=order.status) alarm[0].delayed_by = delayed_by alarm[0].save() #Set order delayed time for "current step" order.delayed_by = delayed_by order.save() delayed_orders.append(order) order = OrderDetailViewSerializer(instance=order).data pusher.push(json.dumps(order)) print "Order delayed \n" else: ontrack_orders.append(order) print "Order on track \n" orders = delayed_orders + ontrack_orders return orders except Exception as e: beam(e)
def post(self, request): try: requested_by = request.data["requested_by"] if "requested_by" in request.data else "" callback = CallBackRequest(contact_number=request.data["contact_number"], requested_by=requested_by) callback.save() cosmocall_request(contact_number=request.data["contact_number"]) return JSONResponse({"Message": "Callback request created"}, status=200) except Exception as e: beam(e) return JSONResponse({"Message": "Something went wrong!"}, status=400)
def get(self, request): """ summary: Get a list of search filters --- """ try: if request.query_params["type"] == 'restaurant': filters = get_restaurant_filters() else: filters = get_menu_filters(restaurant_id=request.query_params["restaurant_id"]) except Exception as e: beam(e) filters = [] return JSONResponse(filters, status=200)
def post(self, request): """ summary: Add a new customer or update details of an existing one --- serializer: CustomerSerializer parameters: - name: primary_number required: false type: string - name: name required: true type: string - name: customer_id required: false type: integer """ try: if "customer_id" in request.data: customer = Customer.objects.get(pk=request.data["customer_id"]) customer.name = request.data["name"] customer.save() response = CustomerDetailSerializer(instance=customer).data else: customer = CustomerSerializer(data=request.data, partial=True) if customer.is_valid(): new_customer = customer.save() response = CustomerDetailSerializer(instance=new_customer).data else: response = customer.errors return JSONResponse(response, status=200) except Exception as e: beam(e) return JSONResponse({"Error": "Something went wrong"}, status=400)
def post(self, request): from django.core.mail import send_mail try: name = request.data["name"] from_email = request.data["from_email"] message = "%s \n\nName: %s" % (request.data["message"], name) send_mail( subject="Contact Us", message=message, from_email=from_email, recipient_list=[ "*****@*****.**", "*****@*****.**", "*****@*****.**", "*****@*****.**", ], fail_silently=False, ) return JSONResponse( {"message": "Thanks for getting in touch! We will get back to you shortly."}, status=200 ) except Exception as e: beam(e)
def put(self, request): """ summary: Upload end point for bill image --- parameters: - name: order_id required: true type: integer - name: bill_image required: true type: file """ try: order = Order.objects.get(id=request.data["order_id"]) order.bill_image = request.FILES["bill_image"] order.save() return JSONResponse({"Success": "Image uploaded"}, status=200) except Exception, e: beam(e) return JSONResponse({"Error": "Invalid response"}, status=400)
def put(self, request): """ summary: Delivery boy or oe sets the order status and other optional details description: "Used by the android app this allows delivery boy to update the status of an order and pass additional attributes such as bill image, money paid to restaurant or customer" --- parameters: - name: order_id required: true type: integer - name: delivery_status required: true type: string - name: amount_paid required: false type: integer - name: payment_card required: false type: integer - name: payment_cash required: false type: integer """ try: valid_status = [key for key in dict(DELIVERY_STATUS)] # Check if required parameters are available if request.data["delivery_status"] in valid_status: order = Order.objects.get(id=request.data["order_id"]) order.status = request.data["delivery_status"] if order.status == "pick_up": # try: # seconds = GoogleMaps().estimate_delivery_time(order.address, (order.restaurant.latitude, # order.restaurant.longitude)) # except Exception as e: seconds = 15 * 60 order.expected_delivery_time = datetime.datetime.now() + datetime.timedelta(seconds=seconds) order.restaurant_amount = request.data["amount_paid"] elif order.status == "delivered": order.delivered_at = datetime.datetime.now() order.payment_card = request.data["payment_card"] order.payment_cash = request.data["payment_cash"] order.deassign_delivery_boy() try: order.discount_on_delivery = request.data["discount_on_delivery"] order.address.latitude = request.data["latitude"] order.address.longitude = request.data["longitude"] order.address.save() except KeyError as k: pass elif order.status == "cancelled": order.deassign_delivery_boy() order.save() OrderLog.objects.create( order=order, message=dict(STOCK_MESSAGES)[order.status], owner_id=request.user.id, owner_type=request.user.agent_type, ) return JSONResponse({"Success": True}, status=200) else: return JSONResponse( {"Error": "Either order id is missing or you have provided a non standard status."}, status=400 ) except Exception as e: print traceback.format_exc(e) beam(e) return JSONResponse({"Error": "Something went wrong"}, status=400)
def post(self, request): try: filters = request.data.get("filters",[]) search = QueryManager(index_name='nomnom', doc_type='dish', query_terms=[], filters=filters, latlong= [], boosters=[]) result = json.loads(search.get_results(offset=0, count=1000)) map_dict = {} result_dict = [] variants =[] i = 0 for c in CART_CATEGORY: result_dict.append({ "cart_category_name": c[0], "display_name": c[1], "items":[] }) map_dict[c[0]] = i i += 1 for r in result['hits']['hits']: i= 0 r = r['_source'] r["variants"] = [] j = 0 variant_position = {} # collect variations of a dish if len(r["dish_variation_names"]): for variant in r["dish_variation_names"]: if not variant in variant_position: r["variants"].append({"name": variant, "line_item": []}) variant_position[variant] = j j += 1 r["variants"][variant_position[variant]]["line_item"].append({"variation_id": r["dish_variation_ids"][i], "portion_size": r["portion_sizes"][i], "quantity": 0, "unit_price": r["unit_price"][i]}) i += 1 else: r["dish_name"] = "Pricing missing for this dish" for e in ["dish_variation_names", "dish_variations", "dish_variation_ids", "portion_sizes", "number_of_pieces", "unit_price", "serving_sizes"]: r.pop(e, None) # Put a dish in a cart category dict result_dict[map_dict[r['cart_category']]]['items'].append(r) #print result_dict response= [] for r in result_dict: if len(r["items"]) > 0: response.append(r) return JSONResponse(data=json.dumps(response), search=True, status=200) except Exception as e: beam(e) print traceback.format_exc(e) return JSONResponse({"Error": traceback.format_exc(e)}, status=400)
def post(self, request): """ - Creates order on request of operator - order is in Awaiting confirmation state - Delivery has not been created till now. - Agent gets an estimated delivery time based on google api request --- serializer: OrderCreateSerializer parameters: - name: agent required: true type: integer - name: customer required: true type: integer - name: address required: true type: integer - name: order_items pytype: OrderLineItemOrderCreateSerializer paramType: body - name: restaurant required: true type: integer - name: total_amount required: true type: decimal - name: service_tax required: false type: decimal - name: vat_tax required: false type: decimal - name: discount_amount required: false type: integer - name: other_charges required: false type: integer responseMessages: - code: 200 - message: order details """ request.data["agent"] = request.user try: if "id" in request.data: order = Order.objects.get(pk=request.data["id"]) edited_order = OrderCreateSerializer() order = edited_order.update(instance=order, validated_data=request.data) # TODO - Completely manual updation of restaurant and delivery boy, raise ticket later try: order.delivery_boy.notify({"order_id": order.id, "status": "updated"}) except Exception: pass OrderLog.objects.create( order=order, message="Order updated", owner_id=request.user.id, owner_type="Agent" ) response = OrderDetailViewSerializer(instance=order).data else: order = OrderCreateSerializer() new_order = order.create(request.data) OrderLog.objects.create( order=new_order, message=dict(STOCK_MESSAGES)["awaiting_confirmation"], owner_id=request.user.id, owner_type="Agent", ) # Figure out if we need to call the restaurant and raise a ticket for that response = new_order.should_call() response["order"] = OrderDetailViewSerializer(instance=response["order"]).data return JSONResponse(response, status=200) except Exception as e: beam(e) return JSONResponse({"Error": "Order creation failed"}, status=400)
def get(self, request): """ summary: This endpoint is called by the ASMX server. It then publishes a push notification of the concerned agent on their cogent_agent_id Auth: Doesn't require the auth token in request headers --- serializer: CustomerDetailSerializer parameters: - name: contact_number required: true type: string - name: forwarded_for required: true type: string - name: agent_id required: true type: integer """ client, order = None, False print "request from asmx server", request.query_params # TODO Check for a B2B customer try: forwarded_for = request.query_params["forwarded_for"] if forwarded_for in B2BCall.keys(): print forwarded_for # client = PhoneNumber.objects.filter(number= forwarded_for, number_type=NUMBER_TYPE[0][0])[0] from restaurant.models import Restaurant restaurant = Restaurant.objects.get(id=B2BCall[forwarded_for]) client = ClientSerializer(instance=restaurant).data except (KeyError, IndexError): pass try: contact_number = request.query_params["contact_number"] customer = Customer.find_by_contact_number(contact_number=contact_number) customer_info = {"primary_number": contact_number, "name": "New Customer", "call_count": 1} if customer: customer.call_count += 1 customer.save() customer_info = CustomerDetailSerializer(instance=customer).data order = customer.get_pending_order() if order: order = OrderDetailViewSerializer(instance=order).data CallLog.log_call(customer, request.query_params["agent_id"]) pusher = PushMessage(channel=request.query_params["agent_id"]) print "pusher order ", order pusher.push( json.dumps({"client": client, "customer": customer_info, "order": order}, default=self.date_handler) ) return JSONResponse({"customer": customer_info}, status=200) except Exception as e: print traceback.format_exc(e) beam(e, request) return JSONResponse({"Success": False}, status=200)
def send_message(self, gcm_ids, data): try: print self.gcm.json_request(registration_ids=gcm_ids, data=data) except Exception as e: beam(e)