From 7a46dd79fff7b277bbf030e41a20c0963334711b Mon Sep 17 00:00:00 2001 From: mahdi Date: Sun, 12 Jan 2025 12:25:59 +0330 Subject: [PATCH] Create shopping-card module --- src/modules/orders/dto/create-order.dto.ts | 1 + src/modules/orders/entities/order.entity.ts | 7 +++ src/modules/products/products.controller.ts | 1 - src/modules/products/products.module.ts | 13 +++- .../receipts/dto/create-receipt.dto.ts | 4 +- .../receipts/entities/receipt.entity.ts | 4 +- .../dto/create-shopping-card.dto.ts | 7 +++ src/modules/shopping-cards/dto/index.ts | 2 + .../dto/update-shopping-card.dto.ts | 4 ++ .../entities/shopping-card.entity.ts | 32 ++++++++++ .../shopping-cards.controller.ts | 51 +++++++++++++++ .../shopping-cards/shopping-cards.module.ts | 22 +++++++ .../shopping-cards.providers.ts | 9 +++ .../shopping-cards/shopping-cards.service.ts | 63 +++++++++++++++++++ src/modules/users/dto/create-user.dto.ts | 27 ++++++++ src/modules/users/entities/user.entity.ts | 4 ++ 16 files changed, 244 insertions(+), 7 deletions(-) create mode 100644 src/modules/shopping-cards/dto/create-shopping-card.dto.ts create mode 100644 src/modules/shopping-cards/dto/index.ts create mode 100644 src/modules/shopping-cards/dto/update-shopping-card.dto.ts create mode 100644 src/modules/shopping-cards/entities/shopping-card.entity.ts create mode 100644 src/modules/shopping-cards/shopping-cards.controller.ts create mode 100644 src/modules/shopping-cards/shopping-cards.module.ts create mode 100644 src/modules/shopping-cards/shopping-cards.providers.ts create mode 100644 src/modules/shopping-cards/shopping-cards.service.ts diff --git a/src/modules/orders/dto/create-order.dto.ts b/src/modules/orders/dto/create-order.dto.ts index a6afd23..f1c1806 100644 --- a/src/modules/orders/dto/create-order.dto.ts +++ b/src/modules/orders/dto/create-order.dto.ts @@ -5,4 +5,5 @@ export class CreateOrderDto { comments: string; shippedDate: Date; shipperName: string; + products: number[]; } diff --git a/src/modules/orders/entities/order.entity.ts b/src/modules/orders/entities/order.entity.ts index 6fb0f43..72271b3 100644 --- a/src/modules/orders/entities/order.entity.ts +++ b/src/modules/orders/entities/order.entity.ts @@ -8,6 +8,7 @@ import { } from 'sequelize-typescript'; import { User } from 'src/modules/users/entities/user.entity'; import { OrderStatuses } from 'src/modules/orders/entities/order-status.entity'; +import { Product } from 'src/modules/products/entities/product.entity'; @Table({ tableName: 'orders' }) export class Order extends Model { @@ -18,6 +19,12 @@ export class Order extends Model { }) orderDate: Date; + @Column({ + type: DataType.ARRAY(DataType.INTEGER), + allowNull: false, + }) + products: number[]; + @ForeignKey(() => OrderStatuses) @Column status: number; diff --git a/src/modules/products/products.controller.ts b/src/modules/products/products.controller.ts index d1ff944..e5e403f 100644 --- a/src/modules/products/products.controller.ts +++ b/src/modules/products/products.controller.ts @@ -10,7 +10,6 @@ import { } from '@nestjs/common'; import { ProductsService } from './products.service'; import { CreateProductDto, UpdateProductDto } from './dto'; -import { UUID } from 'crypto'; import { AuthGuard } from '@nestjs/passport'; @Controller('products') diff --git a/src/modules/products/products.module.ts b/src/modules/products/products.module.ts index 32ab474..bf78394 100644 --- a/src/modules/products/products.module.ts +++ b/src/modules/products/products.module.ts @@ -2,10 +2,21 @@ import { Module } from '@nestjs/common'; import { ProductsService } from './products.service'; import { ProductsController } from './products.controller'; import { productsProviders } from './products.providers'; +import { ShoppingCardsService } from '../shopping-cards/shopping-cards.service'; +import { ReceiptsService } from '../receipts/receipts.service'; +import { shoppingCardsProviders } from '../shopping-cards/shopping-cards.providers'; +import { receiptsProviders } from '../receipts/receipts.providers'; @Module({ controllers: [ProductsController], exports: [ProductsService], - providers: [ProductsService, ...productsProviders], + providers: [ + ProductsService, + ...productsProviders, + ShoppingCardsService, + ReceiptsService, + ...shoppingCardsProviders, + ...receiptsProviders, + ], }) export class ProductsModule {} diff --git a/src/modules/receipts/dto/create-receipt.dto.ts b/src/modules/receipts/dto/create-receipt.dto.ts index 7fed6ec..974ff87 100644 --- a/src/modules/receipts/dto/create-receipt.dto.ts +++ b/src/modules/receipts/dto/create-receipt.dto.ts @@ -1,7 +1,5 @@ -import { Product } from 'src/modules/products/entities/product.entity'; - export class CreateReceiptDto { userId: number; totalPrice: number; - products: Product[]; + products: number[]; } diff --git a/src/modules/receipts/entities/receipt.entity.ts b/src/modules/receipts/entities/receipt.entity.ts index 163334c..ddbf982 100644 --- a/src/modules/receipts/entities/receipt.entity.ts +++ b/src/modules/receipts/entities/receipt.entity.ts @@ -18,10 +18,10 @@ export class Receipt extends Model { totalPrice: number; @Column({ - type: DataType.ARRAY(DataType.JSON), + type: DataType.ARRAY(DataType.INTEGER), allowNull: false, }) - products: Product[]; + products: number[]; @ForeignKey(() => User) @Column diff --git a/src/modules/shopping-cards/dto/create-shopping-card.dto.ts b/src/modules/shopping-cards/dto/create-shopping-card.dto.ts new file mode 100644 index 0000000..c4a718e --- /dev/null +++ b/src/modules/shopping-cards/dto/create-shopping-card.dto.ts @@ -0,0 +1,7 @@ +import { Product } from 'src/modules/products/entities/product.entity'; + +export class CreateShoppingCardDto { + userId: number; + products: number[]; + totalPrice: number; +} diff --git a/src/modules/shopping-cards/dto/index.ts b/src/modules/shopping-cards/dto/index.ts new file mode 100644 index 0000000..21cc83e --- /dev/null +++ b/src/modules/shopping-cards/dto/index.ts @@ -0,0 +1,2 @@ +export * from './create-shopping-card.dto'; +export * from './update-shopping-card.dto'; diff --git a/src/modules/shopping-cards/dto/update-shopping-card.dto.ts b/src/modules/shopping-cards/dto/update-shopping-card.dto.ts new file mode 100644 index 0000000..3e62078 --- /dev/null +++ b/src/modules/shopping-cards/dto/update-shopping-card.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/mapped-types'; +import { CreateShoppingCardDto } from './create-shopping-card.dto'; + +export class UpdateShoppingCardDto extends PartialType(CreateShoppingCardDto) {} diff --git a/src/modules/shopping-cards/entities/shopping-card.entity.ts b/src/modules/shopping-cards/entities/shopping-card.entity.ts new file mode 100644 index 0000000..947e7c8 --- /dev/null +++ b/src/modules/shopping-cards/entities/shopping-card.entity.ts @@ -0,0 +1,32 @@ +import { + Table, + Column, + Model, + DataType, + ForeignKey, + BelongsTo, +} from 'sequelize-typescript'; +import { Product } from 'src/modules/products/entities/product.entity'; +import { User } from 'src/modules/users/entities/user.entity'; + +@Table({ tableName: 'shopping_cards' }) +export class ShoppingCard extends Model { + @Column({ + type: DataType.FLOAT, + allowNull: false, + }) + totalPrice: number; + + @Column({ + type: DataType.ARRAY(DataType.INTEGER), + allowNull: false, + }) + products: number[]; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => User) + user: User; +} diff --git a/src/modules/shopping-cards/shopping-cards.controller.ts b/src/modules/shopping-cards/shopping-cards.controller.ts new file mode 100644 index 0000000..045a2d4 --- /dev/null +++ b/src/modules/shopping-cards/shopping-cards.controller.ts @@ -0,0 +1,51 @@ +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from '@nestjs/common'; +import { ShoppingCardsService } from './shopping-cards.service'; +import { CreateShoppingCardDto, UpdateShoppingCardDto } from './dto'; +import { ReceiptsService } from '../receipts/receipts.service'; +import { CreateReceiptDto } from '../receipts/dto'; + +@Controller('shopping-cards') +export class ShoppingCardsController { + constructor(private readonly shoppingCardsService: ShoppingCardsService) {} + + @Post() + create(@Body() createShoppingCardDto: CreateShoppingCardDto) { + return this.shoppingCardsService.create(createShoppingCardDto); + } + + @Get() + findAll() { + return this.shoppingCardsService.findAll(); + } + + @Get(':id') + findbyUser(@Param('id') id: string) { + return this.shoppingCardsService.findbyUser(+id); + } + + @Patch(':id') + update( + @Param('id') id: string, + @Body() updateShoppingCardDto: UpdateShoppingCardDto, + ) { + return this.shoppingCardsService.update(+id, updateShoppingCardDto); + } + + @Delete('/purchase/:id') + submitPurchase(@Param('id') id: string) { + return this.shoppingCardsService.submitPurchase(+id); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.shoppingCardsService.remove(+id); + } +} diff --git a/src/modules/shopping-cards/shopping-cards.module.ts b/src/modules/shopping-cards/shopping-cards.module.ts new file mode 100644 index 0000000..9bf9917 --- /dev/null +++ b/src/modules/shopping-cards/shopping-cards.module.ts @@ -0,0 +1,22 @@ +import { Module } from '@nestjs/common'; +import { ShoppingCardsService } from './shopping-cards.service'; +import { ShoppingCardsController } from './shopping-cards.controller'; +import { shoppingCardsProviders } from './shopping-cards.providers'; +import { ReceiptsService } from '../receipts/receipts.service'; +import { receiptsProviders } from '../receipts/receipts.providers'; +import { ProductsService } from '../products/products.service'; +import { productsProviders } from '../products/products.providers'; + +@Module({ + controllers: [ShoppingCardsController], + providers: [ + ShoppingCardsService, + ...shoppingCardsProviders, + ReceiptsService, + ...receiptsProviders, + ProductsService, + ...productsProviders, + ], + exports: [ShoppingCardsService], +}) +export class ShoppingCardsModule {} diff --git a/src/modules/shopping-cards/shopping-cards.providers.ts b/src/modules/shopping-cards/shopping-cards.providers.ts new file mode 100644 index 0000000..e5eb7a0 --- /dev/null +++ b/src/modules/shopping-cards/shopping-cards.providers.ts @@ -0,0 +1,9 @@ +import { ShoppingCard } from './entities/shopping-card.entity'; +import { SHOPPING_CARD_REPOSITORY } from '../../core/constants'; + +export const shoppingCardsProviders = [ + { + provide: SHOPPING_CARD_REPOSITORY, + useValue: ShoppingCard, + }, +]; diff --git a/src/modules/shopping-cards/shopping-cards.service.ts b/src/modules/shopping-cards/shopping-cards.service.ts new file mode 100644 index 0000000..2bd0d97 --- /dev/null +++ b/src/modules/shopping-cards/shopping-cards.service.ts @@ -0,0 +1,63 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { CreateShoppingCardDto } from './dto/create-shopping-card.dto'; +import { UpdateShoppingCardDto } from './dto/update-shopping-card.dto'; +import { SHOPPING_CARD_REPOSITORY } from 'src/core/constants'; +import { ShoppingCard } from './entities/shopping-card.entity'; +import { CreateReceiptDto } from '../receipts/dto'; +import { ReceiptsService } from '../receipts/receipts.service'; +import { ProductsService } from '../products/products.service'; + +@Injectable() +export class ShoppingCardsService { + constructor( + @Inject(SHOPPING_CARD_REPOSITORY) + private readonly shoppingCardRepository: typeof ShoppingCard, + private readonly receiptService: ReceiptsService, + private readonly productsService: ProductsService, + ) {} + async create(createShoppingCardDto: CreateShoppingCardDto) { + return await this.shoppingCardRepository.create(createShoppingCardDto); + } + + async findAll() { + return await this.shoppingCardRepository.findAll(); + } + + async findbyUser(id: number) { + return await this.shoppingCardRepository.findAll({ where: { userId: id } }); + } + + async update(id: number, updateShoppingCardDto: UpdateShoppingCardDto) { + const [numberOfAffectedRows, [updatedCard]] = + await this.shoppingCardRepository.update( + { ...updateShoppingCardDto }, + { where: { userId: id }, returning: true }, + ); + return { numberOfAffectedRows, updatedCard }; + } + + async remove(id: number) { + return await this.shoppingCardRepository.destroy({ where: { userId: id } }); + } + + async submitPurchase(id: number) { + const [card] = await this.findbyUser(id); + + let total = 0; + for (let i of card.products) { + const [product] = await this.productsService.findOne(i); + total += product.pricePerUnit; + } + + await this.createReceipt({ + userId: id, + products: card.products, + totalPrice: total, + }); + return await this.remove(id); + } + + private async createReceipt(createReceiptDto: CreateReceiptDto) { + await this.receiptService.create(createReceiptDto); + } +} diff --git a/src/modules/users/dto/create-user.dto.ts b/src/modules/users/dto/create-user.dto.ts index 019d108..1de8996 100644 --- a/src/modules/users/dto/create-user.dto.ts +++ b/src/modules/users/dto/create-user.dto.ts @@ -1,9 +1,36 @@ +import { + IsEmail, + IsEnum, + IsString, + IsNotEmpty, + IsOptional, +} from 'class-validator'; + export class CreateUserDto { + @IsNotEmpty() + @IsString() firstName: string; + + @IsNotEmpty() + @IsString() lastName: string; + + @IsNotEmpty() + @IsEmail() email: string; + + @IsNotEmpty() + @IsString() password: string; + + @IsOptional() + @IsString() phoneNumber: string; + + @IsOptional() + @IsEnum(['mail', 'female']) gender: string; + + @IsOptional() city: string; } diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts index 2011faa..1a4bd32 100644 --- a/src/modules/users/entities/user.entity.ts +++ b/src/modules/users/entities/user.entity.ts @@ -9,6 +9,7 @@ import { import { Order } from '../../orders/entities/order.entity'; import { Wallet } from 'src/modules/wallets/entities/wallet.entity'; import { Receipt } from 'src/modules/receipts/entities/receipt.entity'; +import { ShoppingCard } from 'src/modules/shopping-cards/entities/shopping-card.entity'; @Table({ tableName: 'users' }) export class User extends Model { @@ -69,6 +70,9 @@ export class User extends Model { @HasOne(() => Wallet) wallet: Wallet; + @HasOne(() => ShoppingCard) + shoppingCard: ShoppingCard; + @HasMany(() => Receipt) receipts: Receipt[]; }