Skip to content

Commit

Permalink
Merge pull request #72 from Build-Squad/muditm/eng-31-checkout-page-api
Browse files Browse the repository at this point in the history
eng 31 checkout page api
  • Loading branch information
muditmahajan authored Jan 9, 2024
2 parents 643bad1 + 2a806e3 commit 2a45bd3
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 64 deletions.
6 changes: 3 additions & 3 deletions src/api/marketplace/orders/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Meta:
db_table = "order"

def __str__(self):
return self.buyer.username + " - " + self.status
return (self.buyer.username if self.buyer else 'No buyer') + " - " + self.status + " - " + str(self.created_at)

class OrderItem(models.Model):

Expand All @@ -51,7 +51,7 @@ class Meta:
db_table = "order_item"

def __str__(self):
return self.package.name + " - " + self.status
return (self.service_master.name if self.service_master else 'No service master') + " - " + (self.status if self.status else 'No status') + " - " + str(self.created_at)

class OrderAttachment(models.Model):

Expand Down Expand Up @@ -91,7 +91,7 @@ class Meta:
db_table = "order_item_meta_data"

def __str__(self):
return self.label + " - " + self.field_type
return (self.label if self.label else 'No label') + " - " + (self.field_type if self.field_type else 'No field type')

class OrderItemTracking(models.Model):

Expand Down
50 changes: 47 additions & 3 deletions src/api/marketplace/orders/serializers.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,62 @@
from packages.models import Service
from rest_framework import serializers
from .models import Order, OrderItem, OrderAttachment, OrderItemTracking, OrderMessage, OrderMessageAttachment, Transaction, Review

from .models import Order, OrderItem, OrderAttachment, OrderItemMetaData, OrderItemTracking, OrderMessage, OrderMessageAttachment, Transaction, Review
from django.db import transaction
from django.core.exceptions import ObjectDoesNotExist
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'


class OrderItemSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = '__all__'


class OrderItemMetaDataSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItemMetaData
fields = '__all__'


class MetaDataSerializer(serializers.Serializer):
value = serializers.CharField(allow_null=True)
service_master_meta_data_id = serializers.UUIDField(required=True)


class OrderItemSerializer(serializers.Serializer):
service_id = serializers.UUIDField(required=True)
meta_data = serializers.ListField(child=MetaDataSerializer())


class CreateOrderSerializer(serializers.Serializer):
order_items = serializers.ListField(child=OrderItemSerializer())

# @transaction.atomic
def create(self, validated_data):
order_items = validated_data['order_items']
order = Order.objects.create(
buyer=self.context['request'].user_account)

for order_item_data in order_items:
try:
service = Service.objects.get(id=order_item_data['service_id'])
except ObjectDoesNotExist:
raise serializers.ValidationError(
{"service_id": "Service with id {} does not exist.".format(order_item_data['service_id'])})

order_item = OrderItem.objects.create(
order_id=order, service_master=service.service_master, package=service.package, price=service.price, currency=service.currency, platform_fee=service.platform_fees)

service_master_meta_data = service.service_master.service_master_meta_data_id.all()
for meta_data in order_item_data['meta_data']:
for service_master_meta_data_item in service_master_meta_data:
if service_master_meta_data_item.id == meta_data['service_master_meta_data_id']:
OrderItemMetaData.objects.create(
order_item=order_item, label=service_master_meta_data_item.label, value=meta_data['value'], field_type=service_master_meta_data_item.field_type, span=service_master_meta_data_item.span)
return order

class OrderAttachmentSerializer(serializers.ModelSerializer):
class Meta:
model = OrderAttachment
Expand Down
10 changes: 7 additions & 3 deletions src/api/marketplace/orders/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from marketplace.authentication import JWTAuthentication
from marketplace.services import (
Pagination,
handleServerException,
Expand All @@ -20,6 +21,7 @@
Review,
)
from .serializers import (
CreateOrderSerializer,
OrderSerializer,
OrderItemSerializer,
OrderAttachmentSerializer,
Expand Down Expand Up @@ -52,10 +54,13 @@ def get(self, request):
except Exception as e:
return handleServerException(e)

@swagger_auto_schema(request_body=OrderSerializer)
authentication_classes = [JWTAuthentication]

@swagger_auto_schema(request_body=CreateOrderSerializer)
def post(self, request):
try:
serializer = OrderSerializer(data=request.data)
serializer = CreateOrderSerializer(
data=request.data, context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(
Expand All @@ -71,7 +76,6 @@ def post(self, request):
except Exception as e:
return handleServerException(e)


# Retrieve-Update-Destroy API
class OrderDetail(APIView):
def get_object(self, pk):
Expand Down
2 changes: 1 addition & 1 deletion src/api/marketplace/packages/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def post(self, request):
if serializer.is_valid():
# Get all the wallets of the user
user_wallets = Wallet.objects.filter(
user_id=request.user_account.id, deleted_at=None
user_id=request.user_account.id
)
if len(user_wallets) == 0:
return handleBadRequest("User does not have any wallet")
Expand Down
93 changes: 82 additions & 11 deletions src/ui/app/checkout/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
"use client";

import { notification } from "@/src/components/shared/notification";
import { useAppDispatch, useAppSelector } from "@/src/hooks/useRedux";
import { resetCart, updateFieldValues } from "@/src/reducers/cartSlice";
import { postService } from "@/src/services/httpServices";
import AddIcon from "@mui/icons-material/Add";
import {
Box,
Button,
Expand All @@ -15,32 +20,58 @@ import {
TextField,
Typography,
} from "@mui/material";
import { checkedOutServices, formFields, masterFields } from "./consts";
import AddIcon from "@mui/icons-material/Add";
import { DateTimePicker } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import dayjs from "dayjs";
import { DateTimePicker, TimePicker } from "@mui/x-date-pickers";
import NextLink from "next/link";
import { useAppSelector } from "@/src/hooks/useRedux";
import { notification } from "@/src/components/shared/notification";
import { useRouter } from "next/navigation";
import React, { useEffect } from "react";

export default function CheckoutPage() {
const dispatch = useAppDispatch();
const cart = useAppSelector((state) => state.cart);
const user = useAppSelector((state) => state.user);
const route = useRouter();

const [orderItems, setOrderItems] = React.useState<OrderItemType[]>([]);

if (!user) {
notification("You need to login first", "error");
route.push("/");
return null;
}

const createOrder = async () => {
const body = {
order_items: cart?.orderItems?.map((orderItem) => {
return {
service_id: orderItem?.service?.id,
meta_data:
orderItem?.service?.service_master?.service_master_meta_data?.map(
(metaData) => {
return {
service_master_meta_data_id: metaData?.id,
value: metaData?.value,
};
}
),
};
}),
};
try {
const { isSuccess, message, data } = await postService(
"/orders/order/",
body
);
if (isSuccess) {
notification(message, "success");
dispatch(resetCart());
} else {
notification(message, "error");
}
} finally {
}
};

if (cart?.orderItems?.length === 0) {
return (
<Box
Expand Down Expand Up @@ -76,7 +107,7 @@ export default function CheckoutPage() {
p: 2,
}}
>
{cart?.orderItems?.map((orderItem) => {
{cart?.orderItems?.map((orderItem, index: number) => {
return (
<Box
sx={{
Expand Down Expand Up @@ -150,6 +181,17 @@ export default function CheckoutPage() {
</FormLabel>
{formFields?.field_type === "text" && (
<TextField
value={formFields?.value}
name={formFields?.id}
onChange={(e) => {
dispatch(
updateFieldValues({
index: index,
service_master_meta_data_id: formFields?.id,
value: e.target.value,
})
);
}}
variant="outlined"
fullWidth
placeholder={formFields?.placeholder}
Expand All @@ -163,6 +205,17 @@ export default function CheckoutPage() {
)}
{formFields?.field_type === "long_text" && (
<TextField
name={formFields?.id}
value={formFields?.value}
onChange={(e) => {
dispatch(
updateFieldValues({
index: index,
service_master_meta_data_id: formFields?.id,
value: e.target.value,
})
);
}}
variant="outlined"
fullWidth
multiline
Expand All @@ -181,14 +234,29 @@ export default function CheckoutPage() {
)}
{formFields?.field_type === "date_time" && (
<DateTimePicker
value={dayjs()}
onChange={() => {}}
value={
dayjs(formFields?.value).isValid()
? dayjs(formFields?.value)
: null
}
onChange={(e) => {
dispatch(
updateFieldValues({
index: index,
service_master_meta_data_id: formFields?.id,
value: dayjs(e).format(
"YYYY-MM-DD HH:mm:ss"
),
})
);
}}
slotProps={{
textField: {
size: "small",
variant: "outlined",
fullWidth: true,
// borderRadius: 3,
name: formFields?.id,
sx: {
"& .MuiOutlinedInput-root": {
borderRadius: 3,
Expand Down Expand Up @@ -258,6 +326,9 @@ export default function CheckoutPage() {
minWidth: 100,
mx: 2,
}}
onClick={() => {
createOrder();
}}
>
Save
</Button>
Expand Down
Loading

0 comments on commit 2a45bd3

Please sign in to comment.