diff --git a/src/app.module.ts b/src/app.module.ts index 992ae61..53348e8 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -31,6 +31,7 @@ import { ProductModule } from './modules/product/product.module'; import { ProjectModule } from './modules/project/project.module'; import { VehicleUsageModule } from './modules/vehicle_usage/vehicle_usage.module'; import { SaleQuotationModule } from './modules/sale_quotation/sale_quotation.module'; +import { DomainModule } from './modules/domian/domain.module'; @Module({ imports: [ @@ -77,7 +78,9 @@ import { SaleQuotationModule } from './modules/sale_quotation/sale_quotation.mod VehicleUsageModule, //报价管理 - SaleQuotationModule + SaleQuotationModule, + //域 + DomainModule ], providers: [ { provide: APP_FILTER, useClass: AllExceptionsFilter }, diff --git a/src/common/decorators/domain.decorator.ts b/src/common/decorators/domain.decorator.ts new file mode 100644 index 0000000..bcd02c2 --- /dev/null +++ b/src/common/decorators/domain.decorator.ts @@ -0,0 +1,18 @@ +import { ExecutionContext, createParamDecorator } from '@nestjs/common'; +import { ApiProperty } from '@nestjs/swagger'; +import { IsOptional } from 'class-validator'; +import type { FastifyRequest } from 'fastify'; +/** + * 当前域 + */ +export const Domain = createParamDecorator((_, context: ExecutionContext) => { + const request = context.switchToHttp().getRequest(); + return request.headers['sk-domain']; +}); + +export type SkDomain = number; +export class DomainType { + @ApiProperty({ description: '所属域' }) + @IsOptional() + domain: SkDomain; +} diff --git a/src/common/decorators/http.decorator.ts b/src/common/decorators/http.decorator.ts index f90d311..c94d366 100644 --- a/src/common/decorators/http.decorator.ts +++ b/src/common/decorators/http.decorator.ts @@ -5,6 +5,7 @@ import type { FastifyRequest } from 'fastify'; import { getIp, getIsMobile } from '~/utils/ip.util'; + /** * 快速获取IP */ diff --git a/src/constants/error-code.constant.ts b/src/constants/error-code.constant.ts index 27b8e11..61b5117 100644 --- a/src/constants/error-code.constant.ts +++ b/src/constants/error-code.constant.ts @@ -65,6 +65,8 @@ export enum ErrorEnum { // SaleQuotation SALE_QUOTATION_COMPONENT_DUPLICATED = '1412:存在名称,价格,规格都相同的配件,请检查是否重复录入', - SALE_QUOTATION_TEMPLATE_NAME_DUPLICATE = '1413:模板名已存在' + SALE_QUOTATION_TEMPLATE_NAME_DUPLICATE = '1413:模板名已存在', + //domain + DOMAIN_TITLE_DUPLICATE = '1414:域标题已存在' } diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 4e2a593..66b5b59 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -14,6 +14,7 @@ import { LoginToken } from './models/auth.model'; import { CaptchaService } from './services/captcha.service'; import { AuthUser } from './decorators/auth-user.decorator'; import { ApiSecurityAuth } from '~/common/decorators/swagger.decorator'; +import { Domain, SkDomain } from '~/common/decorators/domain.decorator'; @ApiTags('Auth - 认证模块') @UseGuards(LocalGuard) @@ -35,7 +36,7 @@ export class AuthController { @IsMobile() isMobile: boolean, @Headers('user-agent') ua: string ): Promise { - if(!isMobile){ + if (!isMobile) { await this.captchaService.checkImgCaptcha(dto.captchaId, dto.verifyCode); } const token = await this.authService.login(dto.username, dto.password, ip, ua); @@ -53,7 +54,7 @@ export class AuthController { @Post('register') @ApiOperation({ summary: '注册' }) - async register(@Body() dto: RegisterDto): Promise { - await this.userService.register(dto); + async register(@Domain() domain: SkDomain, @Body() dto: RegisterDto): Promise { + await this.userService.register(dto, domain); } } diff --git a/src/modules/auth/controllers/account.controller.ts b/src/modules/auth/controllers/account.controller.ts index c11feae..65c0661 100644 --- a/src/modules/auth/controllers/account.controller.ts +++ b/src/modules/auth/controllers/account.controller.ts @@ -16,6 +16,7 @@ import { AccountMenus, AccountUpdateDto } from '../dto/account.dto'; import { JwtAuthGuard } from '../guards/jwt-auth.guard'; import { IsMobile } from '~/common/decorators/http.decorator'; import { ResourceDeviceEnum } from '~/constants/enum'; +import { Domain } from '~/common/decorators/domain.decorator'; @ApiTags('Account - 账户模块') @ApiSecurityAuth() diff --git a/src/modules/company/company.controller.ts b/src/modules/company/company.controller.ts index 0333d14..1ad2602 100644 --- a/src/modules/company/company.controller.ts +++ b/src/modules/company/company.controller.ts @@ -16,6 +16,7 @@ import { ApiResult } from '~/common/decorators/api-result.decorator'; import { CompanyEntity } from './company.entity'; import { CompanyDto, CompanyQueryDto, CompanyUpdateDto } from './company.dto'; import { IdParam } from '~/common/decorators/id-param.decorator'; +import { Domain, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('app:company', { LIST: 'list', CREATE: 'create', @@ -24,7 +25,7 @@ export const permissions = definePermission('app:company', { DELETE: 'delete' } as const); -@ApiTags('Company - 公司') +@ApiTags('Company - 公司') @ApiSecurityAuth() @Controller('company') export class CompanyController { @@ -34,8 +35,8 @@ export class CompanyController { @ApiOperation({ summary: '获取公司列表' }) @ApiResult({ type: [CompanyEntity], isPage: true }) @Perm(permissions.LIST) - async list(@Query() dto: CompanyQueryDto) { - return this.companyService.findAll(dto); + async list(@Domain() domain: SkDomain, @Query() dto: CompanyQueryDto) { + return this.companyService.findAll({ ...dto, domain }); } @Get(':id') @@ -49,8 +50,8 @@ export class CompanyController { @Post() @ApiOperation({ summary: '新增公司' }) @Perm(permissions.CREATE) - async create(@Body() dto: CompanyDto): Promise { - await this.companyService.create(dto); + async create(@Domain() domain: SkDomain, @Body() dto: CompanyDto): Promise { + await this.companyService.create({ ...dto, domain }); } @Put(':id') diff --git a/src/modules/company/company.dto.ts b/src/modules/company/company.dto.ts index 6b39ea5..6a9f350 100644 --- a/src/modules/company/company.dto.ts +++ b/src/modules/company/company.dto.ts @@ -15,8 +15,9 @@ import { PagerDto } from '~/common/dto/pager.dto'; import { Storage } from '../tools/storage/storage.entity'; import { IsUnique } from '~/shared/database/constraints/unique.constraint'; import { CompanyEntity } from './company.entity'; +import { DomainType, SkDomain } from '~/common/decorators/domain.decorator'; -export class CompanyDto { +export class CompanyDto extends DomainType { @ApiProperty({ description: '公司名称' }) @IsUnique(CompanyEntity, { message: '已存在同名公司' }) @IsString() @@ -42,7 +43,8 @@ export class ComapnyCreateDto extends PartialType(CompanyDto) { export class CompanyQueryDto extends IntersectionType( PagerDto, - PartialType(CompanyDto) + PartialType(CompanyDto), + DomainType ) { @ApiProperty({ description: '公司名称' }) @IsOptional() diff --git a/src/modules/company/company.entity.ts b/src/modules/company/company.entity.ts index 6608cbc..2f75103 100644 --- a/src/modules/company/company.entity.ts +++ b/src/modules/company/company.entity.ts @@ -3,6 +3,7 @@ import { Column, Entity, JoinTable, ManyToMany, OneToMany, Relation } from 'type import { CommonEntity } from '~/common/entity/common.entity'; import { Storage } from '../tools/storage/storage.entity'; import { ProductEntity } from '../product/product.entity'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Entity({ name: 'company' }) export class CompanyEntity extends CommonEntity { @@ -20,6 +21,10 @@ export class CompanyEntity extends CommonEntity { @ApiProperty({ description: '删除状态:0未删除,1已删除' }) isDelete: number; + @Column({ type: 'int', default: 1, comment: '所属域' }) + @ApiProperty({ description: '所属域' }) + domain: SkDomain; + @ApiHideProperty() @OneToMany(() => ProductEntity, product => product.company) products: Relation; diff --git a/src/modules/company/company.service.ts b/src/modules/company/company.service.ts index aca6da4..8cb1fdd 100644 --- a/src/modules/company/company.service.ts +++ b/src/modules/company/company.service.ts @@ -9,6 +9,7 @@ import { Storage } from '../tools/storage/storage.entity'; import { BusinessException } from '~/common/exceptions/biz.exception'; import { ErrorEnum } from '~/constants/error-code.constant'; import { fieldSearch } from '~/shared/database/field-search'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Injectable() export class CompanyService { @@ -70,11 +71,7 @@ export class CompanyService { throw new BusinessException(ErrorEnum.STORAGE_NOT_FOUND); } // 附件要批量插入 - await manager - .createQueryBuilder() - .relation(CompanyEntity, 'files') - .of(id) - .add(fileIds); + await manager.createQueryBuilder().relation(CompanyEntity, 'files').of(id).add(fileIds); } }); } diff --git a/src/modules/contract/contract.controller.ts b/src/modules/contract/contract.controller.ts index a3e716f..d21578b 100644 --- a/src/modules/contract/contract.controller.ts +++ b/src/modules/contract/contract.controller.ts @@ -16,6 +16,7 @@ import { ApiResult } from '~/common/decorators/api-result.decorator'; import { ContractEntity } from './contract.entity'; import { ContractDto, ContractQueryDto, ContractUpdateDto } from './contract.dto'; import { IdParam } from '~/common/decorators/id-param.decorator'; +import { Domain, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('app:contract', { LIST: 'list', CREATE: 'create', @@ -34,8 +35,8 @@ export class ContractController { @ApiOperation({ summary: '获取合同列表' }) @ApiResult({ type: [ContractEntity], isPage: true }) @Perm(permissions.LIST) - async list(@Query() dto: ContractQueryDto) { - return this.contractService.findAll(dto); + async list(@Domain() domain: SkDomain, @Query() dto: ContractQueryDto) { + return this.contractService.findAll({ ...dto, domain }); } @Get(':id') @@ -49,8 +50,8 @@ export class ContractController { @Post() @ApiOperation({ summary: '新增合同' }) @Perm(permissions.CREATE) - async create(@Body() dto: ContractDto): Promise { - await this.contractService.create(dto); + async create(@Domain() domain: SkDomain, @Body() dto: ContractDto): Promise { + await this.contractService.create({ ...dto, domain }); } @Put(':id') @@ -70,8 +71,10 @@ export class ContractController { @Put('unlink-attachments/:id') @ApiOperation({ summary: '附件解除关联' }) @Perm(permissions.UPDATE) - async unlinkAttachments(@IdParam() id: number, @Body() {fileIds}: ContractUpdateDto): Promise { + async unlinkAttachments( + @IdParam() id: number, + @Body() { fileIds }: ContractUpdateDto + ): Promise { await this.contractService.unlinkAttachments(id, fileIds); } - } diff --git a/src/modules/contract/contract.dto.ts b/src/modules/contract/contract.dto.ts index 3ada817..46e6e85 100644 --- a/src/modules/contract/contract.dto.ts +++ b/src/modules/contract/contract.dto.ts @@ -15,8 +15,9 @@ import { import { PagerDto } from '~/common/dto/pager.dto'; import { Storage } from '../tools/storage/storage.entity'; import { ContractStatusEnum } from '~/constants/enum'; +import { DomainType, SkDomain } from '~/common/decorators/domain.decorator'; -export class ContractDto { +export class ContractDto extends DomainType { @ApiProperty({ description: '合同编号' }) @Matches(/^[a-z0-9A-Z]+$/, { message: '合同编号只能包含字母和数字' }) @IsString() @@ -65,5 +66,7 @@ export class ContractUpdateDto extends PartialType(ContractDto) { } export class ContractQueryDto extends IntersectionType( PagerDto, - PartialType(ContractDto) -) {} + PartialType(ContractDto), + DomainType +) {} + diff --git a/src/modules/contract/contract.entity.ts b/src/modules/contract/contract.entity.ts index d75b05a..40856b7 100644 --- a/src/modules/contract/contract.entity.ts +++ b/src/modules/contract/contract.entity.ts @@ -2,6 +2,7 @@ import { ApiHideProperty, ApiProperty } from '@nestjs/swagger'; import { Column, Entity, JoinTable, ManyToMany, Relation } from 'typeorm'; import { CommonEntity } from '~/common/entity/common.entity'; import { Storage } from '../tools/storage/storage.entity'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Entity({ name: 'contract' }) export class ContractEntity extends CommonEntity { @@ -47,6 +48,10 @@ export class ContractEntity extends CommonEntity { @ApiProperty({ description: '删除状态:0未删除,1已删除' }) isDelete: number; + @Column({ type: 'int', default: 1, comment: '所属域' }) + @ApiProperty({ description: '所属域' }) + domain: SkDomain; + @ManyToMany(() => Storage, storage => storage.contracts) @JoinTable({ name: 'contract_storage', diff --git a/src/modules/contract/contract.service.ts b/src/modules/contract/contract.service.ts index ae961dd..267ef0b 100644 --- a/src/modules/contract/contract.service.ts +++ b/src/modules/contract/contract.service.ts @@ -10,6 +10,7 @@ import { Storage } from '../tools/storage/storage.entity'; import { BusinessException } from '~/common/exceptions/biz.exception'; import { ErrorEnum } from '~/constants/error-code.constant'; import { fieldSearch } from '~/shared/database/field-search'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Injectable() export class ContractService { diff --git a/src/modules/domian/domain.controller.ts b/src/modules/domian/domain.controller.ts new file mode 100644 index 0000000..e0ca43b --- /dev/null +++ b/src/modules/domian/domain.controller.ts @@ -0,0 +1,69 @@ +import { + Body, + Controller, + Get, + Query, + Put, + Delete, + Post, + BadRequestException +} from '@nestjs/common'; +import { ApiOperation, ApiTags } from '@nestjs/swagger'; +import { Perm, definePermission } from '../auth/decorators/permission.decorator'; +import { ApiSecurityAuth } from '~/common/decorators/swagger.decorator'; +import { DomainService } from './domain.service'; +import { ApiResult } from '~/common/decorators/api-result.decorator'; +import { DomainEntity } from './domain.entity'; +import { DomainDto, DomainQueryDto, DomainUpdateDto } from './domain.dto'; +import { IdParam } from '~/common/decorators/id-param.decorator'; +export const permissions = definePermission('app:domain', { + LIST: 'list', + CREATE: 'create', + READ: 'read', + UPDATE: 'update', + DELETE: 'delete' +} as const); + +@ApiTags('Domain - 域') +@ApiSecurityAuth() +@Controller('domain') +export class DomainController { + constructor(private domainService: DomainService) {} + + @Get() + @ApiOperation({ summary: '获取域列表' }) + @ApiResult({ type: [DomainEntity], isPage: true }) + @Perm(permissions.LIST) + async list(@Query() dto: DomainQueryDto) { + return this.domainService.findAll(dto); + } + + @Get(':id') + @ApiOperation({ summary: '获取域信息' }) + @ApiResult({ type: DomainDto }) + @Perm(permissions.READ) + async info(@IdParam() id: number) { + return this.domainService.info(id); + } + + @Post() + @ApiOperation({ summary: '新增域' }) + @Perm(permissions.CREATE) + async create(@Body() dto: DomainDto): Promise { + await this.domainService.create(dto); + } + + @Put(':id') + @ApiOperation({ summary: '更新域' }) + @Perm(permissions.UPDATE) + async update(@IdParam() id: number, @Body() dto: DomainUpdateDto): Promise { + await this.domainService.update(id, dto); + } + + @Delete(':id') + @ApiOperation({ summary: '删除域' }) + @Perm(permissions.DELETE) + async delete(@IdParam() id: number): Promise { + await this.domainService.delete(id); + } +} diff --git a/src/modules/domian/domain.dto.ts b/src/modules/domian/domain.dto.ts new file mode 100644 index 0000000..61d94fb --- /dev/null +++ b/src/modules/domian/domain.dto.ts @@ -0,0 +1,12 @@ +import { ApiProperty, IntersectionType, PartialType } from '@nestjs/swagger'; +import { IsString } from 'class-validator'; +import { PagerDto } from '~/common/dto/pager.dto'; + +export class DomainDto { + @ApiProperty({ description: '域标题' }) + @IsString() + title: string; +} + +export class DomainUpdateDto extends PartialType(DomainDto) {} +export class DomainQueryDto extends IntersectionType(PagerDto, PartialType(DomainDto)) {} diff --git a/src/modules/domian/domain.entity.ts b/src/modules/domian/domain.entity.ts new file mode 100644 index 0000000..8ed3c48 --- /dev/null +++ b/src/modules/domian/domain.entity.ts @@ -0,0 +1,15 @@ +import { ApiHideProperty, ApiProperty } from '@nestjs/swagger'; +import { Column, Entity, JoinTable, ManyToMany, Relation } from 'typeorm'; +import { CommonEntity } from '~/common/entity/common.entity'; +import { Storage } from '../tools/storage/storage.entity'; + +@Entity({ name: 'domain' }) +export class DomainEntity extends CommonEntity { + @Column({ name: 'title', type: 'varchar', length: 255, comment: '域标题' }) + @ApiProperty({ description: '域标题' }) + title: string; + + @Column({ name: 'is_delete', type: 'tinyint', default: 0, comment: '是否删除' }) + @ApiProperty({ description: '删除状态:0未删除,1已删除' }) + isDelete: number; +} diff --git a/src/modules/domian/domain.module.ts b/src/modules/domian/domain.module.ts new file mode 100644 index 0000000..9aaa16f --- /dev/null +++ b/src/modules/domian/domain.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { DomainController } from './domain.controller'; +import { DomainService } from './domain.service'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { DomainEntity } from './domain.entity'; + +@Module({ + imports: [TypeOrmModule.forFeature([DomainEntity])], + controllers: [DomainController], + providers: [DomainService] +}) +export class DomainModule {} diff --git a/src/modules/domian/domain.service.ts b/src/modules/domian/domain.service.ts new file mode 100644 index 0000000..7fdfecd --- /dev/null +++ b/src/modules/domian/domain.service.ts @@ -0,0 +1,95 @@ +import { Injectable } from '@nestjs/common'; +import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; +import { DomainEntity } from './domain.entity'; +import { EntityManager, Like, Not, Repository } from 'typeorm'; +import { DomainDto, DomainQueryDto, DomainUpdateDto } from './domain.dto'; +import { Pagination } from '~/helper/paginate/pagination'; +import { isNumber } from 'lodash'; +import { paginate } from '~/helper/paginate'; +import { Storage } from '../tools/storage/storage.entity'; +import { BusinessException } from '~/common/exceptions/biz.exception'; +import { ErrorEnum } from '~/constants/error-code.constant'; +import { fieldSearch } from '~/shared/database/field-search'; + +@Injectable() +export class DomainService { + constructor( + @InjectEntityManager() private entityManager: EntityManager, + @InjectRepository(DomainEntity) + private domainRepository: Repository + ) {} + + /** + * 查找所有域 + */ + async findAll({ page, pageSize, ...fields }: DomainQueryDto): Promise> { + const queryBuilder = this.domainRepository + .createQueryBuilder('domain') + .where(fieldSearch(fields)) + .andWhere('domain.isDelete = 0'); + + return paginate(queryBuilder, { + page, + pageSize + }); + } + + /** + * 新增 + */ + async create({ title, ...ext }: DomainDto): Promise { + if (await this.checkIsDomainExsit(title)) { + throw new BusinessException(ErrorEnum.DOMAIN_TITLE_DUPLICATE); + } + await this.domainRepository.insert(this.domainRepository.create({ title, ...ext })); + } + + /** + * 更新 + */ + async update(id: number, { title, ...ext }: Partial): Promise { + await this.entityManager.transaction(async manager => { + if (title && (await this.checkIsDomainExsit(title, id))) { + throw new BusinessException(ErrorEnum.CONTRACT_NUMBER_EXIST); + } + await manager.update(DomainEntity, id, { + ...ext, + title + }); + }); + } + + /** + * 是否存在相同的域 + * @param title 域编号 + */ + async checkIsDomainExsit(title: string, id?: number): Promise { + return !!(await this.domainRepository.findOne({ + where: { + title: title, + id: Not(id) + } + })); + } + /** + * 删除 + */ + async delete(id: number): Promise { + // 域比较重要,做逻辑删除 + await this.domainRepository.update(id, { isDelete: 1 }); + } + + /** + * 获取单个域信息 + */ + async info(id: number) { + const info = await this.domainRepository + .createQueryBuilder('domain') + .where({ + id + }) + .andWhere('domain.isDelete = 0') + .getOne(); + return info; + } +} diff --git a/src/modules/materials_inventory/in_out/materials_in_out.controller.ts b/src/modules/materials_inventory/in_out/materials_in_out.controller.ts index 2bf709b..842e065 100644 --- a/src/modules/materials_inventory/in_out/materials_in_out.controller.ts +++ b/src/modules/materials_inventory/in_out/materials_in_out.controller.ts @@ -11,6 +11,7 @@ import { MaterialsInOutDto, MaterialsInOutUpdateDto } from './materials_in_out.dto'; +import { Domain, DomainType, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('materials_inventory:history_in_out', { LIST: 'list', @@ -29,8 +30,8 @@ export class MaterialsInOutController { @ApiOperation({ summary: '获取原材料出入库记录列表' }) @ApiResult({ type: [MaterialsInOutEntity], isPage: true }) @Perm(permissions.LIST) - async list(@Query() dto: MaterialsInOutQueryDto) { - return this.materialsInOutService.findAll(dto); + async list(@Domain() domain: SkDomain, @Query() dto: MaterialsInOutQueryDto) { + return this.materialsInOutService.findAll({ ...dto, domain }); } @Get(':id') @@ -44,8 +45,8 @@ export class MaterialsInOutController { @Post() @ApiOperation({ summary: '新增原材料出入库记录' }) @Perm(permissions.CREATE) - async create(@Body() dto: MaterialsInOutDto): Promise { - return this.materialsInOutService.create(dto); + async create(@Domain() domain: SkDomain, @Body() dto: MaterialsInOutDto): Promise { + return this.materialsInOutService.create({ ...dto, domain }); } @Put(':id') diff --git a/src/modules/materials_inventory/in_out/materials_in_out.dto.ts b/src/modules/materials_inventory/in_out/materials_in_out.dto.ts index 5364295..517c41e 100644 --- a/src/modules/materials_inventory/in_out/materials_in_out.dto.ts +++ b/src/modules/materials_inventory/in_out/materials_in_out.dto.ts @@ -17,12 +17,13 @@ import { isNumber } from 'class-validator'; import dayjs from 'dayjs'; +import { DomainType } from '~/common/decorators/domain.decorator'; import { PagerDto } from '~/common/dto/pager.dto'; import { MaterialsInOrOutEnum } from '~/constants/enum'; import { Storage } from '~/modules/tools/storage/storage.entity'; import { formatToDate } from '~/utils'; -export class MaterialsInOutDto { +export class MaterialsInOutDto extends DomainType { @IsOptional() @IsNumber() @ApiProperty({ description: '项目Id' }) @@ -100,7 +101,10 @@ export class MaterialsInOutUpdateDto extends PartialType(MaterialsInOutDto) { @IsArray() fileIds: number[]; } -export class MaterialsInOutQueryDto extends PagerDto { +export class MaterialsInOutQueryDto extends IntersectionType( + PagerDto, + DomainType +) { @ApiProperty({ description: '出入库时间YYYY-MM-DD' }) @IsOptional() // @IsString() diff --git a/src/modules/materials_inventory/in_out/materials_in_out.entity.ts b/src/modules/materials_inventory/in_out/materials_in_out.entity.ts index 6feef1f..b8e36b0 100644 --- a/src/modules/materials_inventory/in_out/materials_in_out.entity.ts +++ b/src/modules/materials_inventory/in_out/materials_in_out.entity.ts @@ -20,6 +20,7 @@ import { ProjectEntity } from '~/modules/project/project.entity'; import { ParamConfigEntity } from '~/modules/system/param-config/param-config.entity'; import { Storage } from '~/modules/tools/storage/storage.entity'; import { MaterialsInventoryEntity } from '../materials_inventory.entity'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Entity({ name: 'materials_in_out' }) export class MaterialsInOutEntity extends CommonEntity { @Column({ @@ -129,6 +130,10 @@ export class MaterialsInOutEntity extends CommonEntity { @JoinColumn({ name: 'product_id' }) product: ProductEntity; + @Column({ type: 'int', default: 1, comment: '所属域' }) + @ApiProperty({ description: '所属域' }) + domain: SkDomain; + @ManyToMany(() => Storage, storage => storage.materialsInOuts) @JoinTable({ name: 'materials_in_out_storage', diff --git a/src/modules/materials_inventory/materials_inventory.controller.ts b/src/modules/materials_inventory/materials_inventory.controller.ts index da479d1..d7392e4 100644 --- a/src/modules/materials_inventory/materials_inventory.controller.ts +++ b/src/modules/materials_inventory/materials_inventory.controller.ts @@ -13,6 +13,7 @@ import { MaterialsInventoryService } from './materials_inventory.service'; import { MaterialsInventoryEntity } from './materials_inventory.entity'; import { ApiSecurityAuth } from '~/common/decorators/swagger.decorator'; import { FastifyReply } from 'fastify'; +import { Domain, DomainType, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('app:materials_inventory', { LIST: 'list', @@ -33,10 +34,11 @@ export class MaterialsInventoryController { @ApiOperation({ summary: '导出原材料盘点表' }) @Perm(permissions.EXPORT) async exportMaterialsInventoryCheck( + @Domain() domain: SkDomain, @Query() dto: MaterialsInventoryExportDto, @Res() res: FastifyReply ): Promise { - await this.miService.exportMaterialsInventoryCheck(dto, res); + await this.miService.exportMaterialsInventoryCheck({ ...dto, domain }, res); } @Get() diff --git a/src/modules/materials_inventory/materials_inventory.dto.ts b/src/modules/materials_inventory/materials_inventory.dto.ts index 256167b..5d4d89f 100644 --- a/src/modules/materials_inventory/materials_inventory.dto.ts +++ b/src/modules/materials_inventory/materials_inventory.dto.ts @@ -18,13 +18,15 @@ import { Transform } from 'class-transformer'; import dayjs from 'dayjs'; import { formatToDate } from '~/utils'; import { HasInventoryStatusEnum } from '~/constants/enum'; +import { DomainType } from '~/common/decorators/domain.decorator'; -export class MaterialsInventoryDto {} +export class MaterialsInventoryDto extends DomainType {} export class MaterialsInventoryUpdateDto extends PartialType(MaterialsInventoryDto) {} export class MaterialsInventoryQueryDto extends IntersectionType( PagerDto, - PartialType(MaterialsInventoryDto) + PartialType(MaterialsInventoryDto), + DomainType ) { @ApiProperty({ description: '产品名' }) @IsOptional() @@ -46,7 +48,7 @@ export class MaterialsInventoryQueryDto extends IntersectionType( @IsNumber() projectId: number; } -export class MaterialsInventoryExportDto { +export class MaterialsInventoryExportDto extends DomainType { @ApiProperty({ description: '项目' }) @IsOptional() @IsNumber() diff --git a/src/modules/materials_inventory/materials_inventory.entity.ts b/src/modules/materials_inventory/materials_inventory.entity.ts index 69dfc7b..0625be9 100644 --- a/src/modules/materials_inventory/materials_inventory.entity.ts +++ b/src/modules/materials_inventory/materials_inventory.entity.ts @@ -13,6 +13,7 @@ import { CommonEntity } from '~/common/entity/common.entity'; import { ProductEntity } from '../product/product.entity'; import { ProjectEntity } from '../project/project.entity'; import { MaterialsInOutEntity } from './in_out/materials_in_out.entity'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Entity({ name: 'materials_inventory' }) export class MaterialsInventoryEntity extends CommonEntity { @@ -70,6 +71,10 @@ export class MaterialsInventoryEntity extends CommonEntity { @ApiProperty({ description: '删除状态:0未删除,1已删除' }) isDelete: number; + @Column({ type: 'int', default: 1, comment: '所属域' }) + @ApiProperty({ description: '所属域' }) + domain: SkDomain; + @ManyToOne(() => ProjectEntity) @JoinColumn({ name: 'project_id' }) project: ProjectEntity; @@ -89,5 +94,5 @@ export class MaterialsInventoryEntity extends CommonEntity { @ApiHideProperty() @OneToMany(() => MaterialsInOutEntity, inout => inout.inventory) - materialsInOuts: Relation; + materialsInOuts: Relation; } diff --git a/src/modules/materials_inventory/materials_inventory.service.ts b/src/modules/materials_inventory/materials_inventory.service.ts index bcae7e7..a87d29a 100644 --- a/src/modules/materials_inventory/materials_inventory.service.ts +++ b/src/modules/materials_inventory/materials_inventory.service.ts @@ -41,7 +41,7 @@ export class MaterialsInventoryService { * 导出原材料盘点表 */ async exportMaterialsInventoryCheck( - { time, projectId }: MaterialsInventoryExportDto, + { time, projectId, domain }: MaterialsInventoryExportDto, res: FastifyReply ): Promise { const ROW_HEIGHT = 20; diff --git a/src/modules/product/product.controller.ts b/src/modules/product/product.controller.ts index f1c28c2..d91bb61 100644 --- a/src/modules/product/product.controller.ts +++ b/src/modules/product/product.controller.ts @@ -16,6 +16,7 @@ import { ApiResult } from '~/common/decorators/api-result.decorator'; import { ProductEntity } from './product.entity'; import { ProductDto, ProductQueryDto, ProductUpdateDto } from './product.dto'; import { IdParam } from '~/common/decorators/id-param.decorator'; +import { Domain, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('app:product', { LIST: 'list', CREATE: 'create', @@ -34,8 +35,8 @@ export class ProductController { @ApiOperation({ summary: '获取产品列表' }) @ApiResult({ type: [ProductEntity], isPage: true }) @Perm(permissions.LIST) - async list(@Query() dto: ProductQueryDto) { - return this.productService.findAll(dto); + async list(@Domain() domain: SkDomain, @Query() dto: ProductQueryDto) { + return this.productService.findAll({ ...dto, domain }); } @Get(':id') @@ -49,8 +50,8 @@ export class ProductController { @Post() @ApiOperation({ summary: '新增产品' }) @Perm(permissions.CREATE) - async create(@Body() dto: ProductDto): Promise { - await this.productService.create(dto); + async create(@Domain() domain: SkDomain, @Body() dto: ProductDto): Promise { + await this.productService.create({ ...dto, domain }); } @Put(':id') diff --git a/src/modules/product/product.dto.ts b/src/modules/product/product.dto.ts index 85ca3fd..f476345 100644 --- a/src/modules/product/product.dto.ts +++ b/src/modules/product/product.dto.ts @@ -2,13 +2,13 @@ import { ApiProperty, IntersectionType, PartialType } from '@nestjs/swagger'; import { IsArray, IsNumber, IsOptional, IsString } from 'class-validator'; import { PagerDto } from '~/common/dto/pager.dto'; import { Storage } from '../tools/storage/storage.entity'; +import { DomainType } from '~/common/decorators/domain.decorator'; -export class ProductDto { +export class ProductDto extends DomainType { @ApiProperty({ description: '产品名称' }) @IsString() name: string; - @ApiProperty({ description: '产品规格' }) @IsOptional() @IsString() @@ -42,7 +42,8 @@ export class ProductUpdateDto extends PartialType(ProductDto) { export class ProductQueryDto extends IntersectionType( PagerDto, - PartialType(ProductDto) + PartialType(ProductDto), + DomainType ) { @ApiProperty({ description: '所属公司名称' }) @IsOptional() @@ -58,5 +59,4 @@ export class ProductQueryDto extends IntersectionType( @IsOptional() @IsString() keyword?: string; - } diff --git a/src/modules/product/product.entity.ts b/src/modules/product/product.entity.ts index f7bfad6..a424b87 100644 --- a/src/modules/product/product.entity.ts +++ b/src/modules/product/product.entity.ts @@ -15,6 +15,7 @@ import { Storage } from '../tools/storage/storage.entity'; import { CompanyEntity } from '../company/company.entity'; import pinyin from 'pinyin'; import { DictItemEntity } from '../system/dict-item/dict-item.entity'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Entity({ name: 'product' }) export class ProductEntity extends CommonEntity { @Column({ @@ -70,6 +71,10 @@ export class ProductEntity extends CommonEntity { @ManyToOne(() => DictItemEntity) @JoinColumn({ name: 'unit_id' }) unit: DictItemEntity; + + @Column({ type: 'int', default: 1, comment: '所属域' }) + @ApiProperty({ description: '所属域' }) + domain: SkDomain; @ApiHideProperty() @Column({ diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index fca5e25..e844f8b 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -22,6 +22,7 @@ import { UserPasswordDto } from './dto/password.dto'; import { UserDto, UserQueryDto, UserUpdateDto } from './dto/user.dto'; import { UserEntity } from './user.entity'; import { UserService } from './user.service'; +import { Domain, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('system:user', { LIST: 'list', @@ -47,8 +48,8 @@ export class UserController { @ApiOperation({ summary: '获取用户列表' }) @ApiResult({ type: [UserEntity], isPage: true }) @Perm(permissions.LIST) - async list(@Query() dto: UserQueryDto) { - return this.userService.list(dto); + async list(@Domain() domain: SkDomain, @Query() dto: UserQueryDto) { + return this.userService.list(dto, domain); } @Get(':id') diff --git a/src/modules/user/user.entity.ts b/src/modules/user/user.entity.ts index e311827..5069c63 100644 --- a/src/modules/user/user.entity.ts +++ b/src/modules/user/user.entity.ts @@ -13,6 +13,7 @@ import { OneToMany, Relation } from 'typeorm'; +import { SkDomain } from '~/common/decorators/domain.decorator'; import { CommonEntity } from '~/common/entity/common.entity'; @@ -73,6 +74,9 @@ export class UserEntity extends CommonEntity { @Column({ type: 'tinyint', nullable: true, default: 1 }) status: number; + @Column({ type: 'int', default: 1, comment: '所属域' }) + domain: SkDomain; + @ManyToMany(() => RoleEntity, role => role.users) @JoinTable({ name: 'sys_user_roles', diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index 16842a7..9be9d0f 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -28,6 +28,7 @@ import { PasswordUpdateDto } from './dto/password.dto'; import { UserDto, UserQueryDto, UserUpdateDto } from './dto/user.dto'; import { UserEntity } from './user.entity'; import { AccountInfo } from './user.model'; +import { SkDomain } from '~/common/decorators/domain.decorator'; @Injectable() export class UserService { @@ -243,16 +244,10 @@ export class UserService { /** * 查询用户列表 */ - async list({ - page, - pageSize, - username, - nickname, - deptId, - email, - status, - keyword - }: UserQueryDto): Promise> { + async list( + { page, pageSize, username, nickname, deptId, email, status, keyword }: UserQueryDto, + domain: SkDomain + ): Promise> { const queryBuilder = this.userRepository .createQueryBuilder('user') .leftJoinAndSelect('user.dept', 'dept') @@ -337,7 +332,7 @@ export class UserService { /** * 注册 */ - async register({ username, ...data }: RegisterDto): Promise { + async register({ username, ...data }: RegisterDto, domain: SkDomain): Promise { const exists = await this.userRepository.findOneBy({ username }); @@ -352,7 +347,8 @@ export class UserService { username, password, status: 1, - psalt: salt + psalt: salt, + domain }); const user = await manager.save(u); diff --git a/src/shared/database/field-search/index.ts b/src/shared/database/field-search/index.ts index 1067765..8b4d05d 100644 --- a/src/shared/database/field-search/index.ts +++ b/src/shared/database/field-search/index.ts @@ -1,5 +1,6 @@ import { isNumber } from 'lodash'; -import { Between, Like, ObjectLiteral, ObjectType } from 'typeorm'; +import { Between, Like, ObjectLiteral } from 'typeorm'; +import { SkDomain } from '~/common/decorators/domain.decorator'; export const fieldSearch = (entity: Partial): ObjectLiteral => { let result = {}; for (let key in entity) {