feat: add bulk to cart add
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
import { Expose, Type } from "class-transformer";
|
||||||
|
import { IsArray, IsNotEmpty, IsNumber, IsString, Min, ValidateNested } from "class-validator";
|
||||||
|
|
||||||
|
import { ApiProperty } from "../../../common/decorator/swggerDocs";
|
||||||
|
import { IsValidId } from "../../../common/decorator/validation.decorator";
|
||||||
|
import { ProductVariantModel } from "../../product/models/productVariant.model";
|
||||||
|
|
||||||
|
export class BulkCartItemDTO {
|
||||||
|
@Expose()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ type: "number", description: "product id", example: 100000 })
|
||||||
|
productId: number;
|
||||||
|
|
||||||
|
@Expose()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
@IsValidId(ProductVariantModel)
|
||||||
|
@ApiProperty({ type: "string", description: "variant id of a product", example: "66c0d81ecc135bbc22fc44e3" })
|
||||||
|
variantId: string;
|
||||||
|
|
||||||
|
@Expose()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
@ApiProperty({ type: "number", description: "quantity of a product", example: 2 })
|
||||||
|
quantity: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BulkAddToCartDTO {
|
||||||
|
@Expose()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => BulkCartItemDTO)
|
||||||
|
@ApiProperty({
|
||||||
|
type: "string",
|
||||||
|
description: "Array of items to add to cart",
|
||||||
|
example: [
|
||||||
|
{
|
||||||
|
productId: 100000,
|
||||||
|
variantId: "66c0d81ecc135bbc22fc44e3",
|
||||||
|
quantity: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
productId: 100001,
|
||||||
|
variantId: "66c0d81ecc135bbc22fc44e4",
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
items: BulkCartItemDTO[];
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import { controller, httpGet, httpPost, request, requestBody } from "inversify-e
|
|||||||
import { CartService } from "./cart.service";
|
import { CartService } from "./cart.service";
|
||||||
import { HttpStatus } from "../../common";
|
import { HttpStatus } from "../../common";
|
||||||
import { AddToCartDTO } from "./DTO/addToCart.dto";
|
import { AddToCartDTO } from "./DTO/addToCart.dto";
|
||||||
|
import { BulkAddToCartDTO } from "./DTO/bulkAddToCart.dto";
|
||||||
import { RemoveFromCartDTO } from "./DTO/removeFromCart.dto";
|
import { RemoveFromCartDTO } from "./DTO/removeFromCart.dto";
|
||||||
import { UpdateCartDTO } from "./DTO/updateCart.dto";
|
import { UpdateCartDTO } from "./DTO/updateCart.dto";
|
||||||
import { BaseController } from "../../common/base/controller";
|
import { BaseController } from "../../common/base/controller";
|
||||||
@@ -41,6 +42,17 @@ class CartController extends BaseController {
|
|||||||
return this.response(data, HttpStatus.Created);
|
return this.response(data, HttpStatus.Created);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation("add multiple products to user cart")
|
||||||
|
@ApiResponse("successful", HttpStatus.Created)
|
||||||
|
@ApiModel(BulkAddToCartDTO)
|
||||||
|
@ApiAuth()
|
||||||
|
@httpPost("/bulk-add", Guard.authUser(), ValidationMiddleware.validateInput(BulkAddToCartDTO))
|
||||||
|
public async bulkAddToCart(@requestBody() bulkAddToCartDto: BulkAddToCartDTO, @request() req: Request) {
|
||||||
|
const user = req.user as IUser;
|
||||||
|
const data = await this.cartService.bulkAddToCartS(bulkAddToCartDto, user._id.toString());
|
||||||
|
return this.response(data, HttpStatus.Created);
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation("update the user cart")
|
@ApiOperation("update the user cart")
|
||||||
@ApiResponse("successful", HttpStatus.Ok)
|
@ApiResponse("successful", HttpStatus.Ok)
|
||||||
@ApiModel(UpdateCartDTO)
|
@ApiModel(UpdateCartDTO)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ClientSession, Types, startSession } from "mongoose";
|
|||||||
|
|
||||||
import { CartRepository, CartShipItemRepo } from "./cart.repository";
|
import { CartRepository, CartShipItemRepo } from "./cart.repository";
|
||||||
import { AddToCartDTO } from "./DTO/addToCart.dto";
|
import { AddToCartDTO } from "./DTO/addToCart.dto";
|
||||||
|
import { BulkAddToCartDTO } from "./DTO/bulkAddToCart.dto";
|
||||||
import { CartDTO } from "./DTO/cart.dto";
|
import { CartDTO } from "./DTO/cart.dto";
|
||||||
import { RemoveFromCartDTO } from "./DTO/removeFromCart.dto";
|
import { RemoveFromCartDTO } from "./DTO/removeFromCart.dto";
|
||||||
import { UpdateCartDTO } from "./DTO/updateCart.dto";
|
import { UpdateCartDTO } from "./DTO/updateCart.dto";
|
||||||
@@ -79,6 +80,65 @@ class CartService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async bulkAddToCartS(bulkAddToCartDto: BulkAddToCartDTO, userId: string) {
|
||||||
|
const session = await startSession();
|
||||||
|
session.startTransaction();
|
||||||
|
try {
|
||||||
|
const { items } = bulkAddToCartDto;
|
||||||
|
|
||||||
|
// Get or create cart
|
||||||
|
let cart = await this.cartRepo.model.findOne({ user: userId });
|
||||||
|
if (!cart) {
|
||||||
|
cart = (await this.cartRepo.model.create([{ user: userId }], { session }))[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate all products before making any changes
|
||||||
|
for (const item of items) {
|
||||||
|
const existingCartItem = cart.items.find(
|
||||||
|
(cartItem) => cartItem.product === item.productId && cartItem.variant.toString() === item.variantId,
|
||||||
|
);
|
||||||
|
const existingQuantity = existingCartItem ? existingCartItem.quantity : 0;
|
||||||
|
|
||||||
|
await this.validateProduct(item.productId, item.variantId, existingQuantity + item.quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process each item
|
||||||
|
for (const item of items) {
|
||||||
|
const existingCartItem = cart.items.find(
|
||||||
|
(cartItem) => cartItem.product === item.productId && cartItem.variant.toString() === item.variantId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingCartItem) {
|
||||||
|
// Update quantity if item already exists in the cart
|
||||||
|
existingCartItem.quantity += item.quantity;
|
||||||
|
} else {
|
||||||
|
// Add new item to the cart
|
||||||
|
cart.items.push({
|
||||||
|
product: item.productId,
|
||||||
|
quantity: item.quantity,
|
||||||
|
variant: new Types.ObjectId(item.variantId),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await cart.save({ session });
|
||||||
|
|
||||||
|
// Commit the transaction
|
||||||
|
await session.commitTransaction();
|
||||||
|
session.endSession();
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: CartMessage.ItemAdded,
|
||||||
|
cart: await this.getCartS(userId),
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
// Rollback any changes made in the transaction
|
||||||
|
await session.abortTransaction();
|
||||||
|
session.endSession();
|
||||||
|
throw error; // Re-throw the error to be handled by the calling errorHandler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async updateCartS(updateCartDto: UpdateCartDTO, userId: string) {
|
async updateCartS(updateCartDto: UpdateCartDTO, userId: string) {
|
||||||
const { productId, variantId, quantity } = updateCartDto;
|
const { productId, variantId, quantity } = updateCartDto;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user