Skip to content

Instantly share code, notes, and snippets.

@Taofiqq
Created December 31, 2024 21:01
Show Gist options
  • Save Taofiqq/1b5f26498b3af29fcb63d39595cff75f to your computer and use it in GitHub Desktop.
Save Taofiqq/1b5f26498b3af29fcb63d39595cff75f to your computer and use it in GitHub Desktop.
Product Module - MultiTenant Ecommerce API
import {
Controller,
Get,
Post,
Body,
Param,
Delete,
UseGuards,
} from '@nestjs/common';
import { ProductService } from './product.service';
import { CreateProductDto } from './product.dto';
import { CurrentTenant } from '../tenants/tenant.decorator';
import { Tenant } from '../tenants/tenant.entity';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { PermitGuard } from '../auth/guards/permit.guard';
import { RequirePermission } from '../auth/decorators/require-permission.decorator';
@Controller('products')
@UseGuards(JwtAuthGuard, PermitGuard)
export class ProductController {
constructor(private readonly productService: ProductService) {}
@Post()
@RequirePermission('create', 'products')
create(
@Body() createProductDto: CreateProductDto,
@CurrentTenant() tenant: Tenant,
) {
return this.productService.create(createProductDto, tenant.id);
}
@Get()
@RequirePermission('read', 'products')
findAll(@CurrentTenant() tenant: Tenant) {
return this.productService.findAll(tenant.id);
}
@Get(':id')
findOne(@Param('id') id: string, @CurrentTenant() tenant: Tenant) {
return this.productService.findOne(id, tenant.id);
}
@Delete(':id')
remove(@Param('id') id: string, @CurrentTenant() tenant: Tenant) {
return this.productService.remove(id, tenant.id);
}
}
import { IsString, IsOptional, Min, IsNumber } from 'class-validator';
export class CreateProductDto {
@IsString()
name: string;
@IsOptional()
@IsString()
description?: string;
@IsNumber()
@Min(0)
price: number;
@IsNumber()
@Min(0)
stockQuantity: number;
}
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantAwareEntity } from '../tenants/tenant-aware.entity';
@Entity('products')
export class Product extends TenantAwareEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column({ type: 'text', nullable: true })
description: string;
@Column({ type: 'decimal', precision: 10, scale: 2 })
price: number;
@Column({ default: 0 })
stockQuantity: number;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Product } from './product.entity';
import { ProductService } from './product.service';
import { ProductController } from './product.controller';
@Module({
imports: [TypeOrmModule.forFeature([Product])],
controllers: [ProductController],
providers: [ProductService],
exports: [ProductService],
})
export class ProductModule {}
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Product } from './product.entity';
import { CreateProductDto } from './product.dto';
@Injectable()
export class ProductService {
constructor(
@InjectRepository(Product) private productRepository: Repository<Product>,
) {}
create(createProductDto: CreateProductDto, tenantId: string) {
const product = this.productRepository.create({
...createProductDto,
tenantId,
});
return this.productRepository.save(product);
}
findAll(tenantId: string) {
return this.productRepository.find({ where: { tenantId } });
}
findOne(id: string, tenantId: string) {
return this.productRepository.findOne({ where: { id, tenantId } });
}
async remove(id: string, tenantId: string) {
const product = await this.findOne(id, tenantId);
if (product) {
await this.productRepository.remove(product);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment