Skip to content

Commit

Permalink
add discount condition module
Browse files Browse the repository at this point in the history
  • Loading branch information
bahram1249 committed Mar 20, 2024
1 parent ac23602 commit 0a931fc
Show file tree
Hide file tree
Showing 16 changed files with 752 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ import { ECDiscountConditionType } from '@rahino/database/models/ecommerce-eav/e
controllers: [DiscountConditionTypeController],
providers: [DiscountConditionTypeService],
})
export class DiscountConditionModule {}
export class DiscountConditionTypeModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Param,
Post,
Query,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { DiscountConditionService } from './discount-condition.service';
import { JwtGuard } from '@rahino/auth/guard';
import { PermissionGuard } from '@rahino/permission-checker/guard';
import { JsonResponseTransformInterceptor } from '@rahino/response/interceptor';
import {
ApiBearerAuth,
ApiOperation,
ApiQuery,
ApiTags,
} from '@nestjs/swagger';
import { CheckPermission } from '@rahino/permission-checker/decorator';
import { GetUser } from '@rahino/auth/decorator';
import { User } from '@rahino/database/models/core/user.entity';
import { DiscountConditionDto, GetDiscountConditionDto } from './dto';

@ApiTags('Admin-DiscountConditions')
@ApiBearerAuth()
@UseGuards(JwtGuard, PermissionGuard)
@UseInterceptors(JsonResponseTransformInterceptor)
@Controller({
path: '/api/ecommerce/admin/discountConditions',
version: ['1'],
})
export class DiscountConditionController {
constructor(private readonly service: DiscountConditionService) {}

@ApiOperation({ description: 'show all discounts' })
@Get('/')
@ApiQuery({
name: 'filter',
type: GetDiscountConditionDto,
style: 'deepObject',
explode: true,
})
@CheckPermission({
permissionSymbol: 'ecommerce.admin.discountconditions.getall',
})
@HttpCode(HttpStatus.OK)
async findAll(
@GetUser() user: User,
@Query() filter: GetDiscountConditionDto,
) {
return await this.service.findAll(user, filter);
}

@UseGuards(JwtGuard, PermissionGuard)
@ApiBearerAuth()
@ApiOperation({ description: 'show discount by given id' })
@CheckPermission({
permissionSymbol: 'ecommerce.admin.discountconditions.getone',
})
@Get('/:id')
@HttpCode(HttpStatus.OK)
async findById(@GetUser() user: User, @Param('id') entityId: bigint) {
return await this.service.findById(user, entityId);
}

@UseGuards(JwtGuard, PermissionGuard)
@ApiBearerAuth()
@ApiOperation({ description: 'create discount by admin' })
@CheckPermission({
permissionSymbol: 'ecommerce.admin.discountconditions.create',
})
@Post('/')
@HttpCode(HttpStatus.CREATED)
async create(@GetUser() user: User, @Body() dto: DiscountConditionDto) {
return await this.service.create(user, dto);
}

@UseGuards(JwtGuard, PermissionGuard)
@ApiBearerAuth()
@ApiOperation({ description: 'delete discount by admin' })
@Delete('/:id')
@CheckPermission({
permissionSymbol: 'ecommerce.admin.discountconditions.delete',
})
@HttpCode(HttpStatus.OK)
async deleteById(@GetUser() user: User, @Param('id') entityId: bigint) {
return await this.service.deleteById(user, entityId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Module } from '@nestjs/common';
import { DiscountConditionController } from './discount-condition.controller';
import { DiscountConditionService } from './discount-condition.service';
import { UserVendorModule } from '@rahino/ecommerce/user/vendor/user-vendor.module';
import { DiscountConditionProfile } from './mapper';
import { SequelizeModule } from '@nestjs/sequelize';
import { ECDiscountCondition } from '@rahino/database/models/ecommerce-eav/ec-discount-condition.entity';
import { Permission } from '@rahino/database/models/core/permission.entity';
import { User } from '@rahino/database/models/core/user.entity';
import { EntityTypeModule } from '@rahino/eav/admin/entity-type/entity-type.module';
import { ProductModule } from '../product/product.module';
import { UserInventoryModule } from '@rahino/ecommerce/user/inventory/user-inventory.module';

@Module({
imports: [
UserVendorModule,
EntityTypeModule,
ProductModule,
UserInventoryModule,
SequelizeModule.forFeature([User, Permission, ECDiscountCondition]),
],
controllers: [DiscountConditionController],
providers: [DiscountConditionService, DiscountConditionProfile],
})
export class DiscountConditionModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import {
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { DiscountConditionDto, GetDiscountConditionDto } from './dto';
import { User } from '@rahino/database/models/core/user.entity';
import { ECDiscountCondition } from '@rahino/database/models/ecommerce-eav/ec-discount-condition.entity';
import { InjectModel } from '@nestjs/sequelize';
import { QueryOptionsBuilder } from '@rahino/query-filter/sequelize-query-builder';
import { Op, Sequelize } from 'sequelize';
import { DiscountConditionTypeEnum } from '../discount-condition-type/enum';
import { UserVendorService } from '@rahino/ecommerce/user/vendor/user-vendor.service';
import { InjectMapper } from 'automapper-nestjs';
import { Mapper } from 'automapper-core';
import * as _ from 'lodash';
import { EntityTypeService } from '@rahino/eav/admin/entity-type/entity-type.service';
import { ProductService } from '../product/product.service';
import { UserInventoryService } from '@rahino/ecommerce/user/inventory/user-inventory.service';

@Injectable()
export class DiscountConditionService {
constructor(
@InjectModel(ECDiscountCondition)
private readonly repository: typeof ECDiscountCondition,
@InjectMapper()
private readonly mapper: Mapper,
private readonly userVendorService: UserVendorService,
private readonly entityTypeService: EntityTypeService,
private readonly productService: ProductService,
private readonly userInventoryService: UserInventoryService,
) {}

async findAll(user: User, filter: GetDiscountConditionDto) {
const vendorIdsStringify = await this.retrunVendorIdsAsString(user);
let queryBuilder = new QueryOptionsBuilder()
.filter({ discountId: filter.discountId })
.filter(
Sequelize.where(
Sequelize.fn('isnull', 'ECDiscountCondition.isDeleted', 0),
{
[Op.eq]: 0,
},
),
)
.filter(
Sequelize.literal(
` EXISTS (
SELECT 1
FROM ECDiscountConditions Basetbl
WHERE Basetbl.discountId = ${filter.discountId}
AND Basetbl.conditionTypeId = ${DiscountConditionTypeEnum.vendor}
AND Basetbl.conditionValue in (${vendorIdsStringify})
)`.replaceAll(/\s\s+/g, ' '),
),
);
const count = await this.repository.count(queryBuilder.build());
queryBuilder = queryBuilder
.limit(filter.limit)
.offset(filter.offset)
.order({ orderBy: filter.orderBy, sortOrder: filter.sortOrder });
const conditions = await this.repository.findAll(queryBuilder.build());

return {
result: conditions,
total: count,
};
}

async findById(user: User, entityId: bigint) {
const vendorIdsStringify = await this.retrunVendorIdsAsString(user);
let queryBuilder = new QueryOptionsBuilder()
.filter({ id: entityId })
.filter(
Sequelize.where(
Sequelize.fn('isnull', 'ECDiscountCondition.isDeleted', 0),
{
[Op.eq]: 0,
},
),
)
.filter(
Sequelize.literal(
` EXISTS (
SELECT 1
FROM ECDiscountConditions Basetbl
WHERE Basetbl.discountId = ECDiscountCondition.discountId
AND Basetbl.conditionTypeId = ${DiscountConditionTypeEnum.vendor}
AND Basetbl.conditionValue in (${vendorIdsStringify})
)`.replaceAll(/\s\s+/g, ' '),
),
);

const result = await this.repository.findOne(queryBuilder.build());
if (!result) {
throw new NotFoundException('the item with this given id not founded!');
}

return {
result: result,
};
}

async create(user: User, dto: DiscountConditionDto) {
const vendorIds = await this.userVendorService.findVendorIds(user);
const isAny = await this.repository.findOne(
new QueryOptionsBuilder()
.filter({ discountId: dto.discountId })
.filter(
Sequelize.where(
Sequelize.fn('isnull', 'ECDiscountCondition.isDeleted', 0),
{
[Op.eq]: 0,
},
),
)
.filter({ conditionTypeId: DiscountConditionTypeEnum.vendor })
.filter({
conditionValue: {
[Op.in]: vendorIds,
},
})
.build(),
);
if (!isAny) {
throw new ForbiddenException("You don't access to operate this requeset");
}
let find: any = null;
switch (dto.conditionTypeId) {
case DiscountConditionTypeEnum.entityType:
find = (
await this.entityTypeService.findById(Number(dto.conditionValue))
).result;
case DiscountConditionTypeEnum.product:
find = (await this.productService.findById(user, dto.conditionValue))
.result;
case DiscountConditionTypeEnum.inventory:
find = (
await this.userInventoryService.findById(dto.conditionValue, user)
).result;
case DiscountConditionTypeEnum.vendor:
find = await this.userVendorService.isAccessToVendor(
user,
Number(dto.conditionValue),
);
}
if (!find) {
throw new ForbiddenException("You don't access to set this given value");
}
const mappedItem = this.mapper.map(
dto,
DiscountConditionDto,
ECDiscountCondition,
);
const discountCondition = await this.repository.create(
_.omit(mappedItem, ['id']),
);
return { result: discountCondition };
}

async deleteById(user: User, entityId: bigint) {
const vendorIdsStringify = await this.retrunVendorIdsAsString(user);
let queryBuilder = new QueryOptionsBuilder()
.filter({ id: entityId })
.filter(
Sequelize.where(
Sequelize.fn('isnull', 'ECDiscountCondition.isDeleted', 0),
{
[Op.eq]: 0,
},
),
)
.filter(
Sequelize.literal(
` EXISTS (
SELECT 1
FROM ECDiscountConditions Basetbl
WHERE Basetbl.discountId = ECDiscountCondition.discountId
AND Basetbl.conditionTypeId = ${DiscountConditionTypeEnum.vendor}
AND Basetbl.conditionValue in (${vendorIdsStringify})
)`.replaceAll(/\s\s+/g, ' '),
),
);

let result = await this.repository.findOne(queryBuilder.build());
if (!result) {
throw new NotFoundException('the item with this given id not founded!');
}
if (result.isDefault) {
throw new ForbiddenException('the default condition connot be deleted!');
}
result.isDeleted = true;
result = await result.save();
return {
result: result,
};
}

private async retrunVendorIdsAsString(user: User) {
const vendorIds = await this.userVendorService.findVendorIds(user);
const vendorIdsString = vendorIds.map((item) => item.toString());
let vendorIdsStringify = vendorIdsString.join(', ');
return vendorIdsStringify != '' ? vendorIdsStringify : 'NULL';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { IsNumber } from 'class-validator';

export class DiscountConditionDto {
@IsNumber()
discountId: bigint;

@IsNumber()
conditionTypeId: number;

@IsNumber()
conditionValue: bigint;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Type } from 'class-transformer';
import { IsInt } from 'class-validator';

export class DiscountDto {
@IsInt()
@Type(() => Number)
discountId: bigint;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IntersectionType } from '@nestjs/swagger';
import { ListFilter } from '@rahino/query-filter';
import { DiscountDto } from './discount.dto';

export class GetDiscountConditionDto extends IntersectionType(
ListFilter,
DiscountDto,
) {}
2 changes: 2 additions & 0 deletions apps/e-commerce/src/admin/discount-condition/dto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './get-discount-condition.dto';
export * from './discount-condition.dto';
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable } from '@nestjs/common';
import { AutomapperProfile, InjectMapper } from 'automapper-nestjs';
import { DiscountConditionDto } from '../dto';
import { Mapper, createMap, forMember, ignore } from 'automapper-core';
import { ECDiscountCondition } from '@rahino/database/models/ecommerce-eav/ec-discount-condition.entity';

@Injectable()
export class DiscountConditionProfile extends AutomapperProfile {
constructor(@InjectMapper() mapper: Mapper) {
super(mapper);
}

override get profile() {
return (mapper) => {
createMap(
mapper,
DiscountConditionDto,
ECDiscountCondition,
forMember((dest) => dest.id, ignore()),
);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './discount-condition.mapper';
Loading

0 comments on commit 0a931fc

Please sign in to comment.