-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ac23602
commit 0a931fc
Showing
16 changed files
with
752 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
apps/e-commerce/src/admin/discount-condition/discount-condition.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
apps/e-commerce/src/admin/discount-condition/discount-condition.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 {} |
205 changes: 205 additions & 0 deletions
205
apps/e-commerce/src/admin/discount-condition/discount-condition.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
apps/e-commerce/src/admin/discount-condition/dto/discount-condition.dto.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
8 changes: 8 additions & 0 deletions
8
apps/e-commerce/src/admin/discount-condition/dto/discount.dto.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
8 changes: 8 additions & 0 deletions
8
apps/e-commerce/src/admin/discount-condition/dto/get-discount-condition.dto.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
23 changes: 23 additions & 0 deletions
23
apps/e-commerce/src/admin/discount-condition/mapper/discount-condition.mapper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()), | ||
); | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './discount-condition.mapper'; |
Oops, something went wrong.