Skip to content

Commit

Permalink
Fes 28 update cart 2 (#38)
Browse files Browse the repository at this point in the history
* complete mass updating logic

* restrict the mass udpating with the same sku

* update new logic based on new DD

---------

Co-authored-by: NHT <[email protected]>
  • Loading branch information
nfesta2023 and hoangtuan910 authored Jan 12, 2024
1 parent 051435b commit 742999f
Show file tree
Hide file tree
Showing 3 changed files with 262 additions and 36 deletions.
21 changes: 16 additions & 5 deletions src/feature/cart/cart.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,27 @@ export class CartController {
@MessagePattern({ cmd: 'update_cart' })
async updateCart(data: UpdateCartRequest): Promise<UpdateCartResponse> {
if (this.flagService.isFeatureEnabled('fes-28-update-cart')) {
const { customer_id, updated_items, lang = 'vie' } = data;
const {
customer_id,
item_id,
sku_id,
qty_ordered,
advanced_taste_customization_obj,
basic_taste_customization_obj,
notes,
lang = 'vie',
} = data;
const res = new UpdateCartResponse(200, '');
try {
if (updated_items.length <= 0) {
throw new HttpException('Updated Items cannot be empty', 400);
}
const cartItems: CartItem[] =
await this.cartService.updateCartFromEndPoint(
customer_id,
updated_items,
item_id,
sku_id,
qty_ordered,
advanced_taste_customization_obj,
basic_taste_customization_obj,
notes,
lang,
);
res.statusCode = 200;
Expand Down
271 changes: 245 additions & 26 deletions src/feature/cart/cart.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,45 +238,213 @@ export class CartService {

async updateCartFromEndPoint(
customer_id: number,
updated_cart_items: UpdatedCartItem[],
item_id: number,
sku_id: number,
qty_ordered: number,
advanced_taste_customization_obj: OptionSelection[],
basic_taste_customization_obj: BasicTasteSelection[],
notes: string,
lang: string,
): Promise<CartItem[]> {
if (this.flagService.isFeatureEnabled('fes-28-update-cart')) {
const mentionedCartItems = await this.getCartByItemId(
updated_cart_items.map((i) => i.item_id),
customer_id,
// 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,
);
}

const advanced_taste_customization_obj_txt = JSON.stringify(
advanced_taste_customization_obj,
);
const basic_taste_customization_obj_txt = JSON.stringify(
basic_taste_customization_obj,
);

if (mentionedCartItems.length < updated_cart_items.length) {
throw new HttpException(
'There are some of updated items which do not belong to the customer',
400,
//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);
}

// 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();
},
);

return await this.getCart(customer_id);
}

//build new cart
const fullUpdatedItems: CartItem[] = [];
for (const mentionedCartItem of mentionedCartItems) {
const updatedCartItem = updated_cart_items.find(
(i) => i.item_id === mentionedCartItem.item_id,
//Generate advanced_taste_customization, basic_taste_customization and portion_customization
let advanced_taste_customization: string = '';
let basic_taste_customization: string = '';
let portion_customization: string = '';

if (sku_id != mentionedCartItem.sku_id) {
// --- DIFFERENT SKU ---

//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 (updatedCartItem.sku_id != mentionedCartItem.sku_id) {
const isAllowedSku =
await this.commonService.checkIfSkuHasSameMenuItem([
updatedCartItem.sku_id,
mentionedCartItem.sku_id,
]);

if (!isAllowedSku) {
throw new HttpException(
`Updated sku_id ${updatedCartItem.sku_id} does not have the same Menu Item as the current mentioning sku_id`,
400,
);
}
if (!isAllowedSku) {
throw new HttpException(
`Updated sku_id ${sku_id} does not have the same Menu Item as the current mentioning sku_id`,
400,
);
}

//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 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;
}

//---- 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);
}
}
Expand All @@ -289,4 +457,55 @@ export class CartService {
.getMany();
}
}

async massUpdateCartItem(cart_items: CartItem[]): Promise<void> {
//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();
}
},
);
}
}
}
6 changes: 1 addition & 5 deletions src/feature/cart/dto/update-cart-request.dto.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
export class UpdateCartRequest {
customer_id: number;
updated_items: UpdatedCartItem[];
lang?: string;
}

interface UpdatedCartItem {
item_id: number;
sku_id: number;
qty_ordered: number;
advanced_taste_customization_obj: OptionSelection[];
basic_taste_customization_obj: BasicTasteSelection[];
notes: string;
lang?: string;
}

interface OptionSelection {
Expand Down

0 comments on commit 742999f

Please sign in to comment.