diff --git a/src/feature/cart/cart.controller.ts b/src/feature/cart/cart.controller.ts index 3484f76..004db03 100644 --- a/src/feature/cart/cart.controller.ts +++ b/src/feature/cart/cart.controller.ts @@ -22,217 +22,204 @@ export class CartController { ) {} @MessagePattern({ cmd: 'add_cart_item' }) async addCartItem(data: AddToCartRequest): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - const { + const { + customer_id, + sku_id, + qty_ordered, + advanced_taste_customization_obj, + basic_taste_customization_obj, + notes, + } = data; + const res = new AddToCartResponse(200, ''); + try { + const cart = await this.cartService.addCartItem( customer_id, sku_id, qty_ordered, advanced_taste_customization_obj, basic_taste_customization_obj, notes, - } = data; - const res = new AddToCartResponse(200, ''); - try { - const cart = await this.cartService.addCartItem( - customer_id, - sku_id, - qty_ordered, - advanced_taste_customization_obj, - basic_taste_customization_obj, - notes, - ); - //success - res.statusCode = 200; - res.message = 'Add to cart successfully'; - res.data = { - customer_id: customer_id, - cart_info: cart, - }; - } catch (error) { - if (error instanceof HttpException) { - res.statusCode = error.getStatus(); - res.message = error.getResponse(); - res.data = null; - } else { - res.statusCode = 500; - res.message = error.toString(); - res.data = null; - } + ); + //success + res.statusCode = 200; + res.message = 'Add to cart successfully'; + res.data = { + customer_id: customer_id, + cart_info: cart, + }; + } catch (error) { + if (error instanceof HttpException) { + res.statusCode = error.getStatus(); + res.message = error.getResponse(); + res.data = null; + } else { + res.statusCode = 500; + res.message = error.toString(); + res.data = null; } - return res; } + return res; } // end of addCartItem @MessagePattern({ cmd: 'get_cart_detail' }) async getCartDetail(customer_id: number): Promise { - if (this.flagService.isFeatureEnabled('fes-27-get-cart-info')) { - const res = new GetCartDetailResponse(200, ''); + const res = new GetCartDetailResponse(200, ''); - try { - const cartItems: CartItem[] = - await this.cartService.getCart(customer_id); - res.statusCode = 200; - res.message = 'Get cart detail successfully'; - res.data = { - customer_id: customer_id, - cart_info: cartItems, - }; - } catch (error) { - if (error instanceof HttpException) { - res.statusCode = error.getStatus(); - res.message = error.getResponse(); - res.data = null; - } else { - res.statusCode = 500; - res.message = error.toString(); - res.data = null; - } - return res; + try { + const cartItems: CartItem[] = await this.cartService.getCart(customer_id); + res.statusCode = 200; + res.message = 'Get cart detail successfully'; + res.data = { + customer_id: customer_id, + cart_info: cartItems, + }; + } catch (error) { + if (error instanceof HttpException) { + res.statusCode = error.getStatus(); + res.message = error.getResponse(); + res.data = null; + } else { + res.statusCode = 500; + res.message = error.toString(); + res.data = null; } - return res; } + + return res; } // end of getCartDetail @MessagePattern({ cmd: 'update_cart_advanced' }) async updateCartAdvanced( data: UpdateCartAdvancedRequest, ): Promise { - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - const { - customer_id, - item_id, - sku_id, - qty_ordered, - advanced_taste_customization_obj, - basic_taste_customization_obj, - notes, - lang = 'vie', - } = data; - const res = new UpdateCartAdvancedResponse(200, ''); - try { - const cartItems: CartItem[] = - await this.cartService.updateCartAdvancedFromEndPoint( - customer_id, - item_id, - sku_id, - qty_ordered, - advanced_taste_customization_obj, - basic_taste_customization_obj, - notes, - lang, - ); - res.statusCode = 200; - res.message = 'Update cart successfully'; - res.data = { - customer_id: data.customer_id, - cart_info: cartItems, - }; - } catch (error) { - if (error instanceof HttpException) { - res.statusCode = error.getStatus(); - res.message = error.getResponse(); - res.data = null; - } else { - res.statusCode = 500; - res.message = error.toString(); - res.data = null; - } + const { + customer_id, + item_id, + sku_id, + qty_ordered, + advanced_taste_customization_obj, + basic_taste_customization_obj, + notes, + lang = 'vie', + } = data; + const res = new UpdateCartAdvancedResponse(200, ''); + try { + const cartItems: CartItem[] = + await this.cartService.updateCartAdvancedFromEndPoint( + customer_id, + item_id, + sku_id, + qty_ordered, + advanced_taste_customization_obj, + basic_taste_customization_obj, + notes, + lang, + ); + res.statusCode = 200; + res.message = 'Update cart successfully'; + res.data = { + customer_id: data.customer_id, + cart_info: cartItems, + }; + } catch (error) { + if (error instanceof HttpException) { + res.statusCode = error.getStatus(); + res.message = error.getResponse(); + res.data = null; + } else { + res.statusCode = 500; + res.message = error.toString(); + res.data = null; } - - return res; } + + return res; } // end of updateCartAdvanced @MessagePattern({ cmd: 'update_cart_basic' }) async updateCartBasic( data: UpdateCartBasicRequest, ): Promise { - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - const { customer_id, updated_items } = data; - const res = new UpdateCartAdvancedResponse(200, ''); - try { - const cartItems: CartItem[] = - await this.cartService.updateCartBasicFromEndPoint( - customer_id, - updated_items, - ); - res.statusCode = 200; - res.message = 'Update cart successfully'; - res.data = { - customer_id: data.customer_id, - cart_info: cartItems, - }; - } catch (error) { - if (error instanceof HttpException) { - res.statusCode = error.getStatus(); - res.message = error.getResponse(); - res.data = null; - } else { - res.statusCode = 500; - res.message = error.toString(); - res.data = null; - } + const { customer_id, updated_items } = data; + const res = new UpdateCartAdvancedResponse(200, ''); + try { + const cartItems: CartItem[] = + await this.cartService.updateCartBasicFromEndPoint( + customer_id, + updated_items, + ); + res.statusCode = 200; + res.message = 'Update cart successfully'; + res.data = { + customer_id: data.customer_id, + cart_info: cartItems, + }; + } catch (error) { + if (error instanceof HttpException) { + res.statusCode = error.getStatus(); + res.message = error.getResponse(); + res.data = null; + } else { + res.statusCode = 500; + res.message = error.toString(); + res.data = null; } - - return res; } + + return res; } // end of updateCartBasic @MessagePattern({ cmd: 'delete_cart_items' }) async deleteCartItems( requestData: DeleteCartItemRequest, ): Promise { - if (this.flagService.isFeatureEnabled('fes-37-delete-some-of-cart-items')) { - const { customer_id, cart_items } = requestData; - const res = new DeleteCartItemResponse(200, ''); - try { - const cart = await this.cartService.deleteCartItemsFromEndPoint( - customer_id, - cart_items, - ); - res.statusCode = 200; - res.message = 'Delete cart items successfully'; - res.data = { - customer_id: customer_id, - cart_info: cart, - }; - } catch (error) { - if (error instanceof HttpException) { - res.statusCode = error.getStatus(); - res.message = error.getResponse(); - res.data = null; - } else { - res.statusCode = 500; - res.message = error.toString(); - res.data = null; - } + const { customer_id, cart_items } = requestData; + const res = new DeleteCartItemResponse(200, ''); + try { + const cart = await this.cartService.deleteCartItemsFromEndPoint( + customer_id, + cart_items, + ); + res.statusCode = 200; + res.message = 'Delete cart items successfully'; + res.data = { + customer_id: customer_id, + cart_info: cart, + }; + } catch (error) { + if (error instanceof HttpException) { + res.statusCode = error.getStatus(); + res.message = error.getResponse(); + res.data = null; + } else { + res.statusCode = 500; + res.message = error.toString(); + res.data = null; } - return res; } + return res; } // end of deleteCartItems @MessagePattern({ cmd: 'delete_all_cart_item' }) async deleteAllCartItem(customer_id: number): Promise { - if (this.flagService.isFeatureEnabled('fes-36-delete-whole-cart')) { - const res = new GeneralResponse(200, ''); - try { - await this.cartService.deleteAllCartItem(customer_id); - res.statusCode = 200; - res.message = 'Delete all cart items successfully'; + const res = new GeneralResponse(200, ''); + try { + await this.cartService.deleteAllCartItem(customer_id); + res.statusCode = 200; + res.message = 'Delete all cart items successfully'; + res.data = null; + } catch (error) { + if (error instanceof HttpException) { + res.statusCode = error.getStatus(); + res.message = error.getResponse(); + res.data = null; + } else { + res.statusCode = 500; + res.message = error.toString(); res.data = null; - } catch (error) { - if (error instanceof HttpException) { - res.statusCode = error.getStatus(); - res.message = error.getResponse(); - res.data = null; - } else { - res.statusCode = 500; - res.message = error.toString(); - res.data = null; - } } - return res; } + return res; } // end of deleteAllCartItem } diff --git a/src/feature/cart/cart.service.ts b/src/feature/cart/cart.service.ts index c547ea1..b0d74fa 100644 --- a/src/feature/cart/cart.service.ts +++ b/src/feature/cart/cart.service.ts @@ -27,123 +27,69 @@ export class CartService { notes: string, lang: string = 'vie', ): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - const advanced_taste_customization_obj_txt = JSON.stringify( + const advanced_taste_customization_obj_txt = JSON.stringify( + advanced_taste_customization_obj, + ); + const basic_taste_customization_obj_txt = JSON.stringify( + basic_taste_customization_obj, + ); + + //Check if the SKU does exist + const sku = await this.entityManager + .createQueryBuilder(SKU, 'sku') + .leftJoinAndSelect('sku.menu_item', 'menuItem') + .where('sku.sku_id = :sku_id', { sku_id }) + .getOne(); + if (!sku) { + throw new HttpException('SKU does not exist', 404); + } + + // Check if the advanced_taste_customization_obj is all available to this SKU + const advancedTasteCustomizationValidation = + await this.commonService.validateAdvacedTasteCustomizationObjWithMenuItem( advanced_taste_customization_obj, + sku.menu_item_id, ); - const basic_taste_customization_obj_txt = JSON.stringify( - basic_taste_customization_obj, + if (!advancedTasteCustomizationValidation.isValid) { + throw new HttpException( + advancedTasteCustomizationValidation.message, + 400, ); + } - //Check if the SKU does exist - const sku = await this.entityManager - .createQueryBuilder(SKU, 'sku') - .leftJoinAndSelect('sku.menu_item', 'menuItem') - .where('sku.sku_id = :sku_id', { sku_id }) - .getOne(); - if (!sku) { - throw new HttpException('SKU does not exist', 404); - } - - // Check if the advanced_taste_customization_obj is all available to this SKU - const advancedTasteCustomizationValidation = - await this.commonService.validateAdvacedTasteCustomizationObjWithMenuItem( - advanced_taste_customization_obj, - sku.menu_item_id, - ); - if (!advancedTasteCustomizationValidation.isValid) { - throw new HttpException( - advancedTasteCustomizationValidation.message, - 400, - ); - } - - // Check if the basic_taste_customization_obj is all available to this SKU - const basicTasteCustomizationValidation = - await this.commonService.validateBasicTasteCustomizationObjWithMenuItem( - basic_taste_customization_obj, - sku.menu_item_id, - ); - if (!basicTasteCustomizationValidation.isValid) { - throw new HttpException(basicTasteCustomizationValidation.message, 400); - } - - //Get the current cart - const currentCart = await this.getCart(customer_id); - - //Interpret Advance Taste Customization - const advanced_taste_customization = - await this.commonService.interpretAdvanceTaseCustomization( - advanced_taste_customization_obj, - lang, - ); - - //Interpret Basic Taste Customization - const basic_taste_customization = - await this.commonService.interpretBasicTaseCustomization( - basic_taste_customization_obj, - lang, - ); - - //Interpret Portion Customization - const portion_customization = - await this.commonService.interpretPortionCustomization(sku_id, lang); + // Check if the basic_taste_customization_obj is all available to this SKU + const basicTasteCustomizationValidation = + await this.commonService.validateBasicTasteCustomizationObjWithMenuItem( + basic_taste_customization_obj, + sku.menu_item_id, + ); + if (!basicTasteCustomizationValidation.isValid) { + throw new HttpException(basicTasteCustomizationValidation.message, 400); + } - //If cart is empty, create a new cart - if (currentCart.length === 0) { - await this.insertCart( - customer_id, - sku_id, - qty_ordered, - advanced_taste_customization, - basic_taste_customization, - portion_customization, - advanced_taste_customization_obj_txt, - basic_taste_customization_obj_txt, - notes, - sku.menu_item.restaurant_id, - ); - return await this.getCart(customer_id); - } + //Get the current cart + const currentCart = await this.getCart(customer_id); - // Check if the sku_id’s restaurant is the same as the current cart’s items - if (sku.menu_item.restaurant_id != currentCart[0].restaurant_id) { - //Only compare to the first item of the cart. Assume that all of the items - //of the cart have the same restaurant_id - throw new HttpException( - `Added item should have the same restaurant_id as the current cart`, - 400, - ); - } + //Interpret Advance Taste Customization + const advanced_taste_customization = + await this.commonService.interpretAdvanceTaseCustomization( + advanced_taste_customization_obj, + lang, + ); - // Check if the adding item does exist - const existingItem = currentCart.find( - (i) => - i.sku_id == sku_id && - i.advanced_taste_customization_obj == - advanced_taste_customization_obj_txt && - i.basic_taste_customization_obj == - basic_taste_customization_obj_txt && - i.notes == notes, + //Interpret Basic Taste Customization + const basic_taste_customization = + await this.commonService.interpretBasicTaseCustomization( + basic_taste_customization_obj, + lang, ); - if (existingItem) { - //The item does exist => increase the quantity - await this.updateCart( - existingItem.item_id, - existingItem.customer_id, - existingItem.sku_id, - existingItem.qty_ordered + qty_ordered, - existingItem.advanced_taste_customization, - existingItem.basic_taste_customization, - existingItem.portion_customization, - existingItem.advanced_taste_customization_obj, - existingItem.basic_taste_customization_obj, - existingItem.notes, - existingItem.restaurant_id, - ); - return await this.getCart(customer_id); - } + //Interpret Portion Customization + const portion_customization = + await this.commonService.interpretPortionCustomization(sku_id, lang); + + //If cart is empty, create a new cart + if (currentCart.length === 0) { await this.insertCart( customer_id, sku_id, @@ -158,15 +104,64 @@ export class CartService { ); return await this.getCart(customer_id); } + + // Check if the sku_id’s restaurant is the same as the current cart’s items + if (sku.menu_item.restaurant_id != currentCart[0].restaurant_id) { + //Only compare to the first item of the cart. Assume that all of the items + //of the cart have the same restaurant_id + throw new HttpException( + `Added item should have the same restaurant_id as the current cart`, + 400, + ); + } + + // Check if the adding item does exist + const existingItem = currentCart.find( + (i) => + i.sku_id == sku_id && + i.advanced_taste_customization_obj == + advanced_taste_customization_obj_txt && + i.basic_taste_customization_obj == basic_taste_customization_obj_txt && + i.notes == notes, + ); + if (existingItem) { + //The item does exist => increase the quantity + await this.updateCart( + existingItem.item_id, + existingItem.customer_id, + existingItem.sku_id, + existingItem.qty_ordered + qty_ordered, + existingItem.advanced_taste_customization, + existingItem.basic_taste_customization, + existingItem.portion_customization, + existingItem.advanced_taste_customization_obj, + existingItem.basic_taste_customization_obj, + existingItem.notes, + existingItem.restaurant_id, + ); + return await this.getCart(customer_id); + } + + await this.insertCart( + customer_id, + sku_id, + qty_ordered, + advanced_taste_customization, + basic_taste_customization, + portion_customization, + advanced_taste_customization_obj_txt, + basic_taste_customization_obj_txt, + notes, + sku.menu_item.restaurant_id, + ); + return await this.getCart(customer_id); } // end of addCartItem async getCart(customer_id: number): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - return await this.entityManager - .createQueryBuilder(CartItem, 'cart') - .where('cart.customer_id = :customer_id', { customer_id }) - .getMany(); - } + return await this.entityManager + .createQueryBuilder(CartItem, 'cart') + .where('cart.customer_id = :customer_id', { customer_id }) + .getMany(); } // end of getCart async insertCart( @@ -181,25 +176,23 @@ export class CartService { notes: string, restaurant_id: number, ): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - await this.entityManager - .createQueryBuilder() - .insert() - .into(CartItem) - .values({ - customer_id: customer_id, - sku_id: sku_id, - qty_ordered: qty_ordered, - advanced_taste_customization: advanced_taste_customization, - basic_taste_customization: basic_taste_customization, - portion_customization: portion_customization, - advanced_taste_customization_obj: advanced_taste_customization_obj, - basic_taste_customization_obj: basic_taste_customization_obj, - notes: notes, - restaurant_id: restaurant_id, - }) - .execute(); - } + await this.entityManager + .createQueryBuilder() + .insert() + .into(CartItem) + .values({ + customer_id: customer_id, + sku_id: sku_id, + qty_ordered: qty_ordered, + advanced_taste_customization: advanced_taste_customization, + basic_taste_customization: basic_taste_customization, + portion_customization: portion_customization, + advanced_taste_customization_obj: advanced_taste_customization_obj, + basic_taste_customization_obj: basic_taste_customization_obj, + notes: notes, + restaurant_id: restaurant_id, + }) + .execute(); } // end of insertCart async updateCart( @@ -215,25 +208,23 @@ export class CartService { notes: string, restaurant_id: number, ): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - await this.entityManager - .createQueryBuilder() - .update(CartItem) - .set({ - customer_id: customer_id, - sku_id: sku_id, - qty_ordered: qty_ordered, - advanced_taste_customization: advanced_taste_customization, - basic_taste_customization: basic_taste_customization, - portion_customization: portion_customization, - advanced_taste_customization_obj: advanced_taste_customization_obj, - basic_taste_customization_obj: basic_taste_customization_obj, - notes: notes, - restaurant_id: restaurant_id, - }) - .where('item_id = :item_id', { item_id }) - .execute(); - } + await this.entityManager + .createQueryBuilder() + .update(CartItem) + .set({ + customer_id: customer_id, + sku_id: sku_id, + qty_ordered: qty_ordered, + advanced_taste_customization: advanced_taste_customization, + basic_taste_customization: basic_taste_customization, + portion_customization: portion_customization, + advanced_taste_customization_obj: advanced_taste_customization_obj, + basic_taste_customization_obj: basic_taste_customization_obj, + notes: notes, + restaurant_id: restaurant_id, + }) + .where('item_id = :item_id', { item_id }) + .execute(); } // end of updateCart async updateCartAdvancedFromEndPoint( @@ -246,270 +237,260 @@ export class CartService { notes: string, lang: string, ): Promise { - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - // https://n-festa.atlassian.net/browse/FES-28 - - // Get the corresponding cart items in DB - const mentionedCartItem = ( - await this.getCartByItemId([item_id], customer_id) - )[0]; - if (!mentionedCartItem) { - throw new HttpException( - 'Cart item does not belong to the customer or not exist', - 404, - ); - } + // https://n-festa.atlassian.net/browse/FES-28 - const advanced_taste_customization_obj_txt = JSON.stringify( - advanced_taste_customization_obj, - ); - const basic_taste_customization_obj_txt = JSON.stringify( - basic_taste_customization_obj, + // Get the corresponding cart items in DB + const mentionedCartItem = ( + await this.getCartByItemId([item_id], customer_id) + )[0]; + if (!mentionedCartItem) { + throw new HttpException( + 'Cart item does not belong to the customer or not exist', + 404, ); + } - //Check if there any new data - if ( - sku_id == mentionedCartItem.sku_id && - qty_ordered == mentionedCartItem.qty_ordered && - advanced_taste_customization_obj_txt == - mentionedCartItem.advanced_taste_customization_obj && - basic_taste_customization_obj_txt == - mentionedCartItem.basic_taste_customization_obj && - notes == mentionedCartItem.notes - ) { - throw new HttpException('No new data for updating', 400); - } + const advanced_taste_customization_obj_txt = JSON.stringify( + advanced_taste_customization_obj, + ); + const basic_taste_customization_obj_txt = JSON.stringify( + basic_taste_customization_obj, + ); + + //Check if there any new data + if ( + sku_id == mentionedCartItem.sku_id && + qty_ordered == mentionedCartItem.qty_ordered && + advanced_taste_customization_obj_txt == + mentionedCartItem.advanced_taste_customization_obj && + basic_taste_customization_obj_txt == + mentionedCartItem.basic_taste_customization_obj && + notes == mentionedCartItem.notes + ) { + throw new HttpException('No new data for updating', 400); + } - //Check if the SKU does exist - const sku = await this.entityManager - .createQueryBuilder(SKU, 'sku') - .leftJoinAndSelect('sku.menu_item', 'menuItem') - .where('sku.sku_id = :sku_id', { sku_id: sku_id }) - .getOne(); - if (!sku) { - throw new HttpException('SKU does not exist', 404); - } + //Check if the SKU does exist + const sku = await this.entityManager + .createQueryBuilder(SKU, 'sku') + .leftJoinAndSelect('sku.menu_item', 'menuItem') + .where('sku.sku_id = :sku_id', { sku_id: sku_id }) + .getOne(); + if (!sku) { + throw new HttpException('SKU does not exist', 404); + } - // If there is any cart item which is IDENTICAL to the updated item - const identicalCartItem = await this.entityManager - .createQueryBuilder(CartItem, 'cart') - .where('cart.customer_id = :customer_id', { customer_id }) - .andWhere('cart.item_id != :item_id', { item_id }) - .andWhere('cart.sku_id = :sku_id', { sku_id }) - .andWhere( - 'cart.advanced_taste_customization_obj = :advanced_taste_customization_obj', - { - advanced_taste_customization_obj: - advanced_taste_customization_obj_txt, - }, - ) - .andWhere( - 'cart.basic_taste_customization_obj = :basic_taste_customization_obj', - { basic_taste_customization_obj: basic_taste_customization_obj_txt }, - ) - .andWhere('cart.notes = :notes', { notes }) - .getOne(); - - if (identicalCartItem) { - //The item does exist - // => DELETE the updated item & Update the identical item with the increased quantity - - await this.entityManager.transaction( - async (transactionalEntityManager) => { - //DELETE the updated item - await transactionalEntityManager - .createQueryBuilder() - .delete() - .from(CartItem) - .where('item_id = :item_id', { item_id }) - .execute(); - // Update the identical item with the increased quantity - await transactionalEntityManager - .createQueryBuilder() - .update(CartItem) - .set({ - qty_ordered: identicalCartItem.qty_ordered + qty_ordered, - }) - .where('item_id = :item_id', { - item_id: identicalCartItem.item_id, - }) - .execute(); - }, - ); + // If there is any cart item which is IDENTICAL to the updated item + const identicalCartItem = await this.entityManager + .createQueryBuilder(CartItem, 'cart') + .where('cart.customer_id = :customer_id', { customer_id }) + .andWhere('cart.item_id != :item_id', { item_id }) + .andWhere('cart.sku_id = :sku_id', { sku_id }) + .andWhere( + 'cart.advanced_taste_customization_obj = :advanced_taste_customization_obj', + { + advanced_taste_customization_obj: + advanced_taste_customization_obj_txt, + }, + ) + .andWhere( + 'cart.basic_taste_customization_obj = :basic_taste_customization_obj', + { basic_taste_customization_obj: basic_taste_customization_obj_txt }, + ) + .andWhere('cart.notes = :notes', { notes }) + .getOne(); + + if (identicalCartItem) { + //The item does exist + // => DELETE the updated item & Update the identical item with the increased quantity - return await this.getCart(customer_id); - } + await this.entityManager.transaction( + async (transactionalEntityManager) => { + //DELETE the updated item + await transactionalEntityManager + .createQueryBuilder() + .delete() + .from(CartItem) + .where('item_id = :item_id', { item_id }) + .execute(); + // Update the identical item with the increased quantity + await transactionalEntityManager + .createQueryBuilder() + .update(CartItem) + .set({ + qty_ordered: identicalCartItem.qty_ordered + qty_ordered, + }) + .where('item_id = :item_id', { + item_id: identicalCartItem.item_id, + }) + .execute(); + }, + ); - //Generate advanced_taste_customization, basic_taste_customization and portion_customization - let advanced_taste_customization: string = ''; - let basic_taste_customization: string = ''; - let portion_customization: string = ''; + return await this.getCart(customer_id); + } - if (sku_id != mentionedCartItem.sku_id) { - // --- DIFFERENT SKU --- + //Generate advanced_taste_customization, basic_taste_customization and portion_customization + let advanced_taste_customization: string = ''; + let basic_taste_customization: string = ''; + let portion_customization: string = ''; - //Check if a new SKU belongs to the current Menu Item of the current Cart Item - const isAllowedSku = await this.commonService.checkIfSkuHasSameMenuItem( - [sku_id, mentionedCartItem.sku_id], - ); + if (sku_id != mentionedCartItem.sku_id) { + // --- DIFFERENT SKU --- - if (!isAllowedSku) { - throw new HttpException( - `Updated sku_id ${sku_id} does not have the same Menu Item as the current mentioning sku_id`, - 400, - ); - } + //Check if a new SKU belongs to the current Menu Item of the current Cart Item + const isAllowedSku = await this.commonService.checkIfSkuHasSameMenuItem([ + sku_id, + mentionedCartItem.sku_id, + ]); - //Interpret Portion Customization - portion_customization = - await this.commonService.interpretPortionCustomization(sku_id, lang); - } else if (sku_id == mentionedCartItem.sku_id) { - //---- SAME SKU ---- - portion_customization = mentionedCartItem.portion_customization; + if (!isAllowedSku) { + throw new HttpException( + `Updated sku_id ${sku_id} does not have the same Menu Item as the current mentioning sku_id`, + 400, + ); } - //---- COMPARE ADVANCE TASTE CUSTOMIZATION ---- - if ( - advanced_taste_customization_obj_txt != - mentionedCartItem.advanced_taste_customization_obj - ) { - // --- Different advanced taste customiztion --- - // Check if the advanced_taste_customization_obj is all available to this SKU - const advancedTasteCustomizationValidation = - await this.commonService.validateAdvacedTasteCustomizationObjWithMenuItem( - advanced_taste_customization_obj, - sku.menu_item_id, - ); - if (!advancedTasteCustomizationValidation.isValid) { - throw new HttpException( - advancedTasteCustomizationValidation.message, - 400, - ); - } - //Interpret Advance Taste Customization - advanced_taste_customization = - await this.commonService.interpretAdvanceTaseCustomization( - advanced_taste_customization_obj, - lang, - ); - } else if ( - advanced_taste_customization_obj_txt == - mentionedCartItem.advanced_taste_customization_obj - ) { - // --- Same advanced taste customization - advanced_taste_customization = - mentionedCartItem.advanced_taste_customization; - } + //Interpret Portion Customization + portion_customization = + await this.commonService.interpretPortionCustomization(sku_id, lang); + } else if (sku_id == mentionedCartItem.sku_id) { + //---- SAME SKU ---- + portion_customization = mentionedCartItem.portion_customization; + } - //---- COMPARE BASIC TASTE CUSTOMIZATION ---- - if ( - basic_taste_customization_obj_txt != - mentionedCartItem.basic_taste_customization_obj - ) { - // --- Different basic taste customization --- - // Check if the basic_taste_customization_obj is all available to this SKU - const basicTasteCustomizationValidation = - await this.commonService.validateBasicTasteCustomizationObjWithMenuItem( - basic_taste_customization_obj, - sku.menu_item_id, - ); - if (!basicTasteCustomizationValidation.isValid) { - throw new HttpException( - basicTasteCustomizationValidation.message, - 400, - ); - } - //Interpret Basic Taste Customization - basic_taste_customization = - await this.commonService.interpretBasicTaseCustomization( - basic_taste_customization_obj, - lang, - ); - } else if ( - basic_taste_customization_obj_txt == - mentionedCartItem.basic_taste_customization_obj - ) { - // --- Same basic taste customization --- - basic_taste_customization = mentionedCartItem.basic_taste_customization; + //---- COMPARE ADVANCE TASTE CUSTOMIZATION ---- + if ( + advanced_taste_customization_obj_txt != + mentionedCartItem.advanced_taste_customization_obj + ) { + // --- Different advanced taste customiztion --- + // Check if the advanced_taste_customization_obj is all available to this SKU + const advancedTasteCustomizationValidation = + await this.commonService.validateAdvacedTasteCustomizationObjWithMenuItem( + advanced_taste_customization_obj, + sku.menu_item_id, + ); + if (!advancedTasteCustomizationValidation.isValid) { + throw new HttpException( + advancedTasteCustomizationValidation.message, + 400, + ); } + //Interpret Advance Taste Customization + advanced_taste_customization = + await this.commonService.interpretAdvanceTaseCustomization( + advanced_taste_customization_obj, + lang, + ); + } else if ( + advanced_taste_customization_obj_txt == + mentionedCartItem.advanced_taste_customization_obj + ) { + // --- Same advanced taste customization + advanced_taste_customization = + mentionedCartItem.advanced_taste_customization; + } - await this.updateCart( - item_id, - customer_id, - sku_id, - qty_ordered, - advanced_taste_customization, - basic_taste_customization, - portion_customization, - advanced_taste_customization_obj_txt, - basic_taste_customization_obj_txt, - notes, - mentionedCartItem.restaurant_id, - ); - - return await this.getCart(customer_id); + //---- COMPARE BASIC TASTE CUSTOMIZATION ---- + if ( + basic_taste_customization_obj_txt != + mentionedCartItem.basic_taste_customization_obj + ) { + // --- Different basic taste customization --- + // Check if the basic_taste_customization_obj is all available to this SKU + const basicTasteCustomizationValidation = + await this.commonService.validateBasicTasteCustomizationObjWithMenuItem( + basic_taste_customization_obj, + sku.menu_item_id, + ); + if (!basicTasteCustomizationValidation.isValid) { + throw new HttpException(basicTasteCustomizationValidation.message, 400); + } + //Interpret Basic Taste Customization + basic_taste_customization = + await this.commonService.interpretBasicTaseCustomization( + basic_taste_customization_obj, + lang, + ); + } else if ( + basic_taste_customization_obj_txt == + mentionedCartItem.basic_taste_customization_obj + ) { + // --- Same basic taste customization --- + basic_taste_customization = mentionedCartItem.basic_taste_customization; } + + await this.updateCart( + item_id, + customer_id, + sku_id, + qty_ordered, + advanced_taste_customization, + basic_taste_customization, + portion_customization, + advanced_taste_customization_obj_txt, + basic_taste_customization_obj_txt, + notes, + mentionedCartItem.restaurant_id, + ); + + return await this.getCart(customer_id); } // end of updateCartAdvancedFromEndPoint async getCartByItemId(item_ids: number[], customer_id) { - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - return await this.entityManager - .createQueryBuilder(CartItem, 'cart') - .where('cart.customer_id = :customer_id', { customer_id }) - .andWhere('cart.item_id IN (:...item_ids)', { item_ids }) - .getMany(); - } + return await this.entityManager + .createQueryBuilder(CartItem, 'cart') + .where('cart.customer_id = :customer_id', { customer_id }) + .andWhere('cart.item_id IN (:...item_ids)', { item_ids }) + .getMany(); } // end of getCartByItemId async massUpdateCartItem(cart_items: CartItem[]): Promise { //Only do the mass updating if the udated sku has the same as the sku of the current item - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - await this.entityManager.transaction( - async (transactionalEntityManager) => { - // execute queries using transactionalEntityManager - for (const cart_item of cart_items) { - //Check if the SKUs are different - const sku_id = ( - await transactionalEntityManager - .createQueryBuilder(CartItem, 'cart') - .where('cart.item_id = :item_id', { - item_id: cart_item.item_id, - }) - .select('cart.sku_id') - .getOne() - ).sku_id; - - if (sku_id != cart_item.sku_id) { - throw new HttpException( - 'Only do the mass updating if the udated sku has the same as the sku of the current item', - 400, - ); - } - await transactionalEntityManager - .createQueryBuilder() - .update(CartItem) - .set({ - customer_id: cart_item.customer_id, - sku_id: cart_item.sku_id, - qty_ordered: cart_item.qty_ordered, - advanced_taste_customization: - cart_item.advanced_taste_customization, - basic_taste_customization: cart_item.basic_taste_customization, - portion_customization: cart_item.portion_customization, - advanced_taste_customization_obj: - cart_item.advanced_taste_customization_obj, - basic_taste_customization_obj: - cart_item.basic_taste_customization_obj, - notes: cart_item.notes, - restaurant_id: cart_item.restaurant_id, - created_at: cart_item.created_at, - }) - .where('item_id = :item_id', { item_id: cart_item.item_id }) - .execute(); - } - }, - ); - } + await this.entityManager.transaction(async (transactionalEntityManager) => { + // execute queries using transactionalEntityManager + for (const cart_item of cart_items) { + //Check if the SKUs are different + const sku_id = ( + await transactionalEntityManager + .createQueryBuilder(CartItem, 'cart') + .where('cart.item_id = :item_id', { + item_id: cart_item.item_id, + }) + .select('cart.sku_id') + .getOne() + ).sku_id; + + if (sku_id != cart_item.sku_id) { + throw new HttpException( + 'Only do the mass updating if the udated sku has the same as the sku of the current item', + 400, + ); + } + await transactionalEntityManager + .createQueryBuilder() + .update(CartItem) + .set({ + customer_id: cart_item.customer_id, + sku_id: cart_item.sku_id, + qty_ordered: cart_item.qty_ordered, + advanced_taste_customization: + cart_item.advanced_taste_customization, + basic_taste_customization: cart_item.basic_taste_customization, + portion_customization: cart_item.portion_customization, + advanced_taste_customization_obj: + cart_item.advanced_taste_customization_obj, + basic_taste_customization_obj: + cart_item.basic_taste_customization_obj, + notes: cart_item.notes, + restaurant_id: cart_item.restaurant_id, + created_at: cart_item.created_at, + }) + .where('item_id = :item_id', { item_id: cart_item.item_id }) + .execute(); + } + }); } // end of massUpdateCartItem async updateCartBasicFromEndPoint( @@ -517,107 +498,95 @@ export class CartService { quantity_updated_items: QuantityUpdatedItem[], ): Promise { // https://n-festa.atlassian.net/browse/FES-28 - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - // quantity_updated_items cannot be empty - if (!quantity_updated_items || quantity_updated_items.length <= 0) { - throw new HttpException('The updated_items cannot be empty', 400); - } + // quantity_updated_items cannot be empty + if (!quantity_updated_items || quantity_updated_items.length <= 0) { + throw new HttpException('The updated_items cannot be empty', 400); + } - // Get the corresponding cart items in DB - const mentionedCartItems = await this.getCartByItemId( - quantity_updated_items.map((i) => i.item_id), - customer_id, + // Get the corresponding cart items in DB + const mentionedCartItems = await this.getCartByItemId( + quantity_updated_items.map((i) => i.item_id), + customer_id, + ); + // The list of updated items must belong to the customer + if (mentionedCartItems.length != quantity_updated_items.length) { + throw new HttpException( + 'Some of cart items do not belong to the customer or not exist', + 404, ); - // The list of updated items must belong to the customer - if (mentionedCartItems.length != quantity_updated_items.length) { - throw new HttpException( - 'Some of cart items do not belong to the customer or not exist', - 404, - ); - } + } - // The quantity must be greater than 0 - const isQuantityValid = quantity_updated_items.find( - (i) => !Boolean(i.qty_ordered > 0), + // The quantity must be greater than 0 + const isQuantityValid = quantity_updated_items.find( + (i) => !Boolean(i.qty_ordered > 0), + ); + if (isQuantityValid) { + throw new HttpException( + 'The quantity cannot be negative or different from number', + 400, ); - if (isQuantityValid) { - throw new HttpException( - 'The quantity cannot be negative or different from number', - 400, - ); - } + } - // MASS UPDATE - await this.massUpdateCartItemWithQuantity(quantity_updated_items); + // MASS UPDATE + await this.massUpdateCartItemWithQuantity(quantity_updated_items); - return await this.getCart(customer_id); - } + return await this.getCart(customer_id); } // end of updateCartBasicFromEndPoint async massUpdateCartItemWithQuantity( items: QuantityUpdatedItem[], ): Promise { - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - await this.entityManager.transaction( - async (transactionalEntityManager) => { - for (const item of items) { - await transactionalEntityManager - .createQueryBuilder() - .update(CartItem) - .set({ - qty_ordered: item.qty_ordered, - }) - .where('item_id = :item_id', { item_id: item.item_id }) - .execute(); - } - }, - ); - } + await this.entityManager.transaction(async (transactionalEntityManager) => { + for (const item of items) { + await transactionalEntityManager + .createQueryBuilder() + .update(CartItem) + .set({ + qty_ordered: item.qty_ordered, + }) + .where('item_id = :item_id', { item_id: item.item_id }) + .execute(); + } + }); } //end of massUpdateCartItemWithQuantity async deleteAllCartItem(customer_id: number) { - if (this.flagService.isFeatureEnabled('fes-36-delete-whole-cart')) { - await this.entityManager - .createQueryBuilder() - .delete() - .from(CartItem) - .where('customer_id = :customer_id', { customer_id }) - .execute(); - } + await this.entityManager + .createQueryBuilder() + .delete() + .from(CartItem) + .where('customer_id = :customer_id', { customer_id }) + .execute(); } // end of deleteAllCartItem async deleteCartItemsFromEndPoint( customer_id: number, item_ids: number[], ): Promise { - if (this.flagService.isFeatureEnabled('fes-37-delete-some-of-cart-items')) { - //Check if the item_ids belongs to the customers - const mentionedCartItems = await this.getCartByItemId( - item_ids, - customer_id, + //Check if the item_ids belongs to the customers + const mentionedCartItems = await this.getCartByItemId( + item_ids, + customer_id, + ); + if (mentionedCartItems.length != item_ids.length) { + throw new HttpException( + 'Some of cart items do not belong to the customer or not exist', + 404, ); - if (mentionedCartItems.length != item_ids.length) { - throw new HttpException( - 'Some of cart items do not belong to the customer or not exist', - 404, - ); - } + } - //Delete the cart items - await this.deleteCartItems(item_ids); + //Delete the cart items + await this.deleteCartItems(item_ids); - //Get the cart again after deleting the cart items - return await this.getCart(customer_id); - } + //Get the cart again after deleting the cart items + return await this.getCart(customer_id); } // end of deleteCartItemsFromEndPoint async deleteCartItems(item_ids: number[]): Promise { - if (this.flagService.isFeatureEnabled('fes-37-delete-some-of-cart-items')) { - await this.entityManager - .createQueryBuilder() - .delete() - .from(CartItem) - .whereInIds(item_ids) - .execute(); - } + await this.entityManager + .createQueryBuilder() + .delete() + .from(CartItem) + .whereInIds(item_ids) + .execute(); } // end of deleteCartItems } diff --git a/src/feature/common/common.service.ts b/src/feature/common/common.service.ts index fdca17e..b54524e 100644 --- a/src/feature/common/common.service.ts +++ b/src/feature/common/common.service.ts @@ -36,7 +36,7 @@ export class CommonService { .createQueryBuilder(RestaurantExt, 'resExt') .where('resExt.restaurant_id = :id', { id }) .getMany(); - } + } // end of getRestaurantExtension async getReviewsByRestaurantId( restaurant_id: number, @@ -70,7 +70,7 @@ export class CommonService { } return reviews; - } + } // end of getReviewsByRestaurantId async getAvailableSkuDiscountBySkuId(skuId: number): Promise { const now = new Date(); @@ -88,7 +88,8 @@ export class CommonService { }, }); return skuDiscount; - } + } // end of getAvailableSkuDiscountBySkuId + async getAvailableDiscountPrice(sku: SKU) { let discountPrice = sku.price; const skuDiscount = await this.getAvailableSkuDiscountBySkuId(sku.sku_id); @@ -107,7 +108,7 @@ export class CommonService { } return discountPrice; - } + } // end of getAvailableDiscountPrice async convertIntoFoodDTO( menuItem: MenuItem, @@ -171,160 +172,154 @@ export class CommonService { cooking_schedule: menuItem.cooking_schedule, units_sold: menuItem.units_sold, }; - } + } // end of convertIntoFoodDTO async interpretAdvanceTaseCustomization( obj_list: OptionSelection[], lang: string = 'vie', ): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - let result = ''; + let result = ''; - //if object is empty => return '' - if (obj_list.length == 0) { - result = ''; - return result; - } + //if object is empty => return '' + if (obj_list.length == 0) { + result = ''; + return result; + } - const menuItemAttributeIds = obj_list.map((i) => i.option_id); - const menuItemAttributes = await this.entityManager - .createQueryBuilder(MenuItemAttribute, 'menuItemAttribute') - .leftJoinAndSelect('menuItemAttribute.taste_ext', 'taseExt') - .where('menuItemAttribute.attribute_id IN (:...menuItemAttributeIds)', { - menuItemAttributeIds, - }) - .andWhere('menuItemAttribute.type_id = :type', { type: 'taste' }) - .andWhere('taseExt.ISO_language_code = :lang', { lang }) - .getMany(); - - const menuItemAttributeValueIds = obj_list.map((i) => i.value_id); - const menuItemAttributeValues = await this.entityManager - .createQueryBuilder(MenuItemAttributeValue, 'attValue') - .leftJoinAndSelect('attValue.taste_value_ext', 'ext') - .where('attValue.value_id IN (:...menuItemAttributeValueIds)', { - menuItemAttributeValueIds, - }) - .andWhere('attValue.taste_value <> :tasteVal', { tasteVal: 'original' }) //dont generate note for original options - .andWhere('ext.ISO_language_code = :lang', { lang }) - .getMany(); + const menuItemAttributeIds = obj_list.map((i) => i.option_id); + const menuItemAttributes = await this.entityManager + .createQueryBuilder(MenuItemAttribute, 'menuItemAttribute') + .leftJoinAndSelect('menuItemAttribute.taste_ext', 'taseExt') + .where('menuItemAttribute.attribute_id IN (:...menuItemAttributeIds)', { + menuItemAttributeIds, + }) + .andWhere('menuItemAttribute.type_id = :type', { type: 'taste' }) + .andWhere('taseExt.ISO_language_code = :lang', { lang }) + .getMany(); - const strArr = []; - for (const option of obj_list) { - let str = ''; - const menuItemAttribute = menuItemAttributes.find( - (i) => i.attribute_id.toString() == option.option_id, - ); - //check if the option_id has been filtered out - if (!menuItemAttribute) { - continue; - } - const menuItemAttributeValue = menuItemAttributeValues.find( - (i) => i.value_id.toString() == option.value_id, - ); - // check if the value_id has been filtered out - if (!menuItemAttributeValue) { - continue; - } - //check if the option_id and value_id is consistent - belong to the same attribute_id - if ( - menuItemAttributeValue.attribute_id != menuItemAttribute.attribute_id - ) { - console.log( - 'menuItemAttributeValue ', - menuItemAttributeValue.value_id, - ' does not belong to menuItemAttribute ', - menuItemAttribute.attribute_id, - ); - continue; - } - str = - menuItemAttributeValue.taste_value_ext[0].name + - ' ' + - menuItemAttribute.taste_ext[0].name; + const menuItemAttributeValueIds = obj_list.map((i) => i.value_id); + const menuItemAttributeValues = await this.entityManager + .createQueryBuilder(MenuItemAttributeValue, 'attValue') + .leftJoinAndSelect('attValue.taste_value_ext', 'ext') + .where('attValue.value_id IN (:...menuItemAttributeValueIds)', { + menuItemAttributeValueIds, + }) + .andWhere('attValue.taste_value <> :tasteVal', { tasteVal: 'original' }) //dont generate note for original options + .andWhere('ext.ISO_language_code = :lang', { lang }) + .getMany(); - strArr.push(str); + const strArr = []; + for (const option of obj_list) { + let str = ''; + const menuItemAttribute = menuItemAttributes.find( + (i) => i.attribute_id.toString() == option.option_id, + ); + //check if the option_id has been filtered out + if (!menuItemAttribute) { + continue; + } + const menuItemAttributeValue = menuItemAttributeValues.find( + (i) => i.value_id.toString() == option.value_id, + ); + // check if the value_id has been filtered out + if (!menuItemAttributeValue) { + continue; } - result = strArr.join(' - '); + //check if the option_id and value_id is consistent - belong to the same attribute_id + if ( + menuItemAttributeValue.attribute_id != menuItemAttribute.attribute_id + ) { + console.log( + 'menuItemAttributeValue ', + menuItemAttributeValue.value_id, + ' does not belong to menuItemAttribute ', + menuItemAttribute.attribute_id, + ); + continue; + } + str = + menuItemAttributeValue.taste_value_ext[0].name + + ' ' + + menuItemAttribute.taste_ext[0].name; - return result; + strArr.push(str); } - } + result = strArr.join(' - '); + + return result; + } // end of interpretAdvanceTaseCustomization async interpretBasicTaseCustomization( obj_list: BasicTasteSelection[], lang: string = 'vie', ): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - let result: string = ''; - - //if object is empty => return '' - if (obj_list.length == 0) { - result = ''; - return result; - } - - //get unique no_adding_id from obj_list - const uniqueNoAddingIds = obj_list - .map((i) => i.no_adding_id) - .filter((value, index, self) => { - return self.indexOf(value) === index; - }); - - result = ( - await this.entityManager - .createQueryBuilder(NoAddingExt, 'ext') - .where('ext.no_adding_id IN (:...uniqueNoAddingIds)', { - uniqueNoAddingIds, - }) - .andWhere('ext.ISO_language_code = :lang', { lang }) - .getMany() - ) - .map((i) => i.description) - .join(' - '); + let result: string = ''; + //if object is empty => return '' + if (obj_list.length == 0) { + result = ''; return result; } - } + + //get unique no_adding_id from obj_list + const uniqueNoAddingIds = obj_list + .map((i) => i.no_adding_id) + .filter((value, index, self) => { + return self.indexOf(value) === index; + }); + + result = ( + await this.entityManager + .createQueryBuilder(NoAddingExt, 'ext') + .where('ext.no_adding_id IN (:...uniqueNoAddingIds)', { + uniqueNoAddingIds, + }) + .andWhere('ext.ISO_language_code = :lang', { lang }) + .getMany() + ) + .map((i) => i.description) + .join(' - '); + + return result; + } // end of interpretBasicTaseCustomization async interpretPortionCustomization( sku_id: number, lang: string = 'vie', ): Promise { - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - let result: string = ''; - - const skuDetail = await this.entityManager - .createQueryBuilder(SkuDetail, 'skuDetail') - .leftJoinAndSelect('skuDetail.attribute_obj', 'attribute') - .leftJoinAndSelect( - 'attribute.menu_item_attribute_ext_obj', - 'attributeExt', - ) - .leftJoinAndSelect('skuDetail.value_obj', 'value') - .leftJoinAndSelect('value.unit_obj', 'unit') - .where('skuDetail.sku_id = :sku_id', { sku_id }) - .andWhere('attributeExt.ISO_language_code = :lang', { lang }) - .getMany(); - - if (skuDetail.length == 0) { - result = ''; - return result; - } - - result = skuDetail - .map((i) => { - return ( - i.attribute_obj.menu_item_attribute_ext_obj[0].name + - ' ' + - i.value_obj.value + - i.value_obj.unit_obj.symbol - ); - }) - .join(' - '); + let result: string = ''; + + const skuDetail = await this.entityManager + .createQueryBuilder(SkuDetail, 'skuDetail') + .leftJoinAndSelect('skuDetail.attribute_obj', 'attribute') + .leftJoinAndSelect( + 'attribute.menu_item_attribute_ext_obj', + 'attributeExt', + ) + .leftJoinAndSelect('skuDetail.value_obj', 'value') + .leftJoinAndSelect('value.unit_obj', 'unit') + .where('skuDetail.sku_id = :sku_id', { sku_id }) + .andWhere('attributeExt.ISO_language_code = :lang', { lang }) + .getMany(); + if (skuDetail.length == 0) { + result = ''; return result; } - } + + result = skuDetail + .map((i) => { + return ( + i.attribute_obj.menu_item_attribute_ext_obj[0].name + + ' ' + + i.value_obj.value + + i.value_obj.unit_obj.symbol + ); + }) + .join(' - '); + + return result; + } // end of interpretPortionCustomization async getBasicCustomizationByMenuItemId( menu_item_id: number, @@ -337,7 +332,8 @@ export class CommonService { }) .getMany(); return data; - } + } // end of getBasicCustomizationByMenuItemId + async getTasteCustomizationByMenuItemId( menu_item_id: number, ): Promise { @@ -350,106 +346,102 @@ export class CommonService { .andWhere("attribute.type_id = 'taste'") .getMany(); return data; - } + } // end of getTasteCustomizationByMenuItemId async validateAdvacedTasteCustomizationObjWithMenuItem( obj_list: OptionSelection[], menu_item_id: number, ): Promise { // Check if the advanced_taste_customization_obj is all available to this menu item - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - const result: ValidationResult = { - isValid: true, - message: null, - data: null, - }; - const avaibleAdvanceTasteCustomizationList = await this.entityManager - .createQueryBuilder(MenuItemAttribute, 'attribute') - .leftJoinAndSelect('attribute.values', 'values') - .where('attribute.menu_item_id = :menu_item_id', { - menu_item_id, - }) - .andWhere("attribute.type_id = 'taste'") - .getMany(); - for (const obj of obj_list) { - //find the attribute - const attribute = avaibleAdvanceTasteCustomizationList.find( - (i) => i.attribute_id.toString() == obj.option_id, - ); - if (!attribute) { - result.isValid = false; - result.message = `Advanced Taste Customization: option_id ${obj.option_id} cannot be found`; - break; - } - //check the value - const value = attribute.values.find( - (i) => i.value_id.toString() == obj.value_id, - ); - if (!value) { - result.isValid = false; - result.message = `Advanced Taste Customization: value_id ${obj.value_id} is not availabe for option_id ${obj.option_id}`; - break; - } - } + const result: ValidationResult = { + isValid: true, + message: null, + data: null, + }; - return result; + const avaibleAdvanceTasteCustomizationList = await this.entityManager + .createQueryBuilder(MenuItemAttribute, 'attribute') + .leftJoinAndSelect('attribute.values', 'values') + .where('attribute.menu_item_id = :menu_item_id', { + menu_item_id, + }) + .andWhere("attribute.type_id = 'taste'") + .getMany(); + for (const obj of obj_list) { + //find the attribute + const attribute = avaibleAdvanceTasteCustomizationList.find( + (i) => i.attribute_id.toString() == obj.option_id, + ); + if (!attribute) { + result.isValid = false; + result.message = `Advanced Taste Customization: option_id ${obj.option_id} cannot be found`; + break; + } + //check the value + const value = attribute.values.find( + (i) => i.value_id.toString() == obj.value_id, + ); + if (!value) { + result.isValid = false; + result.message = `Advanced Taste Customization: value_id ${obj.value_id} is not availabe for option_id ${obj.option_id}`; + break; + } } - } + + return result; + } // end of validateAdvacedTasteCustomizationObjWithMenuItem async validateBasicTasteCustomizationObjWithMenuItem( obj_list: BasicTasteSelection[], menu_item_id: number, ): Promise { // Check if the advanced_taste_customization_obj is all available to this menu item - if (this.flagService.isFeatureEnabled('fes-24-add-to-cart')) { - const result: ValidationResult = { - isValid: true, - message: null, - data: null, - }; - const avaibleBasicTasteCustomizationList = await this.entityManager - .createQueryBuilder(BasicCustomization, 'basicCustomization') - .where('basicCustomization.menu_item_id = :menu_item_id', { - menu_item_id, - }) - .getMany(); - for (const obj of obj_list) { - //find the attribute - const noAddingId = avaibleBasicTasteCustomizationList.find( - (i) => i.no_adding_id == obj.no_adding_id, - ); - if (!noAddingId) { - result.isValid = false; - result.message = `Basic Taste Customization: no_adding_id ${obj.no_adding_id} cannot be found`; - break; - } - } + const result: ValidationResult = { + isValid: true, + message: null, + data: null, + }; - return result; + const avaibleBasicTasteCustomizationList = await this.entityManager + .createQueryBuilder(BasicCustomization, 'basicCustomization') + .where('basicCustomization.menu_item_id = :menu_item_id', { + menu_item_id, + }) + .getMany(); + for (const obj of obj_list) { + //find the attribute + const noAddingId = avaibleBasicTasteCustomizationList.find( + (i) => i.no_adding_id == obj.no_adding_id, + ); + if (!noAddingId) { + result.isValid = false; + result.message = `Basic Taste Customization: no_adding_id ${obj.no_adding_id} cannot be found`; + break; + } } - } + + return result; + } // end of validateBasicTasteCustomizationObjWithMenuItem async checkIfSkuHasSameMenuItem(sku_ids: number[]): Promise { - if (this.flagService.isFeatureEnabled('fes-28-update-cart')) { - const skuList = await this.entityManager - .createQueryBuilder(SKU, 'sku') - .where('sku.sku_id IN (:...sku_ids)', { sku_ids }) - .getMany(); - - if (skuList.length != sku_ids.length) { - throw new HttpException( - 'There are some sku_id which does not exist', - 404, - ); - } - const menuItems = skuList.map((i) => i.menu_item_id); - const uniqueMenuItems = [...new Set(menuItems)]; - if (uniqueMenuItems.length != 1) { - return false; - } - return true; + const skuList = await this.entityManager + .createQueryBuilder(SKU, 'sku') + .where('sku.sku_id IN (:...sku_ids)', { sku_ids }) + .getMany(); + + if (skuList.length != sku_ids.length) { + throw new HttpException( + 'There are some sku_id which does not exist', + 404, + ); + } + const menuItems = skuList.map((i) => i.menu_item_id); + const uniqueMenuItems = [...new Set(menuItems)]; + if (uniqueMenuItems.length != 1) { + return false; } - } + return true; + } // end of checkIfSkuHasSameMenuItem } diff --git a/src/feature/food/food.controller.ts b/src/feature/food/food.controller.ts index 26ba737..6a99826 100644 --- a/src/feature/food/food.controller.ts +++ b/src/feature/food/food.controller.ts @@ -14,17 +14,15 @@ export class FoodController { @MessagePattern({ cmd: 'get_food_detail_by_id' }) async getFoodDetailById(id: number) { return await this.foodService.getFoodDetailByMenuItemId(id); - } + } // end of getFoodDetailById @MessagePattern({ cmd: 'get_list_of_sku_by_id' }) async getListOfSkuById(id: number) { return await this.foodService.getListOfSkuById(id); - } + } // end of getListOfSkuById @MessagePattern({ cmd: 'get_side_dish_by_menu_item_id' }) async getSideDishByMenuItemId(data: GetSideDishRequest) { - if (this.flagService.isFeatureEnabled('fes-23-get-side-dishes')) { - return await this.foodService.getSideDishByMenuItemId(data); - } - } + return await this.foodService.getSideDishByMenuItemId(data); + } //end of getSideDishByMenuItemId } diff --git a/src/feature/food/food.service.ts b/src/feature/food/food.service.ts index a1d38ea..f1890fa 100644 --- a/src/feature/food/food.service.ts +++ b/src/feature/food/food.service.ts @@ -56,7 +56,7 @@ export class FoodService { max: rawData[0].max, }; return range; - } + } // end of getPriceRangeByMenuItem async getFoodsWithListOfRestaurants(restaurantIds: number[]) { const foodList = await this.menuItemRepo @@ -70,7 +70,7 @@ export class FoodService { .andWhere('sku.is_active = :active', { active: TRUE }) .getMany(); return foodList; - } + } // end of getFoodsWithListOfRestaurants async getFoodsWithListOfMenuItem( menuItems: number[], @@ -132,7 +132,7 @@ export class FoodService { } return foodList; - } + } // end of getFoodsWithListOfMenuItem async getFoodDetailByMenuItemId( menuItemId: number, @@ -237,7 +237,7 @@ export class FoodService { result.message = 'Getting Food Detail Successfully'; result.data = data; return result; - } + } // end of getFoodDetailByMenuItemId async getReviewByMenuItemId(menu_item_id: number): Promise { const reviews: Review[] = []; @@ -264,7 +264,7 @@ export class FoodService { } return reviews; - } + } // end of getReviewByMenuItemId async getRatingStatisticByMenuItemId( menu_item_id: number, @@ -281,7 +281,7 @@ export class FoodService { min_score: Number(data[0].min) || null, }; return result; - } + } // end of getRatingStatisticByMenuItemId async getAllMediaByMenuItemId(menu_item_id: number): Promise { // Get data from table Media @@ -307,7 +307,7 @@ export class FoodService { .orWhere('media.packaging_id IN (:...packaging_ids)', { packaging_ids }) .getMany(); return data; - } + } // end of getAllMediaByMenuItemId async getPackagingByMenuItemId(menu_item_id: number): Promise { const data = await this.entityManager @@ -316,7 +316,7 @@ export class FoodService { .where('packaging.menu_item_id = :menu_item_id', { menu_item_id }) .getMany(); return data; - } + } // end of getPackagingByMenuItemId async getRecipeByMenuItemId(menu_item_id: number): Promise { const data = await this.entityManager @@ -326,7 +326,7 @@ export class FoodService { .where('recipe.menu_item_id = :menu_item_id', { menu_item_id }) .getMany(); return data; - } + } // end of getRecipeByMenuItemId async getPortionCustomizationByMenuItemId( menu_item_id: number, @@ -340,7 +340,7 @@ export class FoodService { .andWhere("attribute.type_id = 'portion'") .getMany(); return data; - } + } // end of getPortionCustomizationByMenuItemId async generatePackageSentenceByLang(packageInfo: Packaging[]) { const sentenceByLang: TextByLang[] = []; @@ -354,7 +354,7 @@ export class FoodService { }); } return sentenceByLang; - } + } // end of generatePackageSentenceByLang async convertPortionCustomization( portionCustomization: MenuItemAttribute[], @@ -387,7 +387,7 @@ export class FoodService { options.push(option); } return options; - } + } // end of convertPortionCustomization async convertTasteCustomization( tasteCustomization: MenuItemAttribute[], @@ -424,7 +424,7 @@ export class FoodService { options.push(option); } return options; - } + } // end of convertTasteCustomization async getListOfSkuById(id: number) { const result = new GeneralResponse(200, ''); @@ -476,7 +476,8 @@ export class FoodService { result.message = 'Getting List Of SKUs Successfully'; result.data = data; return result; - } + } // end of getListOfSkuById + async getSkuPriceUnit(sku_id: number) { const unit = await this.entityManager .createQueryBuilder(Unit, 'unit') @@ -490,7 +491,7 @@ export class FoodService { .where('sku.sku_id = :sku_id', { sku_id }) .getOne(); return unit.symbol; - } + } // end of getSkuPriceUnit async getMenuItemPriceUnit(menu_item_id: number) { const unit = await this.entityManager @@ -504,178 +505,174 @@ export class FoodService { .where('menuItem.menu_item_id = :menu_item_id', { menu_item_id }) .getOne(); return unit.symbol; - } + } // end of getMenuItemPriceUnit async getSideDishByMenuItemId( inputData: GetSideDishRequest, ): Promise { - if (this.flagService.isFeatureEnabled('fes-23-get-side-dishes')) { - const res = new GetSideDishResonse(200, ''); + const res = new GetSideDishResonse(200, ''); - const { menu_item_id, timestamp } = inputData; + const { menu_item_id, timestamp } = inputData; - //Get the list of menu_item_id (side dishes) from table 'Main_Side_Dish' - const sideDishesIds = ( - await this.entityManager - .createQueryBuilder(MainSideDish, 'mainSideDish') - .where('mainSideDish.main_dish_id = :main_dish_id', { - main_dish_id: menu_item_id, - }) - .select('mainSideDish.side_dish_id') - .getMany() - ).map((item) => item.side_dish_id); - - // Check if there is no sidedish for this main dish - if (sideDishesIds.length === 0) { - res.statusCode = 404; - res.message = 'No side dishes found'; - return res; - } + //Get the list of menu_item_id (side dishes) from table 'Main_Side_Dish' + const sideDishesIds = ( + await this.entityManager + .createQueryBuilder(MainSideDish, 'mainSideDish') + .where('mainSideDish.main_dish_id = :main_dish_id', { + main_dish_id: menu_item_id, + }) + .select('mainSideDish.side_dish_id') + .getMany() + ).map((item) => item.side_dish_id); - //Get main dish schedule - const mainDishSchedule = JSON.parse( - ( - await this.entityManager - .createQueryBuilder(MenuItem, 'menuItem') - .where('menuItem.menu_item_id = :menu_item_id', { menu_item_id }) - .getOne() - )?.cooking_schedule || null, - ); + // Check if there is no sidedish for this main dish + if (sideDishesIds.length === 0) { + res.statusCode = 404; + res.message = 'No side dishes found'; + return res; + } - //get the earlies available dayshift of main dish - const earliestDayShift = this.getEarliesAvailabeDayShift( - timestamp, - mainDishSchedule, - ); + //Get main dish schedule + const mainDishSchedule = JSON.parse( + ( + await this.entityManager + .createQueryBuilder(MenuItem, 'menuItem') + .where('menuItem.menu_item_id = :menu_item_id', { menu_item_id }) + .getOne() + )?.cooking_schedule || null, + ); - //Get data for the side dishes - const sideDishes = await this.getFoodsWithListOfMenuItem(sideDishesIds); - - //Filter availabe side dishes - const availableSideDishes = sideDishes.filter((sideDish) => { - const sideDishSchedule: DayShift[] = JSON.parse( - sideDish.cooking_schedule, - ); - const correspondingDayShift = sideDishSchedule.find( - (dayShift) => - dayShift.dayId == earliestDayShift.dayId && - dayShift.from == earliestDayShift.from && - dayShift.to == earliestDayShift.to, - ); - return correspondingDayShift.isAvailable == true; - }); + //get the earlies available dayshift of main dish + const earliestDayShift = this.getEarliesAvailabeDayShift( + timestamp, + mainDishSchedule, + ); - //Convert to DTO - const sideDishesDTOs: FoodDTO[] = []; - for (const availableSideDish of availableSideDishes) { - const sidesideDishesDTO: FoodDTO = - await this.commonService.convertIntoFoodDTO(availableSideDish); - sideDishesDTOs.push(sidesideDishesDTO); - } + //Get data for the side dishes + const sideDishes = await this.getFoodsWithListOfMenuItem(sideDishesIds); - res.statusCode = 200; - res.message = 'Get side dishes successfully'; - res.data = sideDishesDTOs; - return res; + //Filter availabe side dishes + const availableSideDishes = sideDishes.filter((sideDish) => { + const sideDishSchedule: DayShift[] = JSON.parse( + sideDish.cooking_schedule, + ); + const correspondingDayShift = sideDishSchedule.find( + (dayShift) => + dayShift.dayId == earliestDayShift.dayId && + dayShift.from == earliestDayShift.from && + dayShift.to == earliestDayShift.to, + ); + return correspondingDayShift.isAvailable == true; + }); + + //Convert to DTO + const sideDishesDTOs: FoodDTO[] = []; + for (const availableSideDish of availableSideDishes) { + const sidesideDishesDTO: FoodDTO = + await this.commonService.convertIntoFoodDTO(availableSideDish); + sideDishesDTOs.push(sidesideDishesDTO); } - } + + res.statusCode = 200; + res.message = 'Get side dishes successfully'; + res.data = sideDishesDTOs; + return res; + } // end of getSideDishByMenuItemId getEarliesAvailabeDayShift( timestamp: number, schedule: DayShift[], ): DayShift { - if (this.flagService.isFeatureEnabled('fes-23-get-side-dishes')) { - const now = new Date(timestamp); - const currentTimeString = `${now - .getHours() - .toString() - .padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now - .getSeconds() - .toString() - .padStart(2, '0')}`; - console.log(currentTimeString); - const currentDayShift: DayShift = { - dayId: (now.getDay() + 1).toString(), - dayName: '', - from: ' ', - to: '', - }; - switch (currentDayShift.dayId) { - case '1': - currentDayShift.dayName = Day.Sunday; - break; - case '2': - currentDayShift.dayName = Day.Monday; - break; - case '3': - currentDayShift.dayName = Day.Tuesday; - break; - case '4': - currentDayShift.dayName = Day.Wednesday; - break; - case '5': - currentDayShift.dayName = Day.Thursday; - break; - case '6': - currentDayShift.dayName = Day.Friday; - break; - case '7': - currentDayShift.dayName = Day.Saturday; - break; - - default: - break; - } - if ( - currentTimeString >= Shift.MorningFrom && - currentTimeString <= Shift.MorningTo - ) { - currentDayShift.from = Shift.MorningFrom; - currentDayShift.to = Shift.MorningTo; - } else if ( - currentTimeString >= Shift.AfternoonFrom && - currentTimeString <= Shift.AfternoonTo - ) { - currentDayShift.from = Shift.AfternoonFrom; - currentDayShift.to = Shift.AfternoonTo; - } else if ( - currentTimeString >= Shift.NightFrom || - currentTimeString <= Shift.NightTo - ) { - currentDayShift.from = Shift.NightFrom; - currentDayShift.to = Shift.NightTo; - } + const now = new Date(timestamp); + const currentTimeString = `${now + .getHours() + .toString() + .padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now + .getSeconds() + .toString() + .padStart(2, '0')}`; + console.log(currentTimeString); + const currentDayShift: DayShift = { + dayId: (now.getDay() + 1).toString(), + dayName: '', + from: ' ', + to: '', + }; + switch (currentDayShift.dayId) { + case '1': + currentDayShift.dayName = Day.Sunday; + break; + case '2': + currentDayShift.dayName = Day.Monday; + break; + case '3': + currentDayShift.dayName = Day.Tuesday; + break; + case '4': + currentDayShift.dayName = Day.Wednesday; + break; + case '5': + currentDayShift.dayName = Day.Thursday; + break; + case '6': + currentDayShift.dayName = Day.Friday; + break; + case '7': + currentDayShift.dayName = Day.Saturday; + break; + + default: + break; + } + if ( + currentTimeString >= Shift.MorningFrom && + currentTimeString <= Shift.MorningTo + ) { + currentDayShift.from = Shift.MorningFrom; + currentDayShift.to = Shift.MorningTo; + } else if ( + currentTimeString >= Shift.AfternoonFrom && + currentTimeString <= Shift.AfternoonTo + ) { + currentDayShift.from = Shift.AfternoonFrom; + currentDayShift.to = Shift.AfternoonTo; + } else if ( + currentTimeString >= Shift.NightFrom || + currentTimeString <= Shift.NightTo + ) { + currentDayShift.from = Shift.NightFrom; + currentDayShift.to = Shift.NightTo; + } - //Get earliest available day shift - const earliestAvailabeDayShift: DayShift = { - dayId: null, - dayName: null, - from: null, - to: null, - isAvailable: null, - }; - const currentIndex = schedule.findIndex( - (item) => - item.dayId == currentDayShift.dayId && - item.from == currentDayShift.from && - item.to == currentDayShift.to, - ); - for ( - let index = currentIndex; - index < schedule.length + currentIndex; - index++ - ) { - const i = index % schedule.length; - if (schedule[i].isAvailable) { - earliestAvailabeDayShift.dayId = schedule[i].dayId; - earliestAvailabeDayShift.dayName = schedule[i].dayName; - earliestAvailabeDayShift.from = schedule[i].from; - earliestAvailabeDayShift.to = schedule[i].to; - earliestAvailabeDayShift.isAvailable = schedule[i].isAvailable; - break; - } + //Get earliest available day shift + const earliestAvailabeDayShift: DayShift = { + dayId: null, + dayName: null, + from: null, + to: null, + isAvailable: null, + }; + const currentIndex = schedule.findIndex( + (item) => + item.dayId == currentDayShift.dayId && + item.from == currentDayShift.from && + item.to == currentDayShift.to, + ); + for ( + let index = currentIndex; + index < schedule.length + currentIndex; + index++ + ) { + const i = index % schedule.length; + if (schedule[i].isAvailable) { + earliestAvailabeDayShift.dayId = schedule[i].dayId; + earliestAvailabeDayShift.dayName = schedule[i].dayName; + earliestAvailabeDayShift.from = schedule[i].from; + earliestAvailabeDayShift.to = schedule[i].to; + earliestAvailabeDayShift.isAvailable = schedule[i].isAvailable; + break; } - return earliestAvailabeDayShift; } - } + return earliestAvailabeDayShift; + } // end of getEarliesAvailabeDayShift }