This commit is contained in:
BadBUTA 2023-04-25 01:26:47 +08:00
parent 4e4301d18c
commit 45a36cd17e
15 changed files with 843 additions and 0 deletions

View File

@ -14,6 +14,7 @@ import { AllExceptionsFilter } from './logger/any-exception.filter';
import loggerMiddleware from './logger/logger.middleware';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MySqlCompanyModule } from './mysqlcompany/mysqlcompany.module';
import { ZgcModule } from './zgc/zgc.module';
// import { OrmMongoCompanyModule } from './ormmongocompany/ormmongocompany.module';
@Module({
@ -54,6 +55,7 @@ import { MySqlCompanyModule } from './mysqlcompany/mysqlcompany.module';
UsersModule,
MySqlCompanyModule,
// OrmMongoCompanyModule,
ZgcModule,
],
controllers: [AppController],
providers: [

View File

@ -0,0 +1,25 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNumber, IsOptional } from 'class-validator';
export class CategoryCreateDto {
// NOTE: Since the id is auto-inc, so no id for the creation
// id: number;
// ----------------------------------------
@ApiProperty({
type: String,
name: 'name',
description: 'Group name',
required: true,
})
name: string;
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'displayOrder',
description: 'Display order',
required: false,
})
@IsNumber()
@IsOptional()
displayOrder: number | 0;
}

View File

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CategoryCreateDto } from './category-create.dto';
export class CategoryUpdateDto extends PartialType(CategoryCreateDto) {}

View File

@ -0,0 +1,25 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNumber, IsOptional } from 'class-validator';
export class GroupCreateDto {
// NOTE: Since the id is auto-inc, so no id for the creation
// id: number;
// ----------------------------------------
@ApiProperty({
type: String,
name: 'name',
description: 'Group name',
required: true,
})
name: string;
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'displayOrder',
description: 'Display order',
required: false,
})
@IsNumber()
@IsOptional()
displayOrder: number | 0;
}

View File

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { GroupCreateDto } from './group-create.dto';
export class GroupUpdateDto extends PartialType(GroupCreateDto) {}

View File

@ -0,0 +1,25 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNumber, IsOptional } from 'class-validator';
export class ZoneCreateDto {
// NOTE: Since the id is auto-inc, so no id for the creation
// id: number;
// ----------------------------------------
@ApiProperty({
type: String,
name: 'name',
description: 'Zone name',
required: true,
})
name: string;
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'displayOrder',
description: 'Display order',
required: false,
})
@IsNumber()
@IsOptional()
displayOrder: number | 0;
}

View File

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { ZoneCreateDto } from './zone-create.dto';
export class ZoneUpdateDto extends PartialType(ZoneCreateDto) {}

View File

@ -0,0 +1,62 @@
import { ApiProperty } from '@nestjs/swagger';
import {
Column,
Entity,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Group } from './group.entity';
@Entity('categories')
export class Category {
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'id',
description: 'id of category, auto-incremented',
required: true,
})
@PrimaryGeneratedColumn('increment')
id: number;
// ----------------------------------------
@ApiProperty({
type: String,
name: 'name',
description: 'Category name',
required: true,
})
@Column({
type: 'varchar',
})
name: string;
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'displayOrder',
description: 'Display order',
required: false,
})
@Column({
type: 'tinyint',
default: 0,
})
displayOrder: number;
// ----------------------------------------
@ApiProperty({
name: 'group',
description: 'Parent node: group',
type: () => Group,
})
// @ApiPropertyOptional()
@ManyToOne(() => Group, (group) => group.categories, {
nullable: false,
eager: true,
})
// @JoinColumn({ name: 'group_id', referencedColumnName: 'id' })
@JoinColumn({ name: 'xref_group_id' })
group: Group;
}

View File

@ -0,0 +1,73 @@
import { ApiProperty } from '@nestjs/swagger';
import {
Column,
Entity,
JoinColumn,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Zone } from './zone.entity';
import { Category } from './category.entity';
@Entity('groups')
export class Group {
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'id',
description: 'id of group, auto-incremented',
required: true,
})
@PrimaryGeneratedColumn('increment')
id: number;
// ----------------------------------------
@ApiProperty({
type: String,
name: 'name',
description: 'Group name',
required: true,
})
@Column({
type: 'varchar',
})
name: string;
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'displayOrder',
description: 'Display order',
required: false,
})
@Column({
type: 'tinyint',
default: 0,
})
displayOrder: number;
// ----------------------------------------
@ApiProperty({
name: 'zone',
description: 'Parent node: zone',
type: () => Zone,
})
// @ApiPropertyOptional()
@ManyToOne(() => Zone, (zone) => zone.groups, {
nullable: false,
eager: true,
})
@JoinColumn({ name: 'xref_zone_id' })
zone: Zone;
// ----------------------------------------
@ApiProperty({
name: 'categories',
description: 'Children: categories',
type: () => [Category],
})
// @ApiPropertyOptional()
@OneToMany(() => Category, (category) => category.group)
categories: Category[];
}

View File

@ -0,0 +1,51 @@
import { ApiProperty } from '@nestjs/swagger';
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Group } from './group.entity';
@Entity('zones')
export class Zone {
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'id',
description: 'id of zone, auto-incremented',
required: true,
})
@PrimaryGeneratedColumn('increment')
id: number;
// ----------------------------------------
@ApiProperty({
type: String,
name: 'name',
description: 'Zone name',
required: true,
})
@Column({
type: 'varchar',
})
name: string;
// ----------------------------------------
@ApiProperty({
type: Number,
name: 'displayOrder',
description: 'Display order',
required: false,
})
@Column({
type: 'tinyint',
default: 0,
})
displayOrder: number;
// ----------------------------------------
@ApiProperty({
name: 'groups',
description: 'Children: groups',
type: () => [Group],
})
// @ApiPropertyOptional()
@OneToMany(() => Group, (group) => group.zone)
groups: Group[];
}

181
src/zgc/zgc.controller.ts Normal file
View File

@ -0,0 +1,181 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
NotFoundException,
HttpCode,
BadRequestException,
} from '@nestjs/common';
import { ApiResponse } from '@nestjs/swagger';
import { EntityNotFoundError } from 'typeorm';
import { Paginate, PaginateQuery, Paginated } from 'nestjs-paginate';
import { ZgcService } from './zgc.service';
import { ZoneCreateDto } from './dto/zone-create.dto';
import { ZoneUpdateDto } from './dto/zone-update.dto';
import { Zone } from './entities/zone.entity';
import { GroupCreateDto } from './dto/group-create.dto';
import { GroupUpdateDto } from './dto/group-update.dto';
import { Group } from './entities/group.entity';
import { CategoryCreateDto } from './dto/category-create.dto';
import { CategoryUpdateDto } from './dto/category-update.dto';
import { Category } from './entities/category.entity';
@Controller('zgc')
export class ZgcController {
constructor(private readonly service: ZgcService) {}
private handleEntityNotFoundError(id: number, e: Error) {
if (e instanceof EntityNotFoundError) {
throw new NotFoundException(`Not found: id=${id}`);
} else {
throw e;
}
}
// -------------------- Zone --------------------
// --
@Get('/zones')
@ApiResponse({ type: [Zone] })
findZones(@Paginate() query: PaginateQuery): Promise<Paginated<Zone>> {
return this.service.findZones(query);
}
@Get('/zones/:id')
@ApiResponse({ type: Zone })
async findZone(@Param('id') id: number): Promise<Zone | null> {
// NOTE: the + operator returns the numeric representation of the object.
return this.service.findZone(+id).catch((err) => {
this.handleEntityNotFoundError(id, err);
return null;
});
}
@Post('/zones')
@ApiResponse({ type: [Zone] })
createZone(@Body() zoneCreateDto: ZoneCreateDto) {
return this.service.createZone(zoneCreateDto);
}
@Patch('/zones/:id')
// Status 204 because no content will be returned
@HttpCode(204)
async updateZone(
@Param('id') id: number,
@Body() zoneUpdateDto: ZoneUpdateDto,
): Promise<void> {
if (Object.keys(zoneUpdateDto).length === 0) {
throw new BadRequestException('Request body is empty');
}
await this.service.updateZone(+id, zoneUpdateDto).catch((err) => {
this.handleEntityNotFoundError(id, err);
});
}
@Delete('/zones/:id')
@HttpCode(204)
async deleteZone(@Param('id') id: number): Promise<void> {
await this.service.deleteZone(+id).catch((err) => {
this.handleEntityNotFoundError(id, err);
});
}
// -------------------- Group --------------------
// --
@Get('/groups')
@ApiResponse({ type: [Group] })
findGroups(@Paginate() query: PaginateQuery): Promise<Paginated<Group>> {
return this.service.findGroups(query);
}
@Get('/groups/:id')
@ApiResponse({ type: Group })
async findGroup(@Param('id') id: number): Promise<Group | null> {
// NOTE: the + operator returns the numeric representation of the object.
return this.service.findGroup(+id).catch((err) => {
this.handleEntityNotFoundError(id, err);
return null;
});
}
@Post('/groups')
@ApiResponse({ type: [Group] })
createGroup(@Body() zoneCreateDto: GroupCreateDto) {
return this.service.createGroup(zoneCreateDto);
}
@Patch('/groups/:id')
// Status 204 because no content will be returned
@HttpCode(204)
async updateGroup(
@Param('id') id: number,
@Body() zoneUpdateDto: GroupUpdateDto,
): Promise<void> {
if (Object.keys(zoneUpdateDto).length === 0) {
throw new BadRequestException('Request body is empty');
}
await this.service.updateGroup(+id, zoneUpdateDto).catch((err) => {
this.handleEntityNotFoundError(id, err);
});
}
@Delete('/groups/:id')
@HttpCode(204)
async deleteGroup(@Param('id') id: number): Promise<void> {
await this.service.deleteGroup(+id).catch((err) => {
this.handleEntityNotFoundError(id, err);
});
}
// -------------------- Category --------------------
// --
@Get('/categories')
@ApiResponse({ type: [Category] })
findCategories(
@Paginate() query: PaginateQuery,
): Promise<Paginated<Category>> {
return this.service.findCategories(query);
}
@Get('/categories/:id')
@ApiResponse({ type: Category })
async findCategory(@Param('id') id: number): Promise<Category | null> {
// NOTE: the + operator returns the numeric representation of the object.
return this.service.findCategory(+id).catch((err) => {
this.handleEntityNotFoundError(id, err);
return null;
});
}
@Post('/categories')
@ApiResponse({ type: [Category] })
createCategory(@Body() categoryCreateDto: CategoryCreateDto) {
return this.service.createCategory(categoryCreateDto);
}
@Patch('/categories/:id')
// Status 204 because no content will be returned
@HttpCode(204)
async updateCategory(
@Param('id') id: number,
@Body() categoryUpdateDto: CategoryUpdateDto,
): Promise<void> {
if (Object.keys(categoryUpdateDto).length === 0) {
throw new BadRequestException('Request body is empty');
}
await this.service.updateCategory(+id, categoryUpdateDto).catch((err) => {
this.handleEntityNotFoundError(id, err);
});
}
@Delete('/categories/:id')
@HttpCode(204)
async deleteCategory(@Param('id') id: number): Promise<void> {
await this.service.deleteCategory(+id).catch((err) => {
this.handleEntityNotFoundError(id, err);
});
}
}

17
src/zgc/zgc.module.ts Normal file
View File

@ -0,0 +1,17 @@
import { Logger, Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ZgcService } from './zgc.service';
import { ZgcController } from './zgc.controller';
import { Zone } from './entities/zone.entity';
import { Group } from './entities/group.entity';
import { Category } from './entities/category.entity';
@Module({
imports: [TypeOrmModule.forFeature([Zone, Group, Category])],
controllers: [ZgcController],
providers: [Logger, ZgcService],
// If you want to use the repository outside of the module
// which imports TypeOrmModule.forFeature, you'll need to re-export the providers generated by it.
// exports: [TypeOrmModule],
})
export class ZgcModule {}

221
src/zgc/zgc.service.ts Normal file
View File

@ -0,0 +1,221 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { EntityNotFoundError, Repository } from 'typeorm';
import { PaginateQuery, Paginated, paginate } from 'nestjs-paginate';
import { ZoneCreateDto } from './dto/zone-create.dto';
import { ZoneUpdateDto } from './dto/zone-update.dto';
import { Zone } from './entities/zone.entity';
import { GroupCreateDto } from './dto/group-create.dto';
import { GroupUpdateDto } from './dto/group-update.dto';
import { Group } from './entities/group.entity';
import { Category } from './entities/category.entity';
import { CategoryCreateDto } from './dto/category-create.dto';
import { CategoryUpdateDto } from './dto/category-update.dto';
@Injectable()
export class ZgcService {
constructor(
private readonly logger: Logger,
@InjectRepository(Zone)
private zonesRepository: Repository<Zone>,
@InjectRepository(Group)
private groupsRepository: Repository<Group>,
@InjectRepository(Category)
private categoriesRepository: Repository<Category>,
) {}
// -------------------- Zone --------------------
// --
createZone(zoneCreateDto: ZoneCreateDto): Promise<Zone> {
// Use Repository.create() will copy the values to destination object.
const zone = this.zonesRepository.create(zoneCreateDto);
return this.zonesRepository.save(zone);
}
findZones(query: PaginateQuery): Promise<Paginated<Zone>> {
return paginate(query, this.zonesRepository, {
// loadEagerRelations: true,
// relations: { groups: true },
relations: ['groups'],
sortableColumns: ['id', 'name', 'displayOrder'],
defaultSortBy: [
['displayOrder', 'ASC'],
['id', 'ASC'],
['groups.displayOrder', 'ASC'],
['groups.id', 'ASC'],
],
select: [
'id',
'name',
'displayOrder',
'groups.id',
'groups.name',
'groups.displayOrder',
// 'groups.categories.id',
// 'groups.categories.name',
// 'groups.categories.displayOrder',
],
// searchableColumns: ['id', 'name'],
// filterableColumns: {
// 'id': [
// FilterOperator.EQ,
// FilterSuffix.NOT,
// ],
// 'name': [
// FilterOperator.EQ,
// FilterOperator.ILIKE,
// FilterSuffix.NOT,
// ],
// },
});
}
findZone(id: number): Promise<Zone> {
return this.zonesRepository.findOneOrFail({ where: { id } });
}
async updateZone(id: number, zoneUpdateDto: ZoneUpdateDto): Promise<void> {
await this.isZoneExist(id);
await this.zonesRepository.update({ id }, zoneUpdateDto);
}
async deleteZone(id: number): Promise<void> {
await this.isZoneExist(id);
await this.zonesRepository.delete(id);
}
// Helper function: Check if the entity exist.
// If entity does not exsit, return the Promise.reject()
private async isZoneExist(id: number): Promise<void> {
const cnt = await this.zonesRepository.countBy({ id });
if (cnt > 0) {
return;
} else {
return Promise.reject(new EntityNotFoundError(Zone, { where: { id } }));
}
}
// -------------------- Group --------------------
// --
createGroup(groupCreateDto: GroupCreateDto): Promise<Group> {
// Use Repository.create() will copy the values to destination object.
const group = this.groupsRepository.create(groupCreateDto);
return this.groupsRepository.save(group);
}
findGroups(query: PaginateQuery): Promise<Paginated<Group>> {
return paginate(query, this.groupsRepository, {
// loadEagerRelations: true,
// relations: { groups: true },
relations: ['zone', 'categories'],
sortableColumns: ['id', 'name', 'displayOrder'],
select: [
'id',
'name',
'displayOrder',
'zone.id',
'zone.name',
'categories.id',
'categories.name',
'categories.displayOrder',
],
// searchableColumns: ['id', 'name'],
// filterableColumns: {
// 'id': [
// FilterOperator.EQ,
// FilterSuffix.NOT,
// ],
// 'name': [
// FilterOperator.EQ,
// FilterOperator.ILIKE,
// FilterSuffix.NOT,
// ],
// },
});
}
findGroup(id: number): Promise<Group> {
return this.groupsRepository.findOneOrFail({ where: { id } });
}
async updateGroup(id: number, groupUpdateDto: GroupUpdateDto): Promise<void> {
await this.isGroupExist(id);
await this.groupsRepository.update({ id }, groupUpdateDto);
}
async deleteGroup(id: number): Promise<void> {
await this.isGroupExist(id);
await this.groupsRepository.delete(id);
}
// Helper function: Check if the entity exist.
// If entity does not exsit, return the Promise.reject()
private async isGroupExist(id: number): Promise<void> {
const cnt = await this.groupsRepository.countBy({ id });
if (cnt > 0) {
return;
} else {
return Promise.reject(new EntityNotFoundError(Group, { where: { id } }));
}
}
// -------------------- Category --------------------
// --
createCategory(cateogyCreateDto: CategoryCreateDto): Promise<Category> {
// Use Repository.create() will copy the values to destination object.
const cateogy = this.categoriesRepository.create(cateogyCreateDto);
return this.categoriesRepository.save(cateogy);
}
findCategories(query: PaginateQuery): Promise<Paginated<Category>> {
return paginate(query, this.categoriesRepository, {
// loadEagerRelations: true,
// relations: { groups: true },
relations: ['group'],
sortableColumns: ['id', 'name', 'displayOrder'],
select: ['id', 'name', 'displayOrder', 'group.id', 'group.name'],
searchableColumns: ['id', 'name'],
// filterableColumns: {
// 'id': [
// FilterOperator.EQ,
// FilterSuffix.NOT,
// ],
// 'name': [
// FilterOperator.EQ,
// FilterOperator.ILIKE,
// FilterSuffix.NOT,
// ],
// },
});
}
findCategory(id: number): Promise<Category> {
return this.categoriesRepository.findOneOrFail({ where: { id } });
}
async updateCategory(
id: number,
categoryUpdateDto: CategoryUpdateDto,
): Promise<void> {
await this.isCategoryExist(id);
await this.categoriesRepository.update({ id }, categoryUpdateDto);
}
async deleteCategory(id: number): Promise<void> {
await this.isCategoryExist(id);
await this.categoriesRepository.delete(id);
}
// Helper function: Check if the entity exist.
// If entity does not exsit, return the Promise.reject()
private async isCategoryExist(id: number): Promise<void> {
const cnt = await this.categoriesRepository.countBy({ id });
if (cnt > 0) {
return;
} else {
return Promise.reject(
new EntityNotFoundError(Category, { where: { id } }),
);
}
}
}

View File

@ -5,5 +5,34 @@
"created": "2023-04-20T12:42:42.547Z",
"sortNum": 10000,
"folders": []
},
{
"_id": "1d5b8a54-f8ba-480a-96bd-8faf7d7cb4ba",
"colName": "Local NestJS App - ZGC",
"created": "2023-04-24T16:41:46.695Z",
"sortNum": 20000,
"folders": [
{
"_id": "10f85be8-b759-4364-8949-5338d329703a",
"name": "Zone",
"containerId": "",
"created": "2023-04-24T16:41:57.395Z",
"sortNum": 10000
},
{
"_id": "b4b39ee3-0da2-4ec0-b2d4-ace00dd8280d",
"name": "Group",
"containerId": "",
"created": "2023-04-24T17:04:34.098Z",
"sortNum": 20000
},
{
"_id": "a16fc112-ae03-47e0-8eb2-eaf97bcbe36f",
"name": "Categories",
"containerId": "",
"created": "2023-04-24T17:04:47.131Z",
"sortNum": 30000
}
]
}
]

View File

@ -136,5 +136,125 @@
"form": []
},
"tests": []
},
{
"_id": "ee150c28-07bd-4792-b6a8-6551e3e6169b",
"colId": "1d5b8a54-f8ba-480a-96bd-8faf7d7cb4ba",
"containerId": "10f85be8-b759-4364-8949-5338d329703a",
"name": "Get Zones",
"url": "http://localhost:3000/zgc/zones/?limit=3",
"method": "GET",
"sortNum": 10000,
"created": "2023-04-24T16:42:10.562Z",
"modified": "2023-04-24T17:24:36.920Z",
"headers": [],
"params": [
{
"name": "limit",
"value": "3",
"isPath": false
}
],
"tests": []
},
{
"_id": "16119da3-4863-4650-86f5-7fac55269cea",
"colId": "1d5b8a54-f8ba-480a-96bd-8faf7d7cb4ba",
"containerId": "b4b39ee3-0da2-4ec0-b2d4-ace00dd8280d",
"name": "Get Groups",
"url": "http://localhost:3000/zgc/groups/",
"method": "GET",
"sortNum": 10000,
"created": "2023-04-24T16:44:34.640Z",
"modified": "2023-04-24T17:04:37.342Z",
"headers": [],
"params": [],
"tests": []
},
{
"_id": "27716e9b-e0a7-47d4-9fb6-ede300275c5c",
"colId": "1d5b8a54-f8ba-480a-96bd-8faf7d7cb4ba",
"containerId": "a16fc112-ae03-47e0-8eb2-eaf97bcbe36f",
"name": "Get Categories",
"url": "http://localhost:3000/zgc/categories/",
"method": "GET",
"sortNum": 10000,
"created": "2023-04-24T16:47:23.727Z",
"modified": "2023-04-24T17:04:50.733Z",
"headers": [],
"params": [],
"tests": []
},
{
"_id": "d9148936-364a-4e2d-aeb4-ab26adb10d63",
"colId": "1d5b8a54-f8ba-480a-96bd-8faf7d7cb4ba",
"containerId": "a16fc112-ae03-47e0-8eb2-eaf97bcbe36f",
"name": "Add Category",
"url": "http://localhost:3000/zgc/categories/",
"method": "POST",
"sortNum": 20000,
"created": "2023-04-24T17:04:59.718Z",
"modified": "2023-04-24T17:18:30.236Z",
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
],
"params": [],
"body": {
"type": "json",
"raw": "{\n \"name\": \"Cat {{#name}} - {{#number, 100, 999}}\",\n \"group\": {\n \"id\": 1\n }\n}",
"form": []
},
"tests": []
},
{
"_id": "55d7d81e-4779-4d78-aa71-dfa120c9d741",
"colId": "1d5b8a54-f8ba-480a-96bd-8faf7d7cb4ba",
"containerId": "10f85be8-b759-4364-8949-5338d329703a",
"name": "Add Zone",
"url": "http://localhost:3000/zgc/zones/",
"method": "POST",
"sortNum": 20000,
"created": "2023-04-24T17:12:09.466Z",
"modified": "2023-04-24T17:15:32.575Z",
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
],
"params": [],
"body": {
"type": "json",
"raw": "{\n \"name\": \"Zone {{#name}} - {{#number, 100, 999}}\"\n}",
"form": []
},
"tests": []
},
{
"_id": "594e6cf8-5eb6-49cb-b446-4848c36461be",
"colId": "1d5b8a54-f8ba-480a-96bd-8faf7d7cb4ba",
"containerId": "b4b39ee3-0da2-4ec0-b2d4-ace00dd8280d",
"name": "Add Group",
"url": "http://localhost:3000/zgc/groups/",
"method": "POST",
"sortNum": 20000,
"created": "2023-04-24T17:15:59.691Z",
"modified": "2023-04-24T17:24:11.934Z",
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
],
"params": [],
"body": {
"type": "json",
"raw": "{\n \"name\": \"Group {{#name}} - {{#number, 100, 999}}\",\n \"zone\": {\n \"id\": 7\n }\n}",
"form": []
},
"tests": []
}
]