12:51 pm
PragetX
PPP
Update Products in Order
Have to Update Products in Orders and Update the Amounts and Calculate discounts all in one.
Partially update things in Order. Instead of making saving logic of amount and discounts in serializer updated it in Models save methods
class OrderProduct(model.Model):
# ...
def save(self, *args, **kwargs):
# Calculate the amount based on quantity and per_product_price
product_price = ProductPrice.objects.filter(
product=self.product, starting_quantity__lte=self.quantity
).filter(ending_quantity__gte=self.quantity)
if product_price.exists():
self.per_product_price = product_price.first().discount_price
else:
self.per_product_price = self.product.price
self.amount = Decimal(self.quantity) * Decimal(self.per_product_price)
super().save(*args, **kwargs)
class Oredr(model.Model):
def save(self, *args, **kwargs):
# ...
self.amount = OrderProduct.objects.filter(order=self).aggregate(
total_amount=Sum("amount")
)["total_amount"]
# ...Simplified the Update Function in Serializer and moving the calculation logic to model. So that it works in create as well.
class OrderProductUpdateSerializer(serializer.ModelSerializer):
def update(self, instance, validated_data):
order_products = OrderProduct.objects.filter(order=instance).all()
for order_data in orders_data:
order_product = order_products.filter(
product=order_data["product"].id
).first()
if order_product:
order_product.quantity = order_data["quantity"]
order_product.save()
order_products = order_products.exclude(id=order_product.id)
else:
product = Product.objects.filter(id=order_data["product"].id).first()
order_data["product"] = product
order_product_created = OrderProduct.objects.create(
order=instance, **order_data
)
order_products = order_products.exclude(id=order_product_created.id)
print(order_product_created)
for order_product in order_products:
order_product.delete()
super().update(instance, validated_data)
return instance
Update in Order API to include patch of order
class OrderAPI(viewset.ViewSet):
# ...
# ...
def get_serializer_class(self):
# ...
elif self.action in ["partial_update"]:
return OrderUpdateProductSerializer
# ...
# ...
def partial_update(self, request, *args, **kwargs):
serializer = self.get_serializer(
data=request.data, context={"user": request.user}
)
order = self.get_object(request)
if serializer.is_valid():
serializer.partial_update(order, serializer.validated_data)
response = {
"message": "Updated Succesfully",
"data": {"id": order.id},
"status": True,
}
return Response(response, status=status.HTTP_200_OK)
first_error_key = next(iter(serializer.errors))
first_error_value = str(serializer.errors[first_error_key][0])
first_error_key = capitalize_key(first_error_key)
error_message = f"{first_error_key}: {first_error_value}"
response = {"message": error_message, "status": True}
return Response(response, status=status.HTTP_200_OK)InfinityTalks
Chat Feature in InfinityTalks using WebSocket and Asynchronous Django Initially it was written using socketio which doesn’t works with Flutter or giving some issues. Don’t know what. I don’t mind changing from socketio to plain websockets. Here’s What I transformed in Chat Consumer in my code
from datetime import datetime
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer
class ChatConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
try:
await self.accept()
print(f"WebSocket connected: {self.channel_name}")
except Exception as e:
print(f"Error in connect event: {e}")
async def disconnect(self, close_code):
print(f"WebSocket disconnected: {self.channel_name}")
async def receive_json(self, json_data):
print(f"WebSocket receive: {json_data}")
event = json_data.get("event", None)
if event is not None:
await self.__getattribute__(event)(json_data["data"])
async def join_chat(self, data):
"""Event for both customer and listener to join the room"""
try:
customer_id = data.get("user_id")
listener_id = data.get("listener_id")
room = await self.get_room_by_customer_listener(customer_id, listener_id)
if room:
pass
else:
customer = await self.get_user(customer_id)
listener = await self.get_user(listener_id)
room = await self.create_room(customer, listener)
await self.channel_layer.group_add(f"room-{room.id}", self.channel_name)
await self.channel_layer.group_send(
f"room-{room.id}",
{
"type": "chat.message",
"data": {
"status": True,
"message": "success",
"data": {"room": f"room-{room.id}"},
},
},
)
except Exception as e:
print("e: ", e)
async def connect_chat(self, data):
"""For customer to check if the listener is available"""
try:
print("connectChat event")
customer_id = data.get("user_id")
listener_id = data.get("listener_id")
room = await self.get_room_by_customer_listener(customer_id, listener_id)
listener = await self.get_listener(listener_id)
if listener.is_busy:
await self.send_json(
{"status": True, "message": "Listener is busy", "data": None}
)
if not listener.is_available_for_chat:
await self.send_json(
{
"status": True,
"message": "Listener is not available",
"data": None,
}
)
await self.send_json(
{
"status": True,
"message": "Chat request sent to listener",
"data": {"room": f"room-{room.id}"},
}
)
except Exception as e:
print("e: ", e)
async def accept_chat(self, data):
"""For listener to accept the chat request"""
try:
print("acceptChat event")
customer_id = data.get("user_id")
listener_id = data.get("listener_id")
status = data.get("status")
room = await self.get_room_by_customer_listener(customer_id, listener_id)
if status == "rejected":
pass
if status == "accepted":
customer = await self.get_user(customer_id)
listener = await self.get_user(listener_id)
consultation = await self.create_consultation(customer, listener)
print("consultation: ", consultation)
await self.channel_layer.group_send(
f"room-{room.id}",
{
"type": "chat.accepted",
"data": {
"status": True,
"message": "success",
"data": {
"rate": listener.rate,
"is_busy": listener.is_busy,
"type": "chat",
"room": f"room-{room.id}",
},
},
},
)
except Exception as e:
print("e: ", e)
async def on_message(self, data):
"""On message event for both customer and listener"""
try:
room_id = data.get("room_id")
sender_id = data.get("sender_id")
receiver_id = data.get("receiver_id")
consultation_id = data.get("consultation_id")
message = data.get("message")
room = await self.get_room(room_id)
sender = await self.get_user(sender_id)
receiver = await self.get_user(receiver_id)
consultation = await self.get_consultation(consultation_id)
message = await self.create_message(
room, sender, receiver, consultation, message
)
await self.channel_layer.group_send(
room_id,
{
"type": "on.message",
"data": {
"status": True,
"message": "success",
"data": {
"room": room_id,
"sender": sender_id,
"receiver": receiver_id,
"consultation": consultation_id,
"message": message,
"created_at": message.created_at,
},
},
},
)
except Exception as e:
print("e: ", e)
async def pause_chat(self, data):
"""For both if user removes app from background"""
try:
room_id = data.get("room_id")
consultation_id = data.get("consultation_id")
consultation = await self.get_consultation(consultation_id)
if not consultation.exists():
await self.send_json(
{"status": False, "message": "Consultation not found", "data": None}
)
consultation = await self.update_consultation(consultation_id, "paused")
await self.channel_layer.group_send(
room_id,
{
"type": "chat.paused",
"data": {
"status": True,
"message": "Paused",
"data": {"room_id": room_id},
},
},
)
except Exception as e:
print("e: ", e)
async def resume_chat(self, data):
"""For both if user gets back to app"""
try:
room_id = data.get("room_id")
consultation_id = data.get("consultation_id")
consultation = await self.get_consultation(consultation_id)
if not consultation.exists():
await self.send_json(
{"status": False, "message": "Consultation not found", "data": None}
)
consultation = await self.update_consultation(consultation_id, "resumed")
await self.channel_layer.group_send(
room_id,
{
"type": "chat.resumed",
"data": {
"status": True,
"message": "Resumed",
"data": {"room_id": room_id},
},
},
)
except Exception as e:
print("e: ", e)
async def leave_chat(self, data):
"""For customer to leave chat"""
try:
consultaion_id = data.get("consultation_id")
listener_id = data.get("listener_id")
room_id = data.get("room_id")
consultation = await self.get_consultation(consultaion_id)
room = await self.get_room(room_id)
print("room: ", room)
if consultation.exists():
consultation = await self.update_consultation(
consultaion_id, status="completed", end_time=datetime.now(), amount=0
)
await self.update_listener(listener_id, is_busy=False)
await self.channel_layer.group_discard(room_id, self.channel_name)
await self.send_json(
{"status": True, "message": "success", "data": None}
)
except Exception as e:
print("e: ", e)
@database_sync_to_async
def get_room(self, room_id):
from apps.admin_panel.models import ChatRoom
return ChatRoom.objects.filter(id=room_id).first()
@database_sync_to_async
def get_room_by_customer_listener(self, customer_id, listener_id):
from apps.admin_panel.models import ChatRoom
return ChatRoom.objects.filter(
customer=customer_id, listener=listener_id
).first()
@database_sync_to_async
def get_user(self, user_id):
from apps.admin_panel.models import User
return User.objects.filter(id=user_id).first()
@database_sync_to_async
def get_listener(self, listener_id):
from apps.admin_panel.models import ListenerDetail
return ListenerDetail.objects.filter(id=listener_id).first()
@database_sync_to_async
def create_room(self, customer, listener):
from apps.admin_panel.models import ChatRoom
return ChatRoom.objects.create(customer=customer, listener=listener)
@database_sync_to_async
def create_consultation(self, customer, listener):
from apps.admin_panel.models import Consultation
return Consultation.objects.create(
customer=customer, listener=listener, type="chat", status="accepted"
)
@database_sync_to_async
def get_consultation(self, consultation_id):
from apps.admin_panel.models import Consultation
return Consultation.objects.filter(id=consultation_id).first()
@database_sync_to_async
def create_message(self, room, sender, receiver, consultation, message):
from apps.admin_panel.models import ChatMessage
return ChatMessage.objects.create(
room=room,
sender=sender,
receiver=receiver,
consultation=consultation,
message=message,
)
@database_sync_to_async
def update_consultation(self, consultation_id, **kwargs):
from apps.admin_panel.models import Consultation
return Consultation.objects.update(id=consultation_id, **kwargs)
@database_sync_to_async
def update_listener(self, listener_id, **kwargs):
from apps.admin_panel.models import ListenerDetail
return ListenerDetail.objects.update(id=listener_id, **kwargs)Links : Tags : Year : 2024 Month : March 24, March Date : 19th March, Tuesday, 2024, 19th March Category : Daily