diff --git a/backend/src/infrastructure/data_access/repositories/restaurant.repository.ts b/backend/src/infrastructure/data_access/repositories/restaurant.repository.ts index 637e8043..8f85df6c 100644 --- a/backend/src/infrastructure/data_access/repositories/restaurant.repository.ts +++ b/backend/src/infrastructure/data_access/repositories/restaurant.repository.ts @@ -8,6 +8,8 @@ import { RestaurantMapper } from './../../../restaurant/restaurant.mapper'; import { SingleClientRepository } from './singleclient.repository'; import { IRestaurantRepository } from './interfaces/restaurant-repository.interface'; import { RestaurantData, RestaurantDocument } from './schemas'; +import { throwApplicationError } from '../../../infrastructure/utilities/exception-instance'; +import { HttpStatus } from '@nestjs/common'; export class RestaurantRepository extends GenericDocumentRepository @@ -27,6 +29,9 @@ export class RestaurantRepository async getRestaurant(restaurantId: Types.ObjectId): Promise { const restaurantDoc = await this.DocumentModel.findById(restaurantId).populate('singleclient').exec(); + if (!restaurantDoc) { + throwApplicationError(HttpStatus.NOT_FOUND, `Restaurant with id ${restaurantId} does not exist`); + } const restaurant: Restaurant = this.restaurantMapper.toDomain(restaurantDoc); return restaurant; } diff --git a/backend/src/menu/menu-response.dto.ts b/backend/src/menu/menu-response.dto.ts index 6617dbf3..1d93d3c5 100644 --- a/backend/src/menu/menu-response.dto.ts +++ b/backend/src/menu/menu-response.dto.ts @@ -1,4 +1,5 @@ import { Types } from 'mongoose'; +import { IRestaurantResponseDTO } from 'src/restaurant'; import { ICategoryResponseDTO } from './../category/category-response.dto'; import { IAudit } from './../infrastructure/database/mongoDB/base-document.interface'; import { ITemResponseDTO } from './../item/item-response.dto'; @@ -12,4 +13,5 @@ export interface IMenuResponseDTO extends IAudit { restaurantId: Types.ObjectId; category: ICategoryResponseDTO; items?: ITemResponseDTO[]; + restaurant?: IRestaurantResponseDTO; } diff --git a/backend/src/menu/menu-service.interface.ts b/backend/src/menu/menu-service.interface.ts index dbd981da..34c1f914 100644 --- a/backend/src/menu/menu-service.interface.ts +++ b/backend/src/menu/menu-service.interface.ts @@ -10,4 +10,5 @@ export interface IMenuService { updateMenu(props: any, id: Types.ObjectId): Promise>; deleteMenu(id: Types.ObjectId): Promise>; getMenuByRestaurantId(restaurantId: string): Promise>; + getExtendedMenuByRestaurantId(restaurantId: string): Promise>; } diff --git a/backend/src/menu/menu.controller.ts b/backend/src/menu/menu.controller.ts index 01be5b1d..d9e01e96 100644 --- a/backend/src/menu/menu.controller.ts +++ b/backend/src/menu/menu.controller.ts @@ -39,8 +39,10 @@ export class MenuController { return this.menuService.deleteMenu(menuId); } + //Todo. + //This API should require both the merchantId and RestaurantId /singleclient/:singleClientId/:restaurantId @Get('/singleclient/:restaurantId') async getMenusByRestaurantId(@Param('restaurantId') restaurantId: string): Promise> { - return this.menuService.getMenuByRestaurantId(restaurantId); + return this.menuService.getExtendedMenuByRestaurantId(restaurantId); } } diff --git a/backend/src/menu/menu.parser.ts b/backend/src/menu/menu.parser.ts index dc2a0b66..0dfb0604 100644 --- a/backend/src/menu/menu.parser.ts +++ b/backend/src/menu/menu.parser.ts @@ -1,3 +1,4 @@ +import { Restaurant, RestaurantParser } from '../restaurant'; import { AuditParser } from '../audit'; import { CategoryParser } from './../category/category.parser'; import { ITemResponseDTO } from './../item/item-response.dto'; @@ -6,7 +7,7 @@ import { Menu } from './menu'; import { IMenuResponseDTO } from './menu-response.dto'; export class MenuParser { - static createMenuResponse(menu: Menu): IMenuResponseDTO { + static createMenuResponse(menu: Menu, restaurant?: Restaurant): IMenuResponseDTO { const { id, name, description, items, audit, discount, imageUrl, basePrice, category, restaurantId } = menu; let itemsResponse: ITemResponseDTO[] = []; if (items?.length) { @@ -20,13 +21,14 @@ export class MenuParser { imageUrl, basePrice, restaurantId, + restaurant: restaurant ? RestaurantParser.createRestaurantResponse(restaurant) : undefined, category: category ? CategoryParser.createCategoryResponse(category) : undefined, items: itemsResponse, ...AuditParser.createAuditResponse(audit), }; } - static createMenusResponse(menus: Menu[]): IMenuResponseDTO[] { - return menus.map((menu) => this.createMenuResponse(menu)); + static createMenusResponse(menus: Menu[], restaurant?: Restaurant): IMenuResponseDTO[] { + return menus.map((menu) => this.createMenuResponse(menu, restaurant)); } } diff --git a/backend/src/menu/menu.service.ts b/backend/src/menu/menu.service.ts index 10360b1c..e1278b3d 100644 --- a/backend/src/menu/menu.service.ts +++ b/backend/src/menu/menu.service.ts @@ -20,6 +20,7 @@ import { IMenuResponseDTO } from './menu-response.dto'; import { IMenuService } from './menu-service.interface'; import { MenuParser } from './menu.parser'; import { UpdateMenuDTO } from './update-menu.schema'; +import { Restaurant } from 'src/restaurant'; @Injectable() export class MenuService implements IMenuService { private context: Context; @@ -126,6 +127,20 @@ export class MenuService implements IMenuService { if (result.getValue()) { menus = result.getValue(); } - return Result.ok(menus && menus.length ? MenuParser.createMenusResponse(menus) : []); + return Result.ok(menus?.length ? MenuParser.createMenusResponse(menus) : []); + } + + async getExtendedMenuByRestaurantId(restaurantId: string): Promise> { + const result = await this.menuRepository.getMenuByRestaurantId(restaurantId); + let menus: Menu[] | []; + if (result.getValue()) { + menus = result.getValue(); + } + const id = menus[0].restaurantId; + let restaurant: Restaurant | undefined; + if (id) { + restaurant = await this.restaurantRepository.getRestaurant(id); + } + return Result.ok(menus?.length ? MenuParser.createMenusResponse(menus, restaurant) : []); } } diff --git a/backend/src/restaurant/restaurant.mapper.ts b/backend/src/restaurant/restaurant.mapper.ts index 3e6d522f..79f0cb0e 100644 --- a/backend/src/restaurant/restaurant.mapper.ts +++ b/backend/src/restaurant/restaurant.mapper.ts @@ -7,6 +7,7 @@ import { RestaurantData } from './../infrastructure/data_access/repositories/sch import { LocationMapper } from './../location/location.mapper'; import { SingleClientMapper } from './../singleclient/singleclient.mapper'; import { Restaurant } from './restaurant'; +import { SingleClient } from 'src/singleclient'; @Injectable() export class RestaurantMapper implements IMapper { @@ -48,7 +49,7 @@ export class RestaurantMapper implements IMapper { paymentMethod, openingHour, closingHour, - menus: menus && menus.length ? menus.map((menu) => this.menuMapper.toPersistence(menu)) : [], + menus: menus?.length ? menus.map((menu) => this.menuMapper.toPersistence(menu)) : [], location: this.locationMapper.toPersistence(entity.location), singleclientId, singleclient: this.singleclientMapper.toPersistence(entity.singleclient), @@ -62,7 +63,7 @@ export class RestaurantMapper implements IMapper { return document; } - toDomain(document: RestaurantData): Restaurant { + toDomain(document: any): Restaurant { const { name, email, @@ -79,6 +80,8 @@ export class RestaurantMapper implements IMapper { closingHour, menus, singleclientId, + singleclient, + location, } = document; const entity: Restaurant = Restaurant.create( { @@ -96,8 +99,8 @@ export class RestaurantMapper implements IMapper { closingHour, singleclientId, menus: menus.length ? menus.map((menu) => this.menuMapper.toDomain(menu)) : [], - location: this.locationMapper.toDomain(document.location), - singleclient: this.singleclientMapper.toDomain(document.singleclient), + location: this.locationMapper.toDomain(location), + singleclient: singleclient ? this.singleclientMapper.toDomain(singleclient) : undefined, audit: this.auditMapper.toDomain(document), }, _id, diff --git a/backend/src/restaurant/restaurant.parser.ts b/backend/src/restaurant/restaurant.parser.ts index f43f287e..838ca904 100644 --- a/backend/src/restaurant/restaurant.parser.ts +++ b/backend/src/restaurant/restaurant.parser.ts @@ -7,6 +7,7 @@ import { IRestaurantResponseDTO } from './restaurant-response.dto'; export class RestaurantParser { static createRestaurantResponse(restaurant: Restaurant): IRestaurantResponseDTO { const { audit, location, singleclient, menus } = restaurant; + const auditResponse = audit ? { ...AuditParser.createAuditResponse(audit) } : undefined; const restaurantResponse: IRestaurantResponseDTO = { id: restaurant.id, name: restaurant.name, @@ -17,8 +18,8 @@ export class RestaurantParser { timeZone: restaurant.timeZone, menus: MenuParser.createMenusResponse(menus), location: LocationParser.createLocationResponse(location), - ...AuditParser.createAuditResponse(audit), - singleclient: SingleClientParser.createSingleClientResponse(singleclient), + ...auditResponse, + singleclient: singleclient ? SingleClientParser.createSingleClientResponse(singleclient) : undefined, }; return restaurantResponse; } diff --git a/backend/src/singleclient/singleclient.service.ts b/backend/src/singleclient/singleclient.service.ts index b0aed825..2d3bccc2 100644 --- a/backend/src/singleclient/singleclient.service.ts +++ b/backend/src/singleclient/singleclient.service.ts @@ -84,7 +84,6 @@ export class SingleClientService extends AuthService implements ISingleClientSer } return Result.ok(SingleClientParser.createSingleClientResponse(singleclient)); } - ß; async getSingleClients(): Promise> { const isValidUser = await this.validateContext(); diff --git a/frontend/src/apis/orderApi.ts b/frontend/src/apis/orderApi.ts index 83ffd5ca..17cab1c5 100644 --- a/frontend/src/apis/orderApi.ts +++ b/frontend/src/apis/orderApi.ts @@ -2,6 +2,7 @@ import { OrderSummary, SelectedItem } from "./../reducers/cartReducer"; import { useShoppingCart } from "../hooks/UseShoppingCart"; import useAxiosPrivate from "../hooks/useAxiosPrivate"; import { IcartItems } from "../models/order.model"; +import { ICreateOrderDTO } from "../dto/order"; const getOrderSummary = () => { const { GetOrderSummary } = useShoppingCart(); @@ -12,17 +13,19 @@ export const createOrder = async () => { return useAxiosPrivate(); }; -const mapOrderSummaryToOrderRequest = () => { +const order = (): ICreateOrderDTO | undefined => { + let order: ICreateOrderDTO | undefined; const orderSummary = getOrderSummary(); if (orderSummary?.length) { - return { + order = { state: "CREATED", type: "DINE_IN", - singleclientId: "63d792433b857e1697fe7017", + singleClientId: "63d792433b857e1697fe7017", total: calculateOrderTotalPrice(orderSummary) ?? 0, cartItems: cartItemsMapper(orderSummary), }; } + return order; }; const calculateOrderTotalPrice = (orderSummary: OrderSummary[]) => { @@ -46,9 +49,7 @@ const cartItemsMapper = (orderSummary: OrderSummary[]): IcartItems[] => { const cartItems = menus.map((menu) => { return { menuId: menu.id, - total: - menu.menuTotalPrice ?? - 0 - calculateCartItemsTotalPrice(menu.selectedItems ?? []), + total: menu.menuTotalPrice ?? 0 - calculateCartItemsTotalPrice(menu.selectedItems ?? []), note: menu.note, selectedItems: menu.selectedItems?.map((item) => { return { ...item, itemId: item.id }; diff --git a/frontend/src/components/Menu/MenuList.tsx b/frontend/src/components/Menu/MenuList.tsx index 2b56295e..ae5098e5 100644 --- a/frontend/src/components/Menu/MenuList.tsx +++ b/frontend/src/components/Menu/MenuList.tsx @@ -9,6 +9,7 @@ export const MenuList = () => { const axiosPrivate = useAxiosPrivate(); const getMenus = async (): Promise => { + //Todo //remove the add coded value and make it dynamic const response = await axiosPrivate.get("/menus/singleclient/63d792433b857e1697fe7017"); return response.data; diff --git a/frontend/src/dto/order.ts b/frontend/src/dto/order.ts new file mode 100644 index 00000000..e01ca347 --- /dev/null +++ b/frontend/src/dto/order.ts @@ -0,0 +1,9 @@ +import { IcartItems } from "../models/order.model"; + +export interface ICreateOrderDTO { + state: string; + type: string; + singleClientId: string; + total: number; + cartItems: IcartItems[]; +} diff --git a/frontend/src/utility/utils.ts b/frontend/src/utility/utils.ts index d1b97481..c87bac09 100644 --- a/frontend/src/utility/utils.ts +++ b/frontend/src/utility/utils.ts @@ -31,31 +31,31 @@ export const calculateTotalOrderAmount = (): number => { }; export const setLocalStorageData = (key: string, value: string, encrypt: boolean) => { - if (encrypt) { - try { + try { + if (encrypt) { const encryptedText = cryptoJs.AES.encrypt(value, import.meta.env.VITE_SECRET); if (encryptedText) { localStorage.setItem(key, encryptedText.toString()); } - } catch (error) { - console.log("Error while saving user Data", error); + } else { + localStorage.setItem(key, value); } - } else { - localStorage.setItem(key, value); + } catch (error) { + console.log("Error while saving user Data", error); } }; export const getLocalStorageData = (key: string, decrypt: boolean) => { - let value = localStorage.getItem(key); - if (value && decrypt) { - try { + try { + let value = localStorage.getItem(key); + if (value && decrypt) { const decryptedText = cryptoJs.AES.decrypt(value, import.meta.env.VITE_SECRET); return decryptedText.toString(cryptoJs.enc.Utf8); - } catch (error) { - console.log("Error while getting user data", error); } + return value; + } catch (error) { + console.log("Error while getting user data", error); } - return value; }; export const clearStorage = () => {