diff --git a/src/app.module.ts b/src/app.module.ts index 61bef9a..70e8761 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,6 +7,7 @@ import { UsersModule } from './modules/users/users.module'; import { UsersController } from './modules/users/users.controller'; import { ProductsModule } from './modules/products/products.module'; import { AuthModule } from './modules/auth/auth.module'; +import { OrdersModule } from './modules/orders/orders.module'; @Module({ imports: [ @@ -15,6 +16,7 @@ import { AuthModule } from './modules/auth/auth.module'; UsersModule, ProductsModule, AuthModule, + OrdersModule, ], controllers: [AppController, UsersController], providers: [AppService], diff --git a/src/core/constants/index.ts b/src/core/constants/index.ts index 0af31e8..c1829d2 100644 --- a/src/core/constants/index.ts +++ b/src/core/constants/index.ts @@ -4,3 +4,5 @@ export const TEST = 'test'; export const PRODUCTION = 'production'; export const USER_REPOSITORY = 'USER_REPOSITORY'; export const PRODUCT_REPOSITORY = 'PRODUCT_REPOSITORY'; +export const ORDER_REPOSITORY = 'ORDER_REPOSITORY'; +export const ORDER_STATUSES_REPOSITORY = 'ORDER_STATUSES_REPOSITORY'; diff --git a/src/core/database/database.providers.ts b/src/core/database/database.providers.ts index 7b1c4f9..354b795 100644 --- a/src/core/database/database.providers.ts +++ b/src/core/database/database.providers.ts @@ -3,6 +3,8 @@ import { SEQUELIZE, DEVELOPMENT, TEST, PRODUCTION } from '../constants'; import { databaseConfig } from './database.config'; import { User } from 'src/modules/users/entities/user.entity'; import { Product } from 'src/modules/products/entities/product.entity'; +import { OrderStatuses } from 'src/modules/orders/entities/order-status.entity'; +import { Order } from 'src/modules/orders/entities/order.entity'; export const databaseProviders = [ { @@ -23,7 +25,7 @@ export const databaseProviders = [ config = databaseConfig.development; } const sequelize = new Sequelize(config); - sequelize.addModels([User, Product]); + sequelize.addModels([User, Product, Order, OrderStatuses]); await sequelize.sync(); return sequelize; }, diff --git a/src/modules/orders/dto/create-order.dto.ts b/src/modules/orders/dto/create-order.dto.ts new file mode 100644 index 0000000..a6afd23 --- /dev/null +++ b/src/modules/orders/dto/create-order.dto.ts @@ -0,0 +1,8 @@ +export class CreateOrderDto { + userId: number; + orderDate: Date; + status: number; + comments: string; + shippedDate: Date; + shipperName: string; +} diff --git a/src/modules/orders/dto/index.ts b/src/modules/orders/dto/index.ts new file mode 100644 index 0000000..64ad3fb --- /dev/null +++ b/src/modules/orders/dto/index.ts @@ -0,0 +1,2 @@ +export * from './create-order.dto'; +export * from './update-order.dto'; diff --git a/src/modules/orders/dto/update-order.dto.ts b/src/modules/orders/dto/update-order.dto.ts new file mode 100644 index 0000000..e1e9956 --- /dev/null +++ b/src/modules/orders/dto/update-order.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/mapped-types'; +import { CreateOrderDto } from './create-order.dto'; + +export class UpdateOrderDto extends PartialType(CreateOrderDto) {} diff --git a/src/modules/orders/entities/order-status.entity.ts b/src/modules/orders/entities/order-status.entity.ts new file mode 100644 index 0000000..bdfcf20 --- /dev/null +++ b/src/modules/orders/entities/order-status.entity.ts @@ -0,0 +1,14 @@ +import { Table, Column, Model, DataType, HasOne } from 'sequelize-typescript'; +import { Order } from './order.entity'; + +@Table({ tableName: 'order_statuses', timestamps: false }) +export class OrderStatuses extends Model { + @Column({ + type: DataType.STRING, + allowNull: false, + }) + name: string; + + @HasOne(() => Order) + order: Order; +} diff --git a/src/modules/orders/entities/order.entity.ts b/src/modules/orders/entities/order.entity.ts new file mode 100644 index 0000000..6fb0f43 --- /dev/null +++ b/src/modules/orders/entities/order.entity.ts @@ -0,0 +1,52 @@ +import { + Table, + Column, + Model, + DataType, + ForeignKey, + BelongsTo, +} from 'sequelize-typescript'; +import { User } from 'src/modules/users/entities/user.entity'; +import { OrderStatuses } from 'src/modules/orders/entities/order-status.entity'; + +@Table({ tableName: 'orders' }) +export class Order extends Model { + @Column({ + type: DataType.DATE, + allowNull: false, + defaultValue: new Date(), + }) + orderDate: Date; + + @ForeignKey(() => OrderStatuses) + @Column + status: number; + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + comments: string; + + @Column({ + type: DataType.DATE, + allowNull: true, + }) + shippedDate: Date; + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + shipperName: string; + + @ForeignKey(() => User) + @Column + userId: number; + + @BelongsTo(() => User) + user: User; + + @BelongsTo(() => OrderStatuses) + orderStatuses: OrderStatuses; +} diff --git a/src/modules/orders/order-statuses.providers.ts b/src/modules/orders/order-statuses.providers.ts new file mode 100644 index 0000000..6777585 --- /dev/null +++ b/src/modules/orders/order-statuses.providers.ts @@ -0,0 +1,9 @@ +import { OrderStatuses } from './entities/order-status.entity'; +import { ORDER_STATUSES_REPOSITORY } from '../../core/constants'; + +export const orderStatusesProviders = [ + { + provide: ORDER_STATUSES_REPOSITORY, + useValue: OrderStatuses, + }, +]; diff --git a/src/modules/orders/orders.controller.ts b/src/modules/orders/orders.controller.ts new file mode 100644 index 0000000..d19d4a2 --- /dev/null +++ b/src/modules/orders/orders.controller.ts @@ -0,0 +1,42 @@ +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from '@nestjs/common'; +import { OrdersService } from './orders.service'; +import { CreateOrderDto } from './dto/create-order.dto'; +import { UpdateOrderDto } from './dto/update-order.dto'; + +@Controller('orders') +export class OrdersController { + constructor(private readonly ordersService: OrdersService) {} + + @Post() + create(@Body() createOrderDto: CreateOrderDto) { + return this.ordersService.create(createOrderDto); + } + + @Get() + findAll() { + return this.ordersService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.ordersService.findOne(+id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updateOrderDto: UpdateOrderDto) { + return this.ordersService.update(+id, updateOrderDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.ordersService.remove(+id); + } +} diff --git a/src/modules/orders/orders.module.ts b/src/modules/orders/orders.module.ts new file mode 100644 index 0000000..9dbcec1 --- /dev/null +++ b/src/modules/orders/orders.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { OrdersService } from './orders.service'; +import { OrdersController } from './orders.controller'; +import { ordersProviders } from './orders.providers'; + +@Module({ + controllers: [OrdersController], + providers: [OrdersService, ...ordersProviders], + exports: [OrdersService], +}) +export class OrdersModule {} diff --git a/src/modules/orders/orders.providers.ts b/src/modules/orders/orders.providers.ts new file mode 100644 index 0000000..63e26c5 --- /dev/null +++ b/src/modules/orders/orders.providers.ts @@ -0,0 +1,9 @@ +import { Order } from './entities/order.entity'; +import { ORDER_REPOSITORY } from '../../core/constants'; + +export const ordersProviders = [ + { + provide: ORDER_REPOSITORY, + useValue: Order, + }, +]; diff --git a/src/modules/orders/orders.service.ts b/src/modules/orders/orders.service.ts new file mode 100644 index 0000000..a5e84fd --- /dev/null +++ b/src/modules/orders/orders.service.ts @@ -0,0 +1,49 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { CreateOrderDto, UpdateOrderDto } from './dto'; +import { Order } from './entities/order.entity'; +import { ORDER_REPOSITORY } from 'src/core/constants'; +import { OrderStatuses } from './entities/order-status.entity'; +import { User } from '../users/entities/user.entity'; + +@Injectable() +export class OrdersService { + constructor( + @Inject(ORDER_REPOSITORY) private readonly orderRepository: typeof Order, + ) {} + + async create(createOrderDto: CreateOrderDto) { + return await this.orderRepository.create(createOrderDto); + } + + async findAll() { + return await this.orderRepository.findAll(); + + // For joining all the associated tables with the orders table + // return await this.orderRepository.findAll({ + // include: [{ model: User }, { model: OrderStatuses }], + // }); + } + + async findOne(id: number) { + return await this.orderRepository.findAll({ + where: { id }, + }); + } + + async update(id: number, updateOrderDto: UpdateOrderDto) { + const [numberOfAffectedRows, [updatedOrder]] = + await this.orderRepository.update( + { ...updateOrderDto }, + { where: { id }, returning: true }, + ); + return { numberOfAffectedRows, updatedOrder }; + } + + async remove(id: number) { + const deletedOrder = await this.findOne(id); + + await this.orderRepository.destroy({ where: { id } }); + + return deletedOrder; + } +} diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts index 7f4aa45..53f9dca 100644 --- a/src/modules/users/entities/user.entity.ts +++ b/src/modules/users/entities/user.entity.ts @@ -1,4 +1,5 @@ -import { Table, Column, Model, DataType } from 'sequelize-typescript'; +import { Table, Column, Model, DataType, HasMany } from 'sequelize-typescript'; +import { Order } from '../../orders/entities/order.entity'; @Table({ tableName: 'users' }) export class User extends Model { @@ -52,4 +53,7 @@ export class User extends Model { allowNull: true, }) gender: string; + + @HasMany(() => Order) + orders: Order[]; }